Merge remote branch 'davrieb/autotag' into autotag
[ikiwiki.git] / IkiWiki / Render.pm
index d2fa80fbb8fa5f1678627415548fa474ad11d0b0..796af6af22c4b4c1495010e1a49515d2588ef2c0 100644 (file)
@@ -167,6 +167,7 @@ sub scan ($) {
                else {
                        $links{$page}=[];
                }
+               delete $typedlinks{$page};
 
                run_hooks(scan => sub {
                        shift->(
@@ -284,7 +285,7 @@ sub verify_src_file ($$) {
        my $file=decode_utf8(shift);
        my $dir=shift;
 
-       return if -l $file || -d $file;
+       return if -l $file || -d _;
        $file=~s/^\Q$dir\E\/?//;
        return if ! length $file;
        my $page = pagename($file);
@@ -294,11 +295,11 @@ sub verify_src_file ($$) {
                return;
        }
 
-       my ($f) = $file =~ /$config{wiki_file_regexp}/; # untaint
-       if (! defined $f) {
+       my ($file_untainted) = $file =~ /$config{wiki_file_regexp}/; # untaint
+       if (! defined $file_untainted) {
                warn(sprintf(gettext("skipping bad filename %s"), $file)."\n");
        }
-       return ($file,$page,$f);
+       return ($file_untainted, $page);
 }
 
 sub find_src_files () {
@@ -309,8 +310,8 @@ sub find_src_files () {
        find({
                no_chdir => 1,
                wanted => sub {
-                       my ($file,$page,$f) = verify_src_file($_,$config{srcdir});
-                       if ($file) {
+                       my ($file, $page) = verify_src_file($_, $config{srcdir});
+                       if (defined $file) {
                                push @files, $file;
                                if ($pages{$page}) {
                                        debug(sprintf(gettext("%s has multiple possible source pages"), $page));
@@ -323,14 +324,14 @@ sub find_src_files () {
                find({
                        no_chdir => 1,
                        wanted => sub {
-                               my ($file,$page,$f) = verify_src_file($_,$dir);
-                               if ($f) {
+                               my ($file, $page) = verify_src_file($_, $dir);
+                               if (defined $file) {
                                        # avoid underlaydir override
                                        # attacks; see security.mdwn
-                                       if (! -l "$config{srcdir}/$f" &&
+                                       if (! -l "$config{srcdir}/$file" &&
                                            ! -e _) {
                                                if (! $pages{$page}) {
-                                                       push @files, $f;
+                                                       push @files, $file;
                                                        $pages{$page}=1;
                                                }
                                        }
@@ -346,6 +347,8 @@ sub find_new_files ($) {
        my @new;
        my @internal_new;
 
+       my $times_noted;
+
        foreach my $file (@$files) {
                my $page=pagename($file);
                if (exists $pagesources{$page} && $pagesources{$page} ne $file) {
@@ -357,16 +360,33 @@ sub find_new_files ($) {
                        if (isinternal($page)) {
                                push @internal_new, $file;
                        }
-                       else {
+                       elsif ($config{rcs}) {
+                               if (! $times_noted) {
+                                       debug(sprintf(gettext("querying %s for file creation and modification times.."), $config{rcs}));
+                                       $times_noted=1;
+                               }
+
                                push @new, $file;
-                               if ($config{getctime} && -e "$config{srcdir}/$file") {
+                               if ($config{gettime} && -e "$config{srcdir}/$file") {
                                        eval {
-                                               my $time=rcs_getctime("$config{srcdir}/$file");
-                                               $pagectime{$page}=$time;
+                                               my $ctime=rcs_getctime("$config{srcdir}/$file");
+                                               if ($ctime > 0) {
+                                                       $pagectime{$page}=$ctime;
+                                               }
                                        };
                                        if ($@) {
                                                print STDERR $@;
                                        }
+                                       my $mtime;
+                                       eval {
+                                               $mtime=rcs_getmtime("$config{srcdir}/$file");
+                                       };
+                                       if ($@) {
+                                               print STDERR $@;
+                                       }
+                                       elsif ($mtime > 0) {
+                                               utime($mtime, $mtime, "$config{srcdir}/$file");
+                                       }
                                }
                        }
                        $pagecase{lc $page}=$page;
@@ -392,9 +412,8 @@ sub find_del_files ($) {
                        else {
                                push @del, $pagesources{$page};
                        }
-                       $dellinks{$page}= $links{$page};
                        $links{$page}=[];
-                       $delrenderedfiles{$page}= $renderedfiles{$page};
+                       delete $typedlinks{$page};
                        $renderedfiles{$page}=[];
                        $pagemtime{$page}=0;
                }
@@ -496,6 +515,29 @@ sub remove_unrendered () {
        }
 }
 
+sub link_types_changed ($$) {
+       # each is of the form { type => { link => 1 } }
+       my $new = shift;
+       my $old = shift;
+
+       return 0 if !defined $new && !defined $old;
+       return 1 if !defined $new || !defined $old;
+
+       while (my ($type, $links) = each %$new) {
+               foreach my $link (keys %$links) {
+                       return 1 unless exists $old->{$type}{$link};
+               }
+       }
+
+       while (my ($type, $links) = each %$old) {
+               foreach my $link (keys %$links) {
+                       return 1 unless exists $new->{$type}{$link};
+               }
+       }
+
+       return 0;
+}
+
 sub calculate_changed_links ($$$) {
        my ($changed, $del, $oldlink_targets)=@_;
 
@@ -522,6 +564,14 @@ sub calculate_changed_links ($$$) {
                        }
                        $linkchangers{lc($page)}=1;
                }
+
+               # we currently assume that changing the type of a link doesn't
+               # change backlinks
+               if (!exists $linkchangers{lc($page)}) {
+                       if (link_types_changed($typedlinks{$page}, $oldtypedlinks{$page})) {
+                               $linkchangers{lc($page)}=1;
+                       }
+               }
        }
 
        return \%backlinkchanged, \%linkchangers;
@@ -562,7 +612,7 @@ sub render_dependent ($$$$$$$) {
                if (exists $depends{$p} && ! defined $reason) {
                        foreach my $dep (keys %{$depends{$p}}) {
                                my $sub=pagespec_translate($dep);
-                               next if $@ || ! defined $sub;
+                               next unless defined $sub;
 
                                # only consider internal files
                                # if the page explicitly depends
@@ -639,19 +689,15 @@ sub refresh () {
        my ($changed, $internal_changed)=find_changed($files);
        run_hooks(needsbuild => sub { shift->($changed) });
        my $oldlink_targets=calculate_old_links($changed, $del);
+       %del_hash = map { $_ => 1 } @{$del};
 
        foreach my $file (@$changed) {
                scan($file);
        }
 
-       my %del_hash = map {$_, 1} @$del;
-       while (my $autofile = shift (@autofiles)) {
+       while (my $autofile = shift @{[keys %autofiles]}) {
+               my $plugin=$autofiles{$autofile};
                my $page=pagename($autofile);
-    if (exists $del_hash{$page}) {
-                       $links{$page}= $dellinks{$page};
-                       $renderedfiles{$page}= $delrenderedfiles{$page};
-                       delete $del_hash{$page};
-               }
                if ($pages->{$page}) {
                        debug(sprintf(gettext("%s has multiple possible source pages"), $page));
                }
@@ -662,8 +708,8 @@ sub refresh () {
                push @{$changed}, $autofile if find_changed([$autofile]);
 
                scan($autofile);
+               delete $autofiles{$autofile};
        }
-       $del = [keys %del_hash];
 
        calculate_links();
        
@@ -701,6 +747,17 @@ sub refresh () {
        }
 }
 
+sub clean_rendered {
+       lockwiki();
+       loadindex();
+       remove_unrendered();
+       foreach my $page (keys %oldrenderedfiles) {
+               foreach my $file (@{$oldrenderedfiles{$page}}) {
+                       prune($config{destdir}."/".$file);
+               }
+       }
+}
+
 sub commandline_render () {
        lockwiki();
        loadindex();