about summary refs log tree commit homepage
path: root/lib/PublicInbox/RepobrowseGitCommit.pm
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2016-01-18 23:23:42 +0000
committerEric Wong <e@80x24.org>2016-04-05 18:58:27 +0000
commit2b79ca6a1f3f12cac616b2bce800f7f9487c8170 (patch)
tree6ac262195b6ece8e9b8583a42bdec5f4c036d5e7 /lib/PublicInbox/RepobrowseGitCommit.pm
parent66ad0a45c58ed63ec16a35f41f3eda7cb8917c50 (diff)
downloadpublic-inbox-2b79ca6a1f3f12cac616b2bce800f7f9487c8170.tar.gz
Having too many potential links is damaging to cacheability
and hurts performance.
Diffstat (limited to 'lib/PublicInbox/RepobrowseGitCommit.pm')
-rw-r--r--lib/PublicInbox/RepobrowseGitCommit.pm74
1 files changed, 56 insertions, 18 deletions
diff --git a/lib/PublicInbox/RepobrowseGitCommit.pm b/lib/PublicInbox/RepobrowseGitCommit.pm
index b5ffb2bf..e4e0f3c6 100644
--- a/lib/PublicInbox/RepobrowseGitCommit.pm
+++ b/lib/PublicInbox/RepobrowseGitCommit.pm
@@ -2,11 +2,20 @@
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 
 # shows the /commit/ endpoint for git repositories
+#
+# anchors used:
+#        D - diffstat
+#        P - parents
+#        ...and various filenames from to_attr
+# The 'D' and 'P' anchors may conflict with odd filenames, but we won't
+# punish the common case with extra bytes if somebody uses 'D' or 'P'
+# in filenames.
+
 package PublicInbox::RepobrowseGitCommit;
 use strict;
 use warnings;
 use base qw(PublicInbox::RepobrowseBase);
-use PublicInbox::Hval qw(utf8_html);
+use PublicInbox::Hval qw(utf8_html to_attr);
 use PublicInbox::RepobrowseGit qw(git_unquote git_commit_title);
 
 use constant GIT_FMT => '--pretty=format:'.join('%n',
@@ -73,15 +82,15 @@ sub git_commit_stream {
         local $/ = "\0";
         $l = <$log>;
         chomp $l;
-        $fh->write(utf8_html($l)."---\n");
-        git_show_diffstat($req, $h, $fh, $log);
+        $fh->write(utf8_html($l)."<a\nid=D>---</a>\n");
+        my $diff = { anchors => {}, h => $h, p => \@p, rel => $rel };
+        git_show_diffstat($diff, $req, $h, $fh, $log);
         my $help;
         $help = " This is a merge, showing combined diff:\n\n" if ($np > 1);
 
         # diff
         local $/ = "\n";
         my $cmt = '[a-f0-9]+';
-        my $diff = { h => $h, p => \@p, rel => $rel };
         my ($cc_ins, $cc_del);
         while (defined($l = <$log>)) {
                 if ($help) {
@@ -117,6 +126,8 @@ sub git_commit_stream {
         if ($help) {
                 $fh->write(" This is a merge, combined diff is empty.\n");
         }
+
+        show_unchanged($fh, $diff, $qs);
         $fh->write('</pre></body></html>');
 }
 
@@ -174,14 +185,13 @@ sub git_commit_404 {
 }
 
 sub git_show_diffstat {
-        my ($req, $h, $fh, $log) = @_;
+        my ($diff, $req, $h, $fh, $log) = @_;
         local $/ = "\0\0";
         my $l = <$log>;
         chomp $l;
         my @stat = split("\0", $l);
         my $nr = 0;
         my ($nadd, $ndel) = (0, 0);
-        my $rel = $req->{relcmd};
         while (defined($l = shift @stat)) {
                 $l =~ s/\n?(\S+)\t+(\S+)\t+// or next;
                 my ($add, $del) = ($1, $2);
@@ -193,15 +203,14 @@ sub git_show_diffstat {
                 }
                 my $num = sprintf('% 6s/%-6s', $del, $add);
                 if (length $l) {
-                        $l = PublicInbox::Hval->utf8($l);
-                        my $lp = $l->as_path;
-                        my $lh = $l->as_html;
-                        $l = "<a\nhref=\"${rel}commit/$lp?id=$h\">$lh</a>";
-
+                        my $anchor = to_attr(git_unquote($l));
+                        $diff->{anchors}->{$anchor} = $l;
+                        $l = utf8_html($l);
+                        $l = qq(<a\nhref="#$anchor">$l</a>);
                 } else {
                         my $from = shift @stat;
                         my $to = shift @stat;
-                        $l = git_diffstat_rename($rel, $h, $from, $to);
+                        $l = git_diffstat_rename($diff, $h, $from, $to);
                 }
                 ++$nr;
                 $fh->write(' '.$num."\t".$l."\n");
@@ -233,6 +242,8 @@ sub git_diff_ab_hdr {
         $fb = git_unquote($fb);
         $fa =~ s!\Aa/!!;
         $fb =~ s!\Ab/!!;
+        my $anchor = to_attr($fb);
+        delete $diff->{anchors}->{$anchor};
         $fa = $diff->{fa} = PublicInbox::Hval->utf8($fa);
         $fb = $diff->{fb} = PublicInbox::Hval->utf8($fb);
         $diff->{path_a} = $fa->as_path;
@@ -240,7 +251,7 @@ sub git_diff_ab_hdr {
 
         # not wasting bandwidth on links here, yet
         # links in hunk headers are far more useful with line offsets
-        "diff --git $html_a <b>$html_b</b>";
+        qq(<a\nhref=#D\nid="$anchor">diff</a> --git $html_a <b>$html_b</b>);
 }
 
 # @@ -1,2 +3,4 @@ (regular diff)
@@ -272,9 +283,12 @@ sub git_diff_ab_hunk {
 sub git_diff_cc_hdr {
         my ($diff, $combined, $path) = @_;
         my $html_path = utf8_html($path);
-        my $cc = $diff->{cc} = PublicInbox::Hval->utf8(git_unquote($path));
+        $path = git_unquote($path);
+        my $anchor = to_attr($path);
+        delete $diff->{anchors}->{$anchor};
+        my $cc = $diff->{cc} = PublicInbox::Hval->utf8($path);
         $diff->{path_cc} = $cc->as_path;
-        "diff --$combined <b>$html_path</b>";
+        qq(<a\nhref=#D\nid="$anchor">diff</a> --$combined <b>$html_path</b>);
 }
 
 # index abcdef09,01234567..76543210
@@ -333,7 +347,9 @@ sub git_diff_cc_hunk {
 }
 
 sub git_diffstat_rename {
-        my ($rel, $h, $from, $to) = @_;
+        my ($diff, $h, $from, $to) = @_;
+        my $anchor = to_attr(git_unquote($to));
+        $diff->{anchors}->{$anchor} = $to;
         my @from = split('/', $from);
         my @to = split('/', $to);
         my $orig_to = $to;
@@ -348,7 +364,7 @@ sub git_diffstat_rename {
         $to = PublicInbox::Hval->utf8(join('/', @to), $orig_to);
         my $tp = $to->as_path;
         my $th = $to->as_html;
-        $to = "<a\nhref=\"${rel}/commit/$tp?id=$h\">$th</a>";
+        $to = qq(<a\nhref="#$anchor">$th</a>);
         @base ? "$base/{$from =&gt; $to}" : "$from =&gt; $to";
 }
 
@@ -383,7 +399,29 @@ sub git_parent_line {
         my $qs = $q->qs(id => $p);
         my $t = git_commit_title($git, $p);
         $t = defined $t ? utf8_html($t) : '';
-        $pfx . " <a\nhref=\"${rel}commit$path$qs\">$p</a> ". $t . "\n";
+        $pfx . qq( <a\nid=P\nhref="${rel}commit$path$qs">$p</a> $t\n);
+}
+
+# do not break anchor links if the combined diff doesn't show changes:
+sub show_unchanged {
+        my ($fh, $diff, $qs) = @_;
+
+        my @unchanged = sort keys %{$diff->{anchors}};
+        return unless @unchanged;
+        my $anchors = $diff->{anchors};
+        my $s = "\n There are uninteresting changes from this merge.\n" .
+                qq( See <a\nhref="#P">parents</a>, ) .
+                "or view final state(s) below:\n";
+        my $rel = $diff->{rel};
+        foreach my $anchor (@unchanged) {
+                my $fn = $anchors->{$anchor};
+                my $p = PublicInbox::Hval->utf8(git_unquote($fn));
+                $p = $p->as_path;
+                $fn = utf8_html($fn);
+                $s .= qq(\t<a\nid="$anchor"\nhref="${rel}tree/$p$qs">);
+                $s .= "$fn</a>\n";
+        }
+        $fh->write($s);
 }
 
 1;