From owner-freebsd-hackers Fri May 31 18:26:59 2002 Delivered-To: freebsd-hackers@freebsd.org Received: from mailsrv.otenet.gr (mailsrv.otenet.gr [195.170.0.5]) by hub.freebsd.org (Postfix) with ESMTP id B32C837B404; Fri, 31 May 2002 18:26:48 -0700 (PDT) Received: from hades.hell.gr (patr530-b212.otenet.gr [212.205.244.220]) by mailsrv.otenet.gr (8.12.3/8.12.3) with ESMTP id g511QgKT024125; Sat, 1 Jun 2002 04:26:45 +0300 (EEST) Received: from hades.hell.gr (hades [127.0.0.1]) by hades.hell.gr (8.12.3/8.12.3) with ESMTP id g511Qee7004612; Sat, 1 Jun 2002 04:26:40 +0300 (EEST) (envelope-from keramida@FreeBSD.org) Received: (from charon@localhost) by hades.hell.gr (8.12.3/8.12.3/Submit) id g511Huq0004481; Sat, 1 Jun 2002 04:17:56 +0300 (EEST) (envelope-from keramida@FreeBSD.org) Date: Sat, 1 Jun 2002 04:17:54 +0300 From: Giorgos Keramidas To: Matt Dillon Cc: freebsd-hackers@FreeBSD.org Subject: Adding diffs to commit-mail on the fly Message-ID: <20020601011754.GA4357@hades.hell.gr> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG Hi Matt and everyone, I remember that Matt had mentioned adding diffs of the commits to the commit-mail, which would make it possible to quickly view what changed without leaving the MUA and manually searching for the proper CVS diff/rdiff incantation to view the diff. The idea was resting at the back of my mind, and tonight I hacked this Perl script that seems to mostly do what I want, when I pipe a single message to it's STDIN in mbox format. Given a script in Perl or awk or whatever that works like this one, how would you all integrate this with procmail to let it filter all the commit mail of FreeBSD? The code of the script is a bit clumsily written, but here it is for anyone who cares to play with it. You can see a sample of the output of this script, in mbox file format, at: http://www.FreeBSD.org/~keramida/files/freebsd-rdiff.txt - Giorgos ====================================================================== #!/usr/bin/perl # # A filter that copies all the lines from stdin unchanged, until it # matches the magic FreeBSD commit-mail line that says files and # revisions follow. When that line is matched, do our stuff until the # line that matches /^$/; when all file changes are finished. # If this is set to non-zero, then trim EOL whitespace from the # lines of the commit log before copying it to STDOUT. $mail_delete_eol_spaces = 1; # Where would I find the CVSROOT that mirrors the FreeBSD repository? $cvs_root_dir = "/home/ncvs"; # Copy all the lines of STDIN to STDOUT, until we find the part of the # message that contains the file change list. Keep the changelist # lines in an array, and then after the changelist is copied verbatim # to STDOUT too, parse the changelist and call cvs(1) as needed to # view diffs. $in_changelist = 0; # set when we're reading changelist lines @changeset = (); # start with an empty changeset array while (defined($line = )) { chomp $line; if ($mail_delete_eol_spaces) { $line =~ s/\s*$//; } if (($in_changelist eq 0) && ($line =~ m/^ Revision Changes Path$/)) { print "$line\n"; $in_changelist = 1; } elsif ($in_changelist ne 0) { if ($line =~ m/^$/) { $in_changelist = 0; &show_changeset(\@changeset); } else { unless ($line =~ m/^\s*$/) { $line =~ s/^\s+//; push (@changeset,$line); } } print "$line\n"; } else { print "$line\n"; } } sub show_changeset { my $aref = shift; die "No changeset" unless (defined($aref)); print "\n"; print "--- patch begins ---\n"; foreach $line (@$aref) { ($rev, $added, $deleted, $rcsfile) = &valid_changeline($line); $lastrev = &rev_previous($rev); $pipecmd = "cvs -q -d ${cvs_root_dir} rdiff -u -r$lastrev -r$rev $rcsfile"; open(CVSDIFF, "${pipecmd}|") or die "Could not open input pipe from CVS"; while (defined($in = )) { chomp $in; print "$in\n"; } close(CVSDIFF); } print "--- patch ends ---\n"; } sub valid_changeline { my $line = shift; die "No line passed" unless (defined($line)); ($rev, $added, $deleted, $rcsfile) = split /\s+/, $line; die "Invalid revision \[$rev\]" unless &valid_rcsrev($rev); die "Invalid number of added lines \[$added\]" unless &valid_rcslines($added); die "Invalid number of deleted lines \[$deleted\]" unless &valid_rcslines($deleted); die "No rcsfile specified in changeline \[$line\]" unless (defined($rcsfile)); return ($rev, $added, $deleted, $rcsfile); } sub valid_rcsrev { my $rev = shift; die "No RCS version to validate" unless (defined($rev)); my @foo = split /\./, $rev; return 0 if ($#foo == -1); foreach $k (@foo) { return 0 if ($k = m/\D/); } return 1; } sub valid_rcslines { my $num = shift; die "No RCS lines to validate" unless (defined($num)); return ($num =~ m/^[+-]?\d+$/); } sub rev_previous { my $rev = shift; die "No revision specified" unless (defined($rev)); die "Invalid revision number \[$rev\]" unless &valid_rcsrev($rev); @parts = split /\./, $rev; if (($#parts % 2) eq 0) { # This is a branch revision number. # Just delete the last part to find the branchpoint address. $#parts--; } else { # This is a real revision number. Attempt to either reduce # the last numeric value, or remove the two last parts (when # possible) to find the last revision before a branch point # when the last part is equal to 0. $last = $parts[$#parts]; if ($last gt 1) { $parts[$#parts]--; } elsif ($#parts gt 1) { $#parts -= 2; } } return "" . join('.', @parts) . ""; } ====================================================================== To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message