subscription nearly done
authorjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Tue, 25 Apr 2006 00:22:41 +0000 (00:22 +0000)
committerjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Tue, 25 Apr 2006 00:22:41 +0000 (00:22 +0000)
IkiWiki/CGI.pm
IkiWiki/Rcs/SVN.pm
IkiWiki/UserInfo.pm
IkiWiki/Wrapper.pm
basewiki/globlist.mdwn
templates/notifymail.tmpl [new file with mode: 0644]

index 1d642687bbefa7820257fce1dc9994ed42476959..feed00487c23fbd42ba8a7ffffd14b8b1985bce8 100644 (file)
@@ -217,7 +217,8 @@ sub cgi_prefs ($$) { #{{{
        eval q{use CGI::FormBuilder};
        my $form = CGI::FormBuilder->new(
                title => "preferences",
-               fields => [qw(do name password confirm_password email locked_pages)],
+               fields => [qw(do name password confirm_password email 
+                             subscriptions locked_pages)],
                header => 0,
                method => 'POST',
                validate => {
@@ -242,6 +243,8 @@ sub cgi_prefs ($$) { #{{{
                value => $user_name, force => 1);
        $form->field(name => "password", type => "password");
        $form->field(name => "confirm_password", type => "password");
+       $form->field(name => "subscriptions", size => 50,
+               comment => "(".htmllink("", "GlobList", 1).")");
        $form->field(name => "locked_pages", size => 50,
                comment => "(".htmllink("", "GlobList", 1).")");
        
@@ -252,6 +255,8 @@ sub cgi_prefs ($$) { #{{{
        if (! $form->submitted) {
                $form->field(name => "email", force => 1,
                        value => userinfo_get($user_name, "email"));
+               $form->field(name => "subscriptions", force => 1,
+                       value => userinfo_get($user_name, "subscriptions"));
                $form->field(name => "locked_pages", force => 1,
                        value => userinfo_get($user_name, "locked_pages"));
        }
@@ -266,7 +271,7 @@ sub cgi_prefs ($$) { #{{{
                return;
        }
        elsif ($form->submitted eq "Save Preferences" && $form->validate) {
-               foreach my $field (qw(password email locked_pages)) {
+               foreach my $field (qw(password email subscriptions locked_pages)) {
                        if (length $form->field($field)) {
                                userinfo_set($user_name, $field, $form->field($field)) || error("failed to set $field");
                        }
index dd74a05773fec68d477c94aca0666892ec74615b..7d48abb618a761f685a43fc0bf77dec4e7e8c155 100644 (file)
@@ -7,6 +7,7 @@ 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;
@@ -134,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;
                                }
@@ -167,11 +168,12 @@ 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 $ENV{REV}`) {
-               chomp;
-               if (/^[A-Z]+\s+\Q$config{svnpath}\E\/(.*)/) {
+       foreach my $change (`svnlook changed $config{svnrepo} -r $rev`) {
+               chomp $change;
+               if ($change =~ /^[A-Z]+\s+\Q$config{svnpath}\E\/(.*)/) {
                        push @changed_pages, $1;
                }
        }
@@ -179,18 +181,45 @@ sub rcs_notify () { #{{{
        require IkiWiki::UserInfo;
        my @email_recipients=page_subscribers(@changed_pages);
        if (@email_recipients) {
-               eval q{use Mail::Sendmail};
                # 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 $body=`LANG=C svnlook diff $config{svnrepo} -r $ENV{REV} --no-diff-deleted`;
+               my $diff=`svnlook diff $config{svnrepo} -r $rev --no-diff-deleted`;
+
+               my $user=`svnlook author $config{svnrepo} -r $rev`;
+               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 => "$config{wikiname} $ENV{REV} update notification",
-                               Message => $body,
+                               Subject => $subject,
+                               Message => $template->output,
                        ) or error("Failed to send update notification mail");
                }
        }
index f4e261563d3ef625be6e776014a93eaf7fd691f5..8c27714b8e01ac39d31b2477005d48bc4d5ad56a 100644 (file)
@@ -70,12 +70,12 @@ sub page_subscribers (@) { #{{{
        my @ret;
        my $userinfo=userinfo_retrieve();
        foreach my $user (keys %{$userinfo}) {
-               if (exists $user->{subscriptions} &&
-                   length $user->{subscriptions} &&
-                   exists $user->{email} &&
-                   length $user->{email} &&
-                   grep { globmatch($_, $user->{subscriptions}) } @_) {
-                       push @ret, $user->{email};
+               if (exists $userinfo->{$user}->{subscriptions} &&
+                   length $userinfo->{$user}->{subscriptions} &&
+                   exists $userinfo->{$user}->{email} &&
+                   length $userinfo->{$user}->{email} &&
+                   grep { glob_match($_, $userinfo->{$user}->{subscriptions}) } @_) {
+                       push @ret, $userinfo->{$user}->{email};
                }
        }
        return @ret;
index 238f71a91bdc28360e6a0910b1d391c8d45e25d0..d723684463dda687e21be6d18341ce0c6ac0d1d5 100644 (file)
@@ -28,7 +28,6 @@ sub gen_wrapper () { #{{{
        push @envsave, qw{REMOTE_ADDR QUERY_STRING REQUEST_METHOD REQUEST_URI
                       CONTENT_TYPE CONTENT_LENGTH GATEWAY_INTERFACE
                       HTTP_COOKIE} if $config{cgi};
-       push @envsave, qw{REV} if $config{svn};
        my $envsave="";
        foreach my $var (@envsave) {
                $envsave.=<<"EOF"
@@ -36,6 +35,16 @@ sub gen_wrapper () { #{{{
                asprintf(&newenviron[i++], "%s=%s", "$var", s);
 EOF
        }
+       if ($config{svn} && $config{notify}) {
+               # Support running directly as hooks/post-commit by passing
+               # $2 in REV in the environment.
+               $envsave.=<<"EOF"
+       if (argc == 3)
+               asprintf(&newenviron[i++], "REV=%s", argv[2]);
+       else if ((s=getenv("REV")))
+               asprintf(&newenviron[i++], "%s=%s", "REV", s);
+EOF
+       }
        
        $Data::Dumper::Indent=0; # no newlines
        my $configstring=Data::Dumper->Dump([\%config], ['*config']);
@@ -56,7 +65,7 @@ extern char **environ;
 int main (int argc, char **argv) {
        /* Sanitize environment. */
        char *s;
-       char *newenviron[$#envsave+4];
+       char *newenviron[$#envsave+5];
        int i=0;
 $envsave
        newenviron[i++]="HOME=$ENV{HOME}";
index 30bc837aca3f9463daeecf6762c21a50c5d27281..5255a3beec1ea25afe8881e369d52b301520dffe 100644 (file)
@@ -1,5 +1,5 @@
 When the wiki stores lists of pages, such as pages that are locked or pages
-that you want to be emailed if changed, it uses a GlobList.
+whose commit emails you want subscribe to, it uses a GlobList.
 
 This is a list of page names, separated by white space. The "glob" bit is
 that as well as full page names, it can contain glob patterns. "`*`" stands
diff --git a/templates/notifymail.tmpl b/templates/notifymail.tmpl
new file mode 100644 (file)
index 0000000..5a1497a
--- /dev/null
@@ -0,0 +1,5 @@
+The following change has been made to <TMPL_VAR WIKINAME>
+by <TMPL_VAR USER>:
+<TMPL_VAR MESSAGE>
+
+<TMPL_VAR DIFF>