From d9563ea5516e8e786debf223e10ec11695aee9d7 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 9 Feb 2017 01:37:03 +0000 Subject: repobrowse: shorten internal names We'll still be keeping "repobrowse" for the public API for use with .psgi files, but shortening the name means less typing and we may have command-line tools, too. --- lib/PublicInbox/RepoGitSummary.pm | 109 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 lib/PublicInbox/RepoGitSummary.pm (limited to 'lib/PublicInbox/RepoGitSummary.pm') diff --git a/lib/PublicInbox/RepoGitSummary.pm b/lib/PublicInbox/RepoGitSummary.pm new file mode 100644 index 00000000..e9e1458b --- /dev/null +++ b/lib/PublicInbox/RepoGitSummary.pm @@ -0,0 +1,109 @@ +# Copyright (C) 2016 all contributors +# License: AGPL-3.0+ + +# The main summary/landing page of a git repository viewer +package PublicInbox::RepoGitSummary; +use strict; +use warnings; +use PublicInbox::Hval qw(utf8_html); +use base qw(PublicInbox::RepoBase); +use PublicInbox::Qspawn; + +sub call_git_summary { + my ($self, $req) = @_; + my $git = $req->{repo_info}->{git}; + my $env = $req->{env}; + + # n.b. we would use %(HEAD) in for-each-ref --format if we could + # rely on git 1.9.0+, but it's too soon for that in early 2017... + my $cmd = $git->cmd(qw(symbolic-ref HEAD)); + my $rdr = { 2 => $git->err_begin }; + my $qsp = PublicInbox::Qspawn->new($cmd, undef, $rdr); + sub { + my ($res) = @_; # Plack streaming callback + $qsp->psgi_qx($env, undef, sub { + chomp(my $head_ref = ${$_[0]}); + for_each_ref($self, $req, $res, $head_ref); + }); + } +} + +use constant EACH_REF_FMT => '--format=' . + join(' ', map { "%($_)" } + qw(refname objecttype objectname creatordate:short subject)); + +sub for_each_ref { + my ($self, $req, $res, $head_ref) = @_; + my $count = 10; # TODO: configurable + my $fh; + my $repo_info = $req->{repo_info}; + my $git = $repo_info->{git}; + my $refs = $git->popen(qw(for-each-ref --sort=-creatordate), + EACH_REF_FMT, "--count=$count", + qw(refs/heads/ refs/tags/)); + $fh = $res->([200, ['Content-Type'=>'text/html; charset=UTF-8']]); + # ref names are unpredictable in length and requires tables :< + $fh->write($self->html_start($req, + "$repo_info->{repo}: overview") . + ''); + + my $rel = $req->{relcmd}; + while (<$refs>) { + my ($ref, $type, $hex, $date, $s) = split(' ', $_, 5); + my $x = $ref eq $head_ref ? ' (HEAD)' : ''; + $ref =~ s!\Arefs/(?:heads|tags)/!!; + $ref = PublicInbox::Hval->utf8($ref); + my $h = $ref->as_html; + $ref = $ref->as_href; + my $sref; + if ($type eq 'tag') { + $h = "$h"; + $sref = $ref = $rel . 'tag?h=' . $ref; + } elsif ($type eq 'commit') { + $sref = $rel . 'commit?h=' . $ref; + $ref = $rel . 'log?h=' . $ref; + } else { + # no point in wasting code to support tagged + # trees/blobs... + next; + } + chomp $s; + $fh->write(qq() . + qq('); + + } + $fh->write('
$h$x$date ) . utf8_html($s) . + '
'); + + # some people will use README.md or even README.sh here... + my $readme = $repo_info->{readme}; + defined $readme or $readme = [ 'README', 'README.md' ]; + $readme = [ $readme ] if (ref($readme) ne 'ARRAY'); + foreach my $r (@$readme) { + my $doc = $git->cat_file('HEAD:'.$r); + defined $doc or next; + $fh->write('
' . readme_path_links($rel, $r) .
+			" (HEAD)\n\n" . utf8_html($$doc) . '
'); + } + $fh->write(''); + $fh->close; +} + +sub readme_path_links { + my ($rel, $readme) = @_; + my @path = split(m!/+!, $readme); + + my $s = "tree root/"; + my @t; + $s .= join('/', (map { + push @t, $_; + my $e = PublicInbox::Hval->utf8($_, join('/', @t)); + my $ep = $e->as_path; + my $eh = $e->as_html; + $e = "$eh"; + # bold the last one + scalar(@t) == scalar(@path) ? "$e" : $e; + } @path)); +} + +1; -- cgit v1.2.3-24-ge0c7