191501Sjoe#!/usr/bin/perl -w
291501Sjoe
391501Sjoe# $FreeBSD$
491501Sjoe
591501Sjoe# This script takes a filename and revision number as arguments
691501Sjoe# and spits out a list of other files and their revisions that share
791501Sjoe# the same log message.  This is done by referring to the database
891501Sjoe# previously written by running make_commit_db.
991501Sjoe
1091501Sjoeuse strict;
1191501Sjoeuse Digest::MD5 qw(md5_hex);
1291501Sjoe
1391501Sjoemy $dbname = "commitsdb";
1491501Sjoe
1591501Sjoe# Take the filename and revision number from the command line.
1693545Sjoe# Also take a flag to say whether to generate a patch or not.
1793545Sjoemy ($file, $revision, $genpatch) = (shift, shift, shift);
1891501Sjoe
1991501Sjoe# Find the checksum of the named revision.
2091501Sjoemy %possible_files;
2191501Sjoeopen DB, "< $dbname" or die "$!\n";
2291501Sjoemy $cksum;
2391501Sjoewhile (<DB>) {
2491501Sjoe	chomp;
2591501Sjoe	my ($name, $rev, $hash) = split;
2691501Sjoe	$name =~ s/^\.\///g;
2791501Sjoe
2891501Sjoe	$possible_files{$name} = 1 if $file !~ /\// && $name =~ /^.*\/$file/;
2991501Sjoe
3091501Sjoe	next unless $name eq $file and $rev eq $revision;
3191501Sjoe	$cksum = $hash;
3291501Sjoe}
3391501Sjoeclose DB;
3491501Sjoe
3591501Sjoe# Handle the fall-out if the file/revision wasn't matched.
3691501Sjoeunless ($cksum) {
3791501Sjoe	if (%possible_files) {
3891501Sjoe		print "Couldn't find the file. Maybe you meant:\n";
3991501Sjoe		foreach (sort keys %possible_files) {
4091501Sjoe			print "\t$_\n";
4191501Sjoe		}
4291501Sjoe	}
4391501Sjoe	die "Can't find $file rev $revision in database\n";
4491501Sjoe}
4591501Sjoe
4691501Sjoe
4791501Sjoe# Look for similar revisions.
4891501Sjoemy @results;
4991501Sjoeopen DB, "< $dbname" or die "$!\n";
5091501Sjoewhile (<DB>) {
5191501Sjoe	chomp;
5291501Sjoe	my ($name, $rev, $hash) = split;
5391501Sjoe
5491501Sjoe	next unless $hash eq $cksum;
5591501Sjoe
5691501Sjoe	push @results, "$name $rev";
5791501Sjoe}
5891501Sjoeclose DB;
5991501Sjoe
6093556Sjoe# May as well show the log message if we're producing a patch
6193556Sjoeprint `cvs log -r$revision $file` if $genpatch;
6293556Sjoe
6393556Sjoe# Show the commits that match, and their patches if required.
6493545Sjoeforeach my $r (sort @results) {
6593545Sjoe	print "$r\n";
6693545Sjoe	next unless $genpatch;
6791501Sjoe
6893545Sjoe	my ($name, $rev) = split /\s/, $r, 2;
6993545Sjoe	my $prevrev = previous_revision($rev);
7093545Sjoe	print `cvs diff -u -r$prevrev -r$rev $name`;
7193545Sjoe	print "\n\n";
7293545Sjoe}
7393545Sjoe
7493545Sjoe#
7593545Sjoe# Return the previous revision number.
7693545Sjoe#
7793545Sjoesub previous_revision {
7893545Sjoe	my $rev = shift;
7993545Sjoe
8093545Sjoe	$rev =~ /(?:(.*)\.)?([^\.]+)\.([^\.]+)$/;
8193545Sjoe	my ($base, $r1, $r2) = ($1, $2, $3);
8293545Sjoe
8393545Sjoe	my $prevrev = "";
8493545Sjoe	if ($r2 == 1) {
8593545Sjoe		$prevrev = $base;
8693545Sjoe	} else {
8793545Sjoe		$prevrev = "$base." if $base;
8893545Sjoe		$prevrev .= "$r1." . ($r2 - 1);
8993545Sjoe	}
9093545Sjoe	return $prevrev;
9193545Sjoe}
9293545Sjoe
9391501Sjoe#end
94