diff options
author | Eric Wong <e@80x24.org> | 2016-01-29 03:23:39 +0000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2016-04-05 18:58:27 +0000 |
commit | 74bdccb25e66298c3f9c81af0f611ad3adfc5a01 (patch) | |
tree | 88d3ab5ba71af5e2be08e679262595dbe7a95c1c /lib | |
parent | 7d8cc28839176b7fa67c509aae2b4c050e3abbd1 (diff) | |
download | public-inbox-74bdccb25e66298c3f9c81af0f611ad3adfc5a01.tar.gz |
Mostly following cgit, except we do not serve redundant text-only output which wastes bandwidth and doesn't preserve pre-formatting layout which is critical to some messages.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/PublicInbox/Repobrowse.pm | 2 | ||||
-rw-r--r-- | lib/PublicInbox/RepobrowseGitAtom.pm | 117 |
2 files changed, 118 insertions, 1 deletions
diff --git a/lib/PublicInbox/Repobrowse.pm b/lib/PublicInbox/Repobrowse.pm index 91d0ab20..82d38f90 100644 --- a/lib/PublicInbox/Repobrowse.pm +++ b/lib/PublicInbox/Repobrowse.pm @@ -23,7 +23,7 @@ use warnings; use URI::Escape qw(uri_escape_utf8 uri_unescape); use PublicInbox::RepobrowseConfig; -my %CMD = map { lc($_) => $_ } qw(Log Commit Tree Patch Blob Plain Tag); +my %CMD = map { lc($_) => $_ } qw(Log Commit Tree Patch Blob Plain Tag Atom); my %VCS = (git => 'Git'); my %LOADED; diff --git a/lib/PublicInbox/RepobrowseGitAtom.pm b/lib/PublicInbox/RepobrowseGitAtom.pm new file mode 100644 index 00000000..9326841d --- /dev/null +++ b/lib/PublicInbox/RepobrowseGitAtom.pm @@ -0,0 +1,117 @@ +# Copyright (C) 2016 all contributors <meta@public-inbox.org> +# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> + +# show log as an Atom feed +package PublicInbox::RepobrowseGitAtom; +use strict; +use warnings; +use PublicInbox::Hval qw(utf8_html); +use base qw(PublicInbox::RepobrowseBase); +my $ATOM_FMT = '--pretty=tformat:'. + join('%x00', qw(%s %ct %an %ae %at %h %H %b), '', ''); + +use constant DATEFMT => '%Y-%m-%dT%H:%M:%SZ'; +use POSIX qw(strftime); + +sub call_git_atom { + my ($self, $req) = @_; + my $repo_info = $req->{repo_info}; + my $max = $repo_info->{max_commit_count} || 10; + $max = int($max); + $max = 50 if $max == 0; + + my $git = $repo_info->{git}; + my $q = PublicInbox::RepobrowseGitQuery->new($req->{cgi}); + my $h = $q->{h}; + $h eq '' and chomp($h = $git->qx(qw(symbolic-ref --short HEAD))); + + my @cmd = (qw(log --no-notes --no-color --abbrev-commit), + $git->abbrev, $ATOM_FMT, "-$max", $h, '--'); + push @cmd, $req->{expath} if length($req->{expath}); + my $log = $git->popen(@cmd); + + sub { + my ($res) = @_; # Plack callback + my @h = ( 'Content-Type' => 'application/atom+xml' ); + my $fh = $res->([200, \@h]); + $self->git_atom_stream($req, $q, $log, $fh, $h); + $fh->close; + } +} + +sub repo_root_url { + my ($self, $req) = @_; + my $cgi = $req->{cgi}; + my $uri = $cgi->request_uri; + $uri =~ s/\?.+\z//; # no query string + my @uri = split(m!/+!, $uri); + shift @uri; # leading slash + my @extra = @{$req->{extra}}; + while (@uri && @extra && $uri[-1] eq $extra[-1]) { + pop @uri; + pop @extra; + } + pop @uri if $uri[-1] eq 'atom'; # warn if not equal? + $cgi->base . join('/', @uri); +} + +sub git_atom_stream { + my ($self, $req, $q, $log, $fh, $h) = @_; + my $repo_info = $req->{repo_info}; + my $title = join('/', $repo_info->{repo}, @{$req->{extra}}); + $title = utf8_html("$title, branch $h"); + + my $url = $self->repo_root_url($req); + $fh->write(qq(<?xml version="1.0"?>\n) . + qq(<feed\nxmlns="http://www.w3.org/2005/Atom">) . + qq(<title>$title</title>) . + qq(<subtitle>$repo_info->{desc_html}</subtitle>) . + qq(<link\nrel="alternate"\ntype="text/html"\nhref="$url"\n/>)); + my $rel = $req->{relcmd}; + my %acache; + local $/ = "\0"; + while (defined(my $s = <$log>)) { + chomp $s; + my $entry = '<entry><title>'; + $entry .= utf8_html($s); # commit subject + $entry .= '</title><updated>'; + + chomp($s = <$log>); # commit time + $entry .= strftime(DATEFMT, gmtime($s)); + $entry .= '</updated><author><name>'; + + chomp($s = <$log>); # author name + $entry .= $acache{$s} ||= utf8_html($s); + $entry .= '</name><email>'; + + chomp($s = <$log>); # author email + $entry .= $acache{$s} ||= utf8_html($s); + $entry .= '</email></author><published>'; + + chomp($s = <$log>); # author time + $entry .= strftime(DATEFMT, gmtime($s)); + $entry .= '</published>'; + + $entry .= qq(<link\nrel="alternate"\ntype="text/html"\nhref="); + $entry .= $url; + chomp($s = <$log>); # abbreviated commit hash for URL + $entry .= qq(/commit?id=$s"\n/><id>); + chomp($s = <$log>); # unabbreviated commit hash + $entry .= $s; + $entry .= qq(</id>); + + $entry .= qq(<content\ntype="xhtml"><div\nxmlns="); + $entry .= qq(http://www.w3.org/1999/xhtml">); + $entry .= qq(<pre\nstyle="white-space:pre-wrap">\n); + chomp($s = <$log>); + $entry .= utf8_html($s); # body + $fh->write($entry .= qq(</pre></div></content></entry>)); + eval { + local $/ = "\0\n"; + $s = <$log>; + }; + } + $fh->write('</feed>'); +} + +1; |