foreach my $p (keys %pagesources) {
my $r=$sub->($p, location => $page);
my $i=$r->influences;
+ my $static=$r->influences_static;
foreach my $k (keys %$i) {
+ next unless $r || $static || $k eq $page;
$depends_simple{$page}{lc $k} |= $i->{$k};
}
- last if $r->influences_static;
+ last if $static;
}
$depends{$page}{$pagespec} |= $deptype;
my $r=$sub->($p, %params, location => $page);
error(sprintf(gettext("cannot match pages: %s"), $r))
if $r->isa("IkiWiki::ErrorReason");
+ unless ($r) {
+ $r->remove_influence($p);
+ }
$accum |= $r;
if ($r) {
push @matches, $p;
my $anded=shift;
if (! $anded || (($this || %{$this->[1]}) &&
- ($other || %{$other->[1]}))) {
+ ($other || %{$other->[1]}))) {
foreach my $influence (keys %{$other->[1]}) {
$this->[1]{$influence} |= $other->[1]{$influence};
}
}
}
+sub remove_influence {
+ my $this=shift;
+ my $torm=shift;
+
+ delete $this->[1]{$torm};
+}
+
package IkiWiki::ErrorReason;
our @ISA = 'IkiWiki::FailReason';
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", "" => 1);
+ return IkiWiki::FailReason->new("$re does not match $field of $page", $page => $IkiWiki::DEPEND_CONTENT, "" => 1);
}
}
else {
- return IkiWiki::FailReason->new("$page does not have a $field", "" => 1);
+ return IkiWiki::FailReason->new("$page does not have a $field", $page => $IkiWiki::DEPEND_CONTENT);
}
}
-ikiwiki (3.20100406) unstable; urgency=low
+ikiwiki (3.20100422) unstable; urgency=low
This version of ikiwiki has a lot of changes that you need to know about.
-ikiwiki (3.20100415) UNRELEASED; urgency=low
+ikiwiki (3.20100422) UNRELEASED; urgency=low
[ Joey Hess ]
* tag: Automatic creation of tag pages can now be enabled using
$pagestate{index}.
* bzr: Support rcs_getmtime, and fix rcs_getctime implementation
(Jelmer Vernooij)
+ * Quite a lot of new optimisations, and one major fix to a recent
+ performance regression.
-- Joey Hess <joeyh@debian.org> Sun, 04 Apr 2010 12:17:11 -0400
# Change this when some incompatible change is made that requires
# rebuilding all wikis.
-firstcompat=3.20100410
+firstcompat=3.20100422
if [ "$1" = configure ] && \
dpkg --compare-versions "$2" lt "$firstcompat"; then
Ok.. Turns out this was not a problem with the actual influences
calculation or dependency calculation code. Whew! `match_link`
-just didn't set the influence correctly when failing. [[fixed|done]]
+just didn't set the influence correctly when failing. fixed
--[[Joey]]
+
+---
+
+Update: Reopening this because the fix for it rather sucks.
+
+I made `match_link` return on failure an influence of
+type DEPEND_LINKS. So, a tag page that inlines `tagged(foo)`
+gets a `depends_simple` built up that contains link dependencies for
+*every* page in the wiki. A very bloaty way to represent the dependency!
+
+Per [[todo/dependency_types]], `link(done)` only needs to list in
+`depends_simple` the pages that currently match. If a page is modified
+to add the link, the regular dependency calculation code notices that
+a new page matches. If a page that had the link is modified to remove it,
+the `depends_simple` lets ikiwiki remember that the now non-matching page
+matched before.
+
+Where that fell down was `!link(done)`. A page matching that was not added
+to `depends_simple`, because the `link(done)` did not match it. If the page
+is modified to add the link, the regular dependency calculation code
+didn't notice, since the pagespec no longer matched.
+
+In this case, `depends_simple` needs to contain all pages
+that do *not* match `link(done)`, but before my change, it contained
+all pages that *do* match. After my change, it contained all pages.
+
+----
+
+So, seems what is needed is a way for influence info to be manipulated by
+the boolean operations that are applied. One way would be to have two
+sets of influences be returned, one for successful matches, and one for
+failed matches. Normally, these would be the same. For successful
+`match_link`, the successful influence would be the page.
+For failed `match_link`, the failed influence would be the page.
+
+Then, when NOTting a `*Reason`, swap the two sets of influences.
+When ANDing/ORing, combine the individual sets. Querying the object for
+influences should return only the successful influences.
+
+----
+
+Would it be possible to avoid the complication of maintianing two sets of
+influence info?
+
+Well, notice that the influence of `pagespec_match($page, "link(done)")`
+is $page. Iff the match succeeds.
+
+Also, the influence of `pagespec_match($page, "!link(done)")` is
+$page. Iff the (overall) match succeeds.
+
+Does that hold for all cases? If so, the code that populates
+`depends_simple` could just test if the pagespec was successful, and
+if not, avoid adding $page influences, while still adding any other,
+non-$page influences.
+
+----
+
+Hmm, commit f2b3d1341447cbf29189ab490daae418fbe5d02d seems
+thuroughly wrong. So, what about influence info for other matches
+like `!author(foo)` etc? Currently, none is returned, but it should
+be a content influence. (Backlink influence data seems ok.)
+
+----
+
+[[done]] again!
[[!template id=gitbranch branch=origin/autotag author="[[Joey]]"]]
I've pushed an autotag branch of my own, which refactors
things a bit and fixes bugs around deletion/recreation.
-I've tested it somewhat. --[[Joey]]
+I've tested it fairly thouroughly. --[[Joey]]
[f3abeac919c4736429bd3362af6edf51ede8e7fe]: http://git.liegesta.at/?p=ikiwiki.git;a=commitdiff;h=f3abeac919c4736429bd3362af6edf51ede8e7fe (commitdiff for f3abeac919c4736429bd3362af6edf51ede8e7fe)
[4af4d26582f0c2b915d7102fb4a604b176385748]: http://git.liegesta.at/?p=ikiwiki.git;a=commitdiff;h=4af4d26582f0c2b915d7102fb4a604b176385748 (commitdiff for 4af4d26582f0c2b915d7102fb4a604b176385748)
#!/usr/bin/perl
use warnings;
use strict;
-use Test::More tests => 38;
+use Test::More tests => 40;
BEGIN { use_ok("IkiWiki"); }
%config=IkiWiki::defaultconfig();
ok(add_depends("foo9", "*", deptype("monkey")));
ok($IkiWiki::depends{foo9}{"*"} & $IkiWiki::DEPEND_CONTENT);
ok(! ($IkiWiki::depends{foo9}{"*"} & ($IkiWiki::DEPEND_PRESENCE | $IkiWiki::DEPEND_LINKS)));
+
+# Influences are added for dependencies involving links.
+$pagesources{"foo"}="foo.mdwn";
+$links{foo}=[qw{bar}];
+$pagesources{"bar"}="bar.mdwn";
+$links{bar}=[qw{}];
+ok(add_depends("foo", "link(bar) and backlink(meep)"));
+ok($IkiWiki::depends_simple{foo}{foo} == $IkiWiki::DEPEND_LINKS);
#!/usr/bin/perl
use warnings;
use strict;
-use Test::More tests => 94;
+use Test::More tests => 126;
BEGIN { use_ok("IkiWiki"); }
$IkiWiki::pagectime{foo} = 2;
$IkiWiki::pagectime{foo2} = 2;
$IkiWiki::pagectime{foo3} = 1;
+$IkiWiki::pagectime{foo4} = 1;
+$IkiWiki::pagectime{foo5} = 1;
$IkiWiki::pagectime{bar} = 3;
$IkiWiki::pagectime{"post/1"} = 6;
$IkiWiki::pagectime{"post/2"} = 6;
%IkiWiki::depends=();
}
+# A link pagespec is influenced by the pages that currently contain the link.
+# It is not influced by pages that do not currently contain the link,
+# because if those pages were changed to contain it, regular dependency
+# handling would be triggered.
+foreach my $spec ("* and link(bar)", "link(bar)", "no_such_page or link(bar)") {
+ pagespec_match_list("foo2", $spec);
+ ok($IkiWiki::depends_simple{foo2}{foo2} == $IkiWiki::DEPEND_LINKS);
+ ok(! exists $IkiWiki::depends_simple{foo2}{foo}, $spec);
+ %IkiWiki::depends_simple=();
+ %IkiWiki::depends=();
+}
+
+# Oppositely, a pagespec that tests for pages that do not have a link
+# is not influenced by pages that currently contain the link, but
+# is instead influenced by pages that currently do not (but that
+# could be changed to have it).
+foreach my $spec ("* and !link(bar)", "* and !(!(!link(bar)))") {
+ pagespec_match_list("foo2", $spec);
+ ok(! exists $IkiWiki::depends_simple{foo2}{foo2});
+ ok($IkiWiki::depends_simple{foo2}{foo} == $IkiWiki::DEPEND_LINKS, $spec);
+ %IkiWiki::depends_simple=();
+ %IkiWiki::depends=();
+}
+
# a pagespec with backlinks() will add as an influence the page with the links
-foreach my $spec ("bar or (backlink(foo) and !*.png)", "backlink(foo)") {
+foreach my $spec ("bar or (backlink(foo) and !*.png)", "backlink(foo)", "!backlink(foo)") {
pagespec_match_list("foo2", $spec, deptype => deptype("presence"));
ok($IkiWiki::depends{foo2}{$spec} & $IkiWiki::DEPEND_PRESENCE);
ok(! ($IkiWiki::depends{foo2}{$spec} & ($IkiWiki::DEPEND_CONTENT | $IkiWiki::DEPEND_LINKS)));
ok($IkiWiki::depends_simple{foo2}{foo} == $IkiWiki::DEPEND_LINKS);
+ ok(! exists $IkiWiki::depends_simple{foo2}{foo2});
%IkiWiki::depends_simple=();
%IkiWiki::depends=();
pagespec_match_list("foo2", $spec, deptype => deptype("links"));
ok($IkiWiki::depends{foo2}{$spec} & $IkiWiki::DEPEND_LINKS);
ok(! ($IkiWiki::depends{foo2}{$spec} & ($IkiWiki::DEPEND_PRESENCE | $IkiWiki::DEPEND_CONTENT)));
ok($IkiWiki::depends_simple{foo2}{foo} == $IkiWiki::DEPEND_LINKS);
+ ok(! exists $IkiWiki::depends_simple{foo2}{foo2});
%IkiWiki::depends_simple=();
%IkiWiki::depends=();
pagespec_match_list("foo2", $spec, deptype => deptype("presence", "links"));
ok($IkiWiki::depends{foo2}{$spec} & $IkiWiki::DEPEND_LINKS);
ok(! ($IkiWiki::depends{foo2}{$spec} & $IkiWiki::DEPEND_CONTENT));
ok($IkiWiki::depends_simple{foo2}{foo} == $IkiWiki::DEPEND_LINKS);
+ ok(! exists $IkiWiki::depends_simple{foo2}{foo2});
%IkiWiki::depends_simple=();
%IkiWiki::depends=();
pagespec_match_list("foo2", $spec);