From 13e3bf867157226076fcc14a0d3875fd129a66c7 Mon Sep 17 00:00:00 2001 From: joey Date: Mon, 24 Apr 2006 23:09:26 +0000 Subject: [PATCH] commit changes for email subscriptions --- IkiWiki/CGI.pm | 4 +-- IkiWiki/Rcs/SVN.pm | 39 ++++++++++++++++++--- IkiWiki/Rcs/Stub.pm | 3 ++ IkiWiki/Render.pm | 2 ++ IkiWiki/UserInfo.pm | 84 +++++++++++++++++++++++++++++++++++++++++++++ IkiWiki/Wrapper.pm | 1 + debian/changelog | 2 +- debian/postinst | 2 +- ikiwiki | 64 +++++----------------------------- 9 files changed, 137 insertions(+), 64 deletions(-) create mode 100644 IkiWiki/UserInfo.pm diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm index 8201351ca..1d642687b 100644 --- a/IkiWiki/CGI.pm +++ b/IkiWiki/CGI.pm @@ -2,6 +2,7 @@ use warnings; use strict; +use IkiWiki::UserInfo; package IkiWiki; @@ -190,10 +191,9 @@ sub cgi_signin ($$) { #{{{ ); eval q{use Mail::Sendmail}; - my ($fromhost) = $config{cgiurl} =~ m!/([^/]+)!; sendmail( To => userinfo_get($user_name, "email"), - From => "$config{wikiname} admin <".(getpwuid($>))[0]."@".$fromhost.">", + From => "$config{wikiname} admin <$config{adminemail}>", Subject => "$config{wikiname} information", Message => $template->output, ) or error("Failed to send mail"); diff --git a/IkiWiki/Rcs/SVN.pm b/IkiWiki/Rcs/SVN.pm index c6f8f2ab1..dd74a0577 100644 --- a/IkiWiki/Rcs/SVN.pm +++ b/IkiWiki/Rcs/SVN.pm @@ -104,10 +104,6 @@ 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 $state='start'; my ($rev, $user, $when, @pages, @message); @@ -121,7 +117,7 @@ sub rcs_recentchanges ($) { #{{{ $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; @@ -167,6 +163,39 @@ 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 @changed_pages; + foreach my $change (`svnlook changed $config{svnrepo} -r $ENV{REV}`) { + chomp; + if (/^[A-Z]+\s+\Q$config{svnpath}\E\/(.*)/) { + push @changed_pages, $1; + } + } + + 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`; + foreach my $email (@email_recipients) { + sendmail( + To => $email, + From => "$config{wikiname} <$config{adminemail}>", + Subject => "$config{wikiname} $ENV{REV} update notification", + Message => $body, + ) or error("Failed to send update notification mail"); + } + } +} #}}} + sub rcs_getctime () { #{{{ eval q{use Date::Parse}; foreach my $page (keys %pagectime) { diff --git a/IkiWiki/Rcs/Stub.pm b/IkiWiki/Rcs/Stub.pm index d2a6ad003..9bbfde352 100644 --- a/IkiWiki/Rcs/Stub.pm +++ b/IkiWiki/Rcs/Stub.pm @@ -23,6 +23,9 @@ sub rcs_add ($) { sub rcs_recentchanges ($) { } +sub rcs_notify () { +} + sub rcs_getctime () { error "getctime not implemented"; } diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 7148d754e..dfa598da0 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -1,3 +1,5 @@ +#!/usr/bin/perl + package IkiWiki; use warnings; diff --git a/IkiWiki/UserInfo.pm b/IkiWiki/UserInfo.pm new file mode 100644 index 000000000..f4e261563 --- /dev/null +++ b/IkiWiki/UserInfo.pm @@ -0,0 +1,84 @@ +#!/usr/bin/perl + +use warnings; +use strict; +use Storable; + +package IkiWiki; + +sub userinfo_retrieve () { #{{{ + my $userinfo=eval{ Storable::lock_retrieve("$config{wikistatedir}/userdb") }; + return $userinfo; +} #}}} + +sub userinfo_store ($) { #{{{ + my $userinfo=shift; + + my $oldmask=umask(077); + my $ret=Storable::lock_store($userinfo, "$config{wikistatedir}/userdb"); + umask($oldmask); + return $ret; +} #}}} + +sub userinfo_get ($$) { #{{{ + my $user=shift; + my $field=shift; + + my $userinfo=userinfo_retrieve(); + if (! defined $userinfo || + ! exists $userinfo->{$user} || ! ref $userinfo->{$user} || + ! exists $userinfo->{$user}->{$field}) { + return ""; + } + return $userinfo->{$user}->{$field}; +} #}}} + +sub userinfo_set ($$$) { #{{{ + my $user=shift; + my $field=shift; + my $value=shift; + + my $userinfo=userinfo_retrieve(); + if (! defined $userinfo || + ! exists $userinfo->{$user} || ! ref $userinfo->{$user}) { + return ""; + } + + $userinfo->{$user}->{$field}=$value; + return userinfo_store($userinfo); +} #}}} + +sub userinfo_setall ($$) { #{{{ + my $user=shift; + my $info=shift; + + my $userinfo=userinfo_retrieve(); + if (! defined $userinfo) { + $userinfo={}; + } + $userinfo->{$user}=$info; + return userinfo_store($userinfo); +} #}}} + +sub is_admin ($) { #{{{ + my $user_name=shift; + + return grep { $_ eq $user_name } @{$config{adminuser}}; +} #}}} + +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}; + } + } + return @ret; +} #}}} + +1 diff --git a/IkiWiki/Wrapper.pm b/IkiWiki/Wrapper.pm index 2e4925a1f..238f71a91 100644 --- a/IkiWiki/Wrapper.pm +++ b/IkiWiki/Wrapper.pm @@ -28,6 +28,7 @@ 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" diff --git a/debian/changelog b/debian/changelog index 4cc350333..460b260d0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -ikiwiki (0.1) unstable; urgency=low +ikiwiki (0.2) unstable; urgency=low * Initial release. diff --git a/debian/postinst b/debian/postinst index e84955daf..be5f53939 100755 --- a/debian/postinst +++ b/debian/postinst @@ -4,7 +4,7 @@ set -e # Change this when some incompatible change is made that requires # rebuilding all wikis. -firstcompat=0.1 +firstcompat=0.2 wikilist=/etc/ikiwiki/wikilist diff --git a/ikiwiki b/ikiwiki index 6bf58017d..3cf2a7cb3 100755 --- a/ikiwiki +++ b/ikiwiki @@ -27,6 +27,7 @@ sub getconfig () { #{{{ default_pageext => ".mdwn", cgi => 0, svn => 1, + notify => 0, url => '', cgiurl => '', historyurl => '', @@ -39,12 +40,15 @@ sub getconfig () { #{{{ hyperestraier => 0, wrapper => undef, wrappermode => undef, + svnrepo => undef, + svnpath => "trunk", srcdir => undef, destdir => undef, templatedir => "/usr/share/ikiwiki/templates", underlaydir => "/usr/share/ikiwiki/basewiki", setup => undef, adminuser => undef, + adminemail => undef, ); eval q{use Getopt::Long}; @@ -61,10 +65,14 @@ sub getconfig () { #{{{ "hyperestraier" => \$config{hyperestraier}, "rss!" => \$config{rss}, "cgi!" => \$config{cgi}, + "notify!" => \$config{notify}, "url=s" => \$config{url}, "cgiurl=s" => \$config{cgiurl}, "historyurl=s" => \$config{historyurl}, "diffurl=s" => \$config{diffurl}, + "svnrepo" => \$config{svnrepo}, + "svnpath" => \$config{svnpath}, + "adminemail=s" => \$config{adminemail}, "exclude=s@" => sub { $config{wiki_file_prune_regexp}=qr/$config{wiki_file_prune_regexp}|$_[1]/; }, @@ -437,61 +445,6 @@ sub misctemplate ($$) { #{{{ return $template->output; }#}}} -sub userinfo_get ($$) { #{{{ - my $user=shift; - my $field=shift; - - eval q{use Storable}; - my $userdata=eval{ Storable::lock_retrieve("$config{wikistatedir}/userdb") }; - if (! defined $userdata || ! ref $userdata || - ! exists $userdata->{$user} || ! ref $userdata->{$user} || - ! exists $userdata->{$user}->{$field}) { - return ""; - } - return $userdata->{$user}->{$field}; -} #}}} - -sub userinfo_set ($$$) { #{{{ - my $user=shift; - my $field=shift; - my $value=shift; - - eval q{use Storable}; - my $userdata=eval{ Storable::lock_retrieve("$config{wikistatedir}/userdb") }; - if (! defined $userdata || ! ref $userdata || - ! exists $userdata->{$user} || ! ref $userdata->{$user}) { - return ""; - } - - $userdata->{$user}->{$field}=$value; - my $oldmask=umask(077); - my $ret=Storable::lock_store($userdata, "$config{wikistatedir}/userdb"); - umask($oldmask); - return $ret; -} #}}} - -sub userinfo_setall ($$) { #{{{ - my $user=shift; - my $info=shift; - - eval q{use Storable}; - my $userdata=eval{ Storable::lock_retrieve("$config{wikistatedir}/userdb") }; - if (! defined $userdata || ! ref $userdata) { - $userdata={}; - } - $userdata->{$user}=$info; - my $oldmask=umask(077); - my $ret=Storable::lock_store($userdata, "$config{wikistatedir}/userdb"); - umask($oldmask); - return $ret; -} #}}} - -sub is_admin ($) { #{{{ - my $user_name=shift; - - return grep { $_ eq $user_name } @{$config{adminuser}}; -} #}}} - sub glob_match ($$) { #{{{ my $page=shift; my $glob=shift; @@ -544,6 +497,7 @@ sub main () { #{{{ loadindex(); require IkiWiki::Render; rcs_update(); + rcs_notify() if $config{notify}; rcs_getctime() if $config{getctime}; refresh(); saveindex(); -- 2.32.0.93.g670b81a890