4 # summarize and re-format subversion's log output to plain text
6 # Written by Rocco Rutte <pdmef@cs.tu-berlin.de>
7 # for internal use with mutt-ng <http://mutt-ng.berlios.de/>.
12 # -t print only today's messages
13 # -s YYYY-MM-DD print only messages since (and including) date
14 # -i string use string for indentation
15 # -m number break lines at the latest at number columns
16 # -p string prefix for filenames in 'svn log -v' output;
17 # for things like 'A /mutt-ng/trunk/foo' set this
18 # to 'mutt-ng/', i.e. exclude the leading / from
19 # it but include everything up to the last char
20 # before (trunk|tags|branches)
23 # Note: lines matching ``^([^:]+):?$'' will be ignored if the first
24 # submatch in brackets is a known author; i.e. the logs
34 # will be interpreted as only 'added l33t c0d3' if 'Foo Bar' is known as
35 # an author. This does not count when grouping messages for authors,
36 # those lines are just skipped. This is hard-coded, see below.
40 # as the first line of log messages when change is only committed by
41 # someone with access but the original author is someone else. If
42 # there's no such author line, the author's name will be grabbed from
43 # the %committers table below.
49 # hard-coded configuration: this maps user to full names
51 "ak1" => "Andreas Krennmair <ak\@synflood.at>",
52 "nion" => "Nico Golde <nion\@muttng.org>",
53 "pdmef" => "Rocco Rutte <pdmef\@cs.tu-berlin.de>",
54 "dkg1" => "Daniel K. Gebhart <dpkg1\@users.berlios.de>"
59 "filesM" => "Modified",
81 # nicely print log lines in itemized style with eye-candy indentation and
82 # somewhat smart line-breaking
85 my @lines = split (/\n/, $text);
87 print "$indent$indent-";
88 my @words = split (/\ /, $l);
89 my $c = length ($indent);
91 if (length ($w) + $c > $linemax) {
92 print "\n$indent$indent $w";
93 $c = length ($indent);
97 $c += length ($w) + 1;
105 This is: svnlog2changelog.pl
106 written by Rocco Rutte <pdmef\@cs.tu-berlin.de>
107 for use with mutt-ng <http://mutt-ng.berlios.de/>
110 svnlog2changelog.pl -h
111 svn log -v | svnlog2changelog.pl [-t] [-i YYYY-MM-DD] [-m number] [-p string]
114 -t print only today's messages
115 -s YYYY-MM-DD print only messages since (and including) date
116 -i string use string for indentation
117 -m number break lines at the latest at number columns
118 -p string prefix for filenames in 'svn log -v' output;
119 for things like 'A /mutt-ng/trunk/foo' set this
120 to 'mutt-ng/', i.e. exclude the leading / from
121 it but include everything up to the last char
122 before (trunk|tags|branches)
126 - print Subversion's log for today:
127 svn log -v -r "{`date "+%Y-%m-%d"`}:HEAD" | svnlog2changelog.pl -t [-i string]
129 - print Subversion's log since (and including) YYYY-MM-DD
130 svn log -v | svnlog2changelog.pl -s YYYY-MM-DD [-i string]
137 for my $k (keys %committers) {
138 if (substr ($committers{$k}, 0, length ($name)) eq $name) {
145 # get and process options
146 getopts ("tm:s:hi:p:", \%options);
147 if (defined $options{'t'}) {
148 $today = strftime ("%Y-%m-%d", localtime (time ()));
150 if (defined $options{'m'} and $options{'m'} =~ /^[0-9]{2,}$/) {
151 $linemax = $options{'m'};
153 if (defined $options{'s'} and $options{'s'} =~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/) {
154 $since = $options{'s'};
156 if (defined $options{'h'}) {
160 if (defined $options{'i'}) {
161 $indent = $options{'i'};
163 if (defined $options{'p'}) {
164 $pfx = $options{'p'};
171 if ($_ =~ /^r([0-9]+)/) {
176 my @items = split (/\ \|\ /, $_);
177 my @dateinfo = split (/\ /, $items[2]);
178 $curentry = $dateinfo[0];
179 $curauthor = $items[1];
180 $curcomm = $items[1];
181 # _keep_ latest rev. number for day
182 if (not defined ${$changes{$curentry}}{'rev'} or
183 ${$changes{$curentry}}{'rev'} lt substr ($items[0], 1)) {
184 ${$changes{$curentry}}{'rev'} = substr ($items[0], 1);
186 # _keep_ latest commit time for day
187 if (not defined ${$changes{$curentry}}{'time'}) {
188 ${$changes{$curentry}}{'time'} = "$dateinfo[1] $dateinfo[2]";
194 # check log line: contains author?
195 if ($_ =~ /^From: (.*)$/) {
196 $curauthor = "$1 ($curcomm)";
199 elsif (defined $committers{$curauthor}) {
200 $curauthor = "$committers{$curcomm} ($curcomm)";
202 # check log line: contains noise?
203 if (length ($_) == 0 or $_ =~ /^[-]+$/ or
204 $_ =~ /^([^:]+):?$/ and &isknown ($1) or
205 $_ eq "Changed paths:") {
208 # check log line: contains list of changes/deleted/added files?
209 if ((length ($pfx) > 0 and $_ =~ /([AMD]) \/($pfx?.*)?$/) or
210 (length ($pfx) == 0 and $_ =~ /([AMD]) \/(.*)?$/)) {
216 $target =~ s#$pfx##g;
217 ${${$changes{$curentry}}{"files$what"}}{$target} = 1;
219 # here the line really contains the log message
220 # try to be smart and remove itemizations people make
222 $clean =~ s/^[- \t*]*//;
223 if (length ($clean) > 0) {
224 ${${$changes{$curentry}}{'log'}}{$curauthor} .= "$clean (r$currev)\n";
234 for my $k (sort { $b cmp $a } (keys (%changes))) {
236 if (not defined %{${$changes{$k}}{'log'}} or
237 (length ($since) > 0 && length ($today) == 0 && ($k lt $since)) or
238 (length ($today) > 0 && ($k ne $today))) {
241 # print first line with date, time and latest revision for current day
242 print "$first$k ${$changes{$k}}{'time'} ";
245 print "Latest Revision: ${$changes{$k}}{'rev'}\n\n";
246 # per author: print his name and an itemized list of his log msgs.
247 # with smart line-breaking and indentation
248 for my $a (keys %{${$changes{$k}}{'log'}}) {
249 print "$first2$indent";
250 if (defined $committers{$a}) {
251 print $committers{$a};
256 &niceline (${${$changes{$k}}{'log'}}{$a});
259 for my $a (keys %fmap) {
260 if (defined %{${$changes{$k}}{$a}}) {
261 print "$first$indent$fmap{$a} Files:\n";
262 my $fixme = join (", ", keys %{${$changes{$k}}{$a}});