]> sipb.mit.edu Git - ikiwiki.git/blobdiff - IkiWiki.pm
web commit by http://joey.kitenet.net/
[ikiwiki.git] / IkiWiki.pm
index b605ac370ba6a84623887bf8e9087358ee40a0d5..2392c787bedc49e7c34d8c654b6e8d1ef0fb7064 100644 (file)
@@ -16,7 +16,9 @@ our @EXPORT = qw(hook debug error template htmlpage add_depends pagespec_match
                  bestlink htmllink readfile writefile pagetype srcfile pagename
                  displaytime will_render gettext
                  %config %links %renderedfiles %pagesources);
-our $VERSION = 1.01; # plugin interface version
+our $VERSION = 1.01; # plugin interface version, next is ikiwiki version
+our $version='unknown'; # VERSION_AUTOREPLACE done by Makefile, DNE
+my $installdir=''; # INSTALLDIR_AUTOREPLACE done by Makefile, DNE
 
 # Optimisation.
 use Memoize;
@@ -24,11 +26,9 @@ memoize("abs2rel");
 memoize("pagespec_translate");
 memoize("file_pruned");
 
-my $installdir=''; # INSTALLDIR_AUTOREPLACE done by Makefile, DNE
-our $version='unknown'; # VERSION_AUTOREPLACE done by Makefile, DNE
-
 sub defaultconfig () { #{{{
-       wiki_file_prune_regexps => [qr/\.\./, qr/^\./, qr/\/\./, qr/\.x?html?$/,
+       wiki_file_prune_regexps => [qr/\.\./, qr/^\./, qr/\/\./,
+               qr/\.x?html?$/, qr/\.ikiwiki-new$/,
                qr/(^|\/).svn\//, qr/.arch-ids\//, qr/{arch}\//],
        wiki_link_regexp => qr/\[\[(?:([^\]\|]+)\|)?([^\s\]]+)\]\]/,
        wiki_file_regexp => qr/(^[-[:alnum:]_.:\/+]+$)/,
@@ -142,14 +142,19 @@ sub loadplugin ($) { #{{{
        }
 } #}}}
 
-sub error ($) { #{{{
+sub error ($;$) { #{{{
+       my $message=shift;
+       my $cleaner=shift;
        if ($config{cgi}) {
                print "Content-type: text/html\n\n";
                print misctemplate(gettext("Error"),
-                       "<p>".gettext("Error").": @_</p>");
+                       "<p>".gettext("Error").": $message</p>");
+       }
+       log_message(debug => $message) if $config{syslog};
+       if (defined $cleaner) {
+               $cleaner->();
        }
-       log_message(error => @_);
-       exit(1);
+       die $message."\n";
 } #}}}
 
 sub debug ($) { #{{{
@@ -169,7 +174,7 @@ sub log_message ($$) { #{{{
                        $log_open=1;
                }
                eval {
-                       Sys::Syslog::syslog($type, join(" ", @_));
+                       Sys::Syslog::syslog($type, "%s", join(" ", @_));
                }
        }
        elsif (! $config{cgi}) {
@@ -246,7 +251,7 @@ sub readfile ($;$$) { #{{{
        binmode(IN) if ($binary);
        return \*IN if $wantfd;
        my $ret=<IN>;
-       close IN;
+       close IN || error("failed to read $file: $!");
        return $ret;
 } #}}}
 
@@ -255,7 +260,7 @@ sub writefile ($$$;$$) { #{{{
        my $destdir=shift; # directory to put file in
        my $content=shift;
        my $binary=shift;
-       my $wantfd=shift;
+       my $writer=shift;
        
        my $test=$file;
        while (length $test) {
@@ -264,8 +269,12 @@ sub writefile ($$$;$$) { #{{{
                }
                $test=dirname($test);
        }
+       my $newfile="$destdir/$file.ikiwiki-new";
+       if (-l $newfile) {
+               error("cannot write to a symlink ($newfile)");
+       }
 
-       my $dir=dirname("$destdir/$file");
+       my $dir=dirname($newfile);
        if (! -d $dir) {
                my $d="";
                foreach my $s (split(m!/+!, $dir)) {
@@ -275,12 +284,19 @@ sub writefile ($$$;$$) { #{{{
                        }
                }
        }
-       
-       open (OUT, ">$destdir/$file") || error("failed to write $destdir/$file: $!");
+
+       my $cleanup = sub { unlink($newfile) };
+       open (OUT, ">$newfile") || error("failed to write $newfile: $!", $cleanup);
        binmode(OUT) if ($binary);
-       return \*OUT if $wantfd;
-       print OUT $content;
-       close OUT;
+       if ($writer) {
+               $writer->(\*OUT, $cleanup);
+       }
+       else {
+               print OUT $content || error("failed writing to $newfile: $!", $cleanup);
+       }
+       close OUT || error("failed saving $newfile: $!", $cleanup);
+       rename($newfile, "$destdir/$file") || 
+               error("failed renaming $newfile to $destdir/$file: $!", $cleanup);
 } #}}}
 
 my %cleared;
@@ -577,7 +593,7 @@ sub lockwiki () { #{{{
                debug("wiki seems to be locked, waiting for lock");
                my $wait=600; # arbitrary, but don't hang forever to 
                              # prevent process pileup
-               for (1..600) {
+               for (1..$wait) {
                        return if flock(WIKILOCK, 2 | 4);
                        sleep 1;
                }
@@ -626,8 +642,9 @@ sub saveindex () { #{{{
        if (! -d $config{wikistatedir}) {
                mkdir($config{wikistatedir});
        }
-       open (OUT, ">$config{wikistatedir}/index") || 
-               error("cannot write to $config{wikistatedir}/index: $!");
+       my $newfile="$config{wikistatedir}/index.new";
+       my $cleanup = sub { unlink($newfile) };
+       open (OUT, ">$newfile") || error("cannot write to $newfile: $!", $cleanup);
        foreach my $page (keys %oldpagemtime) {
                next unless $oldpagemtime{$page};
                my $line="mtime=$oldpagemtime{$page} ".
@@ -639,9 +656,11 @@ sub saveindex () { #{{{
                if (exists $depends{$page}) {
                        $line.=" depends=".encode_entities($depends{$page}, " \t\n");
                }
-               print OUT $line."\n";
+               print OUT $line."\n" || error("failed writing to $newfile: $!", $cleanup);
        }
-       close OUT;
+       close OUT || error("failed saving to $newfile: $!", $cleanup);
+       rename($newfile, "$config{wikistatedir}/index") ||
+               error("failed renaming $newfile to $config{wikistatedir}/index", $cleanup);
 } #}}}
 
 sub template_file ($) { #{{{