From: Eric Wong <e@yhbt.net>
Date: Wed, 10 Jun 2020 07:04:30 +0000 (+0000)
Subject: git: cat_async: provide requested OID + "missing" on missing blobs
X-Git-Tag: v1.6.0~434
X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=3c7c389f514f9123667926af1613b5c79833085c;p=public-inbox.git

git: cat_async: provide requested OID + "missing" on missing blobs

This will make it easier to implement the retries on
alternates_changed() of the synchronous ->cat_file API.
---

diff --git a/lib/PublicInbox/Git.pm b/lib/PublicInbox/Git.pm
index 1c148086..b3ae2b81 100644
--- a/lib/PublicInbox/Git.pm
+++ b/lib/PublicInbox/Git.pm
@@ -20,7 +20,7 @@ use Errno qw(EINTR);
 our $PIPE_BUFSIZ = 65536; # Linux default
 
 use constant MAX_INFLIGHT =>
-	(($^O eq 'linux' ? 4096 : POSIX::_POSIX_PIPE_BUF()) * 2)
+	(($^O eq 'linux' ? 4096 : POSIX::_POSIX_PIPE_BUF()) * 3)
 	/
 	65; # SHA-256 hex size + "\n" in preparation for git using non-SHA1
 
@@ -157,8 +157,8 @@ sub my_readline ($$) {
 
 sub cat_async_step ($$) {
 	my ($self, $inflight) = @_;
-	die 'BUG: inflight empty or odd' if scalar(@$inflight) < 2;
-	my ($cb, $arg) = splice(@$inflight, 0, 2);
+	die 'BUG: inflight empty or odd' if scalar(@$inflight) < 3;
+	my ($req, $cb, $arg) = splice(@$inflight, 0, 3);
 	my $rbuf = delete($self->{cat_rbuf}) // \(my $new = '');
 	my ($bref, $oid, $type, $size);
 	my $head = my_readline($self->{in}, $rbuf);
@@ -167,7 +167,10 @@ sub cat_async_step ($$) {
 		$bref = my_read($self->{in}, $rbuf, $size + 1) or
 			fail($self, defined($bref) ? 'read EOF' : "read: $!");
 		chop($$bref) eq "\n" or fail($self, 'LF missing after blob');
-	} elsif ($head !~ / missing$/) {
+	} elsif ($head =~ / missing$/) {
+		$type = 'missing';
+		$oid = $req;
+	} else {
 		fail($self, "Unexpected result from async git cat-file: $head");
 	}
 	eval { $cb->($bref, $oid, $type, $size, $arg) };
@@ -344,7 +347,7 @@ sub cat_async ($$$;$) {
 	}
 
 	print { $self->{out} } $oid, "\n" or fail($self, "write error: $!");
-	push(@$inflight, $cb, $arg);
+	push(@$inflight, $oid, $cb, $arg);
 }
 
 sub extract_cmt_time {
diff --git a/t/git.t b/t/git.t
index 0b2089ba..98d16f28 100644
--- a/t/git.t
+++ b/t/git.t
@@ -53,7 +53,7 @@ use_ok 'PublicInbox::Git';
 	is_deeply([$oid_hex, $type, $size], \@x, 'got expected header');
 	is($arg_res, $arg, 'arg passed to cat_async');
 	is_deeply($raw, $bref, 'blob result matches');
-	is_deeply($missing, [ undef, undef, undef, undef, $arg],
+	is_deeply($missing, [ undef, 'non-existent', 'missing', undef, $arg],
 		'non-existent blob gives expected result');
 }