prune: do not prune beyond an optional base directory, and add a test
authorSimon McVittie <smcv@debian.org>
Sat, 7 Apr 2012 16:52:29 +0000 (17:52 +0100)
committerSimon McVittie <smcv@debian.org>
Sat, 7 Apr 2012 16:52:29 +0000 (17:52 +0100)
Previously, prune("wiki/srcdir/sandbox/test.mdwn") could delete srcdir
or even wiki, if they happened to be empty. This is rarely what you
want: there's usually some base directory (destdir, srcdir, transientdir
or another subdirectory of wikistatedir) beyond which you do not want to
delete.

IkiWiki/Plugin/aggregate.pm
IkiWiki/Plugin/amazon_s3.pm
IkiWiki/Plugin/attachment.pm
IkiWiki/Plugin/comments.pm
IkiWiki/Plugin/editpage.pm
IkiWiki/Plugin/po.pm
IkiWiki/Plugin/remove.pm
IkiWiki/Plugin/transient.pm
IkiWiki/Render.pm
t/prune.t [new file with mode: 0755]

index 5e22609c9b354a2b2770762a17cd60bcd5c36535..83bd670cb449f017ce9c35b81262af29ccdb6883 100644 (file)
@@ -201,7 +201,7 @@ sub migrate_to_internal {
                if (-e $oldoutput) {
                        require IkiWiki::Render;
                        debug("removing output file $oldoutput");
-                       IkiWiki::prune($oldoutput);
+                       IkiWiki::prune($oldoutput, $config{destdir});
                }
        }
        
index cfd8cd3477f81dd0758564994f35979419e330a0..a9da6bf12b69dc62f2ee05f22aaaef2c88fe7dde 100644 (file)
@@ -232,8 +232,9 @@ sub writefile ($$$;$$) {
 }
 
 # This is a wrapper around the real prune.
-sub prune ($) {
+sub prune ($;$) {
        my $file=shift;
+       my $up_to=shift;
 
        my @keys=IkiWiki::Plugin::amazon_s3::file2keys($file);
 
@@ -250,7 +251,7 @@ sub prune ($) {
                }
        }
 
-       return $IkiWiki::Plugin::amazon_s3::subs{'IkiWiki::prune'}->($file);
+       return $IkiWiki::Plugin::amazon_s3::subs{'IkiWiki::prune'}->($file, $up_to);
 }
 
 1
index 133a54dafd718f15cb763503c7d9b5d80b17d577..aea70429d0bcc3bc86a776ba8b2dde8352483a37 100644 (file)
@@ -286,7 +286,7 @@ sub attachments_save {
        }
        return unless @attachments;
        require IkiWiki::Render;
-       IkiWiki::prune($dir);
+       IkiWiki::prune($dir, $config{wikistatedir}."/attachments");
 
        # Check the attachments in and trigger a wiki refresh.
        if ($config{rcs}) {
index 0d5e3c078a9c229b409950c1e65eb1affa3787ac..4bf8ae4692acb85426f4e87fd4134824c5c708d9 100644 (file)
@@ -665,9 +665,11 @@ sub commentmoderation ($$) {
 
                                my $page=IkiWiki::dirname($f);
                                my $file="$config{srcdir}/$f";
+                               my $filedir="$config{srcdir}";
                                if (! -e $file) {
                                        # old location
                                        $file="$config{wikistatedir}/comments_pending/".$f;
+                                       $filedir="$config{wikistatedir}/comments_pending";
                                }
 
                                if ($action eq 'Accept') {
@@ -682,7 +684,7 @@ sub commentmoderation ($$) {
                                }
 
                                require IkiWiki::Render;
-                               IkiWiki::prune($file);
+                               IkiWiki::prune($file, $filedir);
                        }
                }
 
index 54051c58c2cf836e258c110d0ec4a47d6ff1e0a2..d3c6959354eeebf550d199870cbe7a1c5d1a818c 100644 (file)
@@ -39,7 +39,7 @@ sub refresh () {
                                }
                                if ($delete) {
                                        debug(sprintf(gettext("removing old preview %s"), $file));
-                                       IkiWiki::prune("$config{destdir}/$file");
+                                       IkiWiki::prune("$config{destdir}/$file", $config{destdir});
                                }
                        }
                        elsif (defined $mtime) {
index 26c6463dabf5705eeb870f2b44bfa51e1cafed59..53e6af92f1db14c668f287724aed7b8b12c6f76a 100644 (file)
@@ -1102,7 +1102,7 @@ sub deletetranslations ($) {
                        IkiWiki::rcs_remove($_);
                }
                else {
-                       IkiWiki::prune("$config{srcdir}/$_");
+                       IkiWiki::prune("$config{srcdir}/$_", $config{srcdir});
                }
        } @todelete;
 
index 14ac01c9bcfc390f370f1a8fca74c3b51d7f0baa..3e9f9b82f3326872d3155678570d34785974e1c2 100644 (file)
@@ -124,7 +124,7 @@ sub removal_confirm ($$@) {
                        my $f=IkiWiki::Plugin::attachment::is_held_attachment($page);
                        if (defined $f) {
                                require IkiWiki::Render;
-                               IkiWiki::prune($f);
+                               IkiWiki::prune($f, "$config{wikistatedir}/attachments");
                        }
                }
        }
@@ -235,7 +235,7 @@ sub sessioncgi ($$) {
                        }
                        else {
                                foreach my $file (@files) {
-                                       IkiWiki::prune("$config{srcdir}/$file");
+                                       IkiWiki::prune("$config{srcdir}/$file", $config{srcdir});
                                }
                        }
                        IkiWiki::refresh();
index 4ea4317d4fde56e6eb2652f70fe0c773316d4290..d4eb005ea2485374410396b5323c3db0c6e6b191 100644 (file)
@@ -43,7 +43,7 @@ sub rendered (@) {
                my $casualty = "$transientdir/$file";
                if (srcfile($file) ne $casualty && -e $casualty) {
                        debug(sprintf(gettext("removing transient version of %s"), $file));
-                       IkiWiki::prune($casualty);
+                       IkiWiki::prune($casualty, $transientdir);
                }
        }
 }
index d6c1f4f4c5ec685ff0cfefcb4c6f7db81163e786..a90d202eef0c10fd480b00459c1238f58052b094 100644 (file)
@@ -262,12 +262,13 @@ sub render ($$) {
        }
 }
 
-sub prune ($) {
+sub prune ($;$) {
        my $file=shift;
+       my $up_to=shift;
 
        unlink($file);
        my $dir=dirname($file);
-       while (rmdir($dir)) {
+       while ((! defined $up_to || $dir =~ m{^\Q$up_to\E\/}) && rmdir($dir)) {
                $dir=dirname($dir);
        }
 }
@@ -447,7 +448,7 @@ sub remove_del (@) {
                }
        
                foreach my $old (@{$oldrenderedfiles{$page}}) {
-                       prune($config{destdir}."/".$old);
+                       prune($config{destdir}."/".$old, $config{destdir});
                }
 
                foreach my $source (keys %destsources) {
@@ -537,7 +538,7 @@ sub remove_unrendered () {
                foreach my $file (@{$oldrenderedfiles{$page}}) {
                        if (! grep { $_ eq $file } @{$renderedfiles{$page}}) {
                                debug(sprintf(gettext("removing %s, no longer built by %s"), $file, $page));
-                               prune($config{destdir}."/".$file);
+                               prune($config{destdir}."/".$file, $config{destdir});
                        }
                }
        }
@@ -844,7 +845,7 @@ sub clean_rendered {
        remove_unrendered();
        foreach my $page (keys %oldrenderedfiles) {
                foreach my $file (@{$oldrenderedfiles{$page}}) {
-                       prune($config{destdir}."/".$file);
+                       prune($config{destdir}."/".$file, $config{destdir});
                }
        }
 }
diff --git a/t/prune.t b/t/prune.t
new file mode 100755 (executable)
index 0000000..8c3925e
--- /dev/null
+++ b/t/prune.t
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 6;
+use File::Path qw(make_path remove_tree);
+
+BEGIN { use_ok("IkiWiki"); }
+BEGIN { use_ok("IkiWiki::Render"); }
+
+%config=IkiWiki::defaultconfig();
+
+remove_tree("t/tmp");
+
+make_path("t/tmp/srcdir/a/b/c");
+make_path("t/tmp/srcdir/d/e/f");
+writefile("a/b/c/d.mdwn", "t/tmp/srcdir", "foo");
+writefile("d/e/f/g.mdwn", "t/tmp/srcdir", "foo");
+IkiWiki::prune("t/tmp/srcdir/d/e/f/g.mdwn");
+ok(-d "t/tmp/srcdir");
+ok(! -e "t/tmp/srcdir/d");
+IkiWiki::prune("t/tmp/srcdir/a/b/c/d.mdwn", "t/tmp/srcdir");
+ok(-d "t/tmp/srcdir");
+ok(! -e "t/tmp/srcdir/a");