package SVNLog::Controller::LogUpdate;
use strict;
use base 'Catalyst::Controller';
use XML::Simple;
use XML::Atom::SimpleFeed;
use Data::UUID;
sub doupdate : Local
{
my ($self, $c) = @_;
my $latest = SVNLog::Model::CDBI::Logentry->maximum_value_of('revision') || 0;
my $min = $latest;
my $max = 'HEAD';
my $svn_cmd_data = '--username '.$c->config->{svn}{username}.' --password '.$c->config->{svn}{password}.' '.$c->config->{svn}{url};
my $log_xml = `svn log --xml --verbose -r $min:$max $svn_cmd_data`;
die "SVN request failed" if not (defined $log_xml and $log_xml =~ m~~);
my $log = XMLin($log_xml, ContentKey => 'path');
my $max_seen = -1;
$c->transaction(sub {
for my $logentry (ref $log->{logentry} eq 'ARRAY' ? @{$log->{logentry}} : ($log->{logentry}))
{
$max_seen = $logentry->{revision} if $logentry->{revision} > $max_seen;
next if $logentry->{revision} <= $latest;
my $paths = $logentry->{paths}->{path};
delete $logentry->{paths};
# Convert into just a string (because XML::Simple doesn't know that's what it should be)
$logentry->{msg} = '' if ref $logentry->{msg};
my $entry = SVNLog::Model::CDBI::Logentry->insert($logentry);
for my $path (ref $paths eq 'ARRAY' ? @$paths : ($paths))
{
SVNLog::Model::CDBI::Paths->insert({logentry => $entry->id, filter_copyfrom(%$path)});
}
}
}) or $c->log->error("Transaction failed: " . $c->error->[-1]);
add_default_public_msgs($c);
open my $text_fh, '>', $c->config->{output}{filename} or die $!;
print $text_fh $self->generate_text($c);
open my $feed_fh, '>', $c->config->{output}{filename_feed} or die $!;
print $feed_fh $self->generate_feed($c);
$c->res->body("Updated log to $max_seen.");
}
sub defaultise : Local
{
my ($self, $c) = @_;
add_default_public_msgs($c);
$c->res->body("Done");
}
# (To reset the database:
# delete from public_message; delete from sqlite_sequence where name = "public_message";
# )
sub add_default_public_msgs
{
my ($c) = @_;
$c->transaction(sub {
my @unmessaged = SVNLog::Model::CDBI::Logentry->retrieve_from_sql(qq{
NOT (SELECT COUNT(*) FROM public_message WHERE public_message.logentry = logentry.id)
ORDER BY logentry.id
});
for my $logentry (@unmessaged)
{
my @lines;
for (split /\n/, $logentry->msg)
{
push @lines, $_ if s/^#\s*//;
}
my $msg = join "\n", @lines;
SVNLog::Model::CDBI::PublicMessage->insert({
logentry => $logentry->id,
msg => $msg,
});
}
});
}
sub createtext : Local
{
my ($self, $c) = @_;
my $out = $self->generate_text($c);
$c->res->body($out);
}
sub createfeed : Local
{
my ($self, $c) = @_;
my $out = $self->generate_feed($c);
$c->res->body($out);
}
sub get_log_entries
{
my ($days, $max) = @_;
my @logentries = ();
for (SVNLog::Model::CDBI::Logentry->recent($days))
{
my $msg = $_->public_msg;
next unless defined $msg and $msg->msg; # skip ones with empty messages
push @logentries, $_;
last if $max and @logentries >= $max;
}
return @logentries;
}
sub generate_text
{
my ($self, $c) = @_;
my $feed_url = $c->config->{output}{feed_url};
my $out = <
0 A.D. Revision Log
EOF
my @logentries = get_log_entries(28, 10);
for (@logentries)
{
my ($revision, $author, $date, $msg) = ($_->revision, $_->author, $_->date, $_->public_msg);
$date =~ s/T.*Z//;
$out .= <revision: $revision
author: $author
date: $date
EOF
my $text = $msg->msg;
$text =~ s/&/&/g;
$text =~ s/</g;
$text =~ s/>/>/g;
$text =~ s/\n/
/g;
$out .= $text . "\n
\n";
}
if (not @logentries)
{
$out .= 'Sorry, no data is available right now.';
}
return $out;
}
sub generate_feed
{
my ($self, $c) = @_;
my $uid_gen = new Data::UUID;
my $feed_url = $c->config->{output}{feed_url};
my $feed = new XML::Atom::SimpleFeed(
title => "0 A.D. Revision Log",
link => "http://play0ad.com/",
link => { rel => 'self', href => $feed_url },
id => "urn:uuid:" . $uid_gen->create_from_name_str('WFG SVN feed', 'feed'),
);
my @logentries = get_log_entries(7);
for (@logentries)
{
my ($revision, $author, $date, $msg) = ($_->revision, $_->author, $_->date, $_->public_msg);
my $uid = $uid_gen->create_from_name_str('WFG SVN feed', $revision);
$feed->add_entry(
title => "Revision $revision - ".$msg->msg,
id => "urn:uuid:$uid",
author => $author,
content => $msg->msg,
published => $date,
updated => $date,
link => "http://play0ad.com/",
);
}
return $feed->as_string;
}
sub filter_copyfrom
{
my @r = @_;
s/^(copyfrom)-(rev|path)$/$1_$2/ for @r;
@r;
}
1;