mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-24 06:20:56 +01:00
Added an intercept to Mercurial's capabilities
command to remove bundle2.
Summary: If Mercurial 3.4+ is used to host repositories in Phabricator, any clients using 3.5+ will receive an exception after the bundle is pushed up. Clients will also fail to update phases for changesets pushed up. Before directly responding to mercurial clients with all capabilities, this change filters out the 'bundle2' capability so the client negotiates using a legacy bundle wire format instead. Test Plan: Server: Mercurial 3.5 Client: Mercurial 3.4 Test with both HTTP and SSH protocols: 1. Create a local commit on client 2. Push commit to server 3. Verify the client emits something like: ``` searching for changes remote: adding changesets remote: adding manifests remote: adding file changes remote: added 1 changesets with 1 changes to 1 files ``` Closes T9450 Reviewers: epriestley, #blessed_reviewers Reviewed By: epriestley, #blessed_reviewers Subscribers: Korvin Maniphest Tasks: T9450 Differential Revision: https://secure.phabricator.com/D14241
This commit is contained in:
parent
3bccb0dcf2
commit
32d4ae8cb2
5 changed files with 90 additions and 2 deletions
|
@ -618,6 +618,7 @@ phutil_register_library_map(array(
|
||||||
'DiffusionMercurialServeSSHWorkflow' => 'applications/diffusion/ssh/DiffusionMercurialServeSSHWorkflow.php',
|
'DiffusionMercurialServeSSHWorkflow' => 'applications/diffusion/ssh/DiffusionMercurialServeSSHWorkflow.php',
|
||||||
'DiffusionMercurialWireClientSSHProtocolChannel' => 'applications/diffusion/ssh/DiffusionMercurialWireClientSSHProtocolChannel.php',
|
'DiffusionMercurialWireClientSSHProtocolChannel' => 'applications/diffusion/ssh/DiffusionMercurialWireClientSSHProtocolChannel.php',
|
||||||
'DiffusionMercurialWireProtocol' => 'applications/diffusion/protocol/DiffusionMercurialWireProtocol.php',
|
'DiffusionMercurialWireProtocol' => 'applications/diffusion/protocol/DiffusionMercurialWireProtocol.php',
|
||||||
|
'DiffusionMercurialWireProtocolTests' => 'applications/diffusion/protocol/__tests__/DiffusionMercurialWireProtocolTests.php',
|
||||||
'DiffusionMercurialWireSSHTestCase' => 'applications/diffusion/ssh/__tests__/DiffusionMercurialWireSSHTestCase.php',
|
'DiffusionMercurialWireSSHTestCase' => 'applications/diffusion/ssh/__tests__/DiffusionMercurialWireSSHTestCase.php',
|
||||||
'DiffusionMergedCommitsQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionMergedCommitsQueryConduitAPIMethod.php',
|
'DiffusionMergedCommitsQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionMergedCommitsQueryConduitAPIMethod.php',
|
||||||
'DiffusionMirrorDeleteController' => 'applications/diffusion/controller/DiffusionMirrorDeleteController.php',
|
'DiffusionMirrorDeleteController' => 'applications/diffusion/controller/DiffusionMirrorDeleteController.php',
|
||||||
|
@ -4341,6 +4342,7 @@ phutil_register_library_map(array(
|
||||||
'DiffusionMercurialServeSSHWorkflow' => 'DiffusionMercurialSSHWorkflow',
|
'DiffusionMercurialServeSSHWorkflow' => 'DiffusionMercurialSSHWorkflow',
|
||||||
'DiffusionMercurialWireClientSSHProtocolChannel' => 'PhutilProtocolChannel',
|
'DiffusionMercurialWireClientSSHProtocolChannel' => 'PhutilProtocolChannel',
|
||||||
'DiffusionMercurialWireProtocol' => 'Phobject',
|
'DiffusionMercurialWireProtocol' => 'Phobject',
|
||||||
|
'DiffusionMercurialWireProtocolTests' => 'PhabricatorTestCase',
|
||||||
'DiffusionMercurialWireSSHTestCase' => 'PhabricatorTestCase',
|
'DiffusionMercurialWireSSHTestCase' => 'PhabricatorTestCase',
|
||||||
'DiffusionMergedCommitsQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
|
'DiffusionMergedCommitsQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
|
||||||
'DiffusionMirrorDeleteController' => 'DiffusionController',
|
'DiffusionMirrorDeleteController' => 'DiffusionController',
|
||||||
|
|
|
@ -536,12 +536,14 @@ final class DiffusionServeController extends DiffusionController {
|
||||||
$body = strlen($stderr)."\n".$stderr;
|
$body = strlen($stderr)."\n".$stderr;
|
||||||
} else {
|
} else {
|
||||||
list($length, $body) = explode("\n", $stdout, 2);
|
list($length, $body) = explode("\n", $stdout, 2);
|
||||||
|
if ($cmd == 'capabilities') {
|
||||||
|
$body = DiffusionMercurialWireProtocol::filterBundle2Capability($body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return id(new DiffusionMercurialResponse())->setContent($body);
|
return id(new DiffusionMercurialResponse())->setContent($body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getMercurialArguments() {
|
private function getMercurialArguments() {
|
||||||
// Mercurial sends arguments in HTTP headers. "Why?", you might wonder,
|
// Mercurial sends arguments in HTTP headers. "Why?", you might wonder,
|
||||||
// "Why would you do this?".
|
// "Why would you do this?".
|
||||||
|
|
|
@ -99,4 +99,34 @@ final class DiffusionMercurialWireProtocol extends Phobject {
|
||||||
return true;
|
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) {
|
||||||
|
$parts = explode(' ', $capabilities);
|
||||||
|
foreach ($parts as $key => $part) {
|
||||||
|
if (preg_match('/^bundle2=/', $part)) {
|
||||||
|
unset($parts[$key]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return implode(' ', $parts);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class DiffusionMercurialWireProtocolTests extends PhabricatorTestCase {
|
||||||
|
|
||||||
|
public function testFilteringBundle2Capability() {
|
||||||
|
// this was the result of running 'capabilities' over
|
||||||
|
// `hg serve --stdio` on my systems with Mercurial 3.5.1, 2.6.2
|
||||||
|
|
||||||
|
$capabilities_with_bundle2_hg_351 =
|
||||||
|
'lookup changegroupsubset branchmap pushkey '.
|
||||||
|
'known getbundle unbundlehash batch stream '.
|
||||||
|
'bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512'.
|
||||||
|
'%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0A'.
|
||||||
|
'hgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps '.
|
||||||
|
'unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024';
|
||||||
|
|
||||||
|
$capabilities_without_bundle2_hg_351 =
|
||||||
|
'lookup changegroupsubset branchmap pushkey '.
|
||||||
|
'known getbundle unbundlehash batch stream '.
|
||||||
|
'unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024';
|
||||||
|
|
||||||
|
$capabilities_hg_262 =
|
||||||
|
'lookup changegroupsubset branchmap pushkey '.
|
||||||
|
'known getbundle unbundlehash batch stream '.
|
||||||
|
'unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024 largefiles=serve';
|
||||||
|
|
||||||
|
$cases = array(
|
||||||
|
array(
|
||||||
|
'name' => pht('Filter bundle2 from Mercurial 3.5.1'),
|
||||||
|
'input' => $capabilities_with_bundle2_hg_351,
|
||||||
|
'expect' => $capabilities_without_bundle2_hg_351,
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
'name' => pht('Filter bundle does not affect Mercurial 2.6.2'),
|
||||||
|
'input' => $capabilities_hg_262,
|
||||||
|
'expect' => $capabilities_hg_262,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($cases as $case) {
|
||||||
|
$actual = DiffusionMercurialWireProtocol::filterBundle2Capability(
|
||||||
|
$case['input']);
|
||||||
|
$this->assertEqual($case['expect'], $actual, $case['name']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -107,8 +107,14 @@ final class DiffusionMercurialServeSSHWorkflow
|
||||||
$this->didSeeWrite = true;
|
$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.
|
// If we're good, return the raw message data.
|
||||||
return $message['raw'];
|
return $raw_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue