fix fetch error

This commit is contained in:
hanyixuanten
2026-08-16 20:45:30 +08:00
parent a41884f7b8
commit b4deffc9d9
2 changed files with 39 additions and 5 deletions
+9 -2
View File
@@ -51,7 +51,11 @@ function git_upload_pack_advertise_native($repository) {
}
function git_upload_pack_parse_request($input) {
$request = array('wants' => array(), 'haves' => array(), 'capabilities' => array());
$request = array(
'wants' => array(),
'haves' => array(),
'capabilities' => array(),
'done' => FALSE);
$first_want = TRUE;
$want_phase_done = FALSE;
$complete = FALSE;
@@ -82,6 +86,7 @@ function git_upload_pack_parse_request($input) {
} else if (preg_match('~^have ([0-9a-f]{40})$~D', $line, $matches)) {
$request['haves'][] = $matches[1];
} else if ($line === 'done') {
$request['done'] = TRUE;
$complete = TRUE;
break;
} else {
@@ -169,9 +174,11 @@ function git_upload_pack_rpc_native($repository, $input) {
if ($last_common === NULL) {
echo git_protocol_format_packet("NAK\n");
} else if (isset($request['capabilities']['multi_ack_detailed'])) {
} else if (isset($request['capabilities']['multi_ack_detailed']) && !$request['done']) {
echo git_protocol_format_packet('ACK '.$last_common." common\n");
echo git_protocol_format_packet('ACK '.$last_common." ready\n");
echo git_protocol_format_packet("NAK\n");
echo git_protocol_format_packet('ACK '.$last_common."\n");
} else {
echo git_protocol_format_packet('ACK '.$last_common."\n");
}
+30 -3
View File
@@ -72,6 +72,29 @@ test_case('upload-pack ACKs a common commit and excludes its history', function
}
});
test_case('upload-pack sends a final ACK after done with detailed negotiation', function () {
$fixture = git_fixture_create();
try {
$history = git_fixture_history($fixture, array('one', 'two'));
git_fixture_write_ref($fixture, 'refs/heads/main', $history[1]);
$request = git_protocol_format_packet(
'want '.$history[1]." multi_ack_detailed side-band-64k\n").'0000'
.git_protocol_format_packet('have '.$history[0]."\n")
.git_protocol_format_packet("done\n");
$input = test_stream($request);
$output = test_capture_output(function () use ($fixture, $input) {
return git_upload_pack_rpc_native(git_fixture_repository($fixture), $input);
});
fclose($input);
$ack = git_protocol_format_packet('ACK '.$history[0]."\n");
test_assert_same($ack, substr($output, 0, strlen($ack)));
test_assert_same(chr(1).'PACK', substr($output, strlen($ack) + 4, 5));
} finally {
test_remove_directory($fixture);
}
});
test_case('upload-pack rejects an unadvertised want', function () {
$fixture = git_fixture_create();
try {
@@ -111,9 +134,13 @@ test_case('upload-pack reports detailed common and ready acknowledgments', funct
});
fclose($input);
test_assert_contains('ACK '.$history[0]." common\n", $output);
test_assert_contains('ACK '.$history[0]." ready\n", $output);
test_assert_contains('PACK', $output);
$common = git_protocol_format_packet('ACK '.$history[0]." common\n");
$ready = git_protocol_format_packet('ACK '.$history[0]." ready\n");
$nak = git_protocol_format_packet("NAK\n");
$ack = git_protocol_format_packet('ACK '.$history[0]."\n");
$prefix = $common.$ready.$nak.$ack;
test_assert_same($prefix, substr($output, 0, strlen($prefix)));
test_assert_same('PACK', substr($output, strlen($prefix), 4));
} finally {
test_remove_directory($fixture);
}