+}
+
+sub rename_hook {
+ my %params = @_;
+
+ my @torename=@{$params{torename}};
+ my %done=%{$params{done}};
+ my $q=$params{cgi};
+ my $session=$params{session};
+
+ return () unless @torename;
+
+ my @nextset;
+ foreach my $torename (@torename) {
+ unless (exists $done{$torename->{src}} && $done{$torename->{src}}) {
+ IkiWiki::run_hooks(rename => sub {
+ push @nextset, shift->(
+ torename => $torename,
+ cgi => $q,
+ session => $session,
+ );
+ });
+ $done{$torename->{src}}=1;
+ }
+ }
+
+ push @torename, rename_hook(
+ torename => \@nextset,
+ done => \%done,
+ cgi => $q,
+ session => $session,
+ );
+
+ # dedup
+ my %seen;
+ return grep { ! $seen{$_->{src}}++ } @torename;
+}
+
+sub do_rename ($$$) {
+ my $rename=shift;
+ my $q=shift;
+ my $session=shift;
+
+ # First, check if this rename is allowed.
+ check_canrename($rename->{src},
+ $rename->{srcfile},
+ $rename->{dest},
+ $rename->{destfile},
+ $q, $session);
+
+ # Ensure that the dest directory exists and is ok.
+ IkiWiki::prep_writefile($rename->{destfile}, $config{srcdir});
+
+ if ($config{rcs}) {
+ IkiWiki::rcs_rename($rename->{srcfile}, $rename->{destfile});
+ }
+ else {
+ if (! rename($config{srcdir}."/".$rename->{srcfile},
+ $config{srcdir}."/".$rename->{destfile})) {
+ error("rename: $!");
+ }
+ }
+
+}
+
+sub fixlinks ($$$) {
+ my $rename=shift;
+ my $session=shift;
+
+ my @fixedlinks;
+
+ foreach my $page (keys %links) {
+ my $needfix=0;
+ foreach my $link (@{$links{$page}}) {
+ my $bestlink=bestlink($page, $link);
+ if ($bestlink eq $rename->{src}) {
+ $needfix=1;
+ last;
+ }
+ }
+ if ($needfix) {
+ my $file=$pagesources{$page};
+ my $oldcontent=readfile($config{srcdir}."/".$file);
+ my $content=renamepage_hook($page, $rename->{src}, $rename->{dest}, $oldcontent);
+ if ($oldcontent ne $content) {
+ my $token=IkiWiki::rcs_prepedit($file);
+ eval { writefile($file, $config{srcdir}, $content) };
+ next if $@;
+ my $conflict=IkiWiki::rcs_commit(
+ $file,
+ sprintf(gettext("update for rename of %s to %s"), $rename->{srcfile}, $rename->{destfile}),
+ $token,
+ $session->param("name"),
+ $ENV{REMOTE_ADDR}
+ );
+ push @fixedlinks, $page if ! defined $conflict;
+ }
+ }
+ }
+
+ return @fixedlinks;
+}