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;
if $@ || ! defined $sub;
my @candidates;
- if (exists $params{filter}) {
- @candidates=grep { ! $params{filter}->($_) } keys %pagesources;
+ if (exists $params{list}) {
+ @candidates=exists $params{filter}
+ ? grep { ! $params{filter}->($_) } @{$params{list}}
+ : @{$params{list}};
}
else {
- @candidates=keys %pagesources;
+ @candidates=exists $params{filter}
+ ? grep { ! $params{filter}->($_) } keys %pagesources
+ : keys %pagesources;
}
if (defined $params{sort}) {
# clear params, remainder is passed to pagespec
my $num=$params{num};
- delete @params{qw{num deptype reverse sort filter}};
+ delete @params{qw{num deptype reverse sort filter list}};
my @matches;
my $firstfail;
my $count=0;
+ my $accum=IkiWiki::SuccessReason->new();
foreach my $p (@candidates) {
my $r=$sub->($p, %params, location => $page);
+ error(sprintf(gettext("cannot match pages: %s"), $r))
+ if $r->isa("IkiWiki::ErrorReason");
+ $accum |= $r;
if ($r) {
- push @matches, [$p, $r];
+ push @matches, $p;
last if defined $num && ++$count == $num;
}
- elsif (! defined $firstfail) {
- $firstfail=$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};
- }
- }
}
- 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");
+ # Add simple dependencies for accumulated influences.
+ my $i=$accum->influences;
+ foreach my $k (keys %$i) {
+ $depends_simple{$page}{lc $k} |= $i->{$k};
}
- return @ret;
+ return @matches;
}
sub pagespec_valid ($) {
'""' => sub { $_[0][0] },
'0+' => sub { 0 },
'!' => sub { bless $_[0], 'IkiWiki::SuccessReason'},
- '&' => sub { $_[0]->merge_influences($_[1]); $_[0] },
+ '&' => sub { $_[0]->merge_influences($_[1], 1); $_[0] },
'|' => sub { $_[1]->merge_influences($_[0]); $_[1] },
fallback => 1,
);
'""' => sub { $_[0][0] },
'0+' => sub { 1 },
'!' => sub { bless $_[0], 'IkiWiki::FailReason'},
- '&' => sub { $_[1]->merge_influences($_[0]); $_[1] },
+ '&' => sub { $_[1]->merge_influences($_[0], 1); $_[1] },
'|' => sub { $_[0]->merge_influences($_[1]); $_[0] },
fallback => 1,
);
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 {
my $this=shift;
my $other=shift;
- foreach my $influence (keys %{$other->[1]}) {
- $this->[1]{$influence} |= $other->[1]{$influence};
+ my $anded=shift;
+
+ if (! $anded || (($this || %{$this->[1]}) &&
+ ($other || %{$other->[1]}))) {
+ foreach my $influence (keys %{$other->[1]}) {
+ $this->[1]{$influence} |= $other->[1]{$influence};
+ }
+ }
+ else {
+ # influence blocker
+ print STDERR "merging $this and $other; found influence blocker\n";
+ $this->[1]={};
+ $this->[2]=1;
+ return;
}
}
my $from=exists $params{location} ? $params{location} : '';
my $links = $IkiWiki::links{$page};
- return IkiWiki::FailReason->new("$page has no links")
+ return IkiWiki::FailReason->new("$page has no links", "" => 1)
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 => $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 ($$;@) {