]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blobdiff - IkiWiki/Rcs/SVN.pm
oops
[git.ikiwiki.info.git] / IkiWiki / Rcs / SVN.pm
index 946412320a35d305e3a9d6aff15411f3ad15eec5..a2e2ff69c475444c6fc93a8357992822267b09c6 100644 (file)
@@ -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 (<SVNLOG>) {
+                       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