Page MenuHomePhabricator

D21697.diff
No OneTemporary

D21697.diff

diff --git a/src/land/engine/ArcanistMercurialLandEngine.php b/src/land/engine/ArcanistMercurialLandEngine.php
--- a/src/land/engine/ArcanistMercurialLandEngine.php
+++ b/src/land/engine/ArcanistMercurialLandEngine.php
@@ -1160,8 +1160,9 @@
'prune --rev %s',
$rev_set);
} else {
- $api->execxLocal(
- '--config extensions.strip= strip --rev %s',
+ $api->execxLocalWithExtension(
+ 'strip',
+ 'strip --rev %s',
$rev_set);
}
}
diff --git a/src/repository/api/ArcanistMercurialAPI.php b/src/repository/api/ArcanistMercurialAPI.php
--- a/src/repository/api/ArcanistMercurialAPI.php
+++ b/src/repository/api/ArcanistMercurialAPI.php
@@ -5,6 +5,13 @@
*/
final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
+ /**
+ * Mercurial deceptively indicates that the default encoding is UTF-8 however
+ * however the actual default appears to be "something else", at least on
+ * Windows systems. Force all mercurial commands to use UTF-8 encoding.
+ */
+ const ROOT_HG_COMMAND = 'hg --encoding utf-8 ';
+
private $branch;
private $localCommitInfo;
private $rawDiffCache = array();
@@ -13,28 +20,24 @@
private $featureFutures = array();
protected function buildLocalFuture(array $argv) {
- $env = $this->getMercurialEnvironmentVariables();
+ $argv[0] = self::ROOT_HG_COMMAND.$argv[0];
- // Mercurial deceptively indicates that the default encoding is UTF-8
- // however the actual default appears to be "something else", at least on
- // Windows systems. Force all mercurial commands to use UTF-8 encoding.
- $argv[0] = 'hg --encoding utf-8 '.$argv[0];
+ return $this->newConfiguredFuture(newv('ExecFuture', $argv));
+ }
- $future = newv('ExecFuture', $argv)
- ->setEnv($env)
- ->setCWD($this->getPath());
+ public function newPassthru($pattern /* , ... */) {
+ $args = func_get_args();
+ $args[0] = self::ROOT_HG_COMMAND.$args[0];
- return $future;
+ return $this->newConfiguredFuture(newv('PhutilExecPassthru', $args));
}
- public function newPassthru($pattern /* , ... */) {
+ private function newConfiguredFuture(PhutilExecutableFuture $future) {
$args = func_get_args();
$env = $this->getMercurialEnvironmentVariables();
- $args[0] = 'hg '.$args[0];
-
- return newv('PhutilExecPassthru', $args)
+ return $future
->setEnv($env)
->setCWD($this->getPath());
}
@@ -730,14 +733,10 @@
'log --template %s --rev . --',
'{node}');
- $argv = array();
- foreach ($this->getMercurialExtensionArguments() as $arg) {
- $argv[] = $arg;
- }
- $argv[] = 'arc-amend';
- $argv[] = '--logfile';
- $argv[] = $tmp_file;
- $this->execxLocal('%Ls', $argv);
+ $this->execxLocalWithExtension(
+ 'arc-hg',
+ 'arc-amend --logfile %s',
+ $tmp_file);
list($new_commit) = $this->execxLocal(
'log --rev tip --template %s --',
@@ -753,13 +752,20 @@
$rebase_args[] = $child;
}
- $this->execxLocal('rebase %Ls --', $rebase_args);
+ $this->execxLocalWithExtension(
+ 'rebase',
+ 'rebase %Ls --',
+ $rebase_args);
} catch (CommandException $ex) {
- $this->execxLocal('rebase --abort --');
+ $this->execxLocalWithExtension(
+ 'rebase',
+ 'rebase --abort --');
throw $ex;
}
- $this->execxLocal('--config extensions.strip= strip --rev %s --',
+ $this->execxLocalWithExtension(
+ 'strip',
+ 'strip --rev %s --',
$current);
}
@@ -1034,6 +1040,115 @@
return $this->executeMercurialFeatureTest($feature, true);
}
+ /**
+ * Returns the necessary flag for using a Mercurial extension. This will
+ * enable Mercurial built-in extensions and the "arc-hg" extension that is
+ * included with Arcanist. This will not enable other extensions, e.g.
+ * "evolve".
+ *
+ * @param string The name of the extension to enable.
+ * @return string A new command pattern that includes the necessary flags to
+ * enable the specified extension.
+ */
+ private function getMercurialExtensionFlag($extension) {
+ switch ($extension) {
+ case 'arc-hg':
+ $path = phutil_get_library_root('arcanist');
+ $path = dirname($path);
+ $path = $path.'/support/hg/arc-hg.py';
+ $ext_config = 'extensions.arg-hg='.$path;
+ break;
+ case 'rebase':
+ $ext_config = 'extensions.rebase=';
+ break;
+ case 'shelve':
+ $ext_config = 'extensions.shelve=';
+ break;
+ case 'strip':
+ $ext_config = 'extensions.strip=';
+ break;
+ default:
+ throw new Exception(
+ pht('Unknown Mercurial Extension: "%s".', $extension));
+ }
+
+ return csprintf('--config %s', $ext_config);
+ }
+
+ /**
+ * Produces the arguments that should be passed to Mercurial command
+ * execution that enables a desired extension.
+ *
+ * @param string The name of the extension to enable.
+ * @param string The command pattern that will be run with the extension
+ * enabled.
+ * @param array Parameters for the command pattern argument.
+ * @return array An array where the first item is a Mercurial command
+ * pattern that includes the necessary flag for enabling the
+ * desired extension, and all remaining items are parameters
+ * to that command pattern.
+ */
+ private function buildMercurialExtensionCommand(
+ $extension,
+ $pattern /* , ... */) {
+
+ $args = func_get_args();
+
+ $pattern_args = array_slice($args, 2);
+
+ $ext_flag = $this->getMercurialExtensionFlag($extension);
+
+ $full_cmd = $ext_flag.' '.$pattern;
+
+ $args = array_merge(
+ array($full_cmd),
+ $pattern_args);
+
+ return $args;
+ }
+
+ public function execxLocalWithExtension(
+ $extension,
+ $pattern /* , ... */) {
+
+ $args = func_get_args();
+ $extended_args = call_user_func_array(
+ array($this, 'buildMercurialExtensionCommand'),
+ $args);
+
+ return call_user_func_array(
+ array($this, 'execxLocal'),
+ $extended_args);
+ }
+
+ public function execFutureLocalWithExtension(
+ $extension,
+ $pattern /* , ... */) {
+
+ $args = func_get_args();
+ $extended_args = call_user_func_array(
+ array($this, 'buildMercurialExtensionCommand'),
+ $args);
+
+ return call_user_func_array(
+ array($this, 'execFutureLocal'),
+ $extended_args);
+ }
+
+ public function execPassthruWithExtension(
+ $extension,
+ $pattern /* , ... */) {
+
+ $args = func_get_args();
+ $extended_args = call_user_func_array(
+ array($this, 'buildMercurialExtensionCommand'),
+ $args);
+
+ return call_user_func_array(
+ array($this, 'execPassthru'),
+ $extended_args);
+ }
+
private function executeMercurialFeatureTest($feature, $resolve) {
if (array_key_exists($feature, $this->featureResults)) {
return $this->featureResults[$feature];
@@ -1059,8 +1174,9 @@
private function newMercurialFeatureFuture($feature) {
switch ($feature) {
case 'shelve':
- return $this->execFutureLocal(
- '--config extensions.shelve= shelve --help --');
+ return $this->execFutureLocalWithExtension(
+ 'shelve',
+ 'shelve --help --');
case 'evolve':
return $this->execFutureLocal('prune --help --');
default:
@@ -1094,17 +1210,6 @@
return new ArcanistMercurialRepositoryRemoteQuery();
}
- public function getMercurialExtensionArguments() {
- $path = phutil_get_library_root('arcanist');
- $path = dirname($path);
- $path = $path.'/support/hg/arc-hg.py';
-
- return array(
- '--config',
- 'extensions.arc-hg='.$path,
- );
- }
-
protected function newNormalizedURI($uri) {
return new ArcanistRepositoryURINormalizer(
ArcanistRepositoryURINormalizer::TYPE_MERCURIAL,
diff --git a/src/repository/marker/ArcanistMercurialRepositoryMarkerQuery.php b/src/repository/marker/ArcanistMercurialRepositoryMarkerQuery.php
--- a/src/repository/marker/ArcanistMercurialRepositoryMarkerQuery.php
+++ b/src/repository/marker/ArcanistMercurialRepositoryMarkerQuery.php
@@ -19,12 +19,6 @@
// to provide a command which works like "git for-each-ref" locally and
// "git ls-remote" when given a remote.
- $argv = array();
- foreach ($api->getMercurialExtensionArguments() as $arg) {
- $argv[] = $arg;
- }
- $argv[] = 'arc-ls-markers';
-
// NOTE: In remote mode, we're using passthru and a tempfile on this
// because it's a remote command and may prompt the user to provide
// credentials interactively. In local mode, we can just read stdout.
@@ -33,20 +27,17 @@
$tmpfile = new TempFile();
Filesystem::remove($tmpfile);
+ $argv = array();
$argv[] = '--output';
$argv[] = phutil_string_cast($tmpfile);
- }
-
- $argv[] = '--';
-
- if ($remote !== null) {
+ $argv[] = '--';
$argv[] = $remote->getRemoteName();
- }
- if ($remote !== null) {
- $passthru = $api->newPassthru('%Ls', $argv);
+ $err = $api->execPassthruWithExtension(
+ 'arc-hg',
+ 'arc-ls-markers %Ls',
+ $argv);
- $err = $passthru->execute();
if ($err) {
throw new Exception(
pht(
@@ -57,8 +48,10 @@
$raw_data = Filesystem::readFile($tmpfile);
unset($tmpfile);
} else {
- $future = $api->newFuture('%Ls', $argv);
- list($raw_data) = $future->resolve();
+ $future = $api->execFutureLocalWithExtension(
+ 'arc-hg',
+ 'arc-ls-markers --');
+ list($err, $raw_data) = $future->resolve();
}
$items = phutil_json_decode($raw_data);
diff --git a/src/repository/state/ArcanistMercurialLocalState.php b/src/repository/state/ArcanistMercurialLocalState.php
--- a/src/repository/state/ArcanistMercurialLocalState.php
+++ b/src/repository/state/ArcanistMercurialLocalState.php
@@ -160,8 +160,9 @@
'arc-%s',
Filesystem::readRandomCharacters(12));
- $api->execxLocal(
- '--config extensions.shelve= shelve --unknown --name %s --',
+ $api->execxLocalWithExtension(
+ 'shelve',
+ 'shelve --unknown --name %s --',
$stash_ref);
$log->writeStatus(
@@ -179,16 +180,18 @@
pht('UNSHELVE'),
pht('Restoring uncommitted changes to working copy.'));
- $api->execxLocal(
- '--config extensions.shelve= unshelve --keep --name %s --',
+ $api->execxLocalWithExtension(
+ 'shelve',
+ 'unshelve --keep --name %s --',
$stash_ref);
}
protected function discardStash($stash_ref) {
$api = $this->getRepositoryAPI();
- $api->execxLocal(
- '--config extensions.shelve= shelve --delete %s --',
+ $api->execxLocalWithExtension(
+ 'shelve',
+ 'shelve --delete %s --',
$stash_ref);
}

File Metadata

Mime Type
text/plain
Expires
Thu, Nov 28, 8:52 PM (13 h, 2 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6799122
Default Alt Text
D21697.diff (10 KB)

Event Timeline