diff options
30 files changed, 349 insertions, 138 deletions
diff --git a/IkiWiki.pm b/IkiWiki.pm index 97d84c9de..b895e12fc 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -28,6 +28,11 @@ our $VERSION = 3.00; # plugin interface version, next is ikiwiki version our $version='unknown'; # VERSION_AUTOREPLACE done by Makefile, DNE 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; memoize("abs2rel"); @@ -1524,18 +1529,28 @@ sub loadindex () { $links{$page}=$d->{links}; $oldlinks{$page}=[@{$d->{links}}]; } - if (exists $d->{depends_simple}) { + if (ref $d->{depends_simple} eq 'ARRAY') { + # old format $depends_simple{$page}={ map { $_ => 1 } @{$d->{depends_simple}} }; } + elsif (exists $d->{depends_simple}) { + $depends{$page}=$d->{depends_simple}; + } if (exists $d->{dependslist}) { + # old format $depends{$page}={ - map { $_ => 1 } @{$d->{dependslist}} + map { $_ => $DEPEND_CONTENT } + @{$d->{dependslist}} }; } + elsif (exists $d->{depends} && ! ref $d->{depends}) { + # old format + $depends{$page}={$d->{depends} => $DEPEND_CONTENT }; + } elsif (exists $d->{depends}) { - $depends{$page}={$d->{depends} => 1}; + $depends{$page}=$d->{depends}; } if (exists $d->{state}) { $pagestate{$page}=$d->{state}; @@ -1581,11 +1596,11 @@ sub saveindex () { }; if (exists $depends{$page}) { - $index{page}{$src}{dependslist} = [ keys %{$depends{$page}} ]; + $index{page}{$src}{depends} = $depends{$page}; } if (exists $depends_simple{$page}) { - $index{page}{$src}{depends_simple} = [ keys %{$depends_simple{$page}} ]; + $index{page}{$src}{depends_simple} = $depends_simple{$page}; } if (exists $pagestate{$page}) { @@ -1753,20 +1768,39 @@ sub rcs_receive () { $hooks{rcs}{rcs_receive}{call}->(); } -sub add_depends ($$) { +sub add_depends ($$;@) { my $page=shift; my $pagespec=shift; - if ($pagespec =~ /$config{wiki_file_regexp}/ && - $pagespec !~ /[\s*?()!]/) { - # a simple dependency, which can be matched by string eq - $depends_simple{$page}{lc $pagespec} = 1; + # Is the pagespec a simple page name? + my $simple=$pagespec =~ /$config{wiki_file_regexp}/ && + $pagespec !~ /[\s*?()!]/; + + my $deptype=$DEPEND_CONTENT; + if (@_) { + my %params=@_; + + # Is the pagespec limited to terms that will continue + # to match pages as long as those pages exist? + my $limited=1; + while ($limited && $pagespec=~m/(\w+)\([^\)]*\)/g) { + $limited = $1 =~ /^(glob|internal|creation_month|creation_day|creation_year|created_before|created_after)$/; + } + + $deptype=$deptype & ~$DEPEND_CONTENT | $DEPEND_PRESENCE + if $params{presence} && $limited; + $deptype=$deptype & ~$DEPEND_CONTENT | $DEPEND_LINKS + if $params{links} && $limited; + } + + if ($simple) { + $depends_simple{$page}{lc $pagespec} |= $deptype; return 1; } return unless pagespec_valid($pagespec); - $depends{$page}{$pagespec} = 1; + $depends{$page}{$pagespec} |= $deptype; return 1; } diff --git a/IkiWiki/Plugin/brokenlinks.pm b/IkiWiki/Plugin/brokenlinks.pm index eb698b0be..9e65f52c6 100644 --- a/IkiWiki/Plugin/brokenlinks.pm +++ b/IkiWiki/Plugin/brokenlinks.pm @@ -23,9 +23,8 @@ sub preprocess (@) { my %params=@_; $params{pages}="*" unless defined $params{pages}; - # Needs to update whenever a page is added or removed, so - # register a dependency. - add_depends($params{page}, $params{pages}); + # Needs to update whenever the links on a page change. + add_depends($params{page}, $params{pages}, links => 1); my @broken; foreach my $link (keys %IkiWiki::brokenlinks) { diff --git a/IkiWiki/Plugin/calendar.pm b/IkiWiki/Plugin/calendar.pm index 5d16dff75..a1117992a 100644 --- a/IkiWiki/Plugin/calendar.pm +++ b/IkiWiki/Plugin/calendar.pm @@ -104,19 +104,22 @@ sub format_month (@) { "$archivebase/$year/".sprintf("%02d", $month), linktext => " $monthname "); } - add_depends($params{page}, "$archivebase/$year/".sprintf("%02d", $month)); + add_depends($params{page}, "$archivebase/$year/".sprintf("%02d", $month), + presence => 1); if (exists $cache{$pagespec}{"$pyear/$pmonth"}) { $purl = htmllink($params{page}, $params{destpage}, "$archivebase/$pyear/" . sprintf("%02d", $pmonth), linktext => " $pmonthname "); } - add_depends($params{page}, "$archivebase/$pyear/".sprintf("%02d", $pmonth)); + add_depends($params{page}, "$archivebase/$pyear/".sprintf("%02d", $pmonth), + presence => 1); if (exists $cache{$pagespec}{"$nyear/$nmonth"}) { $nurl = htmllink($params{page}, $params{destpage}, "$archivebase/$nyear/" . sprintf("%02d", $nmonth), linktext => " $nmonthname "); } - add_depends($params{page}, "$archivebase/$nyear/".sprintf("%02d", $nmonth)); + add_depends($params{page}, "$archivebase/$nyear/".sprintf("%02d", $nmonth), + presence => 1); # Start producing the month calendar $calendar=<<EOF; @@ -209,11 +212,11 @@ EOF # Add dependencies to update the calendar whenever pages # matching the pagespec are added or removed. - add_depends($params{page}, $params{pages}); + add_depends($params{page}, $params{pages}, presence => 1); # Explicitly add all currently linked pages as dependencies, so # that if they are removed, the calendar will be sure to be updated. foreach my $p (@list) { - add_depends($params{page}, $p); + add_depends($params{page}, $p, presence => 1); } return $calendar; @@ -246,19 +249,19 @@ sub format_year (@) { "$archivebase/$year", linktext => "$year"); } - add_depends($params{page}, "$archivebase/$year"); + add_depends($params{page}, "$archivebase/$year", presence => 1); if (exists $cache{$pagespec}{"$pyear"}) { $purl = htmllink($params{page}, $params{destpage}, "$archivebase/$pyear", linktext => "\←"); } - add_depends($params{page}, "$archivebase/$pyear"); + add_depends($params{page}, "$archivebase/$pyear", presence => 1); if (exists $cache{$pagespec}{"$nyear"}) { $nurl = htmllink($params{page}, $params{destpage}, "$archivebase/$nyear", linktext => "\→"); } - add_depends($params{page}, "$archivebase/$nyear"); + add_depends($params{page}, "$archivebase/$nyear", presence => 1); # Start producing the year calendar $calendar=<<EOF; @@ -310,7 +313,7 @@ EOF else { $calendar.=qq{\t<td class="$tag">$monthabbr</td>\n}; } - add_depends($params{page}, "$archivebase/$year/$mtag"); + add_depends($params{page}, "$archivebase/$year/$mtag", presence => 1); $calendar.=qq{\t</tr>\n} if ($month % $params{months_per_row} == 0); } diff --git a/IkiWiki/Plugin/edittemplate.pm b/IkiWiki/Plugin/edittemplate.pm index 0bafc95d0..2dd1dbe68 100644 --- a/IkiWiki/Plugin/edittemplate.pm +++ b/IkiWiki/Plugin/edittemplate.pm @@ -58,7 +58,7 @@ sub preprocess (@) { $pagestate{$params{page}}{edittemplate}{$params{match}}=$link; return "" if ($params{silent} && IkiWiki::yesno($params{silent})); - add_depends($params{page}, $link); + add_depends($params{page}, $link, presence => 1); return sprintf(gettext("edittemplate %s registered for %s"), htmllink($params{page}, $params{destpage}, $link), $params{match}); diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm index ccfadfd69..cebd9037c 100644 --- a/IkiWiki/Plugin/inline.pm +++ b/IkiWiki/Plugin/inline.pm @@ -197,7 +197,7 @@ sub preprocess_inline (@) { split ' ', $params{pagenames}; } else { - add_depends($params{page}, $params{pages}); + add_depends($params{page}, $params{pages}, presence => $quick); @list = pagespec_match_list( [ grep { $_ ne $params{page} } keys %pagesources ], @@ -248,10 +248,9 @@ sub preprocess_inline (@) { } # Explicitly add all currently displayed pages as dependencies, so - # that if they are removed or otherwise changed, the inline will be - # sure to be updated. + # that if they are removed, the inline will be sure to be updated. foreach my $p ($#list >= $#feedlist ? @list : @feedlist) { - add_depends($params{page}, $p); + add_depends($params{page}, $p, presence => $quick); } if ($feeds && exists $params{feedpages}) { diff --git a/IkiWiki/Plugin/linkmap.pm b/IkiWiki/Plugin/linkmap.pm index 941ed5f36..d0671ae0e 100644 --- a/IkiWiki/Plugin/linkmap.pm +++ b/IkiWiki/Plugin/linkmap.pm @@ -28,8 +28,8 @@ sub preprocess (@) { $params{pages}="*" unless defined $params{pages}; - # Needs to update whenever a page is added or removed, so - # register a dependency. + # Needs to update whenever a page is added, removed, or + # its links change, so register a dependency. add_depends($params{page}, $params{pages}); # Can't just return the linkmap here, since the htmlscrubber diff --git a/IkiWiki/Plugin/listdirectives.pm b/IkiWiki/Plugin/listdirectives.pm index bd73f1a04..4023ed7d7 100644 --- a/IkiWiki/Plugin/listdirectives.pm +++ b/IkiWiki/Plugin/listdirectives.pm @@ -84,7 +84,7 @@ sub preprocess (@) { foreach my $plugin (@pluginlist) { $result .= '<li class="listdirectives">'; my $link=linkpage($config{directive_description_dir}."/".$plugin); - add_depends($params{page}, $link); + add_depends($params{page}, $link, presence => 1); $result .= htmllink($params{page}, $params{destpage}, $link); $result .= '</li>'; } diff --git a/IkiWiki/Plugin/map.pm b/IkiWiki/Plugin/map.pm index 54146dc46..625cfdfca 100644 --- a/IkiWiki/Plugin/map.pm +++ b/IkiWiki/Plugin/map.pm @@ -68,13 +68,13 @@ sub preprocess (@) { } # Needs to update whenever a page is added or removed (or in some - # cases, when its content changes, if show=title), so register a - # dependency. - add_depends($params{page}, $params{pages}); + # cases, when its content changes, if show= is specified), so + # register a dependency. + add_depends($params{page}, $params{pages}, presence => ! exists $params{show}); # Explicitly add all currently shown pages, to detect when pages # are removed. foreach my $item (keys %mapitems) { - add_depends($params{page}, $item); + add_depends($params{page}, $item, presence => ! exists $params{show}); } # Create the map. diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index 514b09369..9b041a748 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -195,7 +195,7 @@ sub preprocess (@) { if (! length $link) { error gettext("redir page not found") } - add_depends($page, $link); + add_depends($page, $link, presence => 1); $value=urlto($link, $page); $value.='#'.$redir_anchor if defined $redir_anchor; diff --git a/IkiWiki/Plugin/orphans.pm b/IkiWiki/Plugin/orphans.pm index 711226772..ae330b23b 100644 --- a/IkiWiki/Plugin/orphans.pm +++ b/IkiWiki/Plugin/orphans.pm @@ -23,9 +23,13 @@ sub preprocess (@) { my %params=@_; $params{pages}="*" unless defined $params{pages}; - # Needs to update whenever a page is added or removed, so - # register a dependency. - add_depends($params{page}, $params{pages}); + # Needs to update whenever a link changes, on any page + # since any page could link to one of the pages we're + # considering as orphans. + add_depends($params{page}, "*", links => 1); + # Also needs to update whenever potential orphans are added or + # removed. + add_depends($params{page}, $params{pages}, presence => 1); my @orphans; foreach my $page (pagespec_match_list( diff --git a/IkiWiki/Plugin/pagecount.pm b/IkiWiki/Plugin/pagecount.pm index 5a2301af4..80561350b 100644 --- a/IkiWiki/Plugin/pagecount.pm +++ b/IkiWiki/Plugin/pagecount.pm @@ -23,8 +23,8 @@ sub preprocess (@) { $params{pages}="*" unless defined $params{pages}; # Needs to update count whenever a page is added or removed, so - # register a dependency. - add_depends($params{page}, $params{pages}); + # register a presence dependency. + add_depends($params{page}, $params{pages}, presence => 1); my @pages; if ($params{pages} eq "*") { diff --git a/IkiWiki/Plugin/pagestats.pm b/IkiWiki/Plugin/pagestats.pm index 874ead7e6..0765c1cfa 100644 --- a/IkiWiki/Plugin/pagestats.pm +++ b/IkiWiki/Plugin/pagestats.pm @@ -35,10 +35,13 @@ sub preprocess (@) { $params{pages}="*" unless defined $params{pages}; my $style = ($params{style} or 'cloud'); - # Needs to update whenever a page is added or removed, so - # register a dependency. - add_depends($params{page}, $params{pages}); - add_depends($params{page}, $params{among}) if exists $params{among}; + # Needs to update whenever a page is added or removed. + add_depends($params{page}, $params{pages}, exists => 1); + # Also needs to update when any page with links changes, + # in case the links point to our displayed pages. + # (Among limits this further.) + add_depends($params{page}, exists $params{among} ? $params{among} : "*", + links => 1); my %counts; my $max = 0; diff --git a/IkiWiki/Plugin/postsparkline.pm b/IkiWiki/Plugin/postsparkline.pm index d2e5c2378..3205958d4 100644 --- a/IkiWiki/Plugin/postsparkline.pm +++ b/IkiWiki/Plugin/postsparkline.pm @@ -48,7 +48,7 @@ sub preprocess (@) { error gettext("unknown formula"); } - add_depends($params{page}, $params{pages}); + add_depends($params{page}, $params{pages}, presence => 1); my @list=sort { $params{timehash}->{$b} <=> $params{timehash}->{$a} } pagespec_match_list( diff --git a/IkiWiki/Plugin/progress.pm b/IkiWiki/Plugin/progress.pm index 76d994acc..26c537a84 100644 --- a/IkiWiki/Plugin/progress.pm +++ b/IkiWiki/Plugin/progress.pm @@ -36,8 +36,8 @@ sub preprocess (@) { $fill.="%"; } elsif (defined $params{totalpages} and defined $params{donepages}) { - add_depends($params{page}, $params{totalpages}); - add_depends($params{page}, $params{donepages}); + add_depends($params{page}, $params{totalpages}, presence => 1); + add_depends($params{page}, $params{donepages}, presence => 1); my @pages=keys %pagesources; my $totalcount=0; diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 246c2260d..599bb26e2 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -58,6 +58,52 @@ 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 $l (@{$links{$page}}) { + my $link=bestlink($page, $l); + if (length $link) { + if (! exists $oldlinks{$page} || + ! grep { bestlink($page, $_) eq $link } @{$oldlinks{$page}}) { + $linkchanged{$link}=1; + $linkchangers{lc($page)}=1; + } + } + else { + if (! grep { lc $_ eq lc $l } @{$oldlinks{$page}}) { + $linkchangers{lc($page)}=1 + } + } + + } + } + if (exists $oldlinks{$page}) { + foreach my $l (@{$oldlinks{$page}}) { + my $link=bestlink($page, $l); + if (length $link) { + if (! exists $links{$page} || + ! grep { bestlink($page, $_) eq $link } @{$links{$page}}) { + $linkchanged{$link}=1; + $linkchangers{lc($page)}=1; + } + } + else { + if (! grep { lc $_ eq lc $l } @{$links{$page}}) { + $linkchangers{lc($page)}=1 + } + } + } + } + } + + return \%linkchanged, \%linkchangers; +} + sub genpage ($$) { my $page=shift; my $content=shift; @@ -342,7 +388,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); @@ -407,7 +453,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); } @@ -429,7 +475,7 @@ sub refresh () { 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}; @@ -454,79 +500,90 @@ sub refresh () { } } - if (%rendered || @del || @internal) { + if (%rendered || @del || @internal || @internal_change) { my @changed=(keys %rendered, @del); + my ($linkchanged, $linkchangers)=find_changed_links(@changed); - my %lcchanged = map { lc(pagename($_)) => 1 } @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 (exists $lcchanged{$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; - - # only consider internal files - # if the page explicitly depends - # on such files - foreach my $file (@changed, $d =~ /internal\(/ ? @internal : ()) { - next if $file eq $f; - my $page=pagename($file); - if ($sub->($page, location => $p)) { - $reason = $page; - last D; + my $unsettled; + do { + $unsettled=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 && + $lc_changed{$d}) + || + ($depends_simple{$p}{$d} & $IkiWiki::DEPEND_PRESENCE && + $lc_exists_changed{$d}) + || + ($depends_simple{$p}{$d} & $IkiWiki::DEPEND_LINKS && + $linkchangers->{$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; + + # only consider internal files + # if the page explicitly depends + # on such files + 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; + } - if (defined $reason) { - debug(sprintf(gettext("building %s, which depends on %s"), $f, $reason)); - render($f); - $rendered{$f}=1; - } - } - - # 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; + 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; + } + } } } - } - 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; - } + + if (defined $reason) { + debug(sprintf(gettext("building %s, which depends on %s"), $f, $reason)); + render($f); + $rendered{$f}=1; + $unsettled=1; + last; } } - } - - foreach my $link (keys %linkchanged) { + } while $unsettled; + + # update backlinks at end + foreach my $link (keys %{$linkchanged}) { my $linkfile=$pagesources{$link}; if (defined $linkfile) { next if $rendered{$linkfile}; diff --git a/debian/NEWS b/debian/NEWS index 808105fd5..520f38815 100644 --- a/debian/NEWS +++ b/debian/NEWS @@ -1,3 +1,13 @@ +ikiwiki (3.14159266) UNRELEASED; urgency=low + + To take advantage of significant performance improvements, all + wikis need to be rebuilt on upgrade to this version. If you + listed your wiki in /etc/ikiwiki/wikilist this will be done + automatically when the Debian package is upgraded. Or use + ikiwiki-mass-rebuild to force a rebuild. + + -- Joey Hess <joeyh@debian.org> Mon, 05 Oct 2009 16:48:59 -0400 + ikiwiki (3.1415926) unstable; urgency=low In order to fix a performance bug, all wikis need to be rebuilt on diff --git a/debian/changelog b/debian/changelog index ca5409af7..89d377769 100644 --- a/debian/changelog +++ b/debian/changelog @@ -10,6 +10,25 @@ ikiwiki (3.14159266) UNRELEASED; urgency=low * mirrorlist: Display nothing if list is empty. * Fix a bug that could lead to duplicate links being recorded for tags. + * Added support framework for multiple types of dependencies. + * Allow declaring that a dependency is only affected by page presence + or changes to its links. + (By passing presence => 1 or links => 1 to add_depends.) + * pagecount, calendar, postsparkline, progress: Use a presence dependency, + which makes these directives much less expensive to use, since page + edits will no longer trigger an unnecessary update. + * map: Use a presence dependency unless show= is specified. + This makes maps efficient enough that they can be used on sidebars! + * inline: Use a presence dependency in quick mode. + * brokenlinks: Use a link dependency. + This makes it much more efficient, only updating when really necessary. + * orphans, pagestats: Use a combination of presence and link dependencies. + This makes them more efficient. It also fixes a longstanding bug, + where if only a small set of pages were considered by orphans/pagestats, + changes to links on other pages failed to cause an update. + * Transitive dependencies are now correctly supported. + * Rebuild wikis on upgrade to this version to get improved dependency + info. -- Joey Hess <joeyh@debian.org> Sun, 27 Sep 2009 17:40:03 -0400 diff --git a/debian/postinst b/debian/postinst index 2ba26e5b6..dd4be6e0e 100755 --- a/debian/postinst +++ b/debian/postinst @@ -4,7 +4,7 @@ set -e # Change this when some incompatible change is made that requires # rebuilding all wikis. -firstcompat=3.1415926 +firstcompat=3.14159266 if [ "$1" = configure ] && \ dpkg --compare-versions "$2" lt "$firstcompat"; then diff --git a/doc/bugs/bestlink_change_update_issue.mdwn b/doc/bugs/bestlink_change_update_issue.mdwn index 5ce4a93d2..fee65c0de 100644 --- a/doc/bugs/bestlink_change_update_issue.mdwn +++ b/doc/bugs/bestlink_change_update_issue.mdwn @@ -11,3 +11,6 @@ calculation in refresh(), which doesn't detect that the link has changed in this case. Still true in 1.43 although the code is much different now.. + +> Still true as of 031d1bf5046ab77c796477a19967e7c0c512c417, +> and now this same problem also affects link dependencies. diff --git a/doc/bugs/transitive_dependencies.mdwn b/doc/bugs/transitive_dependencies.mdwn index 9586bc9b0..0a2e9ec28 100644 --- a/doc/bugs/transitive_dependencies.mdwn +++ b/doc/bugs/transitive_dependencies.mdwn @@ -65,4 +65,4 @@ Downsides here: modification to plugins/brokenlinks causes an unnecessary update of plugins, and could be solved by adding more dependency types.) ---[[Joey]] +[[done]] --[[Joey]] diff --git a/doc/ikiwiki/directive/inline.mdwn b/doc/ikiwiki/directive/inline.mdwn index 99f795972..4e087ab6c 100644 --- a/doc/ikiwiki/directive/inline.mdwn +++ b/doc/ikiwiki/directive/inline.mdwn @@ -98,7 +98,7 @@ Here are some less often needed parameters: * `feedonly` - Only generate the feed, do not display the pages inline on the page. * `quick` - Build archives in quick mode, without reading page contents for - metadata. By default, this also turns off generation of any feeds. + metadata. This also turns off generation of any feeds. * `timeformat` - Use this to specify how to display the time or date for pages in the blog. The format string is passed to the strftime(3) function. * `feedpages` - A [[PageSpec]] of inlined pages to include in the rss/atom diff --git a/doc/ikiwiki/directive/pagestats.mdwn b/doc/ikiwiki/directive/pagestats.mdwn index 66f851dbd..f14c80b07 100644 --- a/doc/ikiwiki/directive/pagestats.mdwn +++ b/doc/ikiwiki/directive/pagestats.mdwn @@ -12,13 +12,13 @@ And here's how to create a table of all the pages on the wiki: \[[!pagestats style="table"]] -The optional `among` parameter limits display to pages that match a -[[ikiwiki/PageSpec]]. For instance, to display a cloud of tags used on blog -entries, you could use: +The optional `among` parameter limits the pages whose outgoing links are +considered. For instance, to display a cloud of tags used on blog +entries, while ignoring other pages that use those tags, you could use: \[[!pagestats pages="tags/*" among="blog/posts/*"]] -or to display a cloud of tags related to Linux, you could use: +Or to display a cloud of tags related to Linux, you could use: \[[!pagestats pages="tags/* and not tags/linux" among="tagged(linux)"]] diff --git a/doc/plugins.mdwn b/doc/plugins.mdwn index 527568208..697b4a219 100644 --- a/doc/plugins.mdwn +++ b/doc/plugins.mdwn @@ -1,7 +1,7 @@ Most of ikiwiki's [[features]] are implemented as plugins. Many of these plugins are included with ikiwiki. -[[!pagestats pages="plugins/type/* and !plugins/type/slow"]] +[[!pagestats pages="plugins/type/* and !plugins/type/slow" among="plugins/*"]] There's documentation if you want to [[write]] your own plugins, or you can [[install]] plugins [[contributed|contrib]] by others. @@ -13,7 +13,5 @@ will fit most uses of ikiwiki. ## Plugin directory -[[!inline pages="plugins/* and !plugins/type/* and !plugins/write and -!plugins/write/* and !plugins/contrib and !plugins/install and !*/Discussion" -feedpages="created_after(plugins/graphviz)" archive="yes" sort=title -rootpage="plugins/contrib" postformtext="Add a new plugin named:" show=0]] +[[!map pages="plugins/* and !plugins/type/* and !plugins/write and +!plugins/write/* and !plugins/contrib and !plugins/install and !*/Discussion"]] diff --git a/doc/plugins/contrib.mdwn b/doc/plugins/contrib.mdwn index a03e6a95d..ac6c1b751 100644 --- a/doc/plugins/contrib.mdwn +++ b/doc/plugins/contrib.mdwn @@ -1,6 +1,4 @@ These plugins are provided by third parties and are not currently included in ikiwiki. See [[install]] for installation help. -[[!inline pages="plugins/contrib/* and !*/Discussion" -feedpages="created_after(plugins/contrib/navbar)" archive="yes" -rootpage="plugins/contrib" postformtext="Add a new plugin named:" show=0]] +[[!map pages="plugins/contrib/* and !*/Discussion"]] diff --git a/doc/plugins/orphans.mdwn b/doc/plugins/orphans.mdwn index ea7c4df13..e403c2d18 100644 --- a/doc/plugins/orphans.mdwn +++ b/doc/plugins/orphans.mdwn @@ -10,5 +10,6 @@ Here's a list of orphaned pages on this wiki: [[!orphans pages="* and !news/* and !todo/* and !bugs/* and !users/* and !recentchanges and !examples/* and !tips/* and !sandbox/* and !templates/* and +!forum/* and !*.js and !wikiicons/* and !plugins/*"]] """]] diff --git a/doc/plugins/sidebar.mdwn b/doc/plugins/sidebar.mdwn index 36982eff3..4e356d65a 100644 --- a/doc/plugins/sidebar.mdwn +++ b/doc/plugins/sidebar.mdwn @@ -16,6 +16,10 @@ will turn off the sidebar altogether. Warning: Any change to the sidebar will cause a rebuild of the whole wiki, since every page includes a copy that has to be updated. This can -especially be a problem if the sidebar includes [[inline]] or [[map]] -directives, since any changes to pages inlined or mapped onto the sidebar +especially be a problem if the sidebar includes an [[ikiwiki/directive/inline]] +directive, since any changes to pages inlined into the sidebar will change the sidebar and cause a full wiki rebuild. + +Instead, if you include a [[ikiwiki/directive/map]] directive on the sidebar, +and it does not use the `show` parameter, only adding or removing pages +included in the map will cause a full rebuild. Modifying pages will not. diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 668f8d8b6..133030f08 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -609,10 +609,22 @@ page created from it. (Ie, it appends ".html".) Use this when constructing the filename of a html file. Use `urlto` when generating a link to a page. -#### `add_depends($$)` +#### `add_depends($$;@)` Makes the specified page depend on the specified [[ikiwiki/PageSpec]]. +By default, dependencies are full content dependencies, meaning that the +page will be updated whenever anything matching the PageSpec is modified. +This default can be overridden by additional named parameters, which can be +used to indicate weaker types of dependencies: + +* `presence` if set to true, only the presence of a matching page triggers + the dependency. +* `links` if set to true, any change to links on a matching page + triggers the dependency. This includes when a link is added, removed, + or changes what it points to due to other changes. It does not include + the addition or removal of a duplicate link. + #### `pagespec_match($$;@)` Passed a page name, and [[ikiwiki/PageSpec]], returns true if the diff --git a/doc/todo/dependency_types.mdwn b/doc/todo/dependency_types.mdwn index f13f1448e..f46a6a7c6 100644 --- a/doc/todo/dependency_types.mdwn +++ b/doc/todo/dependency_types.mdwn @@ -162,14 +162,13 @@ Link dependencies: * `add_depends($page, $spec, links => 1, presence => 1)` adds a links + presence dependency. -* `refresh` only rebuilds a page with a links dependency if - pages matched by the pagespec gain or lose links. (What the link - actually points to may change independent of this, due to changes - elsewhere, without it firing.) +* Use backlinks change code to detect changes to link dependencies too. * So, brokenlinks can fire whenever any links in any of the pages it's tracking change, or when pages are added or removed. TODO: How to determine if a pagespec is valid to be used with a links dependency? Use the same simple pagespecs that are valid for presence -dependencies? +dependencies? Seems ok. + +[[done]] diff --git a/ikiwiki-transition b/ikiwiki-transition index 8a20cf655..1bebb1176 100755 --- a/ikiwiki-transition +++ b/ikiwiki-transition @@ -299,7 +299,7 @@ sub oldloadindex { $pagemtime{$page}=$items{mtime}[0]; $oldlinks{$page}=[@{$items{link}}]; $links{$page}=[@{$items{link}}]; - $depends{$page}={ $items{depends}[0] => 1 } if exists $items{depends}; + $depends{$page}={ $items{depends}[0] => $IkiWiki::DEPEND_CONTENT } if exists $items{depends}; $destsources{$_}=$page foreach @{$items{dest}}; $renderedfiles{$page}=[@{$items{dest}}]; $pagecase{lc $page}=$page; diff --git a/t/add_depends.t b/t/add_depends.t new file mode 100644 index 000000000..935a57944 --- /dev/null +++ b/t/add_depends.t @@ -0,0 +1,68 @@ +#!/usr/bin/perl +use warnings; +use strict; +use Test::More tests => 50; + +BEGIN { use_ok("IkiWiki"); } +%config=IkiWiki::defaultconfig(); +$config{srcdir}=$config{destdir}="/dev/null"; +IkiWiki::checkconfig(); + +# avoids adding an unparseable pagespec +ok(! add_depends("foo", "foo and (bar")); +ok(! add_depends("foo", "foo another")); + +# simple and not-so-simple dependencies split +ok(add_depends("foo", "*")); +ok(add_depends("foo", "bar")); +ok(add_depends("foo", "BAZ")); +ok(exists $IkiWiki::depends_simple{foo}{"bar"}); +ok(exists $IkiWiki::depends_simple{foo}{"baz"}); # lowercase +ok(! exists $IkiWiki::depends_simple{foo}{"*"}); +ok(! exists $IkiWiki::depends{foo}{"bar"}); +ok(! exists $IkiWiki::depends{foo}{"baz"}); + +# default dependencies are content dependencies +ok($IkiWiki::depends{foo}{"*"} & $IkiWiki::DEPEND_CONTENT); +ok(! ($IkiWiki::depends{foo}{"*"} & ($IkiWiki::DEPEND_PRESENCE | $IkiWiki::DEPEND_LINKS))); +ok($IkiWiki::depends_simple{foo}{"bar"} & $IkiWiki::DEPEND_CONTENT); +ok(! ($IkiWiki::depends_simple{foo}{"bar"} & ($IkiWiki::DEPEND_PRESENCE | $IkiWiki::DEPEND_LINKS))); + +# adding other dep types standalone +ok(add_depends("foo2", "*", presence => 1)); +ok(add_depends("foo2", "bar", links => 1)); +ok($IkiWiki::depends{foo2}{"*"} & $IkiWiki::DEPEND_PRESENCE); +ok(! ($IkiWiki::depends{foo2}{"*"} & ($IkiWiki::DEPEND_CONTENT | $IkiWiki::DEPEND_LINKS))); +ok($IkiWiki::depends_simple{foo2}{"bar"} & $IkiWiki::DEPEND_LINKS); +ok(! ($IkiWiki::depends_simple{foo2}{"bar"} & ($IkiWiki::DEPEND_PRESENCE | $IkiWiki::DEPEND_CONTENT))); + +# adding combined dep types +ok(add_depends("foo2", "baz", links => 1, presence => 1)); +ok($IkiWiki::depends_simple{foo2}{"baz"} & $IkiWiki::DEPEND_LINKS); +ok($IkiWiki::depends_simple{foo2}{"baz"} & $IkiWiki::DEPEND_PRESENCE); +ok(! ($IkiWiki::depends_simple{foo2}{"baz"} & $IkiWiki::DEPEND_CONTENT)); + +# adding a pagespec that requires page metadata should cause a fallback to +# a content dependency +foreach my $spec ("* and ! link(bar)", "* or link(bar)", "unknownspec()", + "title(hi)", + "* or backlink(yo)", # this one could actually be acceptably be + # detected to not need a content dep .. in + # theory! + ) { + ok(add_depends("foo3", $spec, presence => 1)); + ok($IkiWiki::depends{foo3}{$spec} & $IkiWiki::DEPEND_CONTENT); + ok(! ($IkiWiki::depends{foo3}{$spec} & ($IkiWiki::DEPEND_PRESENCE | $IkiWiki::DEPEND_LINKS))); +} + +# adding dep types to existing dependencies should merge the flags +ok(add_depends("foo2", "baz")); +ok($IkiWiki::depends_simple{foo2}{"baz"} & $IkiWiki::DEPEND_LINKS); +ok($IkiWiki::depends_simple{foo2}{"baz"} & $IkiWiki::DEPEND_PRESENCE); +ok(($IkiWiki::depends_simple{foo2}{"baz"} & $IkiWiki::DEPEND_CONTENT)); +ok(add_depends("foo2", "bar", presence => 1)); # had only links before +ok($IkiWiki::depends_simple{foo2}{"bar"} & ($IkiWiki::DEPEND_LINKS | $IkiWiki::DEPEND_PRESENCE)); +ok(! ($IkiWiki::depends_simple{foo2}{"bar"} & $IkiWiki::DEPEND_CONTENT)); +ok(add_depends("foo", "bar", links => 1)); # had only content before +ok($IkiWiki::depends{foo}{"*"} & ($IkiWiki::DEPEND_CONTENT | $IkiWiki::DEPEND_LINKS)); +ok(! ($IkiWiki::depends{foo}{"*"} & $IkiWiki::DEPEND_PRESENCE)); |