#!/usr/bin/perl
#
# NAME
#   FindDiffFiles - Find files with same name but different contents.
#
# SYNOPSIS
#   FindDiffFiles [pattern] [dir] > DiffFiles
#
# DESCRIPTION
#   This script looks thru  all  the  listed  directories  and  their
#   subdirectories  ('.'  by  default),  and makes a table of all the
#   files whose name matches the pattern (all files by default).   It
#   then  runs  thru  the list in alphabetical order, comparing files
#   that have the same name, and outputs a list  of  the  pairs  with
#   different contents.  This can be useful in finding files that are
#   supposed to be the same but aren't.
#
# CAVEATS
#   There's generally nothing wrong with two files  having  the  same
#   name  but  different contents.  Consider 'Makefile', for example.
#   But in some situations, it can be a problem if  there  are,  say,
#   different  foo.c files in different directories.  So this program
#   doesn't do anything about such files; it just finds them for you.
#   Examining the output list is your problem.
#
# AUTHOR
#   John Chambers <jc@trillian.mit.edu>

$| = 1;
($me = $0) =~ s'.*/'';
$V = $ENV{"V_$me"} || $ENV{"T_$me"} || $ENV{"D_$me"} || 1;
$exitstat = 0;

for $a (@ARGV) {
	if (-d $a) {
		push(@dir,$a);
	} elsif (!$pat) {
		$pat = $a;
	} else {
		print STDERR "$me: Extra arg \"$a\" ignored.\n" if $V>0;
	}
}

$pat = '.+'  if !$pat;
@dir = ('.') if !@dir;

for $d (@dir) {
	&loaddir($d);
}

# Suppress some common file names:
undef $files{Makefile};
undef $files{Manifest};
undef $files{HEADER.html};

for $f (sort keys %files) {
	print "File $f ...\n" if $V>2;
	next if $f =~ /^\./i;
	next if $f =~ /readme/i;
	$l = $files{$f};
	@path = split(' ',$l);
F1:	while ($p1 = shift(@path)) {
		next F1 if !$p1;
		($d1,$i1,$m1,$n1,$u1,$g1,$r1,$s1) = lstat($p1);
F2:		for $p2 (@path) {
			next F2 if !$p2;
			($d2,$i2,$m2,$n2,$u2,$g2,$r2,$s2) = lstat($p2);
			next F2 if ($d1 == $d2 && $i1 == $i2);
			if ($s1 != $s2) {
				print "Diff $p1\t$p2\n";
			} else {
				if (!open(F1,$p1)) {
					print STDERR "$me: Can't read $p1 ($!)\n" if $V>0;
					next F1;
				}
				if (!open(F2,$p2)) {
					print STDERR "$me: Can't read $p2 ($!)\n" if $V>0;
					$p2 = '';	# Don't look at it again.
					next F2;
				}
				while ($l1 = <F1>) {
					if (!($l2 = <F2>)) {
						print "Diff $p1\t$p2\n"; 
						next F2;
					}
					if ($l1 ne $l2) {
						print "Diff $p1\t$p2\n"; 
						next F2;
					}
				}
				print "Same $p1\t$p2\n" if $V>2;
			}
		}
	}
}



exit $exitstat;


sub loaddir {
	local($d) = @_;
	local(*D,$f,$p);
	if (opendir(D,$d)) {
		print "Scan $d ...\n" if $V>1;
		for $f (readdir(D)) { 
			next if ($f =~ /^\.*$/);
			$p = ($d eq '.') ? $f : "$d/$f";
			if (-d $p) {&loaddir($p); next}
			next if ($f !~ $pat);
			$files{$f} .= "$p ";
		}
		closedir(D);
	} else {
		print STDERR "$me: Can't read dir $d ($!)\n" if $V>0;
	}
}
