#!/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";
}
}