]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blobdiff - IkiWiki/Plugin/aggregate.pm
Merge branch 'master' of ssh://git.ikiwiki.info/srv/git/ikiwiki.info
[git.ikiwiki.info.git] / IkiWiki / Plugin / aggregate.pm
index 29bc6d0ceba8349f9db5d49e223b1293882e32c7..fe53d868dbad39d455f59b45c91af54b4ee156cd 100644 (file)
@@ -4,7 +4,7 @@ package IkiWiki::Plugin::aggregate;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use HTML::Parser;
 use HTML::Tagset;
 use HTML::Entities;
@@ -46,7 +46,7 @@ sub getsetup () {
                },
                aggregateinternal => {
                        type => "boolean",
-                       example => 0,
+                       example => 1,
                        description => "enable aggregation to internal pages?",
                        safe => 0, # enabling needs manual transition
                        rebuild => 0,
@@ -61,6 +61,10 @@ sub getsetup () {
 }
 
 sub checkconfig () {
+       if (! defined $config{aggregateinternal}) {
+               $config{aggregateinternal}=1;
+       }
+
        if ($config{aggregate} && ! ($config{post_commit} && 
                                     IkiWiki::commit_hook_enabled())) {
                launchaggregation();
@@ -206,6 +210,8 @@ sub needsbuild (@) {
                        markunseen($feed->{sourcepage});
                }
        }
+
+       return $needsbuild;
 }
 
 sub preprocess (@) {
@@ -245,6 +251,7 @@ sub preprocess (@) {
        $feed->{template}=$params{template} . ".tmpl";
        delete $feed->{unseen};
        $feed->{lastupdate}=0 unless defined $feed->{lastupdate};
+       $feed->{lasttry}=$feed->{lastupdate} unless defined $feed->{lasttry};
        $feed->{numposts}=0 unless defined $feed->{numposts};
        $feed->{newposts}=0 unless defined $feed->{newposts};
        $feed->{message}=gettext("new feed") unless defined $feed->{message};
@@ -293,7 +300,7 @@ sub loadstate () {
        return if $state_loaded;
        $state_loaded=1;
        if (-e "$config{wikistatedir}/aggregate") {
-               open(IN, "$config{wikistatedir}/aggregate") ||
+               open(IN, "<", "$config{wikistatedir}/aggregate") ||
                        die "$config{wikistatedir}/aggregate: $!";
                while (<IN>) {
                        $_=IkiWiki::possibly_foolish_untaint($_);
@@ -330,7 +337,7 @@ sub savestate () {
        garbage_collect();
        my $newfile="$config{wikistatedir}/aggregate.new";
        my $cleanup = sub { unlink($newfile) };
-       open (OUT, ">$newfile") || error("open $newfile: $!", $cleanup);
+       open (OUT, ">", $newfile) || error("open $newfile: $!", $cleanup);
        foreach my $data (values %feeds, values %guids) {
                my @line;
                foreach my $field (keys %$data) {
@@ -342,7 +349,8 @@ sub savestate () {
                                push @line, "tag=$_" foreach @{$data->{tags}};
                        }
                        else {
-                               push @line, "$field=".$data->{$field};
+                               push @line, "$field=".$data->{$field}
+                                       if defined $data->{$field};
                        }
                }
                print OUT join(" ", @line)."\n" || error("write $newfile: $!", $cleanup);
@@ -350,6 +358,20 @@ sub savestate () {
        close OUT || error("save $newfile: $!", $cleanup);
        rename($newfile, "$config{wikistatedir}/aggregate") ||
                error("rename $newfile: $!", $cleanup);
+
+       my $timestamp=undef;
+       foreach my $feed (keys %feeds) {
+               my $t=$feeds{$feed}->{lastupdate}+$feeds{$feed}->{updateinterval};
+               if (! defined $timestamp || $timestamp > $t) {
+                       $timestamp=$t;
+               }
+       }
+       $newfile=~s/\.new$/time/;
+       open (OUT, ">", $newfile) || error("open $newfile: $!", $cleanup);
+       if (defined $timestamp) {
+               print OUT $timestamp."\n";
+       }
+       close OUT || error("save $newfile: $!", $cleanup);
 }
 
 sub garbage_collect () {
@@ -390,14 +412,15 @@ sub mergestate () {
        # fields.
        foreach my $name (keys %myfeeds) {
                if (exists $feeds{$name}) {
-                       foreach my $field (qw{message lastupdate numposts
-                                             newposts error}) {
+                       foreach my $field (qw{message lastupdate lasttry
+                                             numposts newposts error}) {
                                $feeds{$name}->{$field}=$myfeeds{$name}->{$field};
                        }
                }
        }
 
        # New guids can be created during aggregation.
+       # Guids have a few fields that may be updated during aggregation.
        # It's also possible that guids were removed from the on-disk state
        # while the aggregation was in process. That would only happen if
        # their feed was also removed, so any removed guids added back here
@@ -406,6 +429,11 @@ sub mergestate () {
                if (! exists $guids{$guid}) {
                        $guids{$guid}=$myguids{$guid};
                }
+               else {
+                       foreach my $field (qw{md5}) {
+                               $guids{$guid}->{$field}=$myguids{$guid}->{$field};
+                       }
+               }
        }
 }
 
@@ -458,10 +486,10 @@ sub aggregate (@) {
        error($@) if $@;
 
        foreach my $feed (@_) {
-               $feed->{lastupdate}=time;
+               $feed->{lasttry}=time;
                $feed->{newposts}=0;
                $feed->{message}=sprintf(gettext("last checked %s"),
-                       displaytime($feed->{lastupdate}));
+                       displaytime($feed->{lasttry}));
                $feed->{error}=0;
 
                debug(sprintf(gettext("checking feed %s ..."), $feed->{name}));
@@ -483,6 +511,10 @@ sub aggregate (@) {
                        debug($feed->{message});
                        next;
                }
+
+               # lastupdate is only set if we were able to contact the server
+               $feed->{lastupdate}=$feed->{lasttry};
+
                if ($res->status == URI::Fetch::URI_GONE()) {
                        $feed->{message}=gettext("feed not found");
                        $feed->{error}=1;
@@ -524,6 +556,11 @@ sub aggregate (@) {
                }
 
                foreach my $entry ($f->entries) {
+                       # XML::Feed doesn't work around XML::Atom's bizarre
+                       # API, so we will. Real unicode strings? Yes please.
+                       # See [[bugs/Aggregated_Atom_feeds_are_double-encoded]]
+                       local $XML::Atom::ForceUnicode = 1;
+
                        my $c=$entry->content;
                        # atom feeds may have no content, only a summary
                        if (! defined $c && ref $entry->summary) {
@@ -629,11 +666,13 @@ sub add_page (@) {
                # creation time on record for the new page.
                utime $mtime, $mtime, "$config{srcdir}/".htmlfn($guid->{page});
                # Store it in pagectime for expiry code to use also.
-               $IkiWiki::pagectime{$guid->{page}}=$mtime;
+               $IkiWiki::pagectime{$guid->{page}}=$mtime
+                       unless exists $IkiWiki::pagectime{$guid->{page}};
        }
        else {
                # Dummy value for expiry code.
-               $IkiWiki::pagectime{$guid->{page}}=time;
+               $IkiWiki::pagectime{$guid->{page}}=time
+                       unless exists $IkiWiki::pagectime{$guid->{page}};
        }
 }