diff options
author | Eric Wong <e@80x24.org> | 2016-12-13 21:56:39 +0000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2016-12-14 00:22:55 +0000 |
commit | 00488f0cfe9f81d04cd65d09ea783e860c937401 (patch) | |
tree | 24e4d9282d5e7098fc6cbdcc9d5615c46513661f /lib/PublicInbox/RepobrowseGitLog.pm | |
parent | f9d4f28d9761011d3c7ffad9e2c9d1e54b65c519 (diff) | |
parent | 6cdb0221d18b2caed4d0caebf7c20d6eb159497d (diff) | |
download | public-inbox-00488f0cfe9f81d04cd65d09ea783e860c937401.tar.gz |
* origin/repobrowse: (98 commits) t/repobrowse_git_httpd.t: ensure signature exists for split t/repobrowse_git_tree.t: fix test for lack of bold repobrowse: fix alignment of gitlink entries repobrowse: show invalid type for tree views repobrowse: do not bold directory names in tree view repobrowse: reduce checks for response fh repobrowse: larger, short-lived buffer for reading patches repobrowse: reduce risk of callback reference cycles repobrowse: snapshot support for cgit compatibility test: disable warning for Plack::Test::Impl repobrowse: avoid confusing linkification for "diff" repobrowse: git commit view uses pi-httpd.async repobrowse: more consistent variable naming for /commit/ repobrowse: show roughly equivalent "diff-tree" invocation repobrowse: reduce local variables for state management repobrowse: summary handles multiple README types repobrowse: remove bold decorations from diff view repobrowse: common git diff parsing code repobrowse: implement diff view for compatibility examples/repobrowse.psgi: disable Chunked response by default ...
Diffstat (limited to 'lib/PublicInbox/RepobrowseGitLog.pm')
-rw-r--r-- | lib/PublicInbox/RepobrowseGitLog.pm | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/lib/PublicInbox/RepobrowseGitLog.pm b/lib/PublicInbox/RepobrowseGitLog.pm new file mode 100644 index 00000000..0c360e73 --- /dev/null +++ b/lib/PublicInbox/RepobrowseGitLog.pm @@ -0,0 +1,102 @@ +# Copyright (C) 2015 all contributors <meta@public-inbox.org> +# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> + +# show the log view +package PublicInbox::RepobrowseGitLog; +use strict; +use warnings; +use PublicInbox::Hval qw(utf8_html); +use base qw(PublicInbox::RepobrowseBase); +use PublicInbox::RepobrowseGit qw(git_dec_links git_commit_title); +# cannot rely on --date=format-local:... yet, it is too new (September 2015) +my $LOG_FMT = '--pretty=tformat:'. + join('%x00', qw(%h %p %s D%D %ai a%an b%b), '', ''); + +sub call_git_log { + my ($self, $req) = @_; + my $repo_info = $req->{repo_info}; + my $max = $repo_info->{max_commit_count} || 50; + $max = int($max); + $max = 50 if $max == 0; + + my $q = PublicInbox::RepobrowseGitQuery->new($req->{cgi}); + my $h = $q->{h}; + $h eq '' and $h = 'HEAD'; + + my $git = $repo_info->{git}; + my $log = $git->popen(qw(log --no-notes --no-color --abbrev-commit), + $git->abbrev, $LOG_FMT, "-$max", $h, '--'); + sub { + my ($res) = @_; # Plack callback + my $fh = $res->([200, ['Content-Type'=>'text/html']]); + my $title = "log: $repo_info->{repo} ".utf8_html("($h)"); + $fh->write($self->html_start($req, $title)); + git_log_stream($req, $q, $log, $fh, $git); + $fh->close; + } +} + +sub git_log_stream { + my ($req, $q, $log, $fh, $git) = @_; + + my $rel = $req->{relcmd}; + my %acache; + local $/ = "\0\0\n"; + my $nr = 0; + my (@parents, %seen); + while (defined(my $line = <$log>)) { + my ($id, $p, $s, $D, $ai, $an, $b) = split("\0", $line); + $seen{$id} = 1; + my @p = split(' ', $p); + push @parents, @p; + my $plinks; + if (@p == 1) { # typical, single-parent commit + $plinks = qq( / parent <a\nhref="#p$p[0]">$p[0]</a>); + } elsif (@p > 0) { # merge commit + $plinks = ' / parents ' . join(' ', map { + qq(<a\nhref="#p$_">$_</a>); + } @p); + } else { + $plinks = ''; # root commit + } + + $s = utf8_html($s); + $s = qq(<a\nid=p$id\nhref="${rel}commit?id=$id"><b>$s</b></a>); + if ($D =~ /\AD(.+)/) { + $s .= ' ('. join(', ', git_dec_links($rel, $1)) . ')'; + } + + $an =~ s/\Aa//; + $b =~ s/\Ab//; + $b =~ s/\s*\z//s; + + my $ah = $acache{$an} ||= utf8_html($an); + my $nl = $b eq '' ? '' : "\n"; # empty bodies :< + $b = "$s\n- $ah @ $ai\n commit $id$plinks\n$nl" . + utf8_html($b); + $fh->write("\n\n" .$b); + ++$nr; + } + + my $m = ''; + my $np = 0; + foreach my $p (@parents) { + next if $seen{$p}; + $seen{$p} = ++$np; + my $s = git_commit_title($git, $p); + $m .= qq(\n<a\nid=p$p\nhref="?h=$p">$p</a>\t); + $s = defined($s) ? utf8_html($s) : ''; + $m .= qq(<a\nhref="${rel}commit?id=$p">$s</a>); + } + my $foot = "</pre><hr /><pre>"; + if ($np == 0) { + $foot .= "No commits follow"; + } elsif ($np > 1) { + $foot .= "Unseen parent commits to follow (multiple choice):\n"; + } else { + $foot .= "Next parent to follow:\n"; + } + $fh->write($foot .= $m . '</pre></body></html>'); +} + +1; |