+
+ if (defined $reason) {
+ render($f, sprintf(gettext("building %s, which depends on %s"), $f, $reason));
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+sub render_backlinks ($) {
+ my $backlinkchanged=shift;
+ foreach my $link (keys %$backlinkchanged) {
+ my $linkfile=$pagesources{$link};
+ if (defined $linkfile) {
+ render($linkfile, sprintf(gettext("building %s, to update its backlinks"), $linkfile));
+ }
+ }
+}
+
+sub gen_autofile ($$$) {
+ my $autofile=shift;
+ my $pages=shift;
+ my $del=shift;
+
+ if (file_pruned($autofile)) {
+ return;
+ }
+
+ my ($file)="$config{srcdir}/$autofile" =~ /$config{wiki_file_regexp}/; # untaint
+ if (! defined $file) {
+ return;
+ }
+
+ # Remember autofiles that were tried, and never try them again later.
+ if (exists $wikistate{$autofiles{$autofile}{plugin}}{autofile}{$autofile}) {
+ return;
+ }
+ $wikistate{$autofiles{$autofile}{plugin}}{autofile}{$autofile}=1;
+
+ if (srcfile($autofile, 1) || file_pruned($autofile)) {
+ return;
+ }
+
+ if (-l $file || -d _ || -e _) {
+ return;
+ }
+
+ my $page = pagename($file);
+ if ($pages->{$page}) {
+ return;
+ }
+
+ if (grep { $_ eq $autofile } @$del) {
+ return;
+ }
+
+ $autofiles{$autofile}{generator}->();
+ $pages->{$page}=1;
+ return 1;
+}
+
+
+sub refresh () {
+ srcdir_check();
+ run_hooks(refresh => sub { shift->() });
+ my ($files, $pages)=find_src_files();
+ my ($new, $internal_new)=find_new_files($files);
+ my ($del, $internal_del)=find_del_files($pages);
+ my ($changed, $internal_changed)=find_changed($files);
+ run_hooks(needsbuild => sub { shift->($changed) });
+ my $oldlink_targets=calculate_old_links($changed, $del);
+
+ foreach my $file (@$changed) {
+ scan($file);
+ }
+
+ foreach my $autofile (keys %autofiles) {
+ if (gen_autofile($autofile, $pages, $del)) {
+ push @{$files}, $autofile;
+ push @{$new}, $autofile if find_new_files([$autofile]);
+ push @{$changed}, $autofile if find_changed([$autofile]);
+
+ scan($autofile);
+ }
+ }
+
+ calculate_links();
+
+ remove_del(@$del, @$internal_del);
+
+ foreach my $file (@$changed) {
+ render($file, sprintf(gettext("building %s"), $file));
+ }
+ foreach my $file (@$internal_new, @$internal_del, @$internal_changed) {
+ derender_internal($file);
+ }
+
+ my ($backlinkchanged, $linkchangers)=calculate_changed_links($changed,
+ $del, $oldlink_targets);
+
+ foreach my $file (@$new, @$del) {
+ render_linkers($file);
+ }
+
+ if (@$changed || @$internal_changed ||
+ @$del || @$internal_del || @$internal_new) {
+ 1 while render_dependent($files, $new, $internal_new,
+ $del, $internal_del, $internal_changed,
+ $linkchangers);
+ }
+
+ render_backlinks($backlinkchanged);
+ remove_unrendered();
+
+ if (@$del) {
+ run_hooks(delete => sub { shift->(@$del) });
+ }
+ if (%rendered) {
+ run_hooks(change => sub { shift->(keys %rendered) });
+ }
+}
+
+sub clean_rendered {
+ lockwiki();
+ loadindex();
+ remove_unrendered();
+ foreach my $page (keys %oldrenderedfiles) {
+ foreach my $file (@{$oldrenderedfiles{$page}}) {
+ prune($config{destdir}."/".$file);