# Copyright (C) 2015-2016 all contributors # License: AGPL-3.0+ package PublicInbox::RepoGitRaw; use strict; use warnings; use base qw(PublicInbox::RepoBase); use PublicInbox::RepoGitBlob; use PublicInbox::Hval qw(utf8_html); use PublicInbox::Qspawn; sub call_git_raw { my ($self, $req) = @_; my $repo = $req->{-repo}; my $git = $repo->{git}; my $tip = $req->{tip} || $repo->tip; my $id = $tip . ':' . $req->{expath}; my ($cat, $hex, $type, $size) = $git->cat_file_begin($id); return unless defined $cat; my ($r, $buf); my $left = $size; if ($type eq 'blob') { $type = git_blob_mime_type($self, $req, $cat, \$buf, \$left); } elsif ($type eq 'commit' || $type eq 'tag') { $type = 'text/plain'; } elsif ($type eq 'tree') { $git->cat_file_finish($left); return git_tree_raw($req, $git, $hex); } else { $type = 'application/octet-stream'; } git_blob_stream_response($git, $cat, $size, $type, $buf, $left); } sub git_tree_sed ($) { my ($req) = @_; my $buf = ''; my $end; my $pfx = $req->{tpfx}; sub { # $_[0] = buffer or undef my $dst = delete $req->{tstart} || ''; my @files; if (defined $_[0]) { @files = split(/\0/, $buf .= $_[0]); $buf = pop @files if scalar @files; } else { @files = split(/\0/, $buf); $end = ''; } foreach my $n (@files) { $n = PublicInbox::Hval->utf8($n); my $ref = $n->as_path; $dst .= qq(
  • ); $dst .= $n->as_html; $dst .= '
  • '; } $end ? $dst .= $end : $dst; } } # This should follow the cgit DOM structure in case anybody depends on it, # not using
     here as we don't expect people to actually view it much
    sub git_tree_raw {
    	my ($req, $git, $hex) = @_;
    
    	my @ex = @{$req->{extra}};
    	my $rel = $req->{relcmd};
    	my $title = utf8_html(join('/', '', @ex, ''));
    	my $pfx = 'raw/';
    	my $t = "

    $title

      "; if (@ex) { $t .= qq(
    • ../
    • ); my $last = PublicInbox::Hval->utf8($ex[-1])->as_href; $pfx = "$last/"; } $req->{tpfx} = $pfx; $req->{tstart} = "$title".$t; my $cmd = $git->cmd(qw(ls-tree --name-only -z), $git->abbrev, $hex); my $rdr = { 2 => $git->err_begin }; my $qsp = PublicInbox::Qspawn->new($cmd, undef, $rdr); my $env = $req->{env}; $qsp->psgi_return($env, undef, sub { my ($r) = @_; if (!defined $r) { [ 500, [ 'Content-Type', 'text/plain' ], [ $git->err ]]; } else { $env->{'qspawn.filter'} = git_tree_sed($req); [ 200, [ 'Content-Type', 'text/html' ] ]; } }); } 1;