#!/usr/bin/perl # # Perl script to create a chronological HTML file from 'cvs log' output # # cvs2chrono Copyright (C) Dorando 2003 # # 0.3.6 / 24 Apr 2003 / handles branches correctly, for deleted files # 0.3.5 / 18 Apr 2003 / New file list format # 0.3.1 / 16 Apr 2003 / Bugzilla links, diff for webcvs, extended time format # 0.3.0 / 15 Apr 2003 / New parser, generates smaller and better output # 0.2.2 / 14 Apr 2003 / Can now use a namefile, direct link to revisions # 0.2.1 / 14 Apr 2003 / Removes Attic/ in displayed dir, smaller output # 0.2.0 / 14 Apr 2003 / Now XHTML1.1 conform, and takes much less memory # 0.1.0 / 13 Apr 2003 / Initial release # # Permission is granted to redistribute this script under the terms of the # GNU General Public License http://www.gnu.org/copyleft/gpl.html $version="0.3.6"; use Getopt::Std; getopts('b:d:ef:hlMn:o:rsV:w:'); if($opt_h) { print <<"ENDOFHELP"; -b "" Bugzilla URL. -d "" CVS date range. See the -D option. info cvs CVS Common. -e Use extentend time format. example: Tuesday 15th April, 2003 at 15:05:18 -f "" If set, parses this instead of cvs output. Renders -d -and -l useless. -h :-P -l Only the current or topmost directories. -M Predefined variables for MESS. -n "" Includes Namefile. -o "" File to output to. -r Reverses output. Normal output is from newsest to oldest. -s Generates smaller file list output. -V1 Prints current file. -V2 Prints current file and progression of html creation. -w "" Generates links to a webcvs. example: cvs2chrono -d ">=2002/08/01 UTC" -o "messlog" -w "http://cvs.mess.org:6502/cgi-bin/viewcvs.cgi/" Note: cvs outputs only logs for directories that are also in the working dir, so you may want to run 'cvs update' without -P to get logs for deleted directories. ENDOFHELP exit; } if($opt_M) { $opt_b="http://bugzilla.mess.org/show_bug.cgi?id="; # $opt_d=">=2002/08/01 UTC"; $opt_e="-e"; # $opt_f="cvslog"; $opt_o="wip.html"; $opt_n="cvsnames"; $opt_w="http://cvs.mess.org:6502/cgi-bin/viewcvs.cgi/"; } if($opt_d) { $opt_d='-d"'.$opt_d.'"'; } if($opt_l) { $opt_l="-l"; } if(!$opt_o) { $opt_o="chrono.html"; } if($opt_f) { open(LOG,$opt_f) or die "Error: Could not open $opt_f"; @lines=; close(LOG) } else { @lines = `cvs log $opt_l $opt_d `; } my $rev, $file, $time, $author, $logtext, @log; for($i=1;$i<(my $length = @lines);$i++) { if(@lines[$i] =~ /RCS/) { @lines[$i]=~/cvs\/.+?\/(.+?),v/; $file=$1; $file=~s/Attic\///; if($opt_V>0){print "Processing $file\n"}; while(!(@lines[$i-1] =~ /description/)) { $i++; } while(!(@lines[$i] =~ /^=+\n/)) { if(@lines[$i] =~ "^revision (.+)"){$rev=$1;} elsif(@lines[$i] =~ "^date: (.+?); author: (.+?); state: (.+?);"){$time=$1;$author=$2;$state=$3} elsif(!(@lines[$i] =~ /^-+\n/)) { $logtext.=@lines[$i].(@lines[$i+1]=~/^(=|-)+\n/ ? "" : "
"); if($logtext eq "\n
" or $logtext eq "\r\n
") { $logtext=""; } } $i++; if(@lines[$i] =~ /^(=|-)+\n/) { $_=$logtext; s/&/&/g; s//>/g; s/<br \/>/
/g; s/(http:\/\/.+?\.(jpg|jpeg|png|mng|gif))//g; $logtext=$_; push(@log,"$time\n$author\n$file#$rev;$state\t$logtext"); $logtext=""; } } } } @lines = ""; print "Generating $opt_o\n"; use Time::Local; @days=("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"); @months=("January","February","March","April","May","June","July","August","September","October","November","December"); if($opt_r){@log = sort(@log);}else{@log = reverse(sort(@log));} push(@log,""); open(CHRONO,">$opt_o") or die "Error: Could not create $opt_o\n"; print CHRONO <<"HTMLHEADER"; CVS Log
HTMLHEADER if($opt_n){require $opt_n}; for($i=0;$i<(my $length = @log)-1;$i++) { @log[$i]=~/(.+?)\n(.+?)\n(.+?)\t(.*)/s; $time=$1; $author=$2; $file=$3; $files.=($files ? "\n$file" : $file); $logtext=$4; @log[$i+1]=~/.+?\t(.*)/s; if($logtext eq $1){next} for($ii=1;$ii<$names-1;$ii=$ii+2) { if($author eq @names[$ii]){$author=@names[$ii+1];last;} } if($opt_b){$logtext=~s/#([0-9]+)/#$1<\/a>/ig} if($opt_e) { $time=~/(....)\/(..)\/(..) (..).(..).(..)/; @time=localtime(timelocal($6,$5,$4,$3,$2-1,$1)); $time="@days[@time[6]] @time[3]"; if($3==1 || $3==21 || $3==31){$time.="st";} elsif($3==2 || $3==22){$time.="nd";} elsif($3==3 || $3==23){$time.="rd";} else{$time.="th";} $time.=" @months[$2-1], $1 at $4:$5:$6"; } @files=sort(mysort split(/\n/,$files)); $files="";$currentdir=""; foreach $file (@files) { if(index($file,"/")==-1){$file="/".$file;} $file=~/(.*)\/(.*)#(.*)\.(.*);(.*)/; if($currentdir ne $1) { if($files ne ""){$files.="\n"} $currentdir = $1; $files.=$1.":"; } if($files){$files.=" ";} if($opt_w && $5 ne "dead") { $_=($1 eq "" ? "" : $1."/"); if($4==1){$files.="$2*";} else{$files.="$2";} } elsif($5 eq "dead"){$files.="$2"} else{$files.=$2}; } if(!$opt_s) { $files=~s/\n/
\n/g; } print CHRONO "\n
$time by $author
\n$logtext
\n$files

"; #print CHRONO "$time by $author\n
$logtext
$files



\n"; $files=""; if($opt_V>1) { $progression=int($i / ($length-2) * 100)."%\n"; if($oldprogression!=$progression) { $oldprogression=$progression; print $progression; } } } print CHRONO "Generated with cvs2chrono $version\n"; print CHRONO "
"; close(CHRONO); sub mysort { "/$a"=~/(.*)\//; $aa=$1." ".$a; "/$b"=~/(.*)\//; $bb=$1." ".$b; return($aa cmp $bb); }