mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-29 10:12:41 +01:00
Improve mercurial 'arc land' perf by avoiding updates
Summary: Mercurial 'arc land --hold' was taking 90+ seconds on our large repository. Since most of arc land doesn't require any particular working directory, I've changed the mercurial logic to avoid all updates except for two: the one prior to finding the revision (only applies if the user specified --branch), and the one at the end to leave the user in a good state. Also got rid of a 'hg outgoing' call when phases are supported. Also changed the hg-subversion detection to just look for .hg/svn instead of running 'hg svn info', which was taking 4 seconds. Now arc land takes about 50 seconds. Still much worse than git's 25 seconds. One big hot spot is in the two 'hg rebase' calls, which account for 25 seconds (versus 11 seconds of git). Test Plan: Tested arc land with mercurial and git. Tested with and without the --branch options. Reviewers: epriestley, bos, sid0, dschleimer Reviewed By: epriestley CC: aran, Korvin Differential Revision: https://secure.phabricator.com/D5014
This commit is contained in:
parent
688e159319
commit
eda3fc2ab4
2 changed files with 62 additions and 23 deletions
|
@ -12,6 +12,9 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
|
||||||
private $includeDirectoryStateInDiffs;
|
private $includeDirectoryStateInDiffs;
|
||||||
private $rawDiffCache = array();
|
private $rawDiffCache = array();
|
||||||
|
|
||||||
|
private $supportsRebase;
|
||||||
|
private $supportsPhases;
|
||||||
|
|
||||||
protected function buildLocalFuture(array $argv) {
|
protected function buildLocalFuture(array $argv) {
|
||||||
|
|
||||||
// Mercurial has a "defaults" feature which basically breaks automation by
|
// Mercurial has a "defaults" feature which basically breaks automation by
|
||||||
|
@ -113,8 +116,7 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
|
||||||
// Mercurial 2.1 and up have phases which indicate if something is
|
// Mercurial 2.1 and up have phases which indicate if something is
|
||||||
// published or not. To find which revs are outgoing, it's much
|
// published or not. To find which revs are outgoing, it's much
|
||||||
// faster to check the phase instead of actually checking the server.
|
// faster to check the phase instead of actually checking the server.
|
||||||
list($err) = $this->execManualLocal('help phase');
|
if (!$this->supportsPhases()) {
|
||||||
if (!$err) {
|
|
||||||
list($err, $stdout) = $this->execManualLocal(
|
list($err, $stdout) = $this->execManualLocal(
|
||||||
'log --branch %s -r %s --style default',
|
'log --branch %s -r %s --style default',
|
||||||
$this->getBranchName(),
|
$this->getBranchName(),
|
||||||
|
@ -445,6 +447,24 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function supportsRebase() {
|
||||||
|
if ($this->supportsRebase === null) {
|
||||||
|
list ($err) = $this->execManualLocal("help rebase");
|
||||||
|
$this->supportsRebase = $err === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->supportsRebase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supportsPhases() {
|
||||||
|
if ($this->supportsPhases === null) {
|
||||||
|
list ($err) = $this->execManualLocal("help phase");
|
||||||
|
$this->supportsPhases = $err === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->supportsPhases;
|
||||||
|
}
|
||||||
|
|
||||||
public function supportsCommitRanges() {
|
public function supportsCommitRanges() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -770,6 +790,10 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isHgSubversionRepo() {
|
||||||
|
return file_exists($this->getPath('.hg/svn'));
|
||||||
|
}
|
||||||
|
|
||||||
public function getSubversionInfo() {
|
public function getSubversionInfo() {
|
||||||
$info = array();
|
$info = array();
|
||||||
$base_path = null;
|
$base_path = null;
|
||||||
|
|
|
@ -189,8 +189,7 @@ EOTEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->isHg) {
|
if ($this->isHg) {
|
||||||
list ($err) = $repository_api->execManualLocal('svn info');
|
$this->isHgSvn = $repository_api->isHgSubversionRepo();
|
||||||
$this->isHgSvn = !$err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$branch = $this->getArgument('branch');
|
$branch = $this->getArgument('branch');
|
||||||
|
@ -255,8 +254,7 @@ EOTEXT
|
||||||
|
|
||||||
if ($this->isHg) {
|
if ($this->isHg) {
|
||||||
if ($this->useSquash) {
|
if ($this->useSquash) {
|
||||||
list ($err) = $repository_api->execManualLocal("rebase --help");
|
if (!$repository_api->supportsRebase()) {
|
||||||
if ($err) {
|
|
||||||
throw new ArcanistUsageException(
|
throw new ArcanistUsageException(
|
||||||
"You must enable the rebase extension to use ".
|
"You must enable the rebase extension to use ".
|
||||||
"the --squash strategy.");
|
"the --squash strategy.");
|
||||||
|
@ -298,9 +296,11 @@ EOTEXT
|
||||||
|
|
||||||
private function checkoutBranch() {
|
private function checkoutBranch() {
|
||||||
$repository_api = $this->getRepositoryAPI();
|
$repository_api = $this->getRepositoryAPI();
|
||||||
$repository_api->execxLocal(
|
if ($this->getBranchOrBookmark() != $this->branch) {
|
||||||
'checkout %s',
|
$repository_api->execxLocal(
|
||||||
$this->branch);
|
'checkout %s',
|
||||||
|
$this->branch);
|
||||||
|
}
|
||||||
|
|
||||||
echo phutil_console_format(
|
echo phutil_console_format(
|
||||||
"Switched to branch **%s**. Identifying and merging...\n",
|
"Switched to branch **%s**. Identifying and merging...\n",
|
||||||
|
@ -378,14 +378,15 @@ EOTEXT
|
||||||
|
|
||||||
private function pullFromRemote() {
|
private function pullFromRemote() {
|
||||||
$repository_api = $this->getRepositoryAPI();
|
$repository_api = $this->getRepositoryAPI();
|
||||||
$repository_api->execxLocal('checkout %s', $this->onto);
|
|
||||||
|
|
||||||
echo phutil_console_format(
|
|
||||||
"Switched to branch **%s**. Updating branch...\n",
|
|
||||||
$this->onto);
|
|
||||||
|
|
||||||
$local_ahead_of_remote = false;
|
$local_ahead_of_remote = false;
|
||||||
if ($this->isGit) {
|
if ($this->isGit) {
|
||||||
|
$repository_api->execxLocal('checkout %s', $this->onto);
|
||||||
|
|
||||||
|
echo phutil_console_format(
|
||||||
|
"Switched to branch **%s**. Updating branch...\n",
|
||||||
|
$this->onto);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$repository_api->execxLocal('pull --ff-only --no-stat');
|
$repository_api->execxLocal('pull --ff-only --no-stat');
|
||||||
} catch (CommandException $ex) {
|
} catch (CommandException $ex) {
|
||||||
|
@ -404,18 +405,32 @@ EOTEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ($this->isHg) {
|
} else if ($this->isHg) {
|
||||||
// execManual instead of execx because outgoing returns
|
echo phutil_console_format(
|
||||||
// code 1 when there is nothing outgoing
|
"Updating **%s**...\n",
|
||||||
list($err, $out) = $repository_api->execManualLocal(
|
|
||||||
'outgoing -r %s',
|
|
||||||
$this->onto);
|
$this->onto);
|
||||||
|
|
||||||
// $err === 0 means something is outgoing
|
if ($repository_api->supportsPhases()) {
|
||||||
if ($err === 0) {
|
list($out) = $repository_api->execxLocal(
|
||||||
$local_ahead_of_remote = true;
|
'log -r %s --template {phase}', $this->onto);
|
||||||
|
if ($out != 'public') {
|
||||||
|
$local_ahead_of_remote = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// execManual instead of execx because outgoing returns
|
||||||
|
// code 1 when there is nothing outgoing
|
||||||
|
list($err, $out) = $repository_api->execManualLocal(
|
||||||
|
'outgoing -r %s',
|
||||||
|
$this->onto);
|
||||||
|
|
||||||
|
// $err === 0 means something is outgoing
|
||||||
|
if ($err === 0) {
|
||||||
|
$local_ahead_of_remote = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$local_ahead_of_remote) {
|
||||||
try {
|
try {
|
||||||
$repository_api->execxLocal('pull -u');
|
$repository_api->execxLocal('pull');
|
||||||
} catch (CommandException $ex) {
|
} catch (CommandException $ex) {
|
||||||
$err = $ex->getError();
|
$err = $ex->getError();
|
||||||
$stdout = $ex->getStdOut();
|
$stdout = $ex->getStdOut();
|
||||||
|
@ -512,9 +527,9 @@ EOTEXT
|
||||||
|
|
||||||
private function squash() {
|
private function squash() {
|
||||||
$repository_api = $this->getRepositoryAPI();
|
$repository_api = $this->getRepositoryAPI();
|
||||||
$repository_api->execxLocal('checkout %s', $this->onto);
|
|
||||||
|
|
||||||
if ($this->isGit) {
|
if ($this->isGit) {
|
||||||
|
$repository_api->execxLocal('checkout %s', $this->onto);
|
||||||
$repository_api->execxLocal(
|
$repository_api->execxLocal(
|
||||||
'merge --squash --ff-only %s',
|
'merge --squash --ff-only %s',
|
||||||
$this->branch);
|
$this->branch);
|
||||||
|
|
Loading…
Reference in a new issue