/[Frey]/trunk/lib/Frey/SVN.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/lib/Frey/SVN.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 909 - (hide annotations)
Fri Jan 2 16:56:42 2009 UTC (15 years, 4 months ago) by dpavlin
File size: 4588 byte(s)
move files to right and re-format commit messages to something nicer (hopefully)
1 dpavlin 769 package Frey::SVN;
2     use Moose;
3    
4     # Convert output from svn log to html page (with some formatting of
5     # commit messages)
6     #
7     # 2004-04-28 Dobrica Pavlinusic <dpavlin@rot13.org>
8    
9     extends 'Frey';
10     with 'Frey::Web';
11     #with 'Frey::Storage';
12    
13     use XML::Simple;
14 dpavlin 807 use DateTimeX::Easy;
15 dpavlin 769
16     has repository => (
17     is => 'rw',
18     isa => 'Str',
19     required => 1,
20     default => 'file:///home/dpavlin/private/svn/Frey',
21     );
22    
23 dpavlin 770 has limit => (
24     is => 'rw',
25     isa => 'Int',
26     default => 50,
27     );
28    
29 dpavlin 804 sub iterator {
30     my ($self,$coderef) = @_;
31    
32 dpavlin 769 sub sh_regex($$) {
33     my ($cmd,$regex) = @_;
34     open(my $sh, $cmd . ' |') || die "sh_regex failed on $cmd: $!";
35     while(my $l = <$sh>) {
36     chomp($l);
37     if ($l =~ $regex) {
38     if ($1 && $2) {
39     return ($1,$2);
40     } elsif ($1) {
41     return $1;
42     } else {
43     return $l;
44     }
45     }
46     }
47     #warn "can't find $regex in output of $cmd\n";
48     return;
49     }
50    
51     my $path = $self->repository;
52     warn "# path $path\n";
53    
54     my $cmd;
55     if ($path =~ m#file://# || -e "$path/.svn") {
56     $cmd = "svn log -v --xml $path";
57     } else {
58     my $svn_path = sh_regex('svk info', qr#Mirrored From:\s+([^,]+)#i);
59    
60     if (! $svn_path) {
61    
62     my $svk_depot = sh_regex('svk info', qr#Depot Path: (/.+)#i);
63    
64     my $depot = $svk_depot;
65     my $rel_path;
66    
67     my $path = sh_regex('svk depot --list', qr/^$depot\s+(\S+)/i);
68    
69     while (! $path && $depot =~ s{^(/.*/)([^/]+)/?$}{$1} ) {
70     $rel_path = "$2/$rel_path";
71     $path = sh_regex('svk depot --list', qr/^$depot\s+(\S+)/i);
72     }
73    
74     die "can't find depot path '$svk_depot' in svk depot --list\n" unless ($path);
75     $svn_path = "file:///$path/$rel_path";
76     }
77    
78     $cmd = "svn log -v --xml $svn_path";
79     }
80    
81 dpavlin 770 $cmd .= " --limit " . $self->limit if $self->limit;
82    
83 dpavlin 769 warn "# $cmd\n";
84     open(my $fh, $cmd .' |') || die "failed $cmd: $!";
85     my $log;
86     while(<$fh>) {
87     $log .= $_;
88     }
89     close($fh);
90    
91     my $xml = XMLin($log, ForceArray => [ 'logentry', 'path' ]);
92    
93 dpavlin 804 foreach my $e (@{$xml->{'logentry'}}) {
94 dpavlin 875 warn "# e = ",$self->dump( $e ) if $self->debug;
95 dpavlin 804 $coderef->($e);
96     }
97     }
98    
99     sub as_markup {
100     my ($self) = @_;
101    
102     # extract svk revision: r113@athlon (orig r999): dpavlin | 2005-09-01 20:38:07 +0200
103     our $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*';
104    
105     sub encode {
106     my $foo = shift;
107     $foo =~ s/$svk_rev_re//gsm;
108     $foo =~ s/</&lt;/g;
109     $foo =~ s/>/&gt;/g;
110     $foo =~ s/"/&quot;/g;
111 dpavlin 909 # $foo =~ s/([\n\r][\n\r]+)/$1<br\/>/gis;
112 dpavlin 804 $foo =~ s/([\n\r]+)([\-\*]\s+)/$1<br\/>$2/gis;
113     $foo =~ s/([\n\r]+)(r\d+:\s+)/$1<br\/>$2/gis;
114     $foo =~ s/([\n\r]+)(\s+r\d+@)/$1<br\/>$2/gis; # svk
115     return $foo;
116     }
117    
118 dpavlin 769 our $html = '';
119    
120 dpavlin 852 $self->add_css(qq|
121 dpavlin 909 .commit {
122     clear: both;
123     padding-top: 1em;
124     padding-bottom: 1em;
125     border-top: 1px dashed #ccc;
126     }
127     .files {
128     color: #888;
129     font-family: monospace;
130     font-size: 80%;
131     float: right;
132     padding-bottom: 1.2em; /* fix 80% back to original 1em */
133     }
134 dpavlin 852 .date, .revision { color: #666; }
135 dpavlin 909 .message {
136     padding-top: 0.5em;
137     padding-left: 2em; /* like blockquote */
138     white-space: pre-wrap;
139     }
140 dpavlin 852
141     ins { color: #8c8 }
142     del { color: #c88 }
143     |);
144    
145 dpavlin 804 $self->iterator( sub {
146     my $e = shift;
147    
148 dpavlin 769 my $rev = $e->{'revision'};
149     my $date = $e->{'date'};
150    
151     $date =~ s/T/ /;
152     $date =~ s/\.\d+Z$//;
153    
154 dpavlin 852 my $msg = $e->{'msg'};
155     $msg = '' if ref($msg); # FIXME why do I need this, dammit?
156     if ( $msg ) {
157     $msg = encode( $msg );
158     $msg = qq|<div class="message">$msg</div>|;
159     }
160    
161 dpavlin 769 my @files;
162    
163     foreach my $p (@{$e->{'paths'}->{'path'}}) {
164     my ($action,$path) = ($p->{'action'},$p->{'content'});
165    
166     if ($action eq "A") {
167     push @files, "<ins>$path</ins>";
168     } elsif ($action eq "D") {
169     push @files, "<del>$path</del>";
170 dpavlin 851 } else {
171 dpavlin 769 push @files, $path;
172     }
173     }
174    
175 dpavlin 909 $html .= qq|
176     <div class="commit">
177     <span class="date">$date</span>
178     <em>$e->{author}</em>
179     <span class="revision">$e->{revision}</span>
180     <div class="files">\n| . join("<br>\n",@files) . qq|\n</div>
181     $msg
182     </div>
183     |;
184 dpavlin 769
185 dpavlin 804 });
186 dpavlin 769
187     return $html;
188     }
189    
190 dpavlin 805 sub codeswarm_as_markup {
191     my ($self) = @_;
192    
193     $self->content_type('text/xml');
194    
195     my $file_events = '';
196    
197     $self->iterator( sub {
198     my $e = shift;
199    
200     my $rev = $e->{'revision'};
201 dpavlin 807 my $date = DateTimeX::Easy->new( $e->{'date'} )->epoch . '000'; # ms
202 dpavlin 805 my $author = $e->{'author'};
203    
204     foreach my $p (@{$e->{'paths'}->{'path'}}) {
205     my ($action,$path) = ($p->{'action'},$p->{'content'});
206     $file_events .= qq|\t<event filename="$path" date="$date" author="$author" />\n|;
207     }
208    
209     });
210    
211     return qq|<?xml version="1.0"?>
212     <!-- One commit per day for one month by a documenter and programmer. -->
213     <file_events>
214     $file_events
215     </file_events>
216     |;
217    
218     }
219    
220 dpavlin 769 1;

  ViewVC Help
Powered by ViewVC 1.1.26