From: joey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Date: Tue, 25 Apr 2006 00:22:41 +0000 (+0000)
Subject: subscription nearly done
X-Git-Tag: 1.0~47
X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=b7f64d884cd8bd8e1d9e8fb75735530d4c8a135d;p=ikiwiki.git

subscription nearly done
---

diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm
index 1d642687b..feed00487 100644
--- a/IkiWiki/CGI.pm
+++ b/IkiWiki/CGI.pm
@@ -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");
 			}
diff --git a/IkiWiki/Rcs/SVN.pm b/IkiWiki/Rcs/SVN.pm
index dd74a0577..7d48abb61 100644
--- a/IkiWiki/Rcs/SVN.pm
+++ b/IkiWiki/Rcs/SVN.pm
@@ -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");
 		}
 	}
diff --git a/IkiWiki/UserInfo.pm b/IkiWiki/UserInfo.pm
index f4e261563..8c27714b8 100644
--- a/IkiWiki/UserInfo.pm
+++ b/IkiWiki/UserInfo.pm
@@ -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;
diff --git a/IkiWiki/Wrapper.pm b/IkiWiki/Wrapper.pm
index 238f71a91..d72368446 100644
--- a/IkiWiki/Wrapper.pm
+++ b/IkiWiki/Wrapper.pm
@@ -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}";
diff --git a/basewiki/globlist.mdwn b/basewiki/globlist.mdwn
index 30bc837ac..5255a3bee 100644
--- a/basewiki/globlist.mdwn
+++ b/basewiki/globlist.mdwn
@@ -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
index 000000000..5a1497a3f
--- /dev/null
+++ b/templates/notifymail.tmpl
@@ -0,0 +1,5 @@
+The following change has been made to <TMPL_VAR WIKINAME>
+by <TMPL_VAR USER>:
+<TMPL_VAR MESSAGE>
+
+<TMPL_VAR DIFF>