# Copyright (C) 2013-2015 all contributors <meta@public-inbox.org>
# License: AGPLv3 or later (https://www.gnu.org/licenses/agpl-3.0.txt)
+#
+# Used for generating Atom feeds for web-accessible mailing list archives.
package PublicInbox::Feed;
use strict;
use warnings;
use Email::MIME;
use Date::Parse qw(strptime);
use PublicInbox::Hval;
-use PublicInbox::GitCatFile;
+use PublicInbox::Git;
use PublicInbox::View;
use PublicInbox::MID qw/mid_clean mid2path/;
use POSIX qw/strftime/;
use constant {
- DATEFMT => '%Y-%m-%dT%H:%M:%SZ', # atom standard
+ DATEFMT => '%Y-%m-%dT%H:%M:%SZ', # Atom standard
MAX_PER_PAGE => 25, # this needs to be tunable
};
my $max = $ctx->{max} || MAX_PER_PAGE;
my $feed_opts = get_feedopts($ctx);
my $x = atom_header($feed_opts);
- my $git = PublicInbox::GitCatFile->new($ctx->{git_dir});
+ my $git = $ctx->{git} ||= PublicInbox::Git->new($ctx->{git_dir});
each_recent_blob($ctx, sub {
my ($path, undef, $ts) = @_;
if (defined $x) {
- $fh->write($x . '<updated>' .
- strftime(DATEFMT, gmtime($ts)) .
- '</updated>');
+ $fh->write($x . feed_updated(undef, $ts));
$x = undef;
}
add_to_feed($feed_opts, $fh, $path, $git);
});
- $git = undef; # destroy pipes
- _end_feed($fh);
+ end_feed($fh);
}
sub _no_thread {
$fh->close;
}
-sub _end_feed {
+sub end_feed {
my ($fh) = @_;
Email::Address->purge_cache;
$fh->write('</feed>');
$feed_opts->{url} = $html_url;
$feed_opts->{emit_header} = 1;
- my $git = PublicInbox::GitCatFile->new($ctx->{git_dir});
+ my $git = $ctx->{git} ||= PublicInbox::Git->new($ctx->{git_dir});
foreach my $msg (@{$res->{msgs}}) {
add_to_feed($feed_opts, $fh, mid2path($msg->mid), $git);
}
- $git = undef; # destroy pipes
- _end_feed($fh);
+ end_feed($fh);
}
sub emit_html_index {
my $top = "<b>$title</b> (<a\nhref=\"$atom_url\">Atom feed</a>)";
if ($srch) {
- $top = qq{<form\naction=""><tt>$top} .
+ $top = qq{<form\naction=""><pre>$top} .
qq{ <input\nname=q\ntype=text />} .
qq{<input\ntype=submit\nvalue=search />} .
- qq{</tt></form>} .
- PublicInbox::View::PRE_WRAP;
+ q{</pre></form><pre>}
} else {
- $top = PublicInbox::View::PRE_WRAP . $top . "\n";
+ $top = '<pre>' . $top . "\n";
}
$fh->write("<html><head><title>$title</title>" .
"<link\nrel=alternate\ntitle=\"Atom feed\"\n".
"href=\"$atom_url\"\ntype=\"application/atom+xml\"/>" .
+ PublicInbox::Hval::STYLE .
"</head><body>$top");
# if the 'r' query parameter is given, it is a legacy permalink
sub emit_index_nosrch {
my ($ctx, $state, $fh) = @_;
- my $git = PublicInbox::GitCatFile->new($ctx->{git_dir});
+ my $git = $ctx->{git} ||= PublicInbox::Git->new($ctx->{git_dir});
my (undef, $last) = each_recent_blob($ctx, sub {
my ($path, $commit, $ts, $u, $subj) = @_;
$state->{first} ||= $commit;
$head = $cgi->path_info;
$head = qq!<a\nhref="$head">head</a>!;
}
- my $atom = "<a\nhref=\"$feed_opts->{atomurl}\">atom</a>";
+ my $atom = "<a\nhref=\"$feed_opts->{atomurl}\">Atom feed</a>";
"<a\nname=\"s$anchor\">page:</a> $next $head $atom";
}
# get recent messages
# we could use git log -z, but, we already know ssoma will not
# leave us with filenames with spaces in them..
- my @cmd = ('git', "--git-dir=$ctx->{git_dir}",
- qw/log --no-notes --no-color --raw -r
- --abbrev=16 --abbrev-commit/,
- "--format=%h%x00%ct%x00%an%x00%s%x00");
- push @cmd, $range;
-
- my $pid = open(my $log, '-|', @cmd) or
- die('open `'.join(' ', @cmd) . " pipe failed: $!\n");
+ my $git = $ctx->{git} ||= PublicInbox::Git->new($ctx->{git_dir});
+ my $log = $git->popen(qw/log --no-notes --no-color --raw -r
+ --abbrev=16 --abbrev-commit/,
+ "--format=%h%x00%ct%x00%an%x00%s%x00",
+ $range);
my %deleted; # only an optimization at this point
my $last;
my $nr = 0;
my $base;
if (ref($cgi) eq 'CGI') {
$base = $cgi->url(-base);
- } else {
+ } else { # Plack::Request
$base = $cgi->base->as_string;
$base =~ s!/\z!!;
}
PublicInbox::Hval->new_oneline($mime->header($name))->raw;
}
-sub feed_date {
- my ($date) = @_;
- my @t = eval { strptime($date) };
+sub feed_updated {
+ my ($date, $ts) = @_;
+ my @t = eval { strptime($date) } if defined $date;
+ @t = gmtime($ts || time) unless scalar @t;
- scalar(@t) ? strftime(DATEFMT, @t) : 0;
+ '<updated>' . strftime(DATEFMT, @t) . '</updated>';
}
# returns 0 (skipped) or 1 (added)
$mime = undef;
my $date = $header_obj->header('Date');
- $date = PublicInbox::Hval->new_oneline($date);
- $date = feed_date($date->raw) or return 0;
- $date = "<updated>$date</updated>";
+ my $updated = feed_updated($date);
my $title = mime_header($header_obj, 'Subject') or return 0;
$title = title_tag($title);
$email = PublicInbox::Hval->new_oneline($email)->as_html;
if (delete $feed_opts->{emit_header}) {
- $fh->write(atom_header($feed_opts, $title) . $date);
+ $fh->write(atom_header($feed_opts, $title) . $updated);
}
$fh->write("<entry><author><name>$name</name><email>$email</email>" .
- "</author>$title$date" .
+ "</author>$title$updated" .
qq{<content\ntype="xhtml">} .
qq{<div\nxmlns="http://www.w3.org/1999/xhtml">});
$fh->write($content);