]> git.ipfire.org Git - thirdparty/public-inbox.git/commitdiff
repobrowse: support --graph output in log
authorEric Wong <e@80x24.org>
Sat, 26 Dec 2015 12:17:14 +0000 (12:17 +0000)
committerEric Wong <e@80x24.org>
Tue, 5 Apr 2016 18:58:27 +0000 (18:58 +0000)
This may be reverted if it turns out to be unsupportable
due to performance problems.  However it certainly looks
useful for understanding commit history.

I'm keeping it off by default for now since taking over
500ms to render a page is not acceptable.

Even "git log --graph -50 554f6e41067b9e >/dev/null" on
git://git.kernel.org/pub/scm/git/git.git
takes around 700ms on my system.

lib/PublicInbox/RepoBrowseGitLog.pm

index 8ce16eac4e45b8fce335649c6f5a8f5419b7b198..47443878e25c74bdb72e027facce787d2f7fdcbd 100644 (file)
@@ -4,8 +4,17 @@
 package PublicInbox::RepoBrowseGitLog;
 use strict;
 use warnings;
+use PublicInbox::Hval qw(utf8_html);
 use base qw(PublicInbox::RepoBrowseBase);
 
+# enable if we can speed it up..., over 100ms is unnacceptable
+my @graph; # = qw(--graph);
+
+# cannot rely on --date=format-local:... yet, it is too new (September 2015)
+my $LOG_FMT = '--pretty=tformat:'.
+               join('%x00', (@graph ? '' : '%n'), qw(%h s%s D%D));
+my $MSG_FMT = join('%x00', '', qw(%ai a%an b%b));
+
 sub call_git_log {
        my ($self, $req) = @_;
        my $repo_info = $req->{repo_info};
@@ -17,17 +26,14 @@ sub call_git_log {
        my $h = $q->{h};
        $h eq '' and $h = 'HEAD';
 
-       my $fmt = '%h%x00%s%x00%D';
-       $fmt .= '%x00%ai%x00%an%x00%b' if $q->{showmsg};
+       my $fmt = $LOG_FMT;
+       $fmt .= $MSG_FMT if $q->{showmsg};
        $fmt .= '%x00%x00';
 
-       my $ofs = $q->{ofs};
-       $h .= "~$ofs" if $ofs =~ /\A\d+\z/;
-
        my $git = $repo_info->{git};
        my $log = $git->popen(qw(log --no-notes --no-color
-                               --abbrev-commit --abbrev=16),
-                               "--format=$fmt", "-$max", $h);
+                               --abbrev-commit --abbrev=10),
+                               @graph, $fmt, "-$max", $h);
        sub {
                my ($res) = @_; # Plack callback
                my $fh = $res->([200, ['Content-Type'=>'text/html']]);
@@ -52,31 +58,57 @@ sub git_log_stream {
        }
 
        $fh->write("<html><head><title>$desc" .
-               "</title></head><body><tt><b>$desc</b></tt>".
-               PublicInbox::Hval::PRE . "<b>Commit Log</b> ($x)\n");
+               "</title></head><body><pre><b>$desc</b>\n\n".
+               "<b>Commit Log</b> ($x)\n");
+       $fh->write(@graph && $showmsg ? '</pre>' : "\n");
        my %ac;
        local $/ = "\0\0\n";
        my $rel = $req->{relcmd};
        while (defined(my $line = <$log>)) {
-               my ($id, $s, $D, $ai, $an, $b) = split("\0", $line);
-               $line = undef;
-               $s = PublicInbox::Hval->new_oneline($s)->as_html;
+               my @x;
+               my ($gr, $id, $s, $D, $ai, $an, $b) = @x = split("\0", $line);
+
+               # --graph may output graph-only lines without a commit
+               unless (defined $id) {
+                       $fh->write($gr . "\n");
+                       next;
+               }
+
+               $s =~ s/\As//;
+               $s = utf8_html($s);
 
                # TODO: handle $D (decorate)
                $s = qq(<a\nhref="${rel}commit?id=$id">$s</a>);
                if (defined $b) {
-                       # cannot rely on --date=format-local:... yet,
-                       # it is too new (September 2015)
-                       my $ah = $ac{$an} ||=
-                               PublicInbox::Hval->new_oneline($an)->as_html;
-                       $b = PublicInbox::Hval->new($b)->as_html;
-                       $fh->write("<b>$s</b>\n- by $ah @ $ai\n\n$b\n\n");
+                       $an =~ s/\Aa//;
+                       $b =~ s/\Ab//;
+                       $b =~ s/\s*\z//s;
+
+                       my $ah = $ac{$an} ||= utf8_html($an);
+
+                       if (@graph) {
+                               # duplicate the last line of graph as many
+                               # times at it takes to match the number of
+                               # lines in the body:
+                               my $nl = ($b =~ tr/\n/\n/) + 4;
+                               $nl -= ($gr =~ tr/\n/\n/);
+                               $gr =~ s/([^\n]+)\z/($1."\n") x $nl/es;
+                       }
+                       $b = utf8_html($b);
+                       $b = "<b>$s</b>\n- $ah @ $ai\n\n$b";
+                       if (@graph) {
+                               $fh->write('<table><tr><td><pre>'. $gr .
+                                       '</pre></td><td><pre>' . $b .
+                                       '</pre></td></tr></table>');
+                       } else {
+                               $fh->write($b. "\n\n");
+                       }
                } else {
-                       $fh->write($s . "\n");
+                       $fh->write((@graph ? $gr : '') . $s . "\n");
                }
        }
 
-       $fh->write('</pre></body></html>');
+       $fh->write((@graph && $showmsg ? '</pre>' : '') . '</body></html>');
 }
 
 1;