diff --git a/src/applications/diffusion/controller/DiffusionServeController.php b/src/applications/diffusion/controller/DiffusionServeController.php index 74b57b7594..288337e47c 100644 --- a/src/applications/diffusion/controller/DiffusionServeController.php +++ b/src/applications/diffusion/controller/DiffusionServeController.php @@ -328,6 +328,14 @@ final class DiffusionServeController extends DiffusionController { ->write($input) ->resolve(); + if ($err) { + if ($this->isValidGitShallowCloneResponse($stdout, $stderr)) { + // Ignore the error if the response passes this special check for + // validity. + $err = 0; + } + } + if ($err) { return new PhabricatorVCSResponse( 500, @@ -512,5 +520,27 @@ final class DiffusionServeController extends DiffusionController { return implode('', $out); } + private function isValidGitShallowCloneResponse($stdout, $stderr) { + // If you execute `git clone --depth N ...`, git sends a request which + // `git-http-backend` responds to by emitting valid output and then exiting + // with a failure code and an error message. If we ignore this error, + // everything works. + + // This is a pretty funky fix: it would be nice to more precisely detect + // that a request is a `--depth N` clone request, but we don't have any code + // to decode protocol frames yet. Instead, look for reasonable evidence + // in the error and output that we're looking at a `--depth` clone. + + // For evidence this isn't completely crazy, see: + // https://github.com/schacon/grack/pull/7 + + $stdout_regexp = '(^Content-Type: application/x-git-upload-pack-result)m'; + $stderr_regexp = '(The remote end hung up unexpectedly)'; + + $has_pack = preg_match($stdout_regexp, $stdout); + $is_hangup = preg_match($stderr_regexp, $stderr); + + return $has_pack && $is_hangup; + } }