Line # Revision Author
1 40 dpavlin #!/usr/bin/perl -w
2
3 # Convert output from svn log to html page (with some formatting of
4 # commit messages)
5 #
6 # 2004-04-28 Dobrica Pavlinusic <dpavlin@rot13.org>
7
8 use strict;
9 use XML::Simple;
10
11 162 dpavlin my $path = shift || '.';
12 112 dpavlin
13 162 dpavlin # extract svk revision: r113@athlon (orig r999): dpavlin | 2005-09-01 20:38:07 +0200
14 my $svk_rev_re = '\s+(r\d+@\w+(\s+\(orig\s+r\d+\))*:\s+\w+\s+\|\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}\s+\+\d+)\s*';
15 112 dpavlin
16 162 dpavlin
17 40 dpavlin sub encode {
18 my $foo = shift;
19 162 dpavlin $foo =~ s/$svk_rev_re//gsm;
20 40 dpavlin $foo =~ s/</&lt;/g;
21 $foo =~ s/>/&gt;/g;
22 $foo =~ s/"/&quot;/g;
23 $foo =~ s/([\n\r][\n\r]+)/<\/p>$1<p>/gis;
24 $foo =~ s/([\n\r]+)([\-\*]\s+)/$1<br\/>$2/gis;
25 41 dpavlin $foo =~ s/([\n\r]+)(r\d+:\s+)/$1<br\/>$2/gis;
26 162 dpavlin $foo =~ s/([\n\r]+)(\s+r\d+@)/$1<br\/>$2/gis; # svk
27 40 dpavlin return $foo;
28 }
29
30 162 dpavlin sub sh_regex($$) {
31 my ($cmd,$regex) = @_;
32 open(my $sh, $cmd . ' |') || die "sh_regex failed on $cmd: $!";
33 while(my $l = <$sh>) {
34 chomp($l);
35 if ($l =~ $regex) {
36 if ($1 && $2) {
37 return ($1,$2);
38 } elsif ($1) {
39 return $1;
40 } else {
41 return $l;
42 }
43 }
44 }
45 166 dpavlin #warn "can't find $regex in output of $cmd\n";
46 164 dpavlin return;
47 162 dpavlin }
48
49 my $cmd;
50 if ($path =~ m#file://# || -e "$path/.svn") {
51 $cmd = "svn log -v --xml $path";
52 } else {
53 166 dpavlin my $svn_path = sh_regex('svk info', qr#Mirrored From:\s+([^,]+)#i);
54 162 dpavlin
55 166 dpavlin if (! $svn_path) {
56 162 dpavlin
57 166 dpavlin my $svk_depot = sh_regex('svk info', qr#Depot Path: (/.+)#i);
58 164 dpavlin
59 166 dpavlin my $depot = $svk_depot;
60 my $rel_path;
61 164 dpavlin
62 166 dpavlin my $path = sh_regex('svk depot --list', qr/^$depot\s+(\S+)/i);
63 164 dpavlin
64 166 dpavlin while (! $path && $depot =~ s!^(/.*/)([^/]+)/?$!$1! ) {
65 $rel_path = "$2/$rel_path";
66 $path = sh_regex('svk depot --list', qr/^$depot\s+(\S+)/i);
67 }
68 164 dpavlin
69 166 dpavlin die "can't find depot path '$svk_depot' in svk depot --list\n" unless ($path);
70 $svn_path = "file:///$path/$rel_path";
71 }
72
73 $cmd = "svn log -v --xml $svn_path";
74 162 dpavlin }
75
76 warn "# $cmd\n";
77 open(my $fh, $cmd .' |') || die "failed $cmd: $!";
78 40 dpavlin my $log;
79 162 dpavlin while(<$fh>) {
80 40 dpavlin $log .= $_;
81 }
82 162 dpavlin close($fh);
83 40 dpavlin
84 my $xml = XMLin($log, ForceArray => [ 'logentry', 'path' ]);
85
86 foreach my $e (@{$xml->{'logentry'}}) {
87 my $rev = $e->{'revision'};
88 my $date = $e->{'date'};
89
90 $date =~ s/T/ /;
91 $date =~ s/\.\d+Z$//;
92
93 print '<p><tt>'.$date.'</tt> <em>',$e->{'author'},'</em> <tt style="color:#808080">r',$e->{'revision'},'</tt></p>';
94
95 my @files;
96
97 foreach my $p (@{$e->{'paths'}->{'path'}}) {
98 my ($action,$path) = ($p->{'action'},$p->{'content'});
99
100 if ($action eq "A") {
101 push @files, "<ins>$path</ins>";
102 } elsif ($action eq "D") {
103 push @files, "<del>$path</del>";
104 } else{
105 push @files, $path;
106 }
107 }
108
109 41 dpavlin print '<blockquote><p><tt style="color:#808080">',join(", ",@files),':</tt> ',encode($e->{'msg'}),'</p></blockquote>';
110 40 dpavlin
111 }
112