5 # This script walks the tree from the current directory
6 # and spits out a database generated by md5'ing the cvs log
7 # messages of each revision of every file in the tree.
10 use Digest::MD5 qw(md5_hex);
12 my $dbname = "commitsdb";
13 open DB, "> $dbname" or die "$!\n";
15 # Extract all the logs for the current directory.
18 my $dir = shift @dirs;
21 opendir DIR, $dir or die $!;
22 foreach my $f (grep { /[^\.]/ } readdir DIR) {
23 my $filename = "$dir/$f";
25 my %loghash = parse_log_message($filename);
28 $logs{$filename} = {%loghash};
29 } elsif (-d $filename) {
30 next if $filename =~ /\/CVS$/;
31 push @dirs, $filename;
36 # Produce a database of the commits
37 foreach my $f (keys %logs) {
39 foreach my $rev (keys %$file) {
40 my $hash = $$file{$rev};
42 print DB "$f $rev $hash\n";
46 print "\r" . " " x 30 . "\r$dir";
54 ##################################################
55 # Run a cvs log on a file and return a parse entry.
56 ##################################################
57 sub parse_log_message {
60 # Get a log of the file.
61 open LOG, "cvs -R log $file 2>/dev/null |" or die $!;
63 my $log = join "", @log;
66 # Split the log into revisions.
67 my @entries = split /----------------------------\n/, $log;
69 # Throw away the first entry.
72 # Record the hash of the message against the revision.
74 foreach my $e (@entries) {
75 # Get the revision number
76 $e =~ s/^revision\s*(\S*)\n//s;
79 # Strip off any other headers.
81 while ($e =~ s/^(date|branches):([^\n]*)\n//sg) {
83 $user = $1 if $sub =~ /author: (.*?);/;
86 my $hash = string_to_hash($e);
87 $loghash{$rev} = "$user:$hash";
94 ##################################################
95 # Convert a log message into an md5 checksum.
96 ##################################################
100 return md5_hex($logmsg);