wikiname => "wiki",
default_pageext => "mdwn",
cgi => 0,
+ post_commit => 0,
rcs => '',
notify => 0,
url => '',
}
open(WIKILOCK, ">$config{wikistatedir}/lockfile") ||
error ("cannot write to $config{wikistatedir}/lockfile: $!");
- if (! flock(WIKILOCK, 2 | 4)) {
+ if (! flock(WIKILOCK, 2 | 4)) { # LOCK_EX | LOCK_NB
debug("wiki seems to be locked, waiting for lock");
my $wait=600; # arbitrary, but don't hang forever to
# prevent process pileup
close WIKILOCK;
} #}}}
+sub commit_hook_enabled () { #{{{
+ open(COMMITLOCK, "+>$config{wikistatedir}/commitlock") ||
+ error ("cannot write to $config{wikistatedir}/commitlock: $!");
+ if (! flock(WIKILOCK, 1 | 4)) { # LOCK_SH | LOCK_NB to test
+ close WIKILOCK;
+ return 0;
+ }
+ close WIKILOCK;
+ return 1;
+} #}}}
+
+sub disable_commit_hook () { #{{{
+ open(COMMITLOCK, ">$config{wikistatedir}/commitlock") ||
+ error ("cannot write to $config{wikistatedir}/commitlock: $!");
+ if (! flock(COMMITLOCK, 2)) { # LOCK_EX
+ error("failed to get commit lock");
+ }
+} #}}}
+
+sub enable_commit_hook () { #{{{
+ close COMMITLOCK;
+} #}}}
+
sub loadindex () { #{{{
open (IN, "$config{wikistatedir}/index") || return;
while (<IN>) {
return;
}
+ my $conflict;
if ($config{rcs}) {
my $message="";
if (defined $form->field('comments') &&
if ($newfile) {
rcs_add($file);
}
- # prevent deadlock with post-commit hook
- unlockwiki();
- # presumably the commit will trigger an update
- # of the wiki
- my $conflict=rcs_commit($file, $message,
+
+ # Prevent deadlock with post-commit hook by
+ # signaling to it that it should not try to
+ # do anything (except send commit mails).
+ disable_commit_hook();
+ $conflict=rcs_commit($file, $message,
$form->field("rcsinfo"),
$session->param("name"), $ENV{REMOTE_ADDR});
+ enable_commit_hook();
+ rcs_update();
+ }
- if (defined $conflict) {
- $form->field(name => "rcsinfo", value => rcs_prepedit($file),
- force => 1);
- $form->tmpl_param("page_conflict", 1);
- $form->field("editcontent", value => $conflict, force => 1);
- $form->field(name => "comments", value => $form->field('comments'), force => 1);
- $form->field("do", "edit)");
- $form->tmpl_param("page_select", 0);
- $form->field(name => "page", type => 'hidden');
- $form->field(name => "type", type => 'hidden');
- $form->title(sprintf(gettext("editing %s"), $page));
- print $form->render(submit => \@buttons);
- return;
- }
- else {
- # Make sure that the repo is up-to-date;
- # locking prevents the post-commit hook
- # from updating it.
- rcs_update();
- }
+ # Refresh even if there was a conflict, since other changes
+ # may have been committed while the post-commit hook was
+ # disabled.
+ require IkiWiki::Render;
+ refresh();
+ saveindex();
+
+ if (defined $conflict) {
+ $form->field(name => "rcsinfo", value => rcs_prepedit($file),
+ force => 1);
+ $form->tmpl_param("page_conflict", 1);
+ $form->field("editcontent", value => $conflict, force => 1);
+ $form->field(name => "comments", value => $form->field('comments'), force => 1);
+ $form->field("do", "edit)");
+ $form->tmpl_param("page_select", 0);
+ $form->field(name => "page", type => 'hidden');
+ $form->field(name => "type", type => 'hidden');
+ $form->title(sprintf(gettext("editing %s"), $page));
+ print $form->render(submit => \@buttons);
+ return;
}
else {
- require IkiWiki::Render;
- refresh();
- saveindex();
+ # The trailing question mark tries to avoid broken
+ # caches and get the most recent version of the page.
+ redirect($q, "$config{url}/".htmlpage($page)."?updated");
}
-
- # The trailing question mark tries to avoid broken
- # caches and get the most recent version of the page.
- redirect($q, "$config{url}/".htmlpage($page)."?updated");
}
} #}}}
IkiWiki::cgi_savesession($session);
$oldchoice=$session->param($choice_param);
if ($config{rcs}) {
- # prevent deadlock with post-commit hook
- IkiWiki::unlockwiki();
+ disable_commit_hook();
IkiWiki::rcs_commit($pagesources{$page}, "poll vote ($choice)",
IkiWiki::rcs_prepedit($pagesources{$page}),
$session->param("name"), $ENV{REMOTE_ADDR});
+ enable_commit_hook();
+ rcs_update();
}
- else {
- require IkiWiki::Render;
- IkiWiki::refresh();
- IkiWiki::saveindex();
- }
+ require IkiWiki::Render;
+ IkiWiki::refresh();
+ IkiWiki::saveindex();
+
# Need to set cookie in same http response that does the
# redir.
eval q{use CGI::Cookie};
foreach my $wrapper (@wrappers) {
%config=(%startconfig, verbose => 0, %setup, %{$wrapper});
checkconfig();
+ if (! $config{cgi} && ! $config{post_commit}) {
+ $config{post_commit}=1;
+ }
gen_wrapper();
}
%config=(%startconfig);
* Smarter detection of no-op changes to po files.
* Elegant patch from Ethan to clean up the display of page names in the
dropdown when creating a new page.
-
- -- Joey Hess <joeyh@debian.org> Tue, 20 Feb 2007 19:14:39 -0500
+ * Since the CGI had to drop the wiki lock to avoid deadlocking the
+ commit hook, it was possible for one CGI to race another one and "win"
+ the commit of both their files. This race has been fixed by adding a new
+ commitlock, which when locked by the CGI, disables the commit hook
+ (except for commit mails). The CGI then takes care of the updates the
+ commit hook would have done.
+
+ -- Joey Hess <joeyh@debian.org> Wed, 21 Feb 2007 03:35:52 -0500
ikiwiki (1.43) unstable; urgency=low
require IkiWiki::Render;
commandline_render();
}
+ elsif ($config{post_commit} && ! commit_hook_enabled()) {
+ if ($config{notify}) {
+ loadindex();
+ rcs_notify();
+ }
+ }
else {
lockwiki();
loadindex();
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2007-02-20 19:07-0500\n"
+"POT-Creation-Date: 2007-02-21 03:51-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
msgid "creating %s"
msgstr ""
-#: ../IkiWiki/CGI.pm:483 ../IkiWiki/CGI.pm:511 ../IkiWiki/CGI.pm:544
+#: ../IkiWiki/CGI.pm:483 ../IkiWiki/CGI.pm:511 ../IkiWiki/CGI.pm:556
#, perl-format
msgid "editing %s"
msgstr ""
-#: ../IkiWiki/CGI.pm:652
+#: ../IkiWiki/CGI.pm:653
msgid "You are banned."
msgstr ""
-#: ../IkiWiki/CGI.pm:684
+#: ../IkiWiki/CGI.pm:685
msgid "login failed, perhaps you need to turn on cookies?"
msgstr ""
msgid "generating wrappers.."
msgstr ""
-#: ../IkiWiki/Setup/Standard.pm:68
+#: ../IkiWiki/Setup/Standard.pm:71
msgid "rebuilding wiki.."
msgstr ""
-#: ../IkiWiki/Setup/Standard.pm:71
+#: ../IkiWiki/Setup/Standard.pm:74
msgid "refreshing wiki.."
msgstr ""
-#: ../IkiWiki/Setup/Standard.pm:80
+#: ../IkiWiki/Setup/Standard.pm:83
msgid "done"
msgstr ""
msgid "usage: ikiwiki [options] source dest"
msgstr ""
-#: ../IkiWiki.pm:103
+#: ../IkiWiki.pm:104
msgid "Must specify url to wiki with --url when using --cgi"
msgstr ""
-#: ../IkiWiki.pm:150 ../IkiWiki.pm:151
+#: ../IkiWiki.pm:151 ../IkiWiki.pm:152
msgid "Error"
msgstr ""
#. translators: preprocessor directive name,
#. translators: the second a page name, the
#. translators: third a number.
-#: ../IkiWiki.pm:560
+#: ../IkiWiki.pm:561
#, perl-format
msgid "%s preprocessing loop detected on %s at depth %i"
msgstr ""