From fd9d9680242c0d1c835fc56f969f8e2a2618a5de Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 3 Oct 2009 15:37:57 -0400 Subject: document add_depends dependency type interface --- doc/plugins/write.mdwn | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'doc/plugins') diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 668f8d8b6..c244c1f2f 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -609,10 +609,17 @@ 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]]. +Additional named parameters can be passed, to indicate what type of +dependency this is. + +Currently, only a "content" parameter is specified. If set to 0, the +dependency does not involve the content of pages matching the PageSpec, but +only their existence. + #### `pagespec_match($$;@)` Passed a page name, and [[ikiwiki/PageSpec]], returns true if the -- cgit v1.2.3 From a8af271e5aed1c4aef3f66cee0847d609aedc705 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 4 Oct 2009 16:28:14 -0400 Subject: document effect of contentless dependencies on sidebar efficiency --- doc/plugins/sidebar.mdwn | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'doc/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. -- cgit v1.2.3 From be032a7b87d1080f1a54327346cb5b40432a056c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 4 Oct 2009 20:30:21 -0400 Subject: rework dependency types code Simplify, change default content depends number to 1, change interface to make more sense. --- IkiWiki.pm | 35 +++++++++++++++-------------------- IkiWiki/Plugin/calendar.pm | 18 +++++++++--------- IkiWiki/Plugin/edittemplate.pm | 2 +- IkiWiki/Plugin/listdirectives.pm | 2 +- IkiWiki/Plugin/meta.pm | 2 +- IkiWiki/Plugin/pagecount.pm | 4 ++-- IkiWiki/Plugin/postsparkline.pm | 2 +- IkiWiki/Plugin/progress.pm | 4 ++-- IkiWiki/Render.pm | 28 +++++++++++++--------------- doc/plugins/write.mdwn | 15 +++++++++------ ikiwiki-transition | 2 +- 11 files changed, 55 insertions(+), 59 deletions(-) (limited to 'doc/plugins') diff --git a/IkiWiki.pm b/IkiWiki.pm index 5e5dc739d..c1d07531e 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -29,8 +29,8 @@ our $version='unknown'; # VERSION_AUTOREPLACE done by Makefile, DNE our $installdir='/usr'; # INSTALLDIR_AUTOREPLACE done by Makefile, DNE # Page dependency types. -our $DEPEND_EXISTS=1; -our $DEPEND_CONTENT=2; +our $DEPEND_CONTENT=1; +our $DEPEND_PRESENCE=2; # Optimisation. use Memoize; @@ -1540,13 +1540,13 @@ sub loadindex () { if (exists $d->{dependslist}) { # old format $depends{$page}={ - map { $_ => $DEPEND_CONTENT | $DEPEND_EXISTS } + map { $_ => $DEPEND_CONTENT } @{$d->{dependslist}} }; } elsif (exists $d->{depends} && ! ref $d->{depends}) { # old format - $depends{$page}={$d->{depends} => $DEPEND_CONTENT | $DEPEND_EXISTS}; + $depends{$page}={$d->{depends} => $DEPEND_CONTENT }; } elsif (exists $d->{depends}) { $depends{$page}=$d->{depends}; @@ -1771,16 +1771,23 @@ sub add_depends ($$;@) { my $page=shift; my $pagespec=shift; + # Is the pagespec a simple page name? my $simple=$pagespec =~ /$config{wiki_file_regexp}/ && $pagespec !~ /[\s*?()!]/; - my $deptype=$DEPEND_CONTENT | $DEPEND_EXISTS; + my $deptype=$DEPEND_CONTENT; if (@_) { my %params=@_; - if (defined $params{content} && $params{content} == 0 && - ($simple || pagespec_contentless($pagespec))) { - $deptype=$deptype & ~$DEPEND_CONTENT; + + # 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; } if ($simple) { @@ -1976,18 +1983,6 @@ sub pagespec_valid ($) { return ! $@; } -sub pagespec_contentless ($) { - my $spec=shift; - - while ($spec=~m{ - (\w+)\([^\)]*\) # only match pagespec functions - }igx) { - return 0 unless $1=~/^(glob|internal|creation_month|creation_day|creation_year|created_before|created_after)$/; - } - - return 1; -} - sub glob2re ($) { my $re=quotemeta(shift); $re=~s/\\\*/.*/g; diff --git a/IkiWiki/Plugin/calendar.pm b/IkiWiki/Plugin/calendar.pm index a5cc20882..a1117992a 100644 --- a/IkiWiki/Plugin/calendar.pm +++ b/IkiWiki/Plugin/calendar.pm @@ -105,21 +105,21 @@ sub format_month (@) { linktext => " $monthname "); } add_depends($params{page}, "$archivebase/$year/".sprintf("%02d", $month), - content => 0); + 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), - content => 0); + 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), - content => 0); + presence => 1); # Start producing the month calendar $calendar=< 0); + 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, content => 0); + add_depends($params{page}, $p, presence => 1); } return $calendar; @@ -249,19 +249,19 @@ sub format_year (@) { "$archivebase/$year", linktext => "$year"); } - add_depends($params{page}, "$archivebase/$year", content => 0); + 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", content => 0); + 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", content => 0); + add_depends($params{page}, "$archivebase/$nyear", presence => 1); # Start producing the year calendar $calendar=<$monthabbr\n}; } - add_depends($params{page}, "$archivebase/$year/$mtag", content => 0); + add_depends($params{page}, "$archivebase/$year/$mtag", presence => 1); $calendar.=qq{\t\n} if ($month % $params{months_per_row} == 0); } diff --git a/IkiWiki/Plugin/edittemplate.pm b/IkiWiki/Plugin/edittemplate.pm index 89d450725..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, content => 0); + 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/listdirectives.pm b/IkiWiki/Plugin/listdirectives.pm index 96150f986..4023ed7d7 100644 --- a/IkiWiki/Plugin/listdirectives.pm +++ b/IkiWiki/Plugin/listdirectives.pm @@ -84,7 +84,7 @@ sub preprocess (@) { foreach my $plugin (@pluginlist) { $result .= '
  • '; my $link=linkpage($config{directive_description_dir}."/".$plugin); - add_depends($params{page}, $link, content => 0); + add_depends($params{page}, $link, presence => 1); $result .= htmllink($params{page}, $params{destpage}, $link); $result .= '
  • '; } diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index eef3013a0..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, content => 0); + add_depends($page, $link, presence => 1); $value=urlto($link, $page); $value.='#'.$redir_anchor if defined $redir_anchor; diff --git a/IkiWiki/Plugin/pagecount.pm b/IkiWiki/Plugin/pagecount.pm index 17eda0618..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 contentless dependency. - add_depends($params{page}, $params{pages}, content => 0); + # register a presence dependency. + add_depends($params{page}, $params{pages}, presence => 1); my @pages; if ($params{pages} eq "*") { diff --git a/IkiWiki/Plugin/postsparkline.pm b/IkiWiki/Plugin/postsparkline.pm index 694d39575..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}, content => 0); + 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 3b664f4cb..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}, content => 0); - add_depends($params{page}, $params{donepages}, content => 0); + 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 3fc750925..cf0c3fe08 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -473,13 +473,11 @@ sub refresh () { if (exists $depends_simple{$p}) { foreach my $d (keys %{$depends_simple{$p}}) { - if ($depends_simple{$p}{$d} == $IkiWiki::DEPEND_EXISTS) { - if (exists $lc_exists_changed{$d}) { - $reason = $d; - last; - } - } - elsif (exists $lc_changed{$d}) { + 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; } @@ -492,22 +490,22 @@ sub refresh () { next if $@ || ! defined $sub; my @candidates; - if ($depends{$p}{$d} == $IkiWiki::DEPEND_EXISTS) { - @candidates=@exists_changed; - } - else { + 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{$p}{$d} == $IkiWiki::DEPEND_EXISTS) { - push @candidates, @internal; - } - else { + 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) { diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index c244c1f2f..73db6f12a 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -613,12 +613,15 @@ generating a link to a page. Makes the specified page depend on the specified [[ikiwiki/PageSpec]]. -Additional named parameters can be passed, to indicate what type of -dependency this is. - -Currently, only a "content" parameter is specified. If set to 0, the -dependency does not involve the content of pages matching the PageSpec, but -only their existence. +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 in the text of links on a matching page + triggers the dependency #### `pagespec_match($$;@)` diff --git a/ikiwiki-transition b/ikiwiki-transition index c50a748e8..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] => $IkiWiki::DEPEND_CONTENT | $IkiWiki::DEPEND_EXISTS } 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; -- cgit v1.2.3 From c6bf4228d5c988e715ff08a9374b72ce054daa2c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 5 Oct 2009 15:01:05 -0400 Subject: make links dependencies fire if broken links change --- IkiWiki/Render.pm | 41 ++++++++++++++++++++++++++++------------- doc/plugins/write.mdwn | 6 ++++-- 2 files changed, 32 insertions(+), 15 deletions(-) (limited to 'doc/plugins') diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 4e8aae3bc..599bb26e2 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -63,24 +63,39 @@ sub find_changed_links (@_) { 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; + 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 $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; + 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 + } } } } diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 73db6f12a..133030f08 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -620,8 +620,10 @@ 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 in the text of links on 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($$;@)` -- cgit v1.2.3 From fc864515b857694da6752879edeb2f82fd12e3a4 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 5 Oct 2009 15:16:14 -0400 Subject: omit forum and javascript from list --- doc/plugins/orphans.mdwn | 1 + 1 file changed, 1 insertion(+) (limited to 'doc/plugins') diff --git a/doc/plugins/orphans.mdwn b/doc/plugins/orphans.mdwn index ea7c4df13..8c0d0b933 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 !wikiicons/* and !plugins/*"]] """]] -- cgit v1.2.3 From dc6fab3824c9848cdaf8b252253d690f96573d25 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 5 Oct 2009 15:17:36 -0400 Subject: syntax --- doc/plugins/orphans.mdwn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'doc/plugins') diff --git a/doc/plugins/orphans.mdwn b/doc/plugins/orphans.mdwn index 8c0d0b933..e403c2d18 100644 --- a/doc/plugins/orphans.mdwn +++ b/doc/plugins/orphans.mdwn @@ -10,6 +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 +!forum/* and !*.js and !wikiicons/* and !plugins/*"]] """]] -- cgit v1.2.3 From f7d04d106721a6bff6dfd4a0a7aa162cd2ce5536 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 5 Oct 2009 15:26:15 -0400 Subject: switch plugins page to use a map instead of an inline A map just seems a better fit for reference, since it deliniates the contrib plugins better, and orders better. It also has the advantage of being less expensive, since the plugins page does not need to update when eg, the pagecount page changes. Only downside is, no rss feed of new plugins. Which I know a few people were subscribed to. --- doc/plugins.mdwn | 6 ++---- doc/plugins/contrib.mdwn | 4 +--- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'doc/plugins') diff --git a/doc/plugins.mdwn b/doc/plugins.mdwn index 527568208..bd7ee538b 100644 --- a/doc/plugins.mdwn +++ b/doc/plugins.mdwn @@ -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"]] -- cgit v1.2.3 From 4002d7c1a4657e769b036c6e76106991ec5c3897 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 7 Oct 2009 20:31:13 -0400 Subject: add influence info to match_* Also update docs, test suite. --- IkiWiki.pm | 24 ++++++++++++------------ IkiWiki/Plugin/meta.pm | 8 ++++---- debian/changelog | 2 ++ doc/plugins/write.mdwn | 7 +++++++ t/pagespec_match.t | 15 +++++++++++++-- 5 files changed, 38 insertions(+), 18 deletions(-) (limited to 'doc/plugins') diff --git a/IkiWiki.pm b/IkiWiki.pm index 73d2a9763..9c386e154 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -2039,7 +2039,7 @@ use overload ( sub new { my $class = shift; my $value = shift; - return bless [$value, {@_}], $class; + return bless [$value, {map { $_ => 1 } @_}], $class; } sub influences { @@ -2099,23 +2099,23 @@ sub match_link ($$;@) { my $from=exists $params{location} ? $params{location} : ''; my $links = $IkiWiki::links{$page}; - return IkiWiki::FailReason->new("$page has no links") unless $links && @{$links}; + return IkiWiki::FailReason->new("$page has no links", $link) unless $links && @{$links}; my $bestlink = IkiWiki::bestlink($from, $link); foreach my $p (@{$links}) { if (length $bestlink) { - return IkiWiki::SuccessReason->new("$page links to $link") + return IkiWiki::SuccessReason->new("$page links to $link", $page) if $bestlink eq IkiWiki::bestlink($page, $p); } else { - return IkiWiki::SuccessReason->new("$page links to page $p matching $link") + return IkiWiki::SuccessReason->new("$page links to page $p matching $link", $page) if match_glob($p, $link, %params); my ($p_rel)=$p=~/^\/?(.*)/; $link=~s/^\///; - return IkiWiki::SuccessReason->new("$page links to page $p_rel matching $link") + return IkiWiki::SuccessReason->new("$page links to page $p_rel matching $link", $page) if match_glob($p_rel, $link, %params); } } - return IkiWiki::FailReason->new("$page does not link to $link"); + return IkiWiki::FailReason->new("$page does not link to $link", $page); } sub match_backlink ($$;@) { @@ -2131,14 +2131,14 @@ sub match_created_before ($$;@) { if (exists $IkiWiki::pagectime{$testpage}) { if ($IkiWiki::pagectime{$page} < $IkiWiki::pagectime{$testpage}) { - return IkiWiki::SuccessReason->new("$page created before $testpage"); + return IkiWiki::SuccessReason->new("$page created before $testpage", $testpage); } else { - return IkiWiki::FailReason->new("$page not created before $testpage"); + return IkiWiki::FailReason->new("$page not created before $testpage", $testpage); } } else { - return IkiWiki::ErrorReason->new("$testpage does not exist"); + return IkiWiki::ErrorReason->new("$testpage does not exist", $testpage); } } @@ -2151,14 +2151,14 @@ sub match_created_after ($$;@) { if (exists $IkiWiki::pagectime{$testpage}) { if ($IkiWiki::pagectime{$page} > $IkiWiki::pagectime{$testpage}) { - return IkiWiki::SuccessReason->new("$page created after $testpage"); + return IkiWiki::SuccessReason->new("$page created after $testpage", $testpage); } else { - return IkiWiki::FailReason->new("$page not created after $testpage"); + return IkiWiki::FailReason->new("$page not created after $testpage", $testpage); } } else { - return IkiWiki::ErrorReason->new("$testpage does not exist"); + return IkiWiki::ErrorReason->new("$testpage does not exist", $testpage); } } diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index 9b041a748..a8ee5bc85 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -291,21 +291,21 @@ sub match { if (defined $val) { if ($val=~/^$re$/i) { - return IkiWiki::SuccessReason->new("$re matches $field of $page"); + return IkiWiki::SuccessReason->new("$re matches $field of $page", $page); } else { - return IkiWiki::FailReason->new("$re does not match $field of $page"); + return IkiWiki::FailReason->new("$re does not match $field of $page", $page); } } else { - return IkiWiki::FailReason->new("$page does not have a $field"); + return IkiWiki::FailReason->new("$page does not have a $field", $page); } } package IkiWiki::PageSpec; sub match_title ($$;@) { - IkiWiki::Plugin::meta::match("title", @_); + IkiWiki::Plugin::meta::match("title", @_); } sub match_author ($$;@) { diff --git a/debian/changelog b/debian/changelog index dc6ee0a81..565a0cffa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -32,6 +32,8 @@ ikiwiki (3.14159266) UNRELEASED; urgency=low * Transitive dependencies are now correctly supported. * Rebuild wikis on upgrade to this version to get improved dependency info. + * Plugins providing PageSpec `match_*` functions should pass additional + influence information when creating result objects. -- Joey Hess Sun, 27 Sep 2009 17:40:03 -0400 diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 8e8c3311e..6b47033e5 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -982,6 +982,13 @@ an IkiWiki::FailReason object if the match fails. If the match cannot be attempted at all, for any page, it can instead return an IkiWiki::ErrorReason object explaining why. +When constructing these objects, you should also include a list of any +pages whose contents or other metadata influenced the result of the match. +For example, "backlink(foo)" is influenced by the contents of page foo; +"link(foo)" and "title(bar)" are influenced by the contents of any +page they match; "created_before(foo)" is influenced by the metadata of +foo; while "glob(*)" is not influenced by the contents of any page. + ### Setup plugins The ikiwiki setup file is loaded using a pluggable mechanism. If you look diff --git a/t/pagespec_match.t b/t/pagespec_match.t index a1fcba7c8..f73bfdfe1 100755 --- a/t/pagespec_match.t +++ b/t/pagespec_match.t @@ -1,7 +1,7 @@ #!/usr/bin/perl use warnings; use strict; -use Test::More tests => 56; +use Test::More tests => 61; BEGIN { use_ok("IkiWiki"); } @@ -89,6 +89,17 @@ my $ret=pagespec_match("foo", "(invalid"); ok(! $ret, "syntax error"); ok($ret =~ /syntax error/, "error message"); -my $ret=pagespec_match("foo", "bar or foo"); +$ret=pagespec_match("foo", "bar or foo"); ok($ret, "simple match"); is($ret, "foo matches foo", "stringified return"); + +$ret=pagespec_match("foo", "link(bar)"); +is(join(",", $ret->influences), 'foo', "link is influenced by the page with the link"); +$ret=pagespec_match("bar", "backlink(foo)"); +is(join(",", $ret->influences), 'foo', "backlink is influenced by the page with the link"); +$ret=pagespec_match("bar", "backlink(foo)"); +is(join(",", $ret->influences), 'foo', "backlink is influenced by the page with the link"); +$ret=pagespec_match("bar", "created_before(foo)"); +is(join(",", $ret->influences), 'foo', "created_before is influenced by the comparison page"); +$ret=pagespec_match("bar", "created_after(foo)"); +is(join(",", $ret->influences), 'foo', "created_after is influenced by the comparison page"); -- cgit v1.2.3 From 5f9860e65c65aa769f11e550e63cc164b1519710 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 7 Oct 2009 21:48:03 -0400 Subject: add type info to influence information --- IkiWiki.pm | 49 ++++++++++++++++++++++++++++++------------------- IkiWiki/Plugin/meta.pm | 6 +++--- doc/plugins/write.mdwn | 6 +++--- docwiki.setup | 2 +- t/add_depends.t | 14 +++++++------- t/pagespec_match.t | 32 ++++++++++++++++---------------- 6 files changed, 60 insertions(+), 49 deletions(-) (limited to 'doc/plugins') diff --git a/IkiWiki.pm b/IkiWiki.pm index 7adc63139..39a43ddbe 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1795,8 +1795,10 @@ sub add_depends ($$;@) { return if $@; foreach my $p (keys %pagesources) { my $r=$sub->($p, location => $page ); - map { $depends_simple{$page}{lc $_} |= $DEPEND_CONTENT } $r->influences - if $r; + my %i=$r->influences; + foreach my $i (keys %i) { + $depends_simple{$page}{lc $i} |= $i{$i}; + } } $depends{$page}{$pagespec} |= $deptype; @@ -1998,8 +2000,8 @@ use overload ( '""' => sub { $_[0][0] }, '0+' => sub { 0 }, '!' => sub { bless $_[0], 'IkiWiki::SuccessReason'}, - '&' => sub { $_[0][1]={%{$_[0][1]}, %{$_[1][1]}}; $_[0] }, - '|' => sub { $_[1][1]={%{$_[0][1]}, %{$_[1][1]}}; $_[1] }, + '&' => sub { $_[0]->merge_influences($_[1]); $_[0] }, + '|' => sub { $_[1]->merge_influences($_[0]); $_[1] }, fallback => 1, ); @@ -2011,19 +2013,27 @@ use overload ( '""' => sub { $_[0][0] }, '0+' => sub { 1 }, '!' => sub { bless $_[0], 'IkiWiki::FailReason'}, - '&' => sub { $_[1][1]={%{$_[0][1]}, %{$_[1][1]}}; $_[1] }, - '|' => sub { $_[0][1]={%{$_[0][1]}, %{$_[1][1]}}; $_[0] }, + '&' => sub { $_[1]->merge_influences($_[0]); $_[1] }, + '|' => sub { $_[0]->merge_influences($_[1]); $_[0] }, fallback => 1, ); sub new { my $class = shift; my $value = shift; - return bless [$value, {map { $_ => 1 } @_}], $class; + return bless [$value, {@_}], $class; } sub influences { - return keys %{$_[0][1]}; + return %{$_[0][1]}; +} + +sub merge_influences { + my $this=shift; + my $other=shift; + foreach my $influence (keys %{$other->[1]}) { + $this->[1]{$influence} |= $other->[1]{$influence}; + } } package IkiWiki::ErrorReason; @@ -2079,23 +2089,24 @@ sub match_link ($$;@) { my $from=exists $params{location} ? $params{location} : ''; my $links = $IkiWiki::links{$page}; - return IkiWiki::FailReason->new("$page has no links", $page) unless $links && @{$links}; + return IkiWiki::FailReason->new("$page has no links", $page => $IkiWiki::DEPEND_LINKS) + unless $links && @{$links}; my $bestlink = IkiWiki::bestlink($from, $link); foreach my $p (@{$links}) { if (length $bestlink) { - return IkiWiki::SuccessReason->new("$page links to $link", $page) + return IkiWiki::SuccessReason->new("$page links to $link", $page => $IkiWiki::DEPEND_LINKS) if $bestlink eq IkiWiki::bestlink($page, $p); } else { - return IkiWiki::SuccessReason->new("$page links to page $p matching $link", $page) + return IkiWiki::SuccessReason->new("$page links to page $p matching $link", $page => $IkiWiki::DEPEND_LINKS) if match_glob($p, $link, %params); my ($p_rel)=$p=~/^\/?(.*)/; $link=~s/^\///; - return IkiWiki::SuccessReason->new("$page links to page $p_rel matching $link", $page) + return IkiWiki::SuccessReason->new("$page links to page $p_rel matching $link", $page => $IkiWiki::DEPEND_LINKS) if match_glob($p_rel, $link, %params); } } - return IkiWiki::FailReason->new("$page does not link to $link", $page); + return IkiWiki::FailReason->new("$page does not link to $link", $page => $IkiWiki::DEPEND_LINKS); } sub match_backlink ($$;@) { @@ -2111,14 +2122,14 @@ sub match_created_before ($$;@) { if (exists $IkiWiki::pagectime{$testpage}) { if ($IkiWiki::pagectime{$page} < $IkiWiki::pagectime{$testpage}) { - return IkiWiki::SuccessReason->new("$page created before $testpage", $testpage); + return IkiWiki::SuccessReason->new("$page created before $testpage", $testpage => $IkiWiki::DEPEND_PRESENCE); } else { - return IkiWiki::FailReason->new("$page not created before $testpage", $testpage); + return IkiWiki::FailReason->new("$page not created before $testpage", $testpage => $IkiWiki::DEPEND_PRESENCE); } } else { - return IkiWiki::ErrorReason->new("$testpage does not exist", $testpage); + return IkiWiki::ErrorReason->new("$testpage does not exist", $testpage => $IkiWiki::DEPEND_PRESENCE); } } @@ -2131,14 +2142,14 @@ sub match_created_after ($$;@) { if (exists $IkiWiki::pagectime{$testpage}) { if ($IkiWiki::pagectime{$page} > $IkiWiki::pagectime{$testpage}) { - return IkiWiki::SuccessReason->new("$page created after $testpage", $testpage); + return IkiWiki::SuccessReason->new("$page created after $testpage", $testpage => $IkiWiki::DEPEND_PRESENCE); } else { - return IkiWiki::FailReason->new("$page not created after $testpage", $testpage); + return IkiWiki::FailReason->new("$page not created after $testpage", $testpage => $IkiWiki::DEPEND_PRESENCE); } } else { - return IkiWiki::ErrorReason->new("$testpage does not exist", $testpage); + return IkiWiki::ErrorReason->new("$testpage does not exist", $testpage => $IkiWiki::DEPEND_PRESENCE); } } diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index a8ee5bc85..c160e7eba 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -291,14 +291,14 @@ sub match { if (defined $val) { if ($val=~/^$re$/i) { - return IkiWiki::SuccessReason->new("$re matches $field of $page", $page); + return IkiWiki::SuccessReason->new("$re matches $field of $page", $page => $IkiWiki::DEPEND_CONTENT); } else { - return IkiWiki::FailReason->new("$re does not match $field of $page", $page); + return IkiWiki::FailReason->new("$re does not match $field of $page", $page => $IkiWiki::DEPEND_CONTENT); } } else { - return IkiWiki::FailReason->new("$page does not have a $field", $page); + return IkiWiki::FailReason->new("$page does not have a $field", $page => $IkiWiki::DEPEND_CONTENT); } } diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 6b47033e5..232430079 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -982,9 +982,9 @@ an IkiWiki::FailReason object if the match fails. If the match cannot be attempted at all, for any page, it can instead return an IkiWiki::ErrorReason object explaining why. -When constructing these objects, you should also include a list of any -pages whose contents or other metadata influenced the result of the match. -For example, "backlink(foo)" is influenced by the contents of page foo; +When constructing these objects, you should also include information about +of any pages whose contents or other metadata influenced the result of the +match. For example, "backlink(foo)" is influenced by the contents of page foo; "link(foo)" and "title(bar)" are influenced by the contents of any page they match; "created_before(foo)" is influenced by the metadata of foo; while "glob(*)" is not influenced by the contents of any page. diff --git a/docwiki.setup b/docwiki.setup index 52421e501..41c07f024 100644 --- a/docwiki.setup +++ b/docwiki.setup @@ -16,5 +16,5 @@ use IkiWiki::Setup::Standard { userdir => "users", usedirs => 0, prefix_directives => 1, - add_plugins => [qw{goodstuff version haiku polygen fortune}], + add_plugins => [qw{linkmap goodstuff version haiku polygen fortune}], } diff --git a/t/add_depends.t b/t/add_depends.t index d49aa74ce..9f426187b 100755 --- a/t/add_depends.t +++ b/t/add_depends.t @@ -57,17 +57,17 @@ ok($IkiWiki::depends{foo0}{"*"} & ($IkiWiki::DEPEND_CONTENT | $IkiWiki::DEPEND_L ok(! ($IkiWiki::depends{foo0}{"*"} & $IkiWiki::DEPEND_PRESENCE)); # Adding a pagespec that requires page metadata should add the influence -# as an explicit content dependency. +# as an explicit dependency. In the case of a link, a links dependency. $links{foo0}=$links{foo9}=[qw{bar baz}]; foreach my $spec ("* and ! link(bar)", "* or link(bar)") { ok(add_depends("foo3", $spec, presence => 1)); ok($IkiWiki::depends{foo3}{$spec} & $IkiWiki::DEPEND_PRESENCE); ok(! ($IkiWiki::depends{foo3}{$spec} & ($IkiWiki::DEPEND_CONTENT | $IkiWiki::DEPEND_LINKS))); - ok($IkiWiki::depends_simple{foo3}{foo3} == $IkiWiki::DEPEND_CONTENT); + ok($IkiWiki::depends_simple{foo3}{foo3} == $IkiWiki::DEPEND_LINKS); ok(add_depends("foo4", $spec, links => 1)); ok($IkiWiki::depends{foo4}{$spec} & $IkiWiki::DEPEND_LINKS); ok(! ($IkiWiki::depends{foo4}{$spec} & ($IkiWiki::DEPEND_CONTENT | $IkiWiki::DEPEND_PRESENCE))); - ok($IkiWiki::depends_simple{foo4}{foo4} == $IkiWiki::DEPEND_CONTENT); + ok($IkiWiki::depends_simple{foo4}{foo4} == $IkiWiki::DEPEND_LINKS); } # a pagespec with backlinks() will add as an influence the page with the links @@ -76,20 +76,20 @@ foreach my $spec ("bugs or (backlink(foo0) and !*.png)", "backlink(foo)") { ok(add_depends("foo5", $spec, presence => 1)); ok($IkiWiki::depends{foo5}{$spec} & $IkiWiki::DEPEND_PRESENCE); ok(! ($IkiWiki::depends{foo5}{$spec} & ($IkiWiki::DEPEND_CONTENT | $IkiWiki::DEPEND_LINKS))); - ok($IkiWiki::depends_simple{foo5}{foo0} == $IkiWiki::DEPEND_CONTENT); + ok($IkiWiki::depends_simple{foo5}{foo0} == $IkiWiki::DEPEND_LINKS); ok(add_depends("foo6", $spec, links => 1)); ok($IkiWiki::depends{foo6}{$spec} & $IkiWiki::DEPEND_LINKS); ok(! ($IkiWiki::depends{foo6}{$spec} & ($IkiWiki::DEPEND_PRESENCE | $IkiWiki::DEPEND_CONTENT))); - ok($IkiWiki::depends_simple{foo5}{foo0} == $IkiWiki::DEPEND_CONTENT); + ok($IkiWiki::depends_simple{foo5}{foo0} == $IkiWiki::DEPEND_LINKS); ok(add_depends("foo7", $spec, presence => 1, links => 1)); ok($IkiWiki::depends{foo7}{$spec} & $IkiWiki::DEPEND_PRESENCE); ok($IkiWiki::depends{foo7}{$spec} & $IkiWiki::DEPEND_LINKS); ok(! ($IkiWiki::depends{foo7}{$spec} & $IkiWiki::DEPEND_CONTENT)); - ok($IkiWiki::depends_simple{foo7}{foo0} == $IkiWiki::DEPEND_CONTENT); + ok($IkiWiki::depends_simple{foo7}{foo0} == $IkiWiki::DEPEND_LINKS); ok(add_depends("foo8", $spec)); ok($IkiWiki::depends{foo8}{$spec} & $IkiWiki::DEPEND_CONTENT); ok(! ($IkiWiki::depends{foo8}{$spec} & ($IkiWiki::DEPEND_PRESENCE | $IkiWiki::DEPEND_LINKS))); - ok($IkiWiki::depends_simple{foo8}{foo0} == $IkiWiki::DEPEND_CONTENT); + ok($IkiWiki::depends_simple{foo8}{foo0} == $IkiWiki::DEPEND_LINKS); } # content is the default if unknown types are entered diff --git a/t/pagespec_match.t b/t/pagespec_match.t index 1a0db1cef..36fa04370 100755 --- a/t/pagespec_match.t +++ b/t/pagespec_match.t @@ -93,19 +93,19 @@ $ret=pagespec_match("foo", "bar or foo"); ok($ret, "simple match"); is($ret, "foo matches foo", "stringified return"); -$ret=pagespec_match("foo", "link(bar)"); -is(join(",", $ret->influences), 'foo', "link is influenced by the page with the link"); -$ret=pagespec_match("bar", "backlink(foo)"); -is(join(",", $ret->influences), 'foo', "backlink is influenced by the page with the link"); -$ret=pagespec_match("bar", "backlink(foo)"); -is(join(",", $ret->influences), 'foo', "backlink is influenced by the page with the link"); -$ret=pagespec_match("bar", "created_before(foo)"); -is(join(",", $ret->influences), 'foo', "created_before is influenced by the comparison page"); -$ret=pagespec_match("bar", "created_after(foo)"); -is(join(",", $ret->influences), 'foo', "created_after is influenced by the comparison page"); -$ret=pagespec_match("bar", "link(quux) and created_after(foo)"); -is(join(",", sort $ret->influences), 'foo,quux', "influences add up over AND"); -$ret=pagespec_match("bar", "link(quux) and created_after(foo)"); -is(join(",", sort $ret->influences), 'foo,quux', "influences add up over OR"); -$ret=pagespec_match("bar", "!link(quux) and !created_after(foo)"); -is(join(",", sort $ret->influences), 'foo,quux', "influences unaffected by negation"); +my %i=pagespec_match("foo", "link(bar)")->influences; +is(join(",", keys %i), 'foo', "link is influenced by the page with the link"); +%i=pagespec_match("bar", "backlink(foo)")->influences; +is(join(",", keys %i), 'foo', "backlink is influenced by the page with the link"); +%i=pagespec_match("bar", "backlink(foo)")->influences; +is(join(",", keys %i), 'foo', "backlink is influenced by the page with the link"); +%i=pagespec_match("bar", "created_before(foo)")->influences; +is(join(",", keys %i), 'foo', "created_before is influenced by the comparison page"); +%i=pagespec_match("bar", "created_after(foo)")->influences; +is(join(",", keys %i), 'foo', "created_after is influenced by the comparison page"); +%i=pagespec_match("bar", "link(quux) and created_after(foo)")->influences; +is(join(",", sort keys %i), 'bar,foo', "influences add up over AND"); +%i=pagespec_match("bar", "link(quux) and created_after(foo)")->influences; +is(join(",", sort keys %i), 'bar,foo', "influences add up over OR"); +%i=pagespec_match("bar", "!link(quux) and !created_after(foo)")->influences; +is(join(",", sort keys %i), 'bar,foo', "influences unaffected by negation"); -- cgit v1.2.3 From 5e236f5d25b68f5fb4a421b24470419c6042cb1c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 8 Oct 2009 16:49:53 -0400 Subject: add use_pagespec and deptype functions --- IkiWiki.pm | 135 +++++++++++++++++++++++++++++++++++++++++-------- debian/changelog | 4 +- doc/plugins/write.mdwn | 61 +++++++++++++++++----- t/use_pagespec.t | 30 +++++++++++ 4 files changed, 194 insertions(+), 36 deletions(-) create mode 100755 t/use_pagespec.t (limited to 'doc/plugins') diff --git a/IkiWiki.pm b/IkiWiki.pm index 2064c881a..c787612e1 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -17,11 +17,12 @@ use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase %forcerebuild %loaded_plugins}; use Exporter q{import}; -our @EXPORT = qw(hook debug error template htmlpage add_depends pagespec_match - pagespec_match_list bestlink htmllink readfile writefile - pagetype srcfile pagename displaytime will_render gettext urlto - targetpage add_underlay pagetitle titlepage linkpage - newpagefile inject add_link +our @EXPORT = qw(hook debug error template htmlpage deptype use_pagespec + add_depends pagespec_match pagespec_match_list bestlink + htmllink readfile writefile pagetype srcfile pagename + displaytime will_render gettext urlto targetpage + add_underlay pagetitle titlepage linkpage newpagefile + inject add_link %config %links %pagestate %wikistate %renderedfiles %pagesources %destsources); our $VERSION = 3.00; # plugin interface version, next is ikiwiki version @@ -1768,18 +1769,10 @@ sub rcs_receive () { $hooks{rcs}{rcs_receive}{call}->(); } -sub add_depends ($$;@) { +sub add_depends ($$;$) { my $page=shift; my $pagespec=shift; - - my $deptype=0; - if (@_) { - my %params=@_; - - $deptype=$deptype | $DEPEND_PRESENCE if $params{presence}; - $deptype=$deptype | $DEPEND_LINKS if $params{links}; - } - $deptype=$DEPEND_CONTENT unless $deptype; + my $deptype=shift || $DEPEND_CONTENT; # Is the pagespec a simple page name? if ($pagespec =~ /$config{wiki_file_regexp}/ && @@ -1791,18 +1784,118 @@ sub add_depends ($$;@) { # Analyse the pagespec, and match it against all pages # to get a list of influences, and add explicit dependencies # for those. + #my $sub=pagespec_translate($pagespec); + #return if $@; + #foreach my $p (keys %pagesources) { + # my $r=$sub->($p, location => $page ); + # my %i=$r->influences; + # foreach my $i (keys %i) { + # $depends_simple{$page}{lc $i} |= $i{$i}; + # } + #} + print STDERR "warning: use of add_depends; influences not tracked\n"; + + $depends{$page}{$pagespec} |= $deptype; + return 1; +} + +sub use_pagespec ($$;@) { + my $page=shift; + my $pagespec=shift; + my %params=@_; + my $sub=pagespec_translate($pagespec); - return if $@; - foreach my $p (keys %pagesources) { - my $r=$sub->($p, location => $page ); - my %i=$r->influences; + error "syntax error in pagespec \"$pagespec\"" + if $@ || ! defined $sub; + + my @candidates; + if (exists $params{limit}) { + @candidates=grep { $params{limit}->($_) } keys %pagesources; + } + else { + @candidates=keys %pagesources; + } + + if (defined $params{sort}) { + my $f; + if ($params{sort} eq 'title') { + $f=sub { pagetitle(basename($a)) cmp pagetitle(basename($b)) }; + } + elsif ($params{sort} eq 'title_natural') { + eval q{use Sort::Naturally}; + if ($@) { + error(gettext("Sort::Naturally needed for title_natural sort")); + } + $f=sub { Sort::Naturally::ncmp(pagetitle(basename($a)), pagetitle(basename($b))) }; + } + elsif ($params{sort} eq 'mtime') { + $f=sub { $pagemtime{$b} <=> $pagemtime{$a} }; + } + elsif ($params{sort} eq 'age') { + $f=sub { $pagectime{$b} <=> $pagectime{$a} }; + } + else { + error sprintf(gettext("unknown sort type %s"), $params{sort}); + } + @candidates = sort { &$f } @candidates; + } + + @candidates=reverse(@candidates) if $params{reverse}; + + my @matches; + my $firstfail; + my $count=0; + foreach my $p (@candidates) { + my $r=$sub->($p, location => $page); + if ($r) { + push @matches, [$p, $r]; + last if defined $params{num} && ++$count == $params{num}; + } + elsif (! defined $firstfail) { + $firstfail=$r; + } + } + + $depends{$page}{$pagespec} |= ($params{deptype} || $DEPEND_CONTENT); + + my @ret; + if (@matches) { + # Add all influences from successful matches. + foreach my $m (@matches) { + push @ret, $m->[0]; + my %i=$m->[1]->influences; + foreach my $i (keys %i) { + $depends_simple{$page}{lc $i} |= $i{$i}; + } + } + } + elsif (defined $firstfail) { + # Add influences from one failure. (Which one should not + # matter; all should have the same influences.) + my %i=$firstfail->influences; foreach my $i (keys %i) { $depends_simple{$page}{lc $i} |= $i{$i}; } + error(sprintf(gettext("cannot match pages: %s"), $firstfail)); } - $depends{$page}{$pagespec} |= $deptype; - return 1; + return @ret; +} + +sub deptype (@) { + my $deptype=0; + foreach my $type (@_) { + if ($type eq 'presence') { + $deptype |= $DEPEND_PRESENCE; + } + elsif ($type eq 'links') { + $deptype |= $DEPEND_LINKS; + } + elsif ($type eq 'content') { + $deptype |= $DEPEND_CONTENT; + } + } + return $deptype; } sub file_pruned ($$) { diff --git a/debian/changelog b/debian/changelog index 565a0cffa..12ddebac9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -13,7 +13,6 @@ ikiwiki (3.14159266) UNRELEASED; urgency=low * 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. @@ -34,6 +33,9 @@ ikiwiki (3.14159266) UNRELEASED; urgency=low info. * Plugins providing PageSpec `match_*` functions should pass additional influence information when creating result objects. + * Added `use_pagespec` function, that plugins can use to find a list + of matching pages and add dependencies and influences, all at once, + and efficiently. -- Joey Hess Sun, 27 Sep 2009 17:40:03 -0400 diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 232430079..3d5650758 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -609,21 +609,52 @@ 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($$;@)` +### `deptype(@)` + +Use this function to generate ikiwiki's internal representation of a +dependency type from one or more of these keywords: + +* `content` is the default. Any change to the content + of a page triggers the dependency. +* `presence` is only triggered by a change to the presence + of a page. +* `links` is only triggered by a change to the links of a page. + 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. + +If multiple types are specified, they are combined. + +#### `use_pagespec($$;@)` + +Passed a page name, and [[ikiwiki/PageSpec]], returns a list of pages +in the wiki that match the [[ikiwiki/PageSpec]]. + +The page will automatically be made to depend on the specified +[[ikiwiki/PageSpec]], so `add_depends` does not need to be called. This +is significantly more efficient than calling `add_depends` +followed by `pagespec_match_list`. You should use this anytime a plugin +needs to match a set of pages and generate something based on that list. + +Additional named parameters can be specified: + +* `deptype` optionally specifies the type of dependency to add. Use the + `deptype` function to generate a dependency type. +* `limit` is a reference to a function, that is called and passed a page, + and must return true for the page to be included. +* `sort` specifies a sort order for the list. See + [[ikiwiki/PageSpec/sorting]] for the avilable sort methods. +* `reverse` if true, sorts in reverse. +* `num` if nonzero, specifies the maximum number of matching pages that + will be returned. + +#### `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. +This can be overridden by passing a `deptype` value as the third parameter. #### `pagespec_match($$;@)` @@ -984,10 +1015,12 @@ IkiWiki::ErrorReason object explaining why. When constructing these objects, you should also include information about of any pages whose contents or other metadata influenced the result of the -match. For example, "backlink(foo)" is influenced by the contents of page foo; -"link(foo)" and "title(bar)" are influenced by the contents of any -page they match; "created_before(foo)" is influenced by the metadata of -foo; while "glob(*)" is not influenced by the contents of any page. +match. Do this by passing a list of pages, followed by `deptype` values. + +For example, "backlink(foo)" is influenced by the contents of page foo; +"link(foo)" and "title(bar)" are influenced by the contents of any page +they match; "created_before(foo)" is influenced by the metadata of foo; +while "glob(*)" is not influenced by the contents of any page. ### Setup plugins diff --git a/t/use_pagespec.t b/t/use_pagespec.t new file mode 100755 index 000000000..7b904075e --- /dev/null +++ b/t/use_pagespec.t @@ -0,0 +1,30 @@ +#!/usr/bin/perl +use warnings; +use strict; +use Test::More tests => 64; + +BEGIN { use_ok("IkiWiki"); } + +%pagesources=( + foo => "foo.mdwn", + bar => "bar.mdwn", + "post/1" => "post/1.mdwn", + "post/2" => "post/2.mdwn", + "post/3" => "post/3.mdwn", +); + +is_deeply([use_pagespec("foo", "bar")], ["bar"]); +is_deeply([sort(use_pagespec("foo", "post/*"))], ["post/1", "post/2", "post/3"]); +is_deeply([use_pagespec("foo", "post/*", sort => "title", reverse => 1)], + ["post/3", "post/2", "post/1"]); +is_deeply([use_pagespec("foo", "post/*", sort => "title", num => 2)], + ["post/1", "post/2"]); +is_deeply([use_pagespec("foo", "post/*", sort => "title", num => 50)], + ["post/1", "post/2", "post/3"]); +is_deeply([use_pagespec("foo", "post/*", sort => "title", + limit => sub { $_[0] !~ /3/}) ], + ["post/1", "post/2"]); +eval { use_pagespec("foo", "beep") }; +ok($@, "fails with error when unable to match anything"); +eval { use_pagespec("foo", "this is not a legal pagespec!") }; +ok($@, "fails with error when pagespec bad"); -- cgit v1.2.3 From 32cd5f0b798c41b2320a4165c5b6ecc18a4e6e3e Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 8 Oct 2009 18:26:36 -0400 Subject: inline: switch to use_pagespec Taking advantage of every single one of its features, of course. Even had to add one more.. --- IkiWiki/Plugin/inline.pm | 49 +++++++++++++++++++++--------------------------- doc/plugins/write.mdwn | 2 ++ 2 files changed, 23 insertions(+), 28 deletions(-) (limited to 'doc/plugins') diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm index be1781520..748e02df4 100644 --- a/IkiWiki/Plugin/inline.pm +++ b/IkiWiki/Plugin/inline.pm @@ -196,45 +196,37 @@ sub preprocess_inline (@) { @list = map { bestlink($params{page}, $_) } split ' ', $params{pagenames}; + if (yesno($params{reverse})) { + @list=reverse(@list); + } + foreach my $p (@list) { add_depends($params{page}, $p, deptype($quick ? "presence" : "content")); } } else { - add_depends($params{page}, $params{pages}, - deptype($quick ? "presence" : "content")); - - @list = pagespec_match_list( - [ grep { $_ ne $params{page} } keys %pagesources ], - $params{pages}, location => $params{page}); - - if (exists $params{sort} && $params{sort} eq 'title') { - @list=sort { pagetitle(basename($a)) cmp pagetitle(basename($b)) } @list; + my $num=0; + if ($params{show}) { + $num=$params{show}; } - elsif (exists $params{sort} && $params{sort} eq 'title_natural') { - eval q{use Sort::Naturally}; - if ($@) { - error(gettext("Sort::Naturally needed for title_natural sort")); - } - @list=sort { Sort::Naturally::ncmp(pagetitle(basename($a)), pagetitle(basename($b))) } @list; + if ($params{feedshow} && $num < $params{feedshow}) { + $num=$params{feedshow}; } - elsif (exists $params{sort} && $params{sort} eq 'mtime') { - @list=sort { $pagemtime{$b} <=> $pagemtime{$a} } @list; + if ($params{skip}) { + $num+=$params{skip}; } - elsif (! exists $params{sort} || $params{sort} eq 'age') { - @list=sort { $pagectime{$b} <=> $pagectime{$a} } @list; - } - else { - error sprintf(gettext("unknown sort type %s"), $params{sort}); - } - } - if (yesno($params{reverse})) { - @list=reverse(@list); + @list = use_pagespec($params{page}, $params{pages}, + deptype => deptype($quick ? "presence" : "content"), + limit => sub { $_[0] ne $params{page} }, + sort => exists $params{sort} ? $params{sort} : "age", + reverse => yesno($params{reverse}), + num => $num, + ); } if (exists $params{skip}) { - @list=@list[$params{skip} .. scalar @list - 1]; + @list=@list[$params{skip} .. $#list]; } my @feedlist; @@ -253,7 +245,8 @@ sub preprocess_inline (@) { } if ($feeds && exists $params{feedpages}) { - @feedlist=pagespec_match_list(\@feedlist, $params{feedpages}, location => $params{page}); + @feedlist = use_pagespec($params{page}, $params{feedpages}, + list => \@feedlist); } my ($feedbase, $feednum); diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 3d5650758..62bebbeed 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -647,6 +647,8 @@ Additional named parameters can be specified: * `reverse` if true, sorts in reverse. * `num` if nonzero, specifies the maximum number of matching pages that will be returned. +* `list` makes it only match amoung the specified list of pages. + Default is to match amoung all pages in the wiki. #### `add_depends($$;$)` -- cgit v1.2.3 From 5e7b2dea84a35163b599b88efc02cd7ef3e0ad46 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 8 Oct 2009 23:51:06 -0400 Subject: rename use_pagespec to pagespec_match_list To avoid breaking plugins, also support the old pagespec_match_list calling convention, with a deprecation warning. --- IkiWiki.pm | 183 ++++++++++++++++++---------------------- IkiWiki/Plugin/calendar.pm | 2 +- IkiWiki/Plugin/inline.pm | 8 +- IkiWiki/Plugin/map.pm | 3 +- IkiWiki/Plugin/orphans.pm | 2 +- IkiWiki/Plugin/pagecount.pm | 2 +- IkiWiki/Plugin/pagestats.pm | 9 +- IkiWiki/Plugin/postsparkline.pm | 2 +- debian/changelog | 6 +- doc/plugins/write.mdwn | 24 ++---- t/pagespec_match_list.t | 31 +++++++ t/use_pagespec.t | 31 ------- 12 files changed, 140 insertions(+), 163 deletions(-) create mode 100755 t/pagespec_match_list.t delete mode 100755 t/use_pagespec.t (limited to 'doc/plugins') diff --git a/IkiWiki.pm b/IkiWiki.pm index daa71059b..fd7e23524 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -17,7 +17,7 @@ use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase %forcerebuild %loaded_plugins}; use Exporter q{import}; -our @EXPORT = qw(hook debug error template htmlpage deptype use_pagespec +our @EXPORT = qw(hook debug error template htmlpage deptype add_depends pagespec_match pagespec_match_list bestlink htmllink readfile writefile pagetype srcfile pagename displaytime will_render gettext urlto targetpage @@ -1798,91 +1798,6 @@ sub add_depends ($$;$) { return 1; } -sub use_pagespec ($$;@) { - my $page=shift; - my $pagespec=shift; - my %params=@_; - - my $sub=pagespec_translate($pagespec); - error "syntax error in pagespec \"$pagespec\"" - if $@ || ! defined $sub; - - my @candidates; - if (exists $params{limit}) { - @candidates=grep { $params{limit}->($_) } keys %pagesources; - } - else { - @candidates=keys %pagesources; - } - - if (defined $params{sort}) { - my $f; - if ($params{sort} eq 'title') { - $f=sub { pagetitle(basename($a)) cmp pagetitle(basename($b)) }; - } - elsif ($params{sort} eq 'title_natural') { - eval q{use Sort::Naturally}; - if ($@) { - error(gettext("Sort::Naturally needed for title_natural sort")); - } - $f=sub { Sort::Naturally::ncmp(pagetitle(basename($a)), pagetitle(basename($b))) }; - } - elsif ($params{sort} eq 'mtime') { - $f=sub { $pagemtime{$b} <=> $pagemtime{$a} }; - } - elsif ($params{sort} eq 'age') { - $f=sub { $pagectime{$b} <=> $pagectime{$a} }; - } - else { - error sprintf(gettext("unknown sort type %s"), $params{sort}); - } - @candidates = sort { &$f } @candidates; - } - - @candidates=reverse(@candidates) if $params{reverse}; - - my @matches; - my $firstfail; - my $count=0; - foreach my $p (@candidates) { - my $r=$sub->($p, location => $page); - if ($r) { - push @matches, [$p, $r]; - last if defined $params{num} && ++$count == $params{num}; - } - elsif (! defined $firstfail) { - $firstfail=$r; - } - } - - $depends{$page}{$pagespec} |= ($params{deptype} || $DEPEND_CONTENT); - - my @ret; - if (@matches) { - # Add all influences from successful matches. - foreach my $m (@matches) { - push @ret, $m->[0]; - my %i=$m->[1]->influences; - foreach my $i (keys %i) { - $depends_simple{$page}{lc $i} |= $i{$i}; - } - } - } - elsif (defined $firstfail) { - # Add influences from one failure. (Which one should not - # matter; all should have the same influences.) - my %i=$firstfail->influences; - foreach my $i (keys %i) { - $depends_simple{$page}{lc $i} |= $i{$i}; - } - - error(sprintf(gettext("cannot match pages: %s"), $firstfail)) - if $firstfail->isa("IkiWiki::ErrorReason"); - } - - return @ret; -} - sub deptype (@) { my $deptype=0; foreach my $type (@_) { @@ -2055,27 +1970,95 @@ sub pagespec_match ($$;@) { } sub pagespec_match_list ($$;@) { - my $pages=shift; - my $spec=shift; - my @params=@_; + my $page=shift; + my $pagespec=shift; + my %params=@_; - my $sub=pagespec_translate($spec); - error "syntax error in pagespec \"$spec\"" + # Backwards compatability with old calling convention. + if (ref $page) { + print STDERR "warning: a plugin (".caller().") is using pagespec_match_list in an obsolete way, and needs to be updated\n"; + $params{list}=$page; + $page=$params{location}; # ugh! + } + + my $sub=pagespec_translate($pagespec); + error "syntax error in pagespec \"$pagespec\"" if $@ || ! defined $sub; + + my @candidates; + if (exists $params{limit}) { + @candidates=grep { $params{limit}->($_) } keys %pagesources; + } + else { + @candidates=keys %pagesources; + } + + if (defined $params{sort}) { + my $f; + if ($params{sort} eq 'title') { + $f=sub { pagetitle(basename($a)) cmp pagetitle(basename($b)) }; + } + elsif ($params{sort} eq 'title_natural') { + eval q{use Sort::Naturally}; + if ($@) { + error(gettext("Sort::Naturally needed for title_natural sort")); + } + $f=sub { Sort::Naturally::ncmp(pagetitle(basename($a)), pagetitle(basename($b))) }; + } + elsif ($params{sort} eq 'mtime') { + $f=sub { $pagemtime{$b} <=> $pagemtime{$a} }; + } + elsif ($params{sort} eq 'age') { + $f=sub { $pagectime{$b} <=> $pagectime{$a} }; + } + else { + error sprintf(gettext("unknown sort type %s"), $params{sort}); + } + @candidates = sort { &$f } @candidates; + } + + @candidates=reverse(@candidates) if $params{reverse}; - my @ret; - my $r; - foreach my $page (@$pages) { - $r=$sub->($page, @params); - push @ret, $page if $r; + my @matches; + my $firstfail; + my $count=0; + foreach my $p (@candidates) { + my $r=$sub->($p, location => $page); + if ($r) { + push @matches, [$p, $r]; + last if defined $params{num} && ++$count == $params{num}; + } + elsif (! defined $firstfail) { + $firstfail=$r; + } } + + $depends{$page}{$pagespec} |= ($params{deptype} || $DEPEND_CONTENT); - if (! @ret && defined $r && $r->isa("IkiWiki::ErrorReason")) { - error(sprintf(gettext("cannot match pages: %s"), $r)); + my @ret; + if (@matches) { + # Add all influences from successful matches. + foreach my $m (@matches) { + push @ret, $m->[0]; + my %i=$m->[1]->influences; + foreach my $i (keys %i) { + $depends_simple{$page}{lc $i} |= $i{$i}; + } + } } - else { - return @ret; + elsif (defined $firstfail) { + # Add influences from one failure. (Which one should not + # matter; all should have the same influences.) + my %i=$firstfail->influences; + foreach my $i (keys %i) { + $depends_simple{$page}{lc $i} |= $i{$i}; + } + + error(sprintf(gettext("cannot match pages: %s"), $firstfail)) + if $firstfail->isa("IkiWiki::ErrorReason"); } + + return @ret; } sub pagespec_valid ($) { diff --git a/IkiWiki/Plugin/calendar.pm b/IkiWiki/Plugin/calendar.pm index a89175cfb..c50d038df 100644 --- a/IkiWiki/Plugin/calendar.pm +++ b/IkiWiki/Plugin/calendar.pm @@ -74,7 +74,7 @@ sub format_month (@) { my $nyear = $params{nyear}; my %linkcache; - foreach my $p (use_pagespec($params{page}, $params{pagespec}, + foreach my $p (pagespec_match_list($params{page}, $params{pagespec}, # add presence dependencies to update # month calendar when pages are added/removed deptype => deptype("presence"))) { diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm index c02137aed..815a37838 100644 --- a/IkiWiki/Plugin/inline.pm +++ b/IkiWiki/Plugin/inline.pm @@ -216,7 +216,7 @@ sub preprocess_inline (@) { $num+=$params{skip}; } - @list = use_pagespec($params{page}, $params{pages}, + @list = pagespec_match_list($params{page}, $params{pages}, deptype => deptype($quick ? "presence" : "content"), limit => sub { $_[0] ne $params{page} }, sort => exists $params{sort} ? $params{sort} : "age", @@ -245,9 +245,11 @@ sub preprocess_inline (@) { } if ($feeds && exists $params{feedpages}) { - @feedlist = use_pagespec($params{page}, "($params{pages}) and ($params{feedpages})", + @feedlist = pagespec_match_list( + $params{page}, "($params{pages}) and ($params{feedpages})", deptype => deptype($quick ? "presence" : "content"), - list => \@feedlist); + list => \@feedlist, + ); } my ($feedbase, $feednum); diff --git a/IkiWiki/Plugin/map.pm b/IkiWiki/Plugin/map.pm index 634b0e4d6..788b96827 100644 --- a/IkiWiki/Plugin/map.pm +++ b/IkiWiki/Plugin/map.pm @@ -36,7 +36,8 @@ sub preprocess (@) { # Get all the items to map. my %mapitems; - foreach my $page (use_pagespec($params{page}, $params{pages}, deptype => $deptype)) { + foreach my $page (pagespec_match_list($params{page}, $params{pages}, + deptype => $deptype)) { if (exists $params{show} && exists $pagestate{$page} && exists $pagestate{$page}{meta}{$params{show}}) { diff --git a/IkiWiki/Plugin/orphans.pm b/IkiWiki/Plugin/orphans.pm index 607239500..b1ebd1b9d 100644 --- a/IkiWiki/Plugin/orphans.pm +++ b/IkiWiki/Plugin/orphans.pm @@ -28,7 +28,7 @@ sub preprocess (@) { # considering as orphans. add_depends($params{page}, "*", deptype("links")); - my @orphans=use_pagespec($params{page}, $params{pages}, + my @orphans=pagespec_match_list($params{page}, $params{pages}, # update when orphans are added/removed deptype => deptype("presence"), limit => sub { diff --git a/IkiWiki/Plugin/pagecount.pm b/IkiWiki/Plugin/pagecount.pm index 40474b2a1..8d36f057e 100644 --- a/IkiWiki/Plugin/pagecount.pm +++ b/IkiWiki/Plugin/pagecount.pm @@ -32,7 +32,7 @@ sub preprocess (@) { return scalar keys %pagesources; } - return scalar use_pagespec($params{page}, $pages, + return scalar pagespec_match_list($params{page}, $pages, deptype => deptype("presence")); } diff --git a/IkiWiki/Plugin/pagestats.pm b/IkiWiki/Plugin/pagestats.pm index e64f7d9c3..47638210a 100644 --- a/IkiWiki/Plugin/pagestats.pm +++ b/IkiWiki/Plugin/pagestats.pm @@ -37,16 +37,17 @@ sub preprocess (@) { my %counts; my $max = 0; - foreach my $page (use_pagespec($params{page}, $params{pages}, - # update when a displayed page is added or removed - deptype => deptype("presence"))) { + foreach my $page (pagespec_match_list($params{page}, $params{pages}, + # update when a displayed page is added/removed + deptype => deptype("presence"))) { use IkiWiki::Render; my @backlinks = IkiWiki::backlink_pages($page); if (exists $params{among}) { # only consider backlinks from the amoung pages - @backlinks = use_pagespec($params{page}, $params{among}, + @backlinks = pagespec_match_list( + $params{page}, $params{among}, # update whenever links on those pages change deptype => deptype("links"), list => \@backlinks diff --git a/IkiWiki/Plugin/postsparkline.pm b/IkiWiki/Plugin/postsparkline.pm index f51e309c8..1d4532366 100644 --- a/IkiWiki/Plugin/postsparkline.pm +++ b/IkiWiki/Plugin/postsparkline.pm @@ -54,7 +54,7 @@ sub preprocess (@) { } my @list=sort { $params{timehash}->{$b} <=> $params{timehash}->{$a} } - use_pagespec($params{page}, $params{pages}, + pagespec_match_list($params{page}, $params{pages}, deptype => $deptype, limit => sub { $_[0] ne $params{page} }, ); diff --git a/debian/changelog b/debian/changelog index 3a6fdf77d..49809e6cf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -33,9 +33,9 @@ ikiwiki (3.14159266) UNRELEASED; urgency=low info. * Plugins providing PageSpec `match_*` functions should pass additional influence information when creating result objects. - * Added `use_pagespec` function, that plugins can use to find a list - of matching pages and add dependencies and influences, all at once, - and efficiently. + * API change: `pagespec_match_list` has completly changed its interface. + The old interface will be removed soon, and a warning will be printed + if any plugins try to use it. * Optimize away most expensive file prune calls, when refreshing, by only checking new files. diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 62bebbeed..f6ea76c36 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -625,16 +625,16 @@ dependency type from one or more of these keywords: If multiple types are specified, they are combined. -#### `use_pagespec($$;@)` +#### `pagespec_match_list($$;@)` Passed a page name, and [[ikiwiki/PageSpec]], returns a list of pages in the wiki that match the [[ikiwiki/PageSpec]]. The page will automatically be made to depend on the specified [[ikiwiki/PageSpec]], so `add_depends` does not need to be called. This -is significantly more efficient than calling `add_depends` -followed by `pagespec_match_list`. You should use this anytime a plugin -needs to match a set of pages and generate something based on that list. +is significantly more efficient than calling `add_depends` and +`pagespec_match` in a loop. You should use this anytime a plugin +needs to match a set of pages and do something based on that list. Additional named parameters can be specified: @@ -650,6 +650,9 @@ Additional named parameters can be specified: * `list` makes it only match amoung the specified list of pages. Default is to match amoung all pages in the wiki. +Unlike pagespec_match, this may throw an error if there is an error in +the pagespec. + #### `add_depends($$;$)` Makes the specified page depend on the specified [[ikiwiki/PageSpec]]. @@ -672,19 +675,6 @@ The most often used is "location", which specifies the location the PageSpec should match against. If not passed, relative PageSpecs will match relative to the top of the wiki. -#### `pagespec_match_list($$;@)` - -Passed a reference to a list of page names, and [[ikiwiki/PageSpec]], -returns the set of pages that match the [[ikiwiki/PageSpec]]. - -Additional named parameters can be passed, to further limit the match. -The most often used is "location", which specifies the location the -PageSpec should match against. If not passed, relative PageSpecs will match -relative to the top of the wiki. - -Unlike pagespec_match, this may throw an error if there is an error in -the pagespec. - #### `bestlink($$)` Given a page and the text of a link on the page, determine which diff --git a/t/pagespec_match_list.t b/t/pagespec_match_list.t new file mode 100755 index 000000000..85a30b542 --- /dev/null +++ b/t/pagespec_match_list.t @@ -0,0 +1,31 @@ +#!/usr/bin/perl +use warnings; +use strict; +use Test::More tests => 10; + +BEGIN { use_ok("IkiWiki"); } + +%pagesources=( + foo => "foo.mdwn", + bar => "bar.mdwn", + "post/1" => "post/1.mdwn", + "post/2" => "post/2.mdwn", + "post/3" => "post/3.mdwn", +); + +is_deeply([pagespec_match_list("foo", "bar")], ["bar"]); +is_deeply([sort(pagespec_match_list("foo", "post/*"))], ["post/1", "post/2", "post/3"]); +is_deeply([pagespec_match_list("foo", "post/*", sort => "title", reverse => 1)], + ["post/3", "post/2", "post/1"]); +is_deeply([pagespec_match_list("foo", "post/*", sort => "title", num => 2)], + ["post/1", "post/2"]); +is_deeply([pagespec_match_list("foo", "post/*", sort => "title", num => 50)], + ["post/1", "post/2", "post/3"]); +is_deeply([pagespec_match_list("foo", "post/*", sort => "title", + limit => sub { $_[0] !~ /3/}) ], + ["post/1", "post/2"]); +my $r=eval { pagespec_match_list("foo", "beep") }; +ok(eval { pagespec_match_list("foo", "beep") } == 0); +ok(! $@, "does not fail with error when unable to match anything"); +eval { pagespec_match_list("foo", "this is not a legal pagespec!") }; +ok($@, "fails with error when pagespec bad"); diff --git a/t/use_pagespec.t b/t/use_pagespec.t deleted file mode 100755 index 92d7977cf..000000000 --- a/t/use_pagespec.t +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/perl -use warnings; -use strict; -use Test::More tests => 10; - -BEGIN { use_ok("IkiWiki"); } - -%pagesources=( - foo => "foo.mdwn", - bar => "bar.mdwn", - "post/1" => "post/1.mdwn", - "post/2" => "post/2.mdwn", - "post/3" => "post/3.mdwn", -); - -is_deeply([use_pagespec("foo", "bar")], ["bar"]); -is_deeply([sort(use_pagespec("foo", "post/*"))], ["post/1", "post/2", "post/3"]); -is_deeply([use_pagespec("foo", "post/*", sort => "title", reverse => 1)], - ["post/3", "post/2", "post/1"]); -is_deeply([use_pagespec("foo", "post/*", sort => "title", num => 2)], - ["post/1", "post/2"]); -is_deeply([use_pagespec("foo", "post/*", sort => "title", num => 50)], - ["post/1", "post/2", "post/3"]); -is_deeply([use_pagespec("foo", "post/*", sort => "title", - limit => sub { $_[0] !~ /3/}) ], - ["post/1", "post/2"]); -my $r=eval { use_pagespec("foo", "beep") }; -ok(eval { use_pagespec("foo", "beep") } == 0); -ok(! $@, "does not fail with error when unable to match anything"); -eval { use_pagespec("foo", "this is not a legal pagespec!") }; -ok($@, "fails with error when pagespec bad"); -- cgit v1.2.3 From 769b78df078d0287a10166ce828941a491858ff2 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 9 Oct 2009 13:02:10 -0400 Subject: pagespec_match_list allow additional pagespec limit parameters again --- IkiWiki.pm | 12 ++++++++---- doc/plugins/write.mdwn | 7 +++++-- 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'doc/plugins') diff --git a/IkiWiki.pm b/IkiWiki.pm index 475e278c3..f959d868b 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -2019,21 +2019,25 @@ sub pagespec_match_list ($$;@) { @candidates=reverse(@candidates) if $params{reverse}; + $depends{$page}{$pagespec} |= ($params{deptype} || $DEPEND_CONTENT); + + # clear params, remainder is passed to pagespec + my $num=$params{num}; + delete @params{qw{num deptype reverse sort limit}}; + my @matches; my $firstfail; my $count=0; foreach my $p (@candidates) { - my $r=$sub->($p, location => $page); + my $r=$sub->($p, %params, location => $page); if ($r) { push @matches, [$p, $r]; - last if defined $params{num} && ++$count == $params{num}; + last if defined $num && ++$count == $num; } elsif (! defined $firstfail) { $firstfail=$r; } } - - $depends{$page}{$pagespec} |= ($params{deptype} || $DEPEND_CONTENT); my @ret; if (@matches) { diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index f6ea76c36..9661bf4de 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -636,6 +636,9 @@ is significantly more efficient than calling `add_depends` and `pagespec_match` in a loop. You should use this anytime a plugin needs to match a set of pages and do something based on that list. +Unlike pagespec_match, this may throw an error if there is an error in +the pagespec. + Additional named parameters can be specified: * `deptype` optionally specifies the type of dependency to add. Use the @@ -650,8 +653,8 @@ Additional named parameters can be specified: * `list` makes it only match amoung the specified list of pages. Default is to match amoung all pages in the wiki. -Unlike pagespec_match, this may throw an error if there is an error in -the pagespec. +Any other named parameters are passed on to `pagespec_match`, to further +limit the match. #### `add_depends($$;$)` -- cgit v1.2.3 From 6f2cc5ac8cc7e76b3faf20cd7516f82bcb3de7ed Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 9 Oct 2009 13:20:41 -0400 Subject: pagespec_match_list: change limit to filter --- IkiWiki.pm | 6 +++--- IkiWiki/Plugin/inline.pm | 2 +- IkiWiki/Plugin/orphans.pm | 10 +++++----- IkiWiki/Plugin/postsparkline.pm | 2 +- doc/plugins/write.mdwn | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) (limited to 'doc/plugins') diff --git a/IkiWiki.pm b/IkiWiki.pm index f959d868b..49c76c4d4 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1986,8 +1986,8 @@ sub pagespec_match_list ($$;@) { if $@ || ! defined $sub; my @candidates; - if (exists $params{limit}) { - @candidates=grep { $params{limit}->($_) } keys %pagesources; + if (exists $params{filter}) { + @candidates=grep { ! $params{filter}->($_) } keys %pagesources; } else { @candidates=keys %pagesources; @@ -2023,7 +2023,7 @@ sub pagespec_match_list ($$;@) { # clear params, remainder is passed to pagespec my $num=$params{num}; - delete @params{qw{num deptype reverse sort limit}}; + delete @params{qw{num deptype reverse sort filter}}; my @matches; my $firstfail; diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm index 815a37838..0fe0bd2e1 100644 --- a/IkiWiki/Plugin/inline.pm +++ b/IkiWiki/Plugin/inline.pm @@ -218,7 +218,7 @@ sub preprocess_inline (@) { @list = pagespec_match_list($params{page}, $params{pages}, deptype => deptype($quick ? "presence" : "content"), - limit => sub { $_[0] ne $params{page} }, + filter => sub { $_[0] eq $params{page} }, sort => exists $params{sort} ? $params{sort} : "age", reverse => yesno($params{reverse}), num => $num, diff --git a/IkiWiki/Plugin/orphans.pm b/IkiWiki/Plugin/orphans.pm index b1ebd1b9d..702943f87 100644 --- a/IkiWiki/Plugin/orphans.pm +++ b/IkiWiki/Plugin/orphans.pm @@ -31,24 +31,24 @@ sub preprocess (@) { my @orphans=pagespec_match_list($params{page}, $params{pages}, # update when orphans are added/removed deptype => deptype("presence"), - limit => sub { + filter => sub { my $page=shift; # Filter out pages that other pages link to. - return 0 if IkiWiki::backlink_pages($page); + return 1 if IkiWiki::backlink_pages($page); # Toplevel index is assumed to never be orphaned. - return 0 if $page eq 'index'; + return 1 if $page eq 'index'; # If the page has a link to some other page, it's # indirectly linked via that page's backlinks. - return 0 if grep { + return 1 if grep { length $_ && ($_ !~ /\/\Q$config{discussionpage}\E$/i || ! $config{discussion}) && bestlink($page, $_) !~ /^(\Q$page\E|)$/ } @{$links{$page}}; - return 1; + return 0; }, ); diff --git a/IkiWiki/Plugin/postsparkline.pm b/IkiWiki/Plugin/postsparkline.pm index 1d4532366..0d5a12e33 100644 --- a/IkiWiki/Plugin/postsparkline.pm +++ b/IkiWiki/Plugin/postsparkline.pm @@ -56,7 +56,7 @@ sub preprocess (@) { my @list=sort { $params{timehash}->{$b} <=> $params{timehash}->{$a} } pagespec_match_list($params{page}, $params{pages}, deptype => $deptype, - limit => sub { $_[0] ne $params{page} }, + filter => sub { $_[0] eq $params{page} }, ); my @data=eval qq{IkiWiki::Plugin::postsparkline::formula::$formula(\\\%params, \@list)}; diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 9661bf4de..2254d7025 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -643,8 +643,8 @@ Additional named parameters can be specified: * `deptype` optionally specifies the type of dependency to add. Use the `deptype` function to generate a dependency type. -* `limit` is a reference to a function, that is called and passed a page, - and must return true for the page to be included. +* `filter` is a reference to a function, that is called and passed a page, + and returns true if the page should be filtered out of the list. * `sort` specifies a sort order for the list. See [[ikiwiki/PageSpec/sorting]] for the avilable sort methods. * `reverse` if true, sorts in reverse. -- cgit v1.2.3 From 74409f940d24f51a08becb626e266c91d40d69bd Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 9 Oct 2009 17:15:40 -0400 Subject: add_depends: optimise influence calculation I made match_* functions whose influences can vary depending on the page matched set a special "" influence to indicate this. Then add_depends can try just one page, and if static influences are found, stop there. --- IkiWiki.pm | 52 +++++++++++++++++++++++++------------------------- IkiWiki/Plugin/meta.pm | 6 +++--- doc/plugins/write.mdwn | 2 +- 3 files changed, 30 insertions(+), 30 deletions(-) (limited to 'doc/plugins') diff --git a/IkiWiki.pm b/IkiWiki.pm index c67a1e138..cd93fe969 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1780,19 +1780,17 @@ sub add_depends ($$;$) { return 1; } - # Analyse the pagespec, and match it against all pages - # to get a list of influences, and add explicit dependencies - # for those. - #my $sub=pagespec_translate($pagespec); - #return if $@; - #foreach my $p (keys %pagesources) { - # my $r=$sub->($p, location => $page ); - # my %i=$r->influences; - # foreach my $i (keys %i) { - # $depends_simple{$page}{lc $i} |= $i{$i}; - # } - #} - print STDERR "warning: use of add_depends by ".caller()."; influences not tracked\n"; + # Add explicit dependencies for influences. + my $sub=pagespec_translate($pagespec); + return if $@; + foreach my $p (keys %pagesources) { + my $r=$sub->($p, location => $page); + my $i=$r->influences; + foreach my $k (keys %$i) { + $depends_simple{$page}{lc $k} |= $i->{$k}; + } + last if $r->influences_static; + } $depends{$page}{$pagespec} |= $deptype; return 1; @@ -2045,9 +2043,9 @@ sub pagespec_match_list ($$;@) { } # Add simple dependencies for accumulated influences. - my %i=$accum->influences; - foreach my $i (keys %i) { - $depends_simple{$page}{lc $i} |= $i{$i}; + my $i=$accum->influences; + foreach my $k (keys %$i) { + $depends_simple{$page}{lc $k} |= $i->{$k}; } return @matches; @@ -2099,12 +2097,14 @@ sub new { sub influences { my $this=shift; - if (! @_) { - return %{$this->[1]}; - } - else { - $this->[1]={@_}; - } + $this->[1]={@_} if @_; + my %i=%{$this->[1]}; + delete $i{""}; + return \%i; +} + +sub influences_static { + return ! $_[0][1]->{""}; } sub merge_influences { @@ -2173,19 +2173,19 @@ sub match_link ($$;@) { my $bestlink = IkiWiki::bestlink($from, $link); foreach my $p (@{$links}) { if (length $bestlink) { - return IkiWiki::SuccessReason->new("$page links to $link", $page => $IkiWiki::DEPEND_LINKS) + return IkiWiki::SuccessReason->new("$page links to $link", $page => $IkiWiki::DEPEND_LINKS, "" => 1) if $bestlink eq IkiWiki::bestlink($page, $p); } else { - return IkiWiki::SuccessReason->new("$page links to page $p matching $link", $page => $IkiWiki::DEPEND_LINKS) + return IkiWiki::SuccessReason->new("$page links to page $p matching $link", $page => $IkiWiki::DEPEND_LINKS, "" => 1) if match_glob($p, $link, %params); my ($p_rel)=$p=~/^\/?(.*)/; $link=~s/^\///; - return IkiWiki::SuccessReason->new("$page links to page $p_rel matching $link", $page => $IkiWiki::DEPEND_LINKS) + return IkiWiki::SuccessReason->new("$page links to page $p_rel matching $link", $page => $IkiWiki::DEPEND_LINKS, "" => 1) if match_glob($p_rel, $link, %params); } } - return IkiWiki::FailReason->new("$page does not link to $link"); + return IkiWiki::FailReason->new("$page does not link to $link", "" => 1); } sub match_backlink ($$;@) { diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index c675880b3..8dcd73a1a 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -291,14 +291,14 @@ sub match { if (defined $val) { if ($val=~/^$re$/i) { - return IkiWiki::SuccessReason->new("$re matches $field of $page", $page => $IkiWiki::DEPEND_CONTENT); + return IkiWiki::SuccessReason->new("$re matches $field of $page", $page => $IkiWiki::DEPEND_CONTENT, "" => 1); } else { - return IkiWiki::FailReason->new("$re does not match $field of $page"); + return IkiWiki::FailReason->new("$re does not match $field of $page", "" => 1); } } else { - return IkiWiki::FailReason->new("$page does not have a $field"); + return IkiWiki::FailReason->new("$page does not have a $field", "" => 1); } } diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 2254d7025..c72418c3c 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -632,7 +632,7 @@ in the wiki that match the [[ikiwiki/PageSpec]]. The page will automatically be made to depend on the specified [[ikiwiki/PageSpec]], so `add_depends` does not need to be called. This -is significantly more efficient than calling `add_depends` and +is often significantly more efficient than calling `add_depends` and `pagespec_match` in a loop. You should use this anytime a plugin needs to match a set of pages and do something based on that list. -- cgit v1.2.3 From 5dba91cdc88c01ac1d314f24b12eb2cda651e206 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sun, 11 Oct 2009 13:51:23 -0400 Subject: typo --- doc/plugins/calendar.mdwn | 2 +- t/pagespec_match_result.t | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'doc/plugins') diff --git a/doc/plugins/calendar.mdwn b/doc/plugins/calendar.mdwn index d695762b7..8ade70004 100644 --- a/doc/plugins/calendar.mdwn +++ b/doc/plugins/calendar.mdwn @@ -6,7 +6,7 @@ The directive displays a calendar, similar to the typical calendars shown on some blogs. Since ikiwiki is a wiki compiler, to keep the calendar up-to-date, -wikis that include it need to be periodically refreshes, typically by cron +wikis that include it need to be periodically refreshed, typically by cron at midnight. Example crontab: 0 0 * * * ikiwiki -setup ~/ikiwiki.setup -refresh diff --git a/t/pagespec_match_result.t b/t/pagespec_match_result.t index d9c31d6f0..c2112bf14 100755 --- a/t/pagespec_match_result.t +++ b/t/pagespec_match_result.t @@ -57,3 +57,21 @@ ok(! $s->influences->{foo}, "removed 0 influence"); ok(! $s->influences->{bar}, "removed 1 influence"); ok($s->influences->{baz}, "set influence"); ok($s->influences_static); + +# influence blocking +my $r=F()->block & S(foo => 1); +ok(! $r->influences->{foo}, "failed blocker & influence -> does not pass"); +$r=F()->block | S(foo => 1); +ok($r->influences->{foo}, "failed blocker | influence -> does pass"); +$r=S(foo => 1) & F()->block; +ok(! $r->influences->{foo}, "influence & failed blocker -> does not pass"); +$r=S(foo => 1) | F()->block; +ok($r->influences->{foo}, "influence | failed blocker -> does pass"); +$r=S(foo => 1) & F()->block & S(foo => 2); +ok(! $r->influences->{foo}, "influence & failed blocker & influence -> does not pass"); +$r=S(foo => 1) | F()->block | S(foo => 2); +ok($r->influences->{foo}, "influence | failed blocker | influence -> does pass"); +$r=S()->block & S(foo => 1); +ok($r->influences->{foo}, "successful blocker -> does pass"); +$r=(! S()->block) & S(foo => 1); +ok(! $r->influences->{foo}, "! successful blocker -> failed blocker"); -- cgit v1.2.3