#! /usr/bin/perl
#------------------------------------------------------------------------------
# check-files.pl - show differences between files.txt and CVS tree
#
# usage: check-files.pl
#
# Please add package directory names to this file!
#
# Creation:    11.09.2003 jw5
# Last Update: $Id$
#------------------------------------------------------------------------------

# --- MODULES ---
use File::Find;
use strict;
use warnings;

# --- CONFIG ---
$ENV{'LANG'} = 'C';
# Subdirectories to use
my @dirs = (
	"advanced_networking", "ath_pci", "avm-fcclassic", "avm-fcdsl",
	"avm-fcdsl2", "avm-fcdslsl", "avm-fcdslslusb", "avm-fcdslusb", "avm-fcpci",
	"avm-fcpnp", "avm-fcusb", "avm-fcusb2", "avm-fxusb", "avm-fcdslusb2",
	"base",
	"chrony", "cipe", "cpanel", "cpmvrmlog",
	"dns_dhcp", "dhcp", "dhcp_advanced", "djbdns", "doc", "dsl", "dvb", "dyndns", "dyneisfair",
	"easycron",
	"faxrcv",
	"hd", "httpd", "httpd_skins",
	"imonc_unix", "imonc_windows", "isdn",
	"kernel_24", "kernel_26", "kernel_26_xen", 
	"lcd", "lcd4linux", "lirc", "lpdsrv",
	"minicom", "modem", "mtgcapri", "metalog", 
	"oidentd", "openvpn",
	"pcmcia", "ppp", "pppoe_server", "proxy",
	"qos",
	"register", "rrdtool", "rsync",
	"samba_lpd", "shfs", "smbfs", "soekris", "squid",
	"src", "src-non-free", "sshd","surfstation",
	"template", "tools",
	"usb", "usercmd",
	"vbox",
	"wlan", "wrap", "wol"
	
);
# These are pre-compiled pattern, add new ones the same way
my @ignore = (
	qr{\.svn},
	qr{src/src/buildroot/dl/},
	qr{src/src/buildroot/build/},
	qr{src/src/buildroot/target/},
	qr{src/src/fbr/build_i386/},
	qr{src/src/fbr/dl/},
	qr{src/src/kernel-2\../out/},
	qr{src/src/kernel-2\../linux-.+.bz2},
	qr{src/src/kernel-2\../linux-.+/},
	qr{src/src/kernel-2\../build-.+/},
	qr{src/src/kernel-2\../drivers/build-.+/},
	qr{src/src/kernel-2\../drivers/avm-.+},
	qr{src/src/kernel-2\../drivers/avm/},
	qr{src/src/kernel-2\../drivers/avm.sh},
	qr{src/src/kernel-2\../drivers/dl/},
	qr{src/src/fbr/toolchain_build_i386/},
	qr{.+~},
);
# These are the fileslists where all files should be listed...
my @filelists = (
	"files.txt"
);

# --- GLOBAL VARS ---
our (%real_files, %binfiles, %txtfiles, %files, %svn_files, @files, $key, $name, $type);

# --- SUBS ---
sub process_file {
	return unless -f;

	foreach my $pat (@ignore) {
		return if $File::Find::name =~ /$pat/;
	}
	$real_files{$File::Find::name} = 1;
}

# return all keys from the first hash that are not present in the second hash
sub weedout {
	my ($one, $two) = @_;
	grep { !defined($two->{$_}) } keys(%$one);
}

# --- MAIN ---

# read files.txt
print "Reading file list...\n";
foreach my $list (@filelists) {
	open (FILES, "<", $list) or die "can't open '$list': $!";

	while (<FILES>) {
		/^(.) (.*)$/o;
		$type = $1;
		$name = $2;
		if ( -f $name ) {
			$binfiles{$name} = 1 if ( $type =~ /[bB]/);
			$txtfiles{$name} = 1 if ( $type =~ /[dDuU]/);
		}
		$files{$name} = 1;
	}
	close FILES;
}

# read files in directories
print "Searching for files...\n";
find(\&process_file, @dirs);

print "Missing files:\n\n";
print " ".join("\n ", sort(weedout(\%files,\%real_files)))."\n";

print "\n\nNot in files.txt:\n\n";
print " ".join("\n ", sort(weedout(\%real_files,\%files)))."\n";

my $svn = (-d ".svn")? "svn" : "svk";
if (@ARGV == 0) {
	print "\n\nGetting svn state of files ...\n";
	open (SVN, "$svn status -v |") || die "unable to fork svn";
	while (<SVN>) {
		chomp;
		if (/^[^?].*/) {
			/.*\s+(\S+)$/;
			my $file = $1;
			if ($file ne ".") {
				$svn_files{$file} = 1 ;
			}
		}
	}
	close SVN;

	print "Files not in repository:\n\n";
	print " ".join("\n ", sort(weedout(\%files,\%svn_files)))."\n";

	print "\n";
	print "Checking svn properties...\n";

	@files = sort (keys %txtfiles);
	open (SVN, "$svn pg svn:keywords @files |") || die "unable to fork svn";
	while (<SVN>) {
		/^(\S+)\s+-\s(.*)/;
		$name = $1;
		$type = "$2";
		next if ($type =~ /Author\s+Date\s+Id\s+Revision$/);
		print "$name: Wrong value of 'svn:keywords' property: $type\n";
	}
	close SVN;

	foreach $key (sort keys %binfiles) {
		open (SVN, "$svn proplist -v $key |") || die "unable to fork svn";
		while (<SVN>) {
			next if /^Properties/;
			next if /svn:mime-type *: *application\/octet-stream/;
			next if /svn:executable/;
			print "$key: Wrong property or wrong value of property: $_";
		}
		close SVN;
	}

}

print "checking libc version\n";
foreach $key (sort keys %binfiles) {
	open (STRINGS, "strings $key |") || die "unable to fork strings";
	while (<STRINGS>) {
		if (/i386-linux-uclibc/) {
			print "$key: Wrong libc versions: $_";
		}
		if (/libc.so.[56]/) {
			print "$key: Wrong libc versions: $_";
		}
	}
	close STRINGS;
}
# vi: set ts=4 sw=4:
