#!/usr/bin/perl -w

use strict;

sub help {
my $bad = shift;
my $fh = $bad ? \*STDERR : \*STDOUT;
print $fh <<End;
usage: $0 [-f] [-T] from to modules

Each of `from' and `to' can be:
	a tag		sina_3_12_beta
	the head	HEAD
	branch head	sina_3_12
	branch start	sina_3_12:
	first revision	FIRST

-f	include the "from" revision
-T	exclude the "to" revision
-D	continue log messages after a "dead" revision

The comparison will only work if it goes straight up the tree, it can't go down
one branch and up another.
End
exit $bad;
}

use Getopt::Std;
use vars qw/$opt_h $opt_f $opt_T $opt_D/;
getopts("pmhfTDq");
$opt_h && help(0);

my $options = "";
$opt_f and $options .= "-f ";
$opt_T and $options .= "-T ";
$opt_D and $options .= "-D ";

my $comp_options = $opt_f && !$opt_T ? "-s" : "";

my ($from, $to) = (shift, shift);
$to or help(1);

my ($exclude_from) = $from =~ s/-$//;
my ($exclude_to) = $to =~ s/-$//;

for my $module (@ARGV) {
	if (not -d "$module") {
		system "cvs co $module >/dev/null 2>&1" and
			die "cvs co failed\n";
		unlink "sina.log";
	}

	system "cvs log $module > $module.log 2>/dev/null" and
		die "cvs log failed\n";
	system "< $module.log cvs-log-parse > $module.plog" and
		die "cvs-log-parse failed\n";

	my %branch;
	for (`< $module.plog cvs-log-branches | kut 3 | sort -u`) {
		chomp;
		$branch{$_} = 1;
	}

	for (['from', $from], ['to', $to]) {
		my ($fromto, $spec) = @$_;
		if ($spec eq "HEAD") {
			system "< $module.plog cvs-log-head > $module.$fromto" and
				die "cvs-log-head failed\n";
		} elsif ($spec eq "FIRST") {
			system "< $module.plog cvs-log-first > $module.$fromto" and
				die "cvs-log-first failed\n";
		} elsif ($branch{$spec}) {
			system "cvs-log-branch-heads $module.plog | grep \$'^$spec\\t' | kutout 1 > $module.$fromto" and
				die "cvs-log-branch-heads failed\n";
			
		} elsif ($spec =~ s/:$// and $branch{$spec}) {
			system "< $module.plog cvs-log-find-tag $spec | sed 's/\\.0\\.[0-9]*\$//' > $module.$fromto" and
				die "cvs-log-find-tag failed\n";
			
		} else {
			system "< $module.plog cvs-log-find-tag $spec > $module.$fromto" and
				die "cvs-log-find-tag failed\n";
		}
	}
	system "cvs-compare $comp_options $module.from $module.to > $module.comp" and
		die "cvs-compare failed\n";
	system "< $module.comp cvs-log-range $options $module.plog > $module.rlog" and
		die "cvs-log-range failed\n";
	system "< $module.rlog cvs-log-by-file > $module.by-file" and
		die "cvs-log-by-file failed\n";
	system "< $module.rlog cvs-log-by-message > $module.by-message" and
		die "cvs-log-by-message failed\n";
	system "cvs-idiff $module.rlog" and
		die "cvs-idiff failed\n";
	system "< $module.rlog cvs-log-html > $module.html" and
		die "cvs-log-html failed\n";
}
