#!/usr/bin/perl # Extremely simple script that emulates "p4 diff2 -q -t" over any arbitrary # file sets. It checks for differences by looking at the contents of files # in the first set and comparing the contents and revisions in the second set. # For instance, one can see the differences between the state of the depot at # changelist X verses the current changelist: # perl p4-diff.pl //...@X //...#head # The generated output shows only the modified files between the two states # by outputting a modification indicator in the first column, a space, then # the depot name. The indicator uses "+" to mean that the file was added # in the second argument, a "-" to mean the file was removed from the first # to the second, and "!" means that the file was modified. Currently, this # does not track if a file was renamed. # # Using the example above, if the output looks like: # + //depot/1 # - //depot/2 # ! //depot/3 # then this means that the file "//depot/1" did not exist in changelist X, # but exists now; that the file "//depot/2" existed in changelist X, but does # not exist now; that the file "//depot/3" was changed between changelist X # and now. # # This is a general case of some other built-in P4 commands. # # # by Matt Albrecht # # Revision history: # 17-Jun-2003: Initial release $p4cmd = "p4"; sub getFiles($) { my ($set) = @_; my $cmd = "$p4cmd files $set"; print STDERR "<< $cmd\n"; my @lines = `$cmd`; my @files = (); foreach (@lines) { if (/^([^#]+)#(\d+)/) { my @set = ($1,$2); push @files, \@set; } } return @files; } sub getRev2($) { my ($set1) = @_; my @set2 = @{$set1}; return $set2[2]; } sub getRev($) { my ($set1, $index) = @_; my @set2 = @{$set1}; return $set2[1]; } sub getName($) { my ($set1, $index) = @_; my @set2 = @{$set1}; return $set2[0]; } sub isIn($@) { my ($element, @list) = @_; my $name1 = getName($element); foreach my $a (@list) { my $name2 = getName($a); if ($name1 eq $name2) { return getRev($a); } } return 0; } my ($label1, $label2) = @ARGV; my @files1 = getFiles( $label1 ); my @files2 = getFiles( $label2 ); my @in1and2 = (); my @rev1rev2 = (); foreach (@files1) { my $rev2 = isIn( $_, @files2 ); if ($rev2) { push @in1and2, $_; my @set = (getName($_), getRev($_), $rev2); push @rev1rev2, \@set; # do diff } else { print "+ ".getName($_)."\n"; } } foreach (@files2) { if (! isIn( $_, @in1and2 )) { print "- ".getName($_)."\n"; } } foreach (@rev1rev2) { my ($rev1, $rev2) = (getRev($_), getRev2($_)); if ($rev1 != $rev2) { print "! ".getName($_)."#".getRev($_).",#".getRev2($_)."\n"; } }