#!/usr/bin/perl -w
#
# aa_changelog
# $Id: aa_changelog,v 1.4 2002/03/11 12:08:02 hrandoz Exp $
#
# Create a self-maintaining document of Andrea Arcangeli's kernel patches.  
# This is run in directory that has all the sub-patches in an AA release.  
# The directory also contains all of the diff logs from:
# ftp://ftp.kernel.org/pub/linux/kernel/people/andrea/kernels/v2.[24]

# usage: aa_changelog [ -h ]
# -h create web page instead of text document.

# Things we want for each subpatch:
# 1) kernel it first showed up in.
# 2) comments in diff_*log 
# 3) size of sub patch
# 4) create a text or html doc with links to sub-patches. 

use strict;
$0 =~ s#.*/##o;

# convention is for the sub_patches and difflogs to be in /some/dir/$kver,
# so grab kernel version as basename of pwd.
my $kver = `pwd`;
chomp $kver;
$kver =~ s#.*/##o;

# $maj_ver = 2.2 or 2.4
my $maj_ver = $kver;
$maj_ver =~ s/^(\d\.\d).*/$1/;

# Base directory for patches.  Individual patches are in $aa_ftp/v${maj_ver}/$kver.
my $aa_ftp = 'ftp://ftp.kernel.org/pub/linux/kernel/people/andrea/kernels';
$aa_ftp = join '/', $aa_ftp, 'v' . $maj_ver, $kver;

my ($kernel_version, $sub_patch);

# sub_patch without revision, so we can skip sub_patches that are no longer in $kver.
my $sub_norev;

# sub_patch_file is real sub_patch name without any extra 0 in the revision.
my $sub_patch_file;

# size of sub_patch
my $bytes;

# $first_appeared{$sub_patch} = $kernel_version;
my %first_appeared;

my ($html, $all);
for (@ARGV) {
    $html++ if $ARGV[0] eq '-h';
}

# comments for each subpatch
# $comments{$sub_patch} = $comment;
my %comments;

# Andrea's patches start with two digits
my @sub_patches = <[0-9]*>;

# default to first appearance in current version, unless we
# know better.
foreach $sub_patch (@sub_patches) {
	# make revision two digits so sorting is simple.
	$sub_patch =~ s/-(\d($|\.bz2))/-0$1/;
	$first_appeared{$sub_patch} = ''; # place holder
}

my $debug = 0;

# create a hash of the sub_patches without revision
# so we can decide if a sub_patch is still needed.
my %sub_patch;
foreach $sub_patch (@sub_patches) {
	$sub_patch =~ s/-\d+($|\.bz2)//o;
	$sub_patch{$sub_patch} = $sub_patch;
	print "\$sub_patch{$sub_patch} = $sub_patch\n" if $debug;
}

# all diff logs
chomp(my @diff_logs = `ls -tr ../diff_*`);

my $pwd = `pwd`;
chomp $pwd;
if ($#diff_logs == -1) {
	die "$0: Hmm, I didn't find any diff_*logs in ${pwd}/..  : exiting\n";
} elsif ($#sub_patches == -1) {
	die "$0: Hmm, I didn't find any sub_patches in $pwd: exiting\n";
}

my $diff_log;

# grab the kernel revision $sub_patch first appeared in.
# get comments on each subpatch too.
foreach $diff_log (@diff_logs) {
	open(DIFFLOG, "$diff_log") or warn "$0: Could not open $diff_log: $!\n";
	my (@open_sub_patches, $in_comment);
	while (<DIFFLOG>) {
		last if /^URL/o;	# leave out diffstat in diff_2.4.10aa1_2.4.11pre3aa1.log
		last if /^--/o;		# leave out trailer in diff_2.2.20pre2aa1_2.2.20pre3aa1.log
		next if /^Jan /o;	# leave out oops in diff_2.4.17rc2aa2_2.4.18pre2aa1.log
		if (/Only in/) {
			if ($in_comment) {
				$in_comment = 0;
				@open_sub_patches = ();
			}
			s/Only in (.*):(.*)/$1 $2/o;
			($kernel_version, $sub_patch) = split;
			# make revision two digits so sorting is simple.
			$sub_patch =~ s/-(\d($|\.bz2))/-0$1/;
			$kernel_version =~ s:/$::o;
			# we want the first appearance, not the last.
			$first_appeared{$sub_patch} ||= $kernel_version;
			push @open_sub_patches, $sub_patch
			  unless $comments{$sub_patch};
			$sub_patch = '';
		} else {
			$in_comment++;
			if ($html) {
				s/</&lt;/go;
				s/>/&gt;/go;
			}
			foreach my $open_sub_patch (@open_sub_patches) {
				$comments{$open_sub_patch} .= $_;
			}
		}
	}
}

# Anything we know about that isn't in the logs appeared in the current version
foreach $sub_patch ( sort keys %first_appeared ) {
    $first_appeared{$sub_patch} ||= $kver;
}

# Clean up comments.
foreach (values %comments) {
    s/^[ \t]*Rediffed\.[ \t]*\n//gm;
    s/^[ \t]*\n//gm;
}

# html page head
if ($html) {
	print "<html>\n<head><title>Andrea Arcangeli patches for $kver</title>\n";
	print qq(<link rev=made href="mailto:rwhron at earthlink dot net"></head>\n<body>\n<hr>\n);
	print "<h3>Andrea Arcangeli patches for $kver</h3>\n";
	print qq(Patch available at\n<a href="${aa_ftp}.bz2">${aa_ftp}.bz2</a>\n<p>\n\n);
} else {
	print "Andrea Arcangeli patches for $kver\n";
	print "Patch: ${aa_ftp}.bz2\n\n";
}

# display the output
foreach $sub_patch ( sort keys %first_appeared ) {
	# chop off the revision
	print "\$sub_patch = $sub_patch\n" if $debug;
	$sub_norev = $sub_patch_file = $sub_patch;
	$sub_norev =~ s/-\d+($|\.bz2)//o;
	print "\$sub_norev = $sub_norev\n" if $debug;
	# remove extra 0 in revision
	$sub_patch_file =~ s/-0(\d($|\.bz2))/-$1/o;
	print "\$sub_patch_file = $sub_patch_file\n" if $debug;
	next unless $sub_patch{$sub_norev};
	# skip signature files
	next if $sub_patch =~ /\.sign/o;
	if (-f $sub_patch_file) {
		$bytes = (stat($sub_patch_file))[7];
	} else { 
		$bytes = 0;
	}
	if ($html) {
		if (-f $sub_patch_file) {
			print qq(<a href="${aa_ftp}/${sub_patch_file}">$sub_patch_file</a>\n);
		} else {
			print "$sub_patch_file ";
		}
		print "first appeared in $first_appeared{$sub_patch} ";
		print " - $bytes bytes" if $bytes;
		print "\n"
	} else {
		printf "%-70s", "$sub_patch_file first appeared in $first_appeared{$sub_patch}";
		printf "\t%6d bytes", $bytes if $bytes;
		print "\n"
	}
	if ($html) {
		if ($comments{$sub_patch}) {
			print "<pre>\n";
		} else { 
			print "\n<p>\n\n";
		}
	} else {
		print "\n" if $comments{$sub_patch};
	}
	print "$comments{$sub_patch}" if $comments{$sub_patch};
	if ($html and $comments{$sub_patch}) {
		print "</pre>\n";
	}
	print "\n";
}

# bottom of web page
if ($html) {
	print qq(<hr>\npage generated by <a href="$0">$0</a> on );
	print scalar(localtime), "\n</body>\n</html>\n";
}