diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -618,6 +618,7 @@ 'DiffusionMercurialServeSSHWorkflow' => 'applications/diffusion/ssh/DiffusionMercurialServeSSHWorkflow.php', 'DiffusionMercurialWireClientSSHProtocolChannel' => 'applications/diffusion/ssh/DiffusionMercurialWireClientSSHProtocolChannel.php', 'DiffusionMercurialWireProtocol' => 'applications/diffusion/protocol/DiffusionMercurialWireProtocol.php', + 'DiffusionMercurialWireProtocolTests' => 'applications/diffusion/protocol/__tests__/DiffusionMercurialWireProtocolTests.php', 'DiffusionMercurialWireSSHTestCase' => 'applications/diffusion/ssh/__tests__/DiffusionMercurialWireSSHTestCase.php', 'DiffusionMergedCommitsQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionMergedCommitsQueryConduitAPIMethod.php', 'DiffusionMirrorDeleteController' => 'applications/diffusion/controller/DiffusionMirrorDeleteController.php', @@ -4341,6 +4342,7 @@ 'DiffusionMercurialServeSSHWorkflow' => 'DiffusionMercurialSSHWorkflow', 'DiffusionMercurialWireClientSSHProtocolChannel' => 'PhutilProtocolChannel', 'DiffusionMercurialWireProtocol' => 'Phobject', + 'DiffusionMercurialWireProtocolTests' => 'PhabricatorTestCase', 'DiffusionMercurialWireSSHTestCase' => 'PhabricatorTestCase', 'DiffusionMergedCommitsQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionMirrorDeleteController' => 'DiffusionController', diff --git a/src/applications/diffusion/controller/DiffusionServeController.php b/src/applications/diffusion/controller/DiffusionServeController.php --- a/src/applications/diffusion/controller/DiffusionServeController.php +++ b/src/applications/diffusion/controller/DiffusionServeController.php @@ -536,12 +536,14 @@ $body = strlen($stderr)."\n".$stderr; } else { list($length, $body) = explode("\n", $stdout, 2); + if ($cmd == 'capabilities') { + $body = DiffusionMercurialWireProtocol::filterBundle2Capability($body); + } } return id(new DiffusionMercurialResponse())->setContent($body); } - private function getMercurialArguments() { // Mercurial sends arguments in HTTP headers. "Why?", you might wonder, // "Why would you do this?". diff --git a/src/applications/diffusion/protocol/DiffusionMercurialWireProtocol.php b/src/applications/diffusion/protocol/DiffusionMercurialWireProtocol.php --- a/src/applications/diffusion/protocol/DiffusionMercurialWireProtocol.php +++ b/src/applications/diffusion/protocol/DiffusionMercurialWireProtocol.php @@ -99,4 +99,43 @@ return true; } + /** If the server version is running 3.4+ it will respond + * with 'bundle2' capability in the format of "bundle2=(url-encoding)". + * Until we maange to properly package up bundles to send back we + * disallow the client from knowing we speak bundle2 by removing it + * from the capabilities listing. + * + * The format of the capabilties string is: "a space separated list + * of strings representing what commands the server supports" + * @link https://www.mercurial-scm.org/wiki/CommandServer#Protocol + * + * @param string $capabilities - The string of capabilities to + * strip the bundle2 capability from. This is expected to be + * the space-separated list of strings resulting from the + * querying the 'capabilties' command. + * + * @return string The resulting space-separated list of capabilities + * which no longer contains the 'bundle2' capability. This is meant + * to replace the original $body to send back to client. + */ + public static function filterBundle2Capability($capabilities) { + $bundle2_arg = 'bundle2='; + $bundle2_arg_len = strlen($bundle2_arg); + $capabilities_arr = explode(' ', $capabilities); + $arrindex = -1; + $found_bundle2 = false; + foreach ($capabilities_arr as $capability) { + $arrindex++; + if (substr($capability, 0, $bundle2_arg_len) == $bundle2_arg) { + $found_bundle2 = true; + break; + } + } + if ($found_bundle2 && $arrindex > -1) { + unset($capabilities_arr[$arrindex]); + } + $capabilities_without_bundle2 = implode(' ', $capabilities_arr); + return $capabilities_without_bundle2; + } + } diff --git a/src/applications/diffusion/protocol/__tests__/DiffusionMercurialWireProtocolTests.php b/src/applications/diffusion/protocol/__tests__/DiffusionMercurialWireProtocolTests.php new file mode 100644 --- /dev/null +++ b/src/applications/diffusion/protocol/__tests__/DiffusionMercurialWireProtocolTests.php @@ -0,0 +1,30 @@ +assertEqual($expected, $actual, + 'Removal of bundle2 capabilty removes from list'); + + $test_case = self::$capabilitiesHGv262; + $expected = self::$capabilitiesHGv262; + $actual = DiffusionMercurialWireProtocol::filterBundle2Capability( + $test_case); + $this->assertEqual($expected, $actual, + 'Removing does not modify legacy capabilities'); + } +} diff --git a/src/applications/diffusion/ssh/DiffusionMercurialServeSSHWorkflow.php b/src/applications/diffusion/ssh/DiffusionMercurialServeSSHWorkflow.php --- a/src/applications/diffusion/ssh/DiffusionMercurialServeSSHWorkflow.php +++ b/src/applications/diffusion/ssh/DiffusionMercurialServeSSHWorkflow.php @@ -107,8 +107,14 @@ $this->didSeeWrite = true; } + $raw_message = $message['raw']; + if ($command == 'capabilities') { + $raw_message = DiffusionMercurialWireProtocol::filterBundle2Capability( + $raw_message); + } + // If we're good, return the raw message data. - return $message['raw']; + return $raw_message; } }