#!/usr/bin/perl -w

#my $file1 = `mktemp genstat.XXXXXX`;
#FILE2=`mktemp genstat.XXXXXX` || exit1
#FILE3=`mktemp genstat.XXXXXX` || exit1
#
#

my $start = "v2.6.19";
my $end   = "v2.6.24-rc8";

my @core_files = ("init", "block", "ipc", "kernel", "lib", "mm");
my @fs_files = ("fs");
my @driver_files = ("crypto", "drivers", "sound", "security");
my @net_files = ("net");
my @arch_files = ("arch");
my @misc_files = ("Documentation", "scripts", "samples", "usr", "MAINTAINERS", "CREDITS", "README", ".gitignore", "Kbuild", "Makefile");

my $overall_add = 0;
my $overall_del = 0;
my $overall_mod = 0;
my $core_add = 0;
my $core_del = 0;
my $core_mod = 0;
my $fs_add = 0;
my $fs_del = 0;
my $fs_mod = 0;
my $driver_add = 0;
my $driver_del = 0;
my $driver_mod = 0;
my $net_add = 0;
my $net_del = 0;
my $net_mod = 0;
my $arch_add = 0;
my $arch_del = 0;
my $arch_mod = 0;
my $misc_add = 0;
my $misc_del = 0;
my $misc_mod = 0;

sub unknown($$$$$)
{
	my ($filename, $commit, $add, $del, $mod) = @_;
	print "unknown filename='$filename' commit=$commit add=$add del=$del mod=$mod\n";
}

sub include_category($$$$$)
{
	my ($filename, $commit, $add, $del, $mod) = @_;

	if (($filename eq "linux") ||
	    ($filename eq "keys") ||
	    ($filename eq "Kbuild")) {
		$core_add += $add;
		$core_del += $del;
		$core_mod += $mod;
	} elsif (($filename eq "acpi") ||
		 ($filename eq "crypto") ||
		 ($filename eq "media") ||
		 ($filename eq "mtd") ||
		 ($filename eq "pcmcia") ||
		 ($filename eq "rdma") ||
		 ($filename eq "rxrpc") ||
		 ($filename eq "scsi") ||
		 ($filename eq "sound") ||
		 ($filename eq "video")) {
		$driver_add += $add;
		$driver_del += $del;
		$driver_mod += $mod;
	} elsif (($filename eq "net")) {
		$net_add += $add;
		$net_del += $del;
		$net_mod += $mod;
	} elsif (($filename eq "xen") ||
		 ($filename eq "math-emu")) {
		$arch_add += $add;
		$arch_del += $del;
		$arch_mod += $mod;
	} else {
		# see if this is arch
		my @a = split(/-/,$filename);
		if ($a[0] eq "asm") {
			$arch_add += $add;
			$arch_del += $del;
			$arch_mod += $mod;
		} else {
			unknown($filename, $commit, $add, $del, $mod);
		}
	}
}

sub filename_category($$$$$)
{

	my ($filename, $commit, $add, $del, $mod) = @_;
	my @f = split(/\//,$filename);
	my $basename = $f[0];

	if ($basename eq "include") {
		include_category($f[1], $commit, $add, $del, $mod);
	} elsif (grep { /$basename/ } @core_files) {
		$core_add += $add;
		$core_del += $del;
		$core_mod += $mod;
	} elsif (grep { /$basename/ } @fs_files) {
		$fs_add += $add;
		$fs_del += $del;
		$fs_mod += $mod;
	} elsif (grep { /$basename/ } @driver_files) {
		$driver_add += $add;
		$driver_del += $del;
		$driver_mod += $mod;
	} elsif (grep { /$basename/ } @net_files) {
		$net_add += $add;
		$net_del += $del;
		$net_mod += $mod;
	} elsif (grep { /$basename/ } @arch_files) {
		$arch_add += $add;
		$arch_del += $del;
		$arch_mod += $mod;
	} elsif (grep { /$basename/ } @misc_files) {
		$misc_add += $add;
		$misc_del += $del;
		$misc_mod += $mod;
	} else {
		unknown($filename, $commit, $add, $del, $mod);
	}

}


sub print_data($$$$)
{
	my ($basename, $add, $del, $mod) = @_;
	my $percent_add = $add/$overall_add*100;
	my $percent_del = $del/$overall_del*100;
	my $percent_mod = $mod/$overall_mod*100;

	print "$basename:\n";
	print "\tadded    = $add\t$percent_add%\n";
	print "\tdeleted  = $del\t$percent_del%\n";
	print "\tmodified = $mod\t$percent_mod%\n";
}

print "Figuring stats for $start to $end\n";

open GIT, "git-rev-list --no-merges --parents $start..$end | " || die "cant run git";

my $parent;
my $commit;
my $file_add;
my $file_del;
my $filename;
my $num_commits = 0;

while (<GIT>) {
	$num_commits++;
	chomp;
	my @arr = split;
	$commit = $arr[0];
	$parent = $arr[1];
	# print "commit = $commit\n";
	# print "parent = $parent\n\n";

	open DIFF, "git diff -M --numstat $parent..$commit |";
	while (<DIFF>) {
		my $mod = 0;
		my $del = 0;
		my $add = 0;
		chomp;
		my @file_arr = split;
		$file_add = $file_arr[0];
		$file_del = $file_arr[1];
		$filename = $file_arr[2];

		# compute the number of modified lines for this file

		if ($file_add == $file_del) {
			# print "equal\n";
			$mod = $file_add;
		} elsif ($file_add < $file_del) {
			# print "add less than del\n";
			$mod = $file_add;
			$del = $file_del - $file_add;
		} else {
			# print "add greater than del\n";
			$mod = $file_del;
			$add = $file_add - $file_del;
		}
		$overall_add += $add;
		$overall_del += $del;
		$overall_mod += $mod;
		# print ("mod = $mod add = $add del = $del\n");
		# print "$filename\n";
		filename_category($filename, $commit, $add, $del, $mod);
	}
	close DIFF;
}

print "number of commits = $num_commits\n";
print "added    = $overall_add\n";
print "deleted  = $overall_del\n";
print "modified = $overall_mod\n";

print_data("core", $core_add, $core_del, $core_mod);
print_data("filesystems", $fs_add, $fs_del, $fs_mod);
print_data("drivers", $driver_add, $driver_del, $driver_mod);
print_data("arch", $arch_add, $arch_del, $arch_mod);
print_data("net", $net_add, $net_del, $net_mod);
print_data("misc", $misc_add, $misc_del, $misc_mod);

exit;

