# shows the /tag/ endpoint for git repositories
package PublicInbox::RepoGitTag;
use strict;
use warnings;
use base qw(PublicInbox::RepoBase);
use POSIX qw(strftime);
use PublicInbox::Hval qw(utf8_html);
use PublicInbox::Qspawn;
my %cmd_map = ( # type => action
commit => 'commit',
tag => 'tag',
# tree/blob fall back to 'show'
);
sub call_git_tag {
my ($self, $req) = @_;
my $tip = $req->{tip};
defined $tip or return git_tag_list($self, $req);
sub {
my ($res) = @_;
git_tag_show($self, $req, $tip, $res);
}
}
sub read_err {
my ($fh, $type, $hex) = @_;
$fh->write("
error reading $type $hex");
}
sub git_show_tag_as_tag {
my ($self, $fh, $req, $h, $cat, $left, $type, $hex) = @_;
my $buf = '';
my $offset = 0;
while ($$left > 0) {
my $r = read($cat, $buf, $$left, $offset);
unless (defined $r) {
read_err($fh, $type, $hex);
last;
}
$offset += $r;
$$left -= $r;
}
my $head;
($head, $buf) = split(/\r?\n\r?\n/, $buf, 2);
my %h = map { split(/[ \t]/, $_, 2) } split(/\r?\n/, $head);
my $tag = utf8_html($h{tag});
$type = $h{type} || '(unknown)';
my $obj = $h{object};
$h = $self->html_start($req, 'tag: ' . $tag);
my $label = "$type $obj";
my $cmd = $cmd_map{$type} || 'show';
my $rel = $req->{relcmd};
my $obj_link = qq($label);
$head = $h . "\n\n tag $tag\nobject $obj_link\n";
if (my $tagger = $h{tagger}) {
$head .= 'tagger ' . join("\t", creator_split($tagger)) . "\n";
}
$fh->write($head . "\n");
# n.b. tag subjects may not have a blank line after them,
# but we bold the first line anyways
my @buf = split(/\r?\n/s, $buf);
if (defined(my $subj = shift @buf)) {
$fh->write('' . utf8_html($subj) . "\n");
$fh->write(utf8_html($_) . "\n") foreach @buf;
}
}
sub git_tag_show {
my ($self, $req, $h, $res) = @_;
my $git = $req->{-repo}->{git};
my $fh;
# yes, this could still theoretically show anything,
# but a tag could also point to anything:
$git->cat_file("refs/tags/$h", sub {
my ($cat, $left, $type, $hex) = @_;
$fh = $res->($self->rt(200, 'html'));
$h = PublicInbox::Hval->utf8($h);
my $m = "git_show_${type}_as_tag";
# git_show_tag_as_tag, git_show_commit_as_tag,
# git_show_tree_as_tag, git_show_blob_as_tag
if ($self->can($m)) {
$self->$m($fh, $req, $h, $cat, $left, $type, $hex);
} else {
$self->unknown_tag_type($fh, $req, $h, $type, $hex);
}
});
unless ($fh) {
$fh = $res->($self->rt(404, 'html'));
$fh->write(invalid_tag_start($req, $h));
}
$fh->write('