#!/usr/bin/perl -l

use File::Temp qw/tempfile/;
use Fcntl qw/:seek/;

my @req_files = qw/ChangeLog version.c/;
my $fname = "ChangeLog";
my $tagname = "";

# we have files to checkin in argv. if empty, then checkin all.
if (@ARGV) {
    # some files are required in every checkin...
    for my $r (@req_files) {
        push @ARGV, $r unless grep {$_ eq $r} @ARGV;
    }
}

# not perfect, but system() is not perfect either...
my $file_list = join " ", @ARGV;

open IN, $fname or die "open $fname: $!\n";
($logf, $logfname) = tempfile("commit_log.XXXXX") or die "tempfile: $!\n";
(undef, $diffname) = tempfile("commit_diff.XXXXX") or die "tempfile: $!\n";

$SIG{INT} = $SIG{HUP} = $SIG{QUIT} = $SIG{TERM} = \&cleanup;

print "=== LOG MESSAGE ===";
while (<IN>) {
    chomp;
    $tagname = $1 if /^\s+\*\s+([A-Z0-9-]+)\s*$/;
    last if /^200/ and $. != 1;
    print $logf $_ if not /^\s*$/;
    print if not /^\s*$/;
}

close IN or die "close $fname: $!\n";
close $logf or die "close $logfname: $!\n";

if (not $tagname) {
    warn "no tagname found, aborting" if not $tagname;
    exit 1;
}

my $cmd = "cvs diff $file_list > $diffname";
print $cmd;
system $cmd;
# cvs diff has got botched exit status and no way of knowing if it succeeded.
die "No changes! What are you checking in???\n" if not $?;

# assume pathsep = ':' and dirsep = '/'
if (grep { -x "$_/diffstat" } split ":", $ENV{PATH}) {
    print "=== DIFFSTAT ===";
    system "diffstat < $diffname"
		and die "diffstat failed!\n";
}

$cmd = '${PAGER:-less} < '.$diffname;
print "=== REVIEW CHANGES? ===";
if (<STDIN> =~ /^[yY]/) {
    system $cmd
		and die "PAGER failed???\n";
} 

# always tag all files.
$cmd = "cvs commit -R -F $logfname $file_list && cvs tag -R $tagname";
print "=== COMMIT? ===";
if (<STDIN> =~ /^[yY]/) {
    print $cmd;
    system $cmd
		and die "cvs commit or tag failed!\n";
} 

END {
    cleanup();
}

sub cleanup {
    unlink $logfname;
    unlink $diffname;
    exit 0;
}
