X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/f5a5df14b7daeb032137c293c4db288e84429dfa..fae3db5baa0223cc5a24780d3de440367fe28bbf:/IkiWiki/Rcs/SVN.pm?ds=sidebyside diff --git a/IkiWiki/Rcs/SVN.pm b/IkiWiki/Rcs/SVN.pm index 946412320..a2e2ff69c 100644 --- a/IkiWiki/Rcs/SVN.pm +++ b/IkiWiki/Rcs/SVN.pm @@ -1,10 +1,13 @@ -#!/usr/bin/perl -T +#!/usr/bin/perl # For subversion support. use warnings; use strict; package IkiWiki; + +my $svn_log_infoline=qr/^r(\d+)\s+\|\s+([^\s]+)\s+\|\s+(\d+-\d+-\d+\s+\d+:\d+:\d+\s+[-+]?\d+).*/; +my $svn_webcommit=qr/^web commit by (\w+):?(.*)/; sub svn_info ($$) { #{{{ my $field=shift; @@ -102,25 +105,20 @@ sub rcs_recentchanges ($) { #{{{ if (-d "$config{srcdir}/.svn") { my $svn_url=svn_info("URL", $config{srcdir}); - # FIXME: currently assumes that the wiki is somewhere - # under trunk in svn, doesn't support other layouts. - my ($svn_base)=$svn_url=~m!(/trunk(?:/.*)?)$!; - my $div=qr/^--------------------+$/; - my $infoline=qr/^r(\d+)\s+\|\s+([^\s]+)\s+\|\s+(\d+-\d+-\d+\s+\d+:\d+:\d+\s+[-+]?\d+).*/; my $state='start'; my ($rev, $user, $when, @pages, @message); - foreach (`LANG=C svn log --limit $num -v '$svn_url'`) { + foreach (`LANG=C svn log -v '$svn_url'`) { chomp; if ($state eq 'start' && /$div/) { $state='header'; } - elsif ($state eq 'header' && /$infoline/) { + elsif ($state eq 'header' && /$svn_log_infoline/) { $rev=$1; $user=$2; $when=concise(ago(time - str2time($3))); } - elsif ($state eq 'header' && /^\s+[A-Z]\s+\Q$svn_base\E\/([^ ]+)(?:$|\s)/) { + elsif ($state eq 'header' && /^\s+[A-Z]+\s+\/\Q$config{svnpath}\E\/([^ ]+)(?:$|\s)/) { my $file=$1; my $diffurl=$config{diffurl}; $diffurl=~s/\[\[file\]\]/$file/g; @@ -137,7 +135,7 @@ sub rcs_recentchanges ($) { #{{{ elsif ($state eq 'body' && /$div/) { my $committype="web"; if (defined $message[0] && - $message[0]->{line}=~/^web commit by (\w+):?(.*)/) { + $message[0]->{line}=~/$svn_webcommit/) { $user="$1"; $message[0]->{line}=$2; } @@ -166,4 +164,94 @@ sub rcs_recentchanges ($) { #{{{ return @ret; } #}}} +sub rcs_notify () { #{{{ + if (! exists $ENV{REV}) { + error("REV is not set, not running from svn post-commit hook, cannot send notifications"); + } + my $rev=int(possibly_foolish_untaint($ENV{REV})); + + my @changed_pages; + foreach my $change (`svnlook changed $config{svnrepo} -r $rev`) { + chomp $change; + if ($change =~ /^[A-Z]+\s+\Q$config{svnpath}\E\/(.*)/) { + push @changed_pages, $1; + } + } + + require IkiWiki::UserInfo; + my @email_recipients=page_subscribers(@changed_pages); + if (@email_recipients) { + # TODO: if a commit spans multiple pages, this will send + # subscribers a diff that might contain pages they did not + # sign up for. Should separate the diff per page and + # reassemble into one mail with just the pages subscribed to. + my $diff=`svnlook diff $config{svnrepo} -r $rev --no-diff-deleted`; + + my $user=`svnlook author $config{svnrepo} -r $rev`; + chomp $user; + my $message=`svnlook log $config{svnrepo} -r $rev`; + if ($message=~/$svn_webcommit/) { + $user="$1"; + $message=$2; + } + + my $subject="$config{wikiname} update of "; + if (@changed_pages > 2) { + $subject.="$changed_pages[0] $changed_pages[1] etc"; + } + else { + $subject.=join(" ", @changed_pages); + } + $subject.=" by $user"; + + my $template=HTML::Template->new( + filename => "$config{templatedir}/notifymail.tmpl" + ); + $template->param( + wikiname => $config{wikiname}, + diff => $diff, + user => $user, + message => $message, + ); + + eval q{use Mail::Sendmail}; + foreach my $email (@email_recipients) { + sendmail( + To => $email, + From => "$config{wikiname} <$config{adminemail}>", + Subject => $subject, + Message => $template->output, + ) or error("Failed to send update notification mail"); + } + } +} #}}} + +sub rcs_getctime () { #{{{ + eval q{use Date::Parse}; + foreach my $page (keys %pagectime) { + my $file="$config{srcdir}/$pagesources{$page}"; + next unless -e $file; + my $child = open(SVNLOG, "-|"); + if (! $child) { + exec("svn", "log", $file) || error("svn log $file failed to run"); + } + + my $date; + while () { + if (/$svn_log_infoline/) { + $date=$3; + } + } + close SVNLOG || warn "svn log $file exited $?"; + + if (! defined $date) { + warn "failed to parse svn log for $file\n"; + next; + } + + $pagectime{$page}=$date=str2time($date); + debug("found ctime ".localtime($date)." for $page"); + } +} #}}} + 1