prune: do not prune beyond an optional base directory, and add a test

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.
master
Simon McVittie 2012-04-07 17:52:29 +01:00
parent f5f41fa59a
commit 5674e7fc12
10 changed files with 42 additions and 15 deletions

View File

@ -201,7 +201,7 @@ sub migrate_to_internal {
if (-e $oldoutput) { if (-e $oldoutput) {
require IkiWiki::Render; require IkiWiki::Render;
debug("removing output file $oldoutput"); debug("removing output file $oldoutput");
IkiWiki::prune($oldoutput); IkiWiki::prune($oldoutput, $config{destdir});
} }
} }

View File

@ -232,8 +232,9 @@ sub writefile ($$$;$$) {
} }
# This is a wrapper around the real prune. # This is a wrapper around the real prune.
sub prune ($) { sub prune ($;$) {
my $file=shift; my $file=shift;
my $up_to=shift;
my @keys=IkiWiki::Plugin::amazon_s3::file2keys($file); 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 1

View File

@ -286,7 +286,7 @@ sub attachments_save {
} }
return unless @attachments; return unless @attachments;
require IkiWiki::Render; require IkiWiki::Render;
IkiWiki::prune($dir); IkiWiki::prune($dir, $config{wikistatedir}."/attachments");
# Check the attachments in and trigger a wiki refresh. # Check the attachments in and trigger a wiki refresh.
if ($config{rcs}) { if ($config{rcs}) {

View File

@ -665,9 +665,11 @@ sub commentmoderation ($$) {
my $page=IkiWiki::dirname($f); my $page=IkiWiki::dirname($f);
my $file="$config{srcdir}/$f"; my $file="$config{srcdir}/$f";
my $filedir="$config{srcdir}";
if (! -e $file) { if (! -e $file) {
# old location # old location
$file="$config{wikistatedir}/comments_pending/".$f; $file="$config{wikistatedir}/comments_pending/".$f;
$filedir="$config{wikistatedir}/comments_pending";
} }
if ($action eq 'Accept') { if ($action eq 'Accept') {
@ -682,7 +684,7 @@ sub commentmoderation ($$) {
} }
require IkiWiki::Render; require IkiWiki::Render;
IkiWiki::prune($file); IkiWiki::prune($file, $filedir);
} }
} }

View File

@ -39,7 +39,7 @@ sub refresh () {
} }
if ($delete) { if ($delete) {
debug(sprintf(gettext("removing old preview %s"), $file)); debug(sprintf(gettext("removing old preview %s"), $file));
IkiWiki::prune("$config{destdir}/$file"); IkiWiki::prune("$config{destdir}/$file", $config{destdir});
} }
} }
elsif (defined $mtime) { elsif (defined $mtime) {

View File

@ -1102,7 +1102,7 @@ sub deletetranslations ($) {
IkiWiki::rcs_remove($_); IkiWiki::rcs_remove($_);
} }
else { else {
IkiWiki::prune("$config{srcdir}/$_"); IkiWiki::prune("$config{srcdir}/$_", $config{srcdir});
} }
} @todelete; } @todelete;

View File

@ -124,7 +124,7 @@ sub removal_confirm ($$@) {
my $f=IkiWiki::Plugin::attachment::is_held_attachment($page); my $f=IkiWiki::Plugin::attachment::is_held_attachment($page);
if (defined $f) { if (defined $f) {
require IkiWiki::Render; require IkiWiki::Render;
IkiWiki::prune($f); IkiWiki::prune($f, "$config{wikistatedir}/attachments");
} }
} }
} }
@ -235,7 +235,7 @@ sub sessioncgi ($$) {
} }
else { else {
foreach my $file (@files) { foreach my $file (@files) {
IkiWiki::prune("$config{srcdir}/$file"); IkiWiki::prune("$config{srcdir}/$file", $config{srcdir});
} }
} }
IkiWiki::refresh(); IkiWiki::refresh();

View File

@ -43,7 +43,7 @@ sub rendered (@) {
my $casualty = "$transientdir/$file"; my $casualty = "$transientdir/$file";
if (srcfile($file) ne $casualty && -e $casualty) { if (srcfile($file) ne $casualty && -e $casualty) {
debug(sprintf(gettext("removing transient version of %s"), $file)); debug(sprintf(gettext("removing transient version of %s"), $file));
IkiWiki::prune($casualty); IkiWiki::prune($casualty, $transientdir);
} }
} }
} }

View File

@ -262,12 +262,13 @@ sub render ($$) {
} }
} }
sub prune ($) { sub prune ($;$) {
my $file=shift; my $file=shift;
my $up_to=shift;
unlink($file); unlink($file);
my $dir=dirname($file); my $dir=dirname($file);
while (rmdir($dir)) { while ((! defined $up_to || $dir =~ m{^\Q$up_to\E\/}) && rmdir($dir)) {
$dir=dirname($dir); $dir=dirname($dir);
} }
} }
@ -447,7 +448,7 @@ sub remove_del (@) {
} }
foreach my $old (@{$oldrenderedfiles{$page}}) { foreach my $old (@{$oldrenderedfiles{$page}}) {
prune($config{destdir}."/".$old); prune($config{destdir}."/".$old, $config{destdir});
} }
foreach my $source (keys %destsources) { foreach my $source (keys %destsources) {
@ -537,7 +538,7 @@ sub remove_unrendered () {
foreach my $file (@{$oldrenderedfiles{$page}}) { foreach my $file (@{$oldrenderedfiles{$page}}) {
if (! grep { $_ eq $file } @{$renderedfiles{$page}}) { if (! grep { $_ eq $file } @{$renderedfiles{$page}}) {
debug(sprintf(gettext("removing %s, no longer built by %s"), $file, $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(); remove_unrendered();
foreach my $page (keys %oldrenderedfiles) { foreach my $page (keys %oldrenderedfiles) {
foreach my $file (@{$oldrenderedfiles{$page}}) { foreach my $file (@{$oldrenderedfiles{$page}}) {
prune($config{destdir}."/".$file); prune($config{destdir}."/".$file, $config{destdir});
} }
} }
} }

23
t/prune.t 100755
View File

@ -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");