X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FFeed.pm;h=65375fad679ed542852f1c53e9a3a686e6c1e963;hb=3cda6050b7c8f73e7fd86f88efc5cd42d0c13f73;hp=258ef03b7f716e1e2a70cfbdd4d1eef051b6eacc;hpb=f76f265a851944b5dedcc3be5f3b5224b6ebda89;p=public-inbox.git diff --git a/lib/PublicInbox/Feed.pm b/lib/PublicInbox/Feed.pm index 258ef03b..65375fad 100644 --- a/lib/PublicInbox/Feed.pm +++ b/lib/PublicInbox/Feed.pm @@ -1,5 +1,7 @@ # Copyright (C) 2013-2015 all contributors # 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; @@ -7,12 +9,12 @@ use Email::Address; 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 }; @@ -53,7 +55,8 @@ sub atom_header { qq(\n) . qq{} . qq{$title} . - qq({url}"/>) . + qq() . qq({atomurl}"/>) . qq(mailto:$feed_opts->{id_addr}); } @@ -64,19 +67,16 @@ sub emit_atom { 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 . '' . - strftime(DATEFMT, gmtime($ts)) . - ''); + $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 { @@ -86,7 +86,7 @@ sub _no_thread { $fh->close; } -sub _end_feed { +sub end_feed { my ($fh) = @_; Email::Address->purge_cache; $fh->write(''); @@ -105,12 +105,11 @@ sub emit_atom_thread { $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 { @@ -122,26 +121,25 @@ sub emit_html_index { my $title = $feed_opts->{description} || ''; $title = PublicInbox::Hval->new_oneline($title)->as_html; - my $atom_url = $feed_opts->{atomurl}; my ($footer, $param, $last); my $state = { ctx => $ctx, seen => {}, anchor_idx => 0 }; my $srch = $ctx->{srch}; - my $top = "$title (Atom feed)"; + my $top = "$title (Atom feed)"; if ($srch) { - $top = qq{$top} . + $top = qq{
$top} .
 			  qq{ } .
 			  qq{} .
-			  qq{} .
-			  PublicInbox::View::PRE_WRAP;
+			  q{
}
 	} else {
-		$top = PublicInbox::View::PRE_WRAP . $top . "\n";
+		$top = '
' . $top . "\n";
 	}
 
 	$fh->write("$title" .
 		   "" .
+		   "href=\"new.atom\"\ntype=\"application/atom+xml\"/>" .
+		   PublicInbox::Hval::STYLE .
 		   "$top");
 
 	# if the 'r' query parameter is given, it is a legacy permalink
@@ -167,7 +165,7 @@ sub emit_html_index {
 
 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;
@@ -196,7 +194,7 @@ sub nav_footer {
 		$head = $cgi->path_info;
 		$head = qq!head!;
 	}
-	my $atom = "{atomurl}\">atom";
+	my $atom = "{atomurl}\">Atom feed";
 	"page: $next $head $atom";
 }
 
@@ -219,14 +217,11 @@ sub each_recent_blob {
 	# 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;
@@ -260,7 +255,6 @@ sub each_recent_blob {
 		}
 	}
 
-	close $log; # we may EPIPE here
 	# for pagination
 	($first_commit, $last_commit);
 }
@@ -274,7 +268,6 @@ sub get_feedopts {
 	my %rv;
 	if (open my $fh, '<', "$ctx->{git_dir}/description") {
 		chomp($rv{description} = <$fh>);
-		close $fh;
 	} else {
 		$rv{description} = '($GIT_DIR/description missing)';
 	}
@@ -289,14 +282,7 @@ sub get_feedopts {
 
 	my $url_base;
 	if ($cgi) {
-		my $base;
-		if (ref($cgi) eq 'CGI') {
-			$base = $cgi->url(-base);
-		} else {
-			$base = $cgi->base->as_string;
-			$base =~ s!/\z!!;
-		}
-		$url_base = "$base/$listname";
+		$url_base = $cgi->base->as_string . $listname;
 		if (my $mid = $ctx->{mid}) { # per-thread feed:
 			$rv{atomurl} = "$url_base/$mid/t.atom";
 		} else {
@@ -317,11 +303,12 @@ sub mime_header {
 	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;
+	'' . strftime(DATEFMT, @t) . '';
 }
 
 # returns 0 (skipped) or 1 (added)
@@ -333,7 +320,7 @@ sub add_to_feed {
 	my $midurl = $feed_opts->{midurl};
 
 	my $header_obj = $mime->header_obj;
-	my $mid = $header_obj->header('Message-ID');
+	my $mid = $header_obj->header_raw('Message-ID');
 	defined $mid or return 0;
 	$mid = PublicInbox::Hval->new_msgid($mid);
 	my $href = $mid->as_href;
@@ -342,9 +329,7 @@ sub add_to_feed {
 	$mime = undef;
 
 	my $date = $header_obj->header('Date');
-	$date = PublicInbox::Hval->new_oneline($date);
-	$date = feed_date($date->raw) or return 0;
-	$date = "$date";
+	my $updated = feed_updated($date);
 
 	my $title = mime_header($header_obj, 'Subject') or return 0;
 	$title = title_tag($title);
@@ -356,10 +341,10 @@ sub add_to_feed {
 	$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("$name$email" .
-		   "$title$date" .
+		   "$title$updated" .
 		   qq{} .
 		   qq{});
 	$fh->write($content);