+# called by GzipFilter->close after translate
+sub zflush { $_[0]->SUPER::zflush('</pre>', $_[0]->_html_end) }
+
+# called by GzipFilter->write or GetlineBody->getline
+sub translate {
+ my $ctx = shift;
+ my $rec = $_[0] // return zflush($ctx); # getline
+ my @out;
+ my $fbuf = delete($ctx->{fbuf}) // shift;
+ $fbuf .= shift while @_;
+ if ($ctx->{-heads}) {
+ while ($fbuf =~ s/\A([^\n]+)\n//s) {
+ utf8::decode(my $x = $1);
+ push @out, _refs_heads_link($x, '../../');
+ }
+ } else {
+ my ($snap_pfx, @snap_fmt) = _snapshot_link_prep($ctx);
+ while ($fbuf =~ s/\A([^\n]+)\n//s) {
+ utf8::decode(my $x = $1);
+ push @out, _refs_tags_link($x, '../../',
+ $snap_pfx, @snap_fmt);
+ }
+ }
+ $ctx->{fbuf} = $fbuf;
+ $ctx->SUPER::translate(@out);
+}
+
+sub _refs_parse_hdr { # {parse_hdr} for Qspawn
+ my ($r, $bref, $ctx) = @_;
+ my ($code, $top);
+ if ($r == 0) {
+ $code = 404;
+ $top = $ctx->{-heads} ? $NO_HEADS : $NO_TAGS;
+ } else {
+ $code = 200;
+ $top = $ctx->{-heads} ? $HEADS_CMD : $TAGS_CMD;
+ }
+ PublicInbox::WwwStream::html_init($ctx);
+ bless $ctx, __PACKAGE__; # re-bless for ->translate
+ print { $ctx->{zfh} } '<pre>', $top;
+ [ $code, delete($ctx->{-res_hdr}), $ctx ]; # [2] is qspawn.filter
+}
+
+sub refs_foo { # /$REPO/refs/{heads,tags} endpoints
+ my ($self, $ctx, $pfx) = @_;
+ $ctx->{wcr} = $self;
+ $ctx->{-upfx} = '../../';
+ $ctx->{-heads} = 1 if $pfx eq 'refs/heads';
+ my $qsp = PublicInbox::Qspawn->new([@EACH_REF, $pfx ],
+ { GIT_DIR => $ctx->{git}->{git_dir} });
+ $qsp->psgi_return($ctx->{env}, undef, \&_refs_parse_hdr, $ctx);
+}
+