X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=svnlog2changelog.pl;fp=svnlog2changelog.pl;h=d35e9f1186bf9a85cd8979a14787231320907c5d;hp=0000000000000000000000000000000000000000;hb=b2f6783657f7f0cef2c4dc09966515f478030b0b;hpb=6650f84c0990f8cd61814f9a43aea5bc870e57ff diff --git a/svnlog2changelog.pl b/svnlog2changelog.pl new file mode 100755 index 0000000..d35e9f1 --- /dev/null +++ b/svnlog2changelog.pl @@ -0,0 +1,230 @@ +#!/usr/bin/perl -w + +# Purpose: +# summarize and re-format subversion's log output to plain text +# +# Written by Rocco Rutte +# for internal use with mutt-ng . +# +# License: GPL +# +# Usage/Options: +# -t print only today's messages +# -s YYYY-MM-DD print only messages since (and including) date +# -i string use string for indentation +# -m number break lines at the latest at number columns +# -h help +# +# Note: lines matching ``^([^:]+):?$'' will be ignored if the first +# submatch in brackets is a known author; i.e. the logs +# +# | Foo Bar +# | added l33t c0d3 +# +# and +# +# | Foo Bar: +# | added l33t c0d3 +# +# will be interpreted as only 'added l33t c0d3' if 'Foo Bar' is known as +# an author. This does not count when grouping messages for authors, +# those lines are just skipped. This is hard-coded, see below. + +use strict; +use POSIX; +use Getopt::Std; + +# hard-coded configuration: this maps user to full names +my %commiters = ( + "ak1" => "Andreas Krennmair", + "nion" => "Nico Golde", + "pdmef" => "Rocco Rutte", + "dkg1" => "Daniel K. Gebhart" +); + +my %fmap = ( + "filesA" => "Added", + "filesM" => "Modified", + "filesD" => "Deleted" +); + +# default config +my %options = (); +my $linemax = 70; +my $today = ""; +my $since = ""; +my $indent = " "; + +# some stuff we need +my $currev = 0; +my $lastrev = 0; +my @curlog = (); +my $curentry = ""; +my $curauthor = ""; +my $count = 0; +my %changes = (); + +# nicely print log lines in itemized style with eye-candy indentation and +# somewhat smart line-breaking +sub niceline { + my ($text) = (@_); + my @lines = split (/\n/, $text); + for my $l (@lines) { + print "$indent$indent-"; + my @words = split (/\ /, $l); + my $c = length ($indent); + for my $w (@words) { + if (length ($w) + $c > $linemax) { + print "\n$indent$indent $w"; + $c = length ($indent); + } else { + print " $w"; + } + $c += length ($w) + 1; + } + print "\n"; + } +} + +sub usage { + print < +for use with mutt-ng + +Usage: + Print help: + svn log | svnlog2changelog.pl -h + + Print Subversion's log for today: + svn log | svnlog2changelog.pl -t [-i string] + + Print Subversion's log since (and including) YYYY-MM-DD + svn log | svnlog2changelog.pl -s YYYY-MM-DD [-i string] +EOF + ; +} + +sub isknown { + my ($name) = (@_); + for my $k (keys %commiters) { + if ($commiters{$k} eq $name) { + return (1); + } + } + return (0); +} + +# get and process options +getopts ("tm:s:hi:", \%options); +if (defined $options{'t'}) { + $today = strftime ("%Y-%m-%d", localtime (time ())); +} +if (defined $options{'m'} and $options{'m'} =~ /^[0-9]{2,}$/) { + $linemax = $options{'m'}; +} +if (defined $options{'s'} and $options{'s'} =~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/) { + $since = $options{'s'}; +} +if (defined $options{'h'}) { + &usage (); + exit (0); +} +if (defined $options{'i'}) { + $indent = $options{'i'}; +} + +# parse log +while () { + chomp; + if ($_ =~ /^r([0-9]+)/) { + $currev = $1; + @curlog = (); + $curauthor = ""; + $count = 0; + my @items = split (/\ \|\ /, $_); + my @dateinfo = split (/\ /, $items[2]); + $curentry = $dateinfo[0]; + ${$changes{$curentry}}{'author'} = $items[1]; + $curauthor = $items[1]; + # _keep_ latest rev. number for day + if (not defined ${$changes{$curentry}}{'rev'}) { + ${$changes{$curentry}}{'rev'} = substr ($items[0], 1); + } + # _keep_ latest commit time for day + if (not defined ${$changes{$curentry}}{'time'}) { + ${$changes{$curentry}}{'time'} = "$dateinfo[1] $dateinfo[2]"; + } + $count++; + next; + } + if ($count > 0) { + # ignore noise + if (length ($_) == 0 or $_ =~ /^[-]+$/ or + $_ =~ /^([^:]+):?$/ and &isknown ($1) or + $_ eq "Changed paths:") { + next; + } + if ($_ =~ /([A-Z]) \/((trunk|branches|tags).*)$/) { + my $what = $1; + my $target = $2; + ${${$changes{$curentry}}{"files$what"}}{$target} = 1; + } else { + # try to be smart and remove itemizations people make + my $clean = $_; + $clean =~ s/^[- \t*]*//; + if (length ($clean) > 0) { + # _pre_pend space for continued log and newline for + # new log lines for new revisions +# if (defined ${${$changes{$curentry}}{'log'}}{$curauthor} and +# length (${${$changes{$curentry}}{'log'}}{$curauthor}) > 0) { +# if ($lastrev eq $currev) { +# ${${$changes{$curentry}}{'log'}}{$curauthor} .= " "; +# } else { +# ${${$changes{$curentry}}{'log'}}{$curauthor} .= "\n"; +# } +# } +# ${${$changes{$curentry}}{'log'}}{$curauthor} .= "$clean"; + ${${$changes{$curentry}}{'log'}}{$curauthor} .= "$clean\n"; + $lastrev = $currev; + } + } + } +} + +my $first = ""; +my $first2 = ""; + +for my $k (sort { $b cmp $a } (keys (%changes))) { + # ignore noise + if (not defined %{${$changes{$k}}{'log'}} or + (length ($since) > 0 && length ($today) == 0 && ($k lt $since)) or + (length ($today) > 0 && ($k ne $today))) { + next; + } + # print first line with date, time and latest revision for current day + print "$first$k ${$changes{$k}}{'time'} "; + $first = "\n"; + $first2 = ""; + print "Latest Revision: ${$changes{$k}}{'rev'}\n\n"; + # per author: print his name and an itemized list of his log msgs. + # with smart line-breaking and indentation + for my $a (keys %{${$changes{$k}}{'log'}}) { + print "$first2$indent"; + if (defined $commiters{$a}) { + print $commiters{$a}; + } else { + print $a; + } + print ":\n"; + &niceline (${${$changes{$k}}{'log'}}{$a}); + $first2 = "\n"; + } + for my $a (keys %fmap) { + if (defined %{${$changes{$k}}{$a}}) { + print "$first$indent$fmap{$a} Files:\n"; + my $fixme = join (", ", keys %{${$changes{$k}}{$a}}); + &niceline ($fixme); + } + } +}