#!/usr/bin/perl -w # # cvsdiff: Show the differences between two revisions of a file, # with the corresponding log entries. # # $dotat: scripts/cvsdiff,v 1.9 2002/08/12 10:26:49 fanf2 Exp $ use strict; use IO::Pipe; sub dopipe (@); sub cvsdiff (@); die "usage: $0 [ [rev1 [rev2]]]\n" if @ARGV > 3; if(@ARGV < 1) { cvsdiff; exit; } my $file = $ARGV[0]; # work out revision numbers # my $rev1; my $rev2; if(@ARGV > 1) { $rev1 = $ARGV[1]; $rev2 = $ARGV[-1]; } else { my $status = dopipe "cvs", "status", $file; # XXX maybe we should understand more about cvs status if($status =~ /Status: Unknown/) { exit; } if($status =~ /Status: Locally Modified/) { cvsdiff $file; exit $?/256; } $status =~ /Working revision:\s+([0-9.]+)/; $rev1 = $1; $status =~ /Repository revision:\s+([0-9.]+)/; $rev2 = $1; } # check revision numbers are in the right order # if((split /\./, $rev2)[-1] < (split /\./, $rev1)[-1]) { my $tmp = $rev2; $rev2 = $rev1; $rev1 = $tmp; } # if revision numbers are equal then show previous change # first revision number for cvs log has to be one more than for cvs diff # my $rev1log; my $rev1diff; { my @rev = split /\./, $rev1; if($rev1 eq $rev2) { # be careful about the start of a branch $rev[-1] -= 1 or $#rev -= 2; # be careful about revision 1.1 @rev = (1,1) unless @rev > 0; $rev1log = $rev1; $rev1diff = join '.', @rev; } else { $rev[-1] += 1; $rev1log = join '.', @rev; $rev1diff = $rev1; } } # print log entries { my $log = dopipe "cvs", "log", "-r$rev1log:$rev2", $file; $log =~ s/\n={77}$//; my $sep = "-"x28 . "\n"; my @log = split /^$sep/mo, $log; shift @log; # strip off rubric print $sep; print join $sep, reverse @log; print $sep; } # print diff # cvsdiff "-r", $rev1diff, "-r", $rev2, $file; exit $?/256; sub cvsdiff (@) { my $diff = dopipe "cvs", "diff", @_; $diff =~ s/^[^-+@ ][^\n]+\n//gm; print $diff; } sub dopipe (@) { # ensure that we don't have anything in our buffers when we fork flush STDOUT; my $pipe = new IO::Pipe; die "$0: pipe: $!\n" unless defined $pipe; $pipe->reader(@_); $pipe->input_record_separator(undef); my $text = $pipe->getline; $pipe->close or die "$0: close @_: $!\n"; return $text; }