]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/ViewVCS.pm
viewvcs: show message for 404||500 errors
[public-inbox.git] / lib / PublicInbox / ViewVCS.pm
index e0fdf63999c20aaf7e3ce58442d1a12b3b3d15f2..99f5e24fb6be98cff0b63c6c6236e80e8f4b9bf0 100644 (file)
@@ -62,8 +62,11 @@ sub dbg_log ($) {
                return '<pre>debug log seek error</pre>';
        }
        $log = do { local $/; <$log> } // do {
-               warn "readline(log): $!";
-               return '<pre>debug log read error</pre>';
+               if (!eof($log)) {
+                       warn "readline(log): $!";
+                       return '<pre>debug log read error</pre>';
+               }
+               '';
        };
        return '' if $log eq '';
        $ctx->{-linkify} //= PublicInbox::Linkify->new;
@@ -125,6 +128,27 @@ sub cmt_title { # git->cat_async callback
                cmt_finalize($ctx);
 }
 
+sub do_cat_async {
+       my ($ctx, $cb, @req) = @_;
+       # favor git(1) over Gcf2 (libgit2) for SHA-256 support
+       $ctx->{git}->cat_async($_, $cb, $ctx) for @req;
+       if ($ctx->{env}->{'pi-httpd.async'}) {
+               PublicInbox::GitAsyncCat::watch_cat($ctx->{git});
+       } else { # synchronous, generic PSGI
+               $ctx->{git}->cat_async_wait;
+       }
+}
+
+sub do_check_async {
+       my ($ctx, $cb, @req) = @_;
+       if ($ctx->{env}->{'pi-httpd.async'}) {
+               async_check($ctx, $_, $cb, $ctx) for @req;
+       } else { # synchronous, generic PSGI
+               $ctx->{git}->check_async($_, $cb, $ctx) for @req;
+               $ctx->{git}->check_async_wait;
+       }
+}
+
 sub show_commit_start { # ->psgi_qx callback
        my ($bref, $ctx) = @_;
        if (my $qsp_err = delete $ctx->{-qsp_err}) {
@@ -142,16 +166,7 @@ sub show_commit_start { # ->psgi_qx callback
        return cmt_finalize($ctx) if !$P;
        @{$ctx->{-cmt_P}} = split(/ /, $P);
        @{$ctx->{-cmt_p}} = split(/ /, $p); # abbreviated
-       if ($ctx->{env}->{'pi-httpd.async'}) {
-               for (@{$ctx->{-cmt_P}}) {
-                       ibx_async_cat($ctx, $_, \&cmt_title, $ctx);
-               }
-       } else { # synchronous
-               for (@{$ctx->{-cmt_P}}) {
-                       $ctx->{git}->cat_async($_, \&cmt_title, $ctx);
-               }
-               $ctx->{git}->cat_async_wait;
-       }
+       do_cat_async($ctx, \&cmt_title, @{$ctx->{-cmt_P}});
 }
 
 sub ibx_url_for {
@@ -196,13 +211,15 @@ sub cmt_finalize {
                $au =~ s/>/>$x/;
        }
        $_ = ascii_html($_) for ($au, $co);
+       my $ibx_url = ibx_url_for($ctx) // $upfx;
        $au =~ s!(&gt; +)([0-9]{4,}-\S+ \S+)!
                my ($gt, $t) = ($1, $2);
                $t =~ tr/ :-//d;
                qq($gt<a
-href="$upfx?t=$t"
+href="$ibx_url?t=$t"
 title="list contemporary emails">$2</a>)
                !e;
+
        $ctx->{-title_html} = $s = $ctx->{-linkify}->to_html($s);
        my ($P, $p, $pt) = delete @$ctx{qw(-cmt_P -cmt_p -cmt_pt)};
        $_ = qq(<a href="$upfx$_/s/">).shift(@$p).'</a> '.shift(@$pt) for @$P;
@@ -473,30 +490,43 @@ sub show_tag ($$) {
        my ($ctx, $res) = @_;
        my ($git, $oid) = @$res;
        $ctx->{git} = $git;
-       if ($ctx->{env}->{'pi-httpd.async'}) {
-               ibx_async_cat($ctx, $oid, \&show_tag_result, $ctx);
-       } else { # synchronous (generic PSGI)
-               $git->cat_async($oid, \&show_tag_result, $ctx);
-               $git->cat_async_wait;
-       }
+       do_cat_async($ctx, \&show_tag_result, $oid);
 }
 
 # user_cb for SolverGit, called as: user_cb->($result_or_error, $uarg)
 sub solve_result {
        my ($res, $ctx) = @_;
        my $hints = delete $ctx->{hints};
-       $res or return html_page($ctx, 404, dbg_log($ctx));
-       ref($res) eq 'ARRAY' or return html_page($ctx, 500, dbg_log($ctx));
+       $res or return html_page($ctx, 404, 'Not found', dbg_log($ctx));
+       ref($res) eq 'ARRAY' or
+               return html_page($ctx, 500, 'Internal error', dbg_log($ctx));
 
        my ($git, $oid, $type, $size, $di) = @$res;
        return show_commit($ctx, $res) if $type eq 'commit';
        return show_tree($ctx, $res) if $type eq 'tree';
        return show_tag($ctx, $res) if $type eq 'tag';
        return show_other($ctx, $res) if $type ne 'blob';
+       my $fn = $di->{path_b} // $hints->{path_b};
        my $paths = $ctx->{-paths} //= do {
-               my $path = to_filename($di->{path_b}//$hints->{path_b}//'blob');
+               my $path = to_filename($fn // 'blob');
                my $raw_more = qq[(<a\nhref="$path">raw</a>)];
-               [ $path, $raw_more ];
+               my @def;
+
+               # XXX not sure if this is the correct wording
+               if (defined($fn)) {
+                       $raw_more .= qq(
+name: ${\ascii_html($fn)} \t # note: path name is non-authoritative<a
+href="#pathdef" id=top>(*)</a>);
+                       $def[0] = "<hr><pre\nid=pathdef>" .
+'(*) Git path names are given by the tree(s) the blob belongs to.
+    Blobs themselves have no identifier aside from the hash of its contents.'.
+qq(<a\nhref="#top">^</a></pre>);
+               }
+               [ $path, $raw_more, @def ];
+       };
+       $ctx->{-q_value_html} //= do {
+               my $s = defined($fn) ? 'dfn:'.ascii_html($fn).' ' : '';
+               $s.'dfpost:'.substr($oid, 0, 7);
        };
 
        if ($size > $MAX_SIZE) {
@@ -508,12 +538,7 @@ EOM
        }
        bless $ctx, 'PublicInbox::WwwStream'; # for DESTROY
        $ctx->{git} = $git;
-       if ($ctx->{env}->{'pi-httpd.async'}) {
-               ibx_async_cat($ctx, $oid, \&show_blob, $ctx);
-       } else { # synchronous
-               $git->cat_async($oid, \&show_blob, $ctx);
-               $git->cat_async_wait;
-       }
+       do_cat_async($ctx, \&show_blob, $oid);
 }
 
 sub show_blob { # git->cat_async callback
@@ -531,7 +556,7 @@ sub show_blob { # git->cat_async callback
                return delete($ctx->{-wcb})->([200, $h, [ $$blob ]]);
        }
 
-       my ($path, $raw_more) = @{delete $ctx->{-paths}};
+       my ($path, $raw_more, @def) = @{delete $ctx->{-paths}};
        $bin and return html_page($ctx, 200,
                                "<pre>blob $oid $size bytes (binary)" .
                                " $raw_more</pre>".dbg_log($ctx));
@@ -558,7 +583,7 @@ sub show_blob { # git->cat_async callback
        $x .= '</pre></td><td><pre> </pre></td>'. # pad for non-CSS users
                "<td\nclass=lines><pre\nstyle='white-space:pre'><code>";
        html_page($ctx, 200, $x, $ctx->{-linkify}->linkify_2($$blob),
-               '</code></pre></td></tr></table>'.dbg_log($ctx));
+               '</code></pre></td></tr></table>'.dbg_log($ctx), @def);
 }
 
 # GET /$INBOX/$GIT_OBJECT_ID/s/
@@ -573,7 +598,10 @@ sub show ($$;$) {
        }
        $ctx->{fn} = $fn;
        $ctx->{-tmp} = File::Temp->newdir("solver.$oid_b-XXXX", TMPDIR => 1);
-       open $ctx->{lh}, '+>>', "$ctx->{-tmp}/solve.log" or die "open: $!";
+       unless ($ctx->{lh}) {
+               open $ctx->{lh}, '+>>', "$ctx->{-tmp}/solve.log" or
+                       die "open: $!";
+       }
        my $solver = PublicInbox::SolverGit->new($ctx->{ibx},
                                                \&solve_result, $ctx);
        $solver->{gits} //= [ $ctx->{git} ];