X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/f3288100175bfae15a954e39916ef227e5cc9d0a..d3e0a54344a8ca5ac0a30af9f0a41cdb08df06ff:/IkiWiki/Render.pm diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 5cb67ea07..cf0c3fe08 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -8,26 +8,31 @@ use IkiWiki; use Encode; my %backlinks; -my $backlinks_calculated=0; +our %brokenlinks; +my $links_calculated=0; -sub calculate_backlinks () { - return if $backlinks_calculated; - %backlinks=(); +sub calculate_links () { + return if $links_calculated; + %backlinks=%brokenlinks=(); foreach my $page (keys %links) { foreach my $link (@{$links{$page}}) { my $bestlink=bestlink($page, $link); - if (length $bestlink && $bestlink ne $page) { - $backlinks{$bestlink}{$page}=1; + if (length $bestlink) { + $backlinks{$bestlink}{$page}=1 + if $bestlink ne $page; + } + else { + push @{$brokenlinks{$link}}, $page; } } } - $backlinks_calculated=1; + $links_calculated=1; } sub backlink_pages ($) { my $page=shift; - calculate_backlinks(); + calculate_links(); return keys %{$backlinks{$page}}; } @@ -83,11 +88,10 @@ sub genpage ($$) { $actions++; } if ($config{discussion}) { - my $discussionlink=lc(gettext("Discussion")); - if ($page !~ /.*\/\Q$discussionlink\E$/ && + if ($page !~ /.*\/\Q$config{discussionpage}\E$/ && (length $config{cgiurl} || - exists $links{$page."/".$discussionlink})) { - $template->param(discussionlink => htmllink($page, $page, gettext("Discussion"), noimageinline => 1, forcesubpage => 1)); + exists $links{$page."/".$config{discussionpage}})) { + $template->param(discussionlink => htmllink($page, $page, $config{discussionpage}, noimageinline => 1, forcesubpage => 1)); $actions++; } } @@ -153,7 +157,7 @@ sub scan ($) { if ($config{discussion}) { # Discussion links are a special case since they're # not in the text of the page, but on its template. - $links{$page}=[ $page."/".lc(gettext("Discussion")) ]; + $links{$page}=[ $page."/".lc($config{discussionpage}) ]; } else { $links{$page}=[]; @@ -206,6 +210,7 @@ sub render ($) { if (defined $type) { my $page=pagename($file); delete $depends{$page}; + delete $depends_simple{$page}; will_render($page, htmlpage($page), 1); return if $type=~/^_/; @@ -220,6 +225,7 @@ sub render ($) { } else { delete $depends{$file}; + delete $depends_simple{$file}; will_render($file, $file, 1); if ($config{hardlink}) { @@ -336,7 +342,7 @@ sub refresh () { run_hooks(refresh => sub { shift->() }); my ($files, $exists)=find_src_files(); - my (%rendered, @add, @del, @internal); + my (%rendered, @add, @del, @internal, @internal_change); # check for added or removed pages foreach my $file (@$files) { my $page=pagename($file); @@ -379,12 +385,13 @@ sub refresh () { $links{$page}=[]; $renderedfiles{$page}=[]; $pagemtime{$page}=0; - prune($config{destdir}."/".$_) - foreach @{$oldrenderedfiles{$page}}; + foreach my $old (@{$oldrenderedfiles{$page}}) { + prune($config{destdir}."/".$old); + } delete $pagesources{$page}; - foreach (keys %destsources) { - if ($destsources{$_} eq $page) { - delete $destsources{$_}; + foreach my $source (keys %destsources) { + if ($destsources{$source} eq $page) { + delete $destsources{$source}; } } } @@ -400,7 +407,7 @@ sub refresh () { $forcerebuild{$page}) { $pagemtime{$page}=$stat[9]; if (isinternal($page)) { - push @internal, $file; + push @internal_change, $file; # Preprocess internal page in scan-only mode. preprocess($page, $page, readfile($srcfile), 1); } @@ -416,16 +423,17 @@ sub refresh () { debug(sprintf(gettext("scanning %s"), $file)); scan($file); } - calculate_backlinks(); + calculate_links(); foreach my $file (@needsbuild) { debug(sprintf(gettext("building %s"), $file)); render($file); $rendered{$file}=1; } - foreach my $file (@internal) { + foreach my $file (@internal, @internal_change) { # internal pages are not rendered my $page=pagename($file); delete $depends{$page}; + delete $depends_simple{$page}; foreach my $old (@{$renderedfiles{$page}}) { delete $destsources{$old}; } @@ -446,28 +454,80 @@ sub refresh () { } } - if (%rendered || @del || @internal) { - my @changed=(keys %rendered, @del); - - # rebuild dependant pages - foreach my $f (@$files) { - next if $rendered{$f}; - my $p=pagename($f); - if (exists $depends{$p}) { - # only consider internal files - # if the page explicitly depends on such files - foreach my $file (@changed, $depends{$p}=~/internal\(/ ? @internal : ()) { - next if $f eq $file; - my $page=pagename($file); - if (pagespec_match($page, $depends{$p}, location => $p)) { - debug(sprintf(gettext("building %s, which depends on %s"), $f, $page)); - render($f); - $rendered{$f}=1; - last; + if (%rendered || @del || @internal || @internal_change) { + my @changed; + my $changes; + do { + $changes=0; + @changed=(keys %rendered, @del); + my @exists_changed=(@add, @del); + + my %lc_changed = map { lc(pagename($_)) => 1 } @changed; + my %lc_exists_changed = map { lc(pagename($_)) => 1 } @exists_changed; + + # rebuild dependant pages + foreach my $f (@$files) { + next if $rendered{$f}; + my $p=pagename($f); + my $reason = undef; + + if (exists $depends_simple{$p}) { + foreach my $d (keys %{$depends_simple{$p}}) { + if (($depends_simple{$p}{$d} & $IkiWiki::DEPEND_CONTENT && + exists $lc_changed{$d}) + || + ($depends_simple{$p}{$d} & $IkiWiki::DEPEND_PRESENCE && + exists $lc_exists_changed{$d})) { + $reason = $d; + last; + } + } + } + + if (exists $depends{$p} && ! defined $reason) { + D: foreach my $d (keys %{$depends{$p}}) { + my $sub=pagespec_translate($d); + next if $@ || ! defined $sub; + + my @candidates; + if ($depends_simple{$p}{$d} & $IkiWiki::DEPEND_CONTENT) { + @candidates=@changed; + } + elsif ($depends{$p}{$d} & $IkiWiki::DEPEND_PRESENCE) { + @candidates=@exists_changed; + } + # only consider internal files + # if the page explicitly depends + # on such files + if ($d =~ /internal\(/) { + if ($depends_simple{$p}{$d} & $IkiWiki::DEPEND_CONTENT) { + push @candidates, @internal, @internal_change; + } + elsif ($depends{$p}{$d} & $IkiWiki::DEPEND_PRESENCE) { + push @candidates, @internal; + } + } + + foreach my $file (@candidates) { + next if $file eq $f; + my $page=pagename($file); + if ($sub->($page, location => $p)) { + $reason = $page; + last D; + } + } } } + + if (defined $reason) { + debug(sprintf(gettext("building %s, which depends on %s"), $f, $reason)); + render($f); + $rendered{$f}=1; + $changes++; + last; + } } - } + } while $changes; # handle backlinks; if a page has added/removed links, # update the pages it links to