summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoey Hess <joey@gnu.kitenet.net>2009-10-05 14:08:46 -0400
committerJoey Hess <joey@gnu.kitenet.net>2009-10-05 14:33:23 -0400
commit666a9613a12e3b3d36cdd1e818c44f1890f05b0d (patch)
treea6647cb17401f3f49feb8e13044c939811ab055c
parent89b65695e778699742bcf93b0ab0304fd53e30ca (diff)
implement links dependencies
Involved some code refactoring so that same code that detects link changes for backlinks updating can be used for link dependency checking. The nice thing is that link dep checking is thus comopletly free!
-rw-r--r--IkiWiki.pm3
-rw-r--r--IkiWiki/Render.pm111
2 files changed, 65 insertions, 49 deletions
diff --git a/IkiWiki.pm b/IkiWiki.pm
index 0bb0c1746..b895e12fc 100644
--- a/IkiWiki.pm
+++ b/IkiWiki.pm
@@ -31,6 +31,7 @@ our $installdir='/usr'; # INSTALLDIR_AUTOREPLACE done by Makefile, DNE
# Page dependency types.
our $DEPEND_CONTENT=1;
our $DEPEND_PRESENCE=2;
+our $DEPEND_LINKS=4;
# Optimisation.
use Memoize;
@@ -1788,6 +1789,8 @@ sub add_depends ($$;@) {
$deptype=$deptype & ~$DEPEND_CONTENT | $DEPEND_PRESENCE
if $params{presence} && $limited;
+ $deptype=$deptype & ~$DEPEND_CONTENT | $DEPEND_LINKS
+ if $params{links} && $limited;
}
if ($simple) {
diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm
index 324ef24fa..4e8aae3bc 100644
--- a/IkiWiki/Render.pm
+++ b/IkiWiki/Render.pm
@@ -58,6 +58,37 @@ sub backlinks ($) {
return @links;
}
+sub find_changed_links (@_) {
+ my %linkchanged;
+ my %linkchangers;
+ foreach my $file (@_) {
+ my $page=pagename($file);
+
+ if (exists $links{$page}) {
+ foreach my $link (map { bestlink($page, $_) } @{$links{$page}}) {
+ if (length $link &&
+ (! exists $oldlinks{$page} ||
+ ! grep { bestlink($page, $_) eq $link } @{$oldlinks{$page}})) {
+ $linkchanged{$link}=1;
+ $linkchangers{lc($page)}=1;
+ }
+ }
+ }
+ if (exists $oldlinks{$page}) {
+ foreach my $link (map { bestlink($page, $_) } @{$oldlinks{$page}}) {
+ if (length $link &&
+ (! exists $links{$page} ||
+ ! grep { bestlink($page, $_) eq $link } @{$links{$page}})) {
+ $linkchanged{$link}=1;
+ $linkchangers{lc($page)}=1;
+ }
+ }
+ }
+ }
+
+ return \%linkchanged, \%linkchangers;
+}
+
sub genpage ($$) {
my $page=shift;
my $content=shift;
@@ -455,10 +486,12 @@ sub refresh () {
}
if (%rendered || @del || @internal || @internal_change) {
- my @changed;
- my $changes;
+ my @changed=(keys %rendered, @del);
+ my ($linkchanged, $linkchangers)=find_changed_links(@changed);
+
+ my $unsettled;
do {
- $changes=0;
+ $unsettled=0;
@changed=(keys %rendered, @del);
my @exists_changed=(@add, @del);
@@ -474,10 +507,14 @@ sub refresh () {
if (exists $depends_simple{$p}) {
foreach my $d (keys %{$depends_simple{$p}}) {
if (($depends_simple{$p}{$d} & $IkiWiki::DEPEND_CONTENT &&
- exists $lc_changed{$d})
+ $lc_changed{$d})
||
($depends_simple{$p}{$d} & $IkiWiki::DEPEND_PRESENCE &&
- exists $lc_exists_changed{$d})) {
+ $lc_exists_changed{$d})
+ ||
+ ($depends_simple{$p}{$d} & $IkiWiki::DEPEND_LINKS &&
+ $linkchangers->{$d})
+ ) {
$reason = $d;
last;
}
@@ -489,29 +526,30 @@ sub refresh () {
my $sub=pagespec_translate($d);
next if $@ || ! defined $sub;
- my @candidates;
- if ($depends{$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{$p}{$d} & $IkiWiki::DEPEND_CONTENT) {
- push @candidates, @internal, @internal_change;
- }
- elsif ($depends{$p}{$d} & $IkiWiki::DEPEND_PRESENCE) {
- push @candidates, @internal;
- }
+ my $internal_dep=$d =~ /internal\(/;
+
+ my @candidates;
+ if ($depends{$p}{$d} & $IkiWiki::DEPEND_PRESENCE) {
+ @candidates=@exists_changed;
+ push @candidates, @internal
+ if $internal_dep;
}
-
+ if (($depends{$p}{$d} & ($IkiWiki::DEPEND_CONTENT | $IkiWiki::DEPEND_LINKS))) {
+ @candidates=@changed;
+ push @candidates, @internal, @internal_change
+ if $internal_dep;
+ }
+
foreach my $file (@candidates) {
next if $file eq $f;
my $page=pagename($file);
if ($sub->($page, location => $p)) {
+ if ($depends{$p}{$d} & $IkiWiki::DEPEND_LINKS) {
+ next unless $linkchangers->{lc($page)};
+ }
$reason = $page;
last D;
}
@@ -523,39 +561,14 @@ sub refresh () {
debug(sprintf(gettext("building %s, which depends on %s"), $f, $reason));
render($f);
$rendered{$f}=1;
- $changes++;
+ $unsettled=1;
last;
}
}
- } while $changes;
+ } while $unsettled;
- # handle backlinks; if a page has added/removed links,
- # update the pages it links to
- my %linkchanged;
- foreach my $file (@changed) {
- my $page=pagename($file);
-
- if (exists $links{$page}) {
- foreach my $link (map { bestlink($page, $_) } @{$links{$page}}) {
- if (length $link &&
- (! exists $oldlinks{$page} ||
- ! grep { bestlink($page, $_) eq $link } @{$oldlinks{$page}})) {
- $linkchanged{$link}=1;
- }
- }
- }
- if (exists $oldlinks{$page}) {
- foreach my $link (map { bestlink($page, $_) } @{$oldlinks{$page}}) {
- if (length $link &&
- (! exists $links{$page} ||
- ! grep { bestlink($page, $_) eq $link } @{$links{$page}})) {
- $linkchanged{$link}=1;
- }
- }
- }
- }
-
- foreach my $link (keys %linkchanged) {
+ # update backlinks at end
+ foreach my $link (keys %{$linkchanged}) {
my $linkfile=$pagesources{$link};
if (defined $linkfile) {
next if $rendered{$linkfile};