1package SVNLog::Controller::LogUpdate; 2 3use strict; 4use base 'Catalyst::Controller'; 5 6use XML::Simple; 7use XML::Atom::SimpleFeed; 8use Data::UUID; 9 10sub doupdate : Local 11{ 12 my ($self, $c) = @_; 13 14 my $latest = SVNLog::Model::CDBI::Logentry->maximum_value_of('revision') || 0; 15 my $min = $latest; 16 my $max = 'HEAD'; 17 18 my $svn_cmd_data = '--username '.$c->config->{svn}{username}.' --password '.$c->config->{svn}{password}.' '.$c->config->{svn}{url}; 19 my $log_xml = `svn log --xml --verbose -r $min:$max $svn_cmd_data`; 20 die "SVN request failed" if not (defined $log_xml and $log_xml =~ m~</log>~); 21 22 my $log = XMLin($log_xml, ContentKey => 'path'); 23 24 my $max_seen = -1; 25 26 $c->transaction(sub { 27 for my $logentry (ref $log->{logentry} eq 'ARRAY' ? @{$log->{logentry}} : ($log->{logentry})) 28 { 29 $max_seen = $logentry->{revision} if $logentry->{revision} > $max_seen; 30 next if $logentry->{revision} <= $latest; 31 32 my $paths = $logentry->{paths}->{path}; 33 delete $logentry->{paths}; 34 35 # Convert <msg></msg> into just a string (because XML::Simple doesn't know that's what it should be) 36 $logentry->{msg} = '' if ref $logentry->{msg}; 37 38 my $entry = SVNLog::Model::CDBI::Logentry->insert($logentry); 39 40 for my $path (ref $paths eq 'ARRAY' ? @$paths : ($paths)) 41 { 42 SVNLog::Model::CDBI::Paths->insert({logentry => $entry->id, filter_copyfrom(%$path)}); 43 } 44 } 45 }) or $c->log->error("Transaction failed: " . $c->error->[-1]); 46 47 add_default_public_msgs($c); 48 49 open my $text_fh, '>', $c->config->{output}{filename} or die $!; 50 print $text_fh $self->generate_text($c); 51 open my $feed_fh, '>', $c->config->{output}{filename_feed} or die $!; 52 print $feed_fh $self->generate_feed($c); 53 54 $c->res->body("Updated log to $max_seen."); 55} 56 57sub defaultise : Local 58{ 59 my ($self, $c) = @_; 60 add_default_public_msgs($c); 61 $c->res->body("Done"); 62} 63 64# (To reset the database: 65# delete from public_message; delete from sqlite_sequence where name = "public_message"; 66# ) 67 68sub add_default_public_msgs 69{ 70 my ($c) = @_; 71 72 $c->transaction(sub { 73 my @unmessaged = SVNLog::Model::CDBI::Logentry->retrieve_from_sql(qq{ 74 NOT (SELECT COUNT(*) FROM public_message WHERE public_message.logentry = logentry.id) 75 ORDER BY logentry.id 76 }); 77 for my $logentry (@unmessaged) 78 { 79 my @lines; 80 for (split /\n/, $logentry->msg) 81 { 82 push @lines, $_ if s/^#\s*//; 83 } 84 my $msg = join "\n", @lines; 85 86 SVNLog::Model::CDBI::PublicMessage->insert({ 87 logentry => $logentry->id, 88 msg => $msg, 89 }); 90 } 91 }); 92} 93 94sub createtext : Local 95{ 96 my ($self, $c) = @_; 97 my $out = $self->generate_text($c); 98 $c->res->body($out); 99} 100 101sub createfeed : Local 102{ 103 my ($self, $c) = @_; 104 my $out = $self->generate_feed($c); 105 $c->res->body($out); 106} 107 108sub get_log_entries 109{ 110 my ($days, $max) = @_; 111 my @logentries = (); 112 for (SVNLog::Model::CDBI::Logentry->recent($days)) 113 { 114 my $msg = $_->public_msg; 115 next unless defined $msg and $msg->msg; # skip ones with empty messages 116 117 push @logentries, $_; 118 119 last if $max and @logentries >= $max; 120 } 121 return @logentries; 122} 123 124sub generate_text 125{ 126 my ($self, $c) = @_; 127 128 my $feed_url = $c->config->{output}{feed_url}; 129 my $out = <<EOF; 130<!DOCTYPE html> 131<title>0 A.D. Revision Log</title> 132<style> 133body { 134 color: #fff; 135 margin: 3px; 136 background-color: #000; 137 font-family: Geneva, Arial, Helvetica, sans-serif; 138 font-size: 10px; 139} 140img { 141 border: 0; 142} 143</style> 144<a href="$feed_url" target="_top"><img alt="Atom feed" title="Subscribe to feed of revision log" src="/feed-icon-16x16.png" style="float: right"></a> 145EOF 146 147 my @logentries = get_log_entries(28, 10); 148 149 for (@logentries) 150 { 151 my ($revision, $author, $date, $msg) = ($_->revision, $_->author, $_->date, $_->public_msg); 152 153 $date =~ s/T.*Z//; 154 $out .= <<EOF; 155<b>revision:</b> $revision<br> 156<b>author:</b> $author<br> 157<b>date:</b> $date<br> 158EOF 159 my $text = $msg->msg; 160 $text =~ s/&/&/g; 161 $text =~ s/</</g; 162 $text =~ s/>/>/g; 163 $text =~ s/\n/<br>/g; 164 $out .= $text . "\n<hr>\n"; 165 } 166 167 if (not @logentries) 168 { 169 $out .= 'Sorry, no data is available right now.'; 170 } 171 172 return $out; 173} 174 175sub generate_feed 176{ 177 my ($self, $c) = @_; 178 179 my $uid_gen = new Data::UUID; 180 181 my $feed_url = $c->config->{output}{feed_url}; 182 183 my $feed = new XML::Atom::SimpleFeed( 184 title => "0 A.D. Revision Log", 185 link => "http://play0ad.com/", 186 link => { rel => 'self', href => $feed_url }, 187 id => "urn:uuid:" . $uid_gen->create_from_name_str('WFG SVN feed', 'feed'), 188 ); 189 190 my @logentries = get_log_entries(7); 191 192 for (@logentries) 193 { 194 my ($revision, $author, $date, $msg) = ($_->revision, $_->author, $_->date, $_->public_msg); 195 196 my $uid = $uid_gen->create_from_name_str('WFG SVN feed', $revision); 197 198 $feed->add_entry( 199 title => "Revision $revision - ".$msg->msg, 200 id => "urn:uuid:$uid", 201 author => $author, 202 content => $msg->msg, 203 published => $date, 204 updated => $date, 205 link => "http://play0ad.com/", 206 ); 207 } 208 209 return $feed->as_string; 210} 211 212sub filter_copyfrom 213{ 214 my @r = @_; 215 s/^(copyfrom)-(rev|path)$/$1_$2/ for @r; 216 @r; 217} 218 2191; 220