1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-21 22:32:41 +01:00

In "arc land" under Git, confirm branch creation

Summary: Ref T13546. If "arc land" would create a branch, warn the user before it does.

Test Plan: Ran "arc land --onto mtarse", a typo of "master".

Maniphest Tasks: T13546

Differential Revision: https://secure.phabricator.com/D21354
This commit is contained in:
epriestley 2020-06-11 06:45:34 -07:00
parent 33bb0acf97
commit b0a9ef8351
5 changed files with 131 additions and 9 deletions

View file

@ -876,6 +876,8 @@ final class ArcanistGitLandEngine
}
protected function confirmOntoRefs(array $onto_refs) {
$api = $this->getRepositoryAPI();
foreach ($onto_refs as $onto_ref) {
if (!strlen($onto_ref)) {
throw new PhutilArgumentUsageException(
@ -886,10 +888,61 @@ final class ArcanistGitLandEngine
}
}
// TODO: Check that these refs really exist in the remote? Checking the
// remote is expensive and users probably rarely specify "--onto" manually,
// but if "arc land" creates branches without prompting when you make typos
// that also seems questionable.
$markers = $api->newMarkerRefQuery()
->withRemotes(array($this->getOntoRemoteRef()))
->withNames($onto_refs)
->execute();
$markers = mgroup($markers, 'getName');
$new_markers = array();
foreach ($onto_refs as $onto_ref) {
if (isset($markers[$onto_ref])) {
// Remote already has a branch with this name, so we're fine: we
// aren't creatinga new branch.
continue;
}
$new_markers[] = id(new ArcanistMarkerRef())
->setMarkerType(ArcanistMarkerRef::TYPE_BRANCH)
->setName($onto_ref);
}
if ($new_markers) {
echo tsprintf(
"\n%!\n%W\n\n",
pht('CREATE %s BRANCHE(S)', phutil_count($new_markers)),
pht(
'These %s symbol(s) do not exist in the remote. They will be '.
'created as new branches:',
phutil_count($new_markers)));
foreach ($new_markers as $new_marker) {
echo tsprintf('%s', $new_marker->newRefView());
}
echo tsprintf("\n");
$is_hold = $this->getShouldHold();
if ($is_hold) {
echo tsprintf(
"%?\n",
pht(
'You are using "--hold", so execution will stop before the '.
'%s branche(s) are actually created. You will be given '.
'instructions to create the branches.',
phutil_count($new_markers)));
}
$query = pht(
'Create %s new branche(s) in the remote?',
phutil_count($new_markers));
$this->getWorkflow()
->getPrompt('arc.land.create')
->setQuery($query)
->execute();
}
}
protected function selectOntoRefs(array $symbols) {
@ -1238,6 +1291,7 @@ final class ArcanistGitLandEngine
$api = $this->getRepositoryAPI();
// Make sure that our "into" target is valid.
$log = $this->getLogEngine();
$api = $this->getRepositoryAPI();
if ($this->getIntoEmpty()) {
// If we're running under "--into-empty", we don't have to do anything.

View file

@ -1569,4 +1569,9 @@ abstract class ArcanistLandEngine
return $command->execute();
}
final protected function getOntoRemoteRef() {
return id(new ArcanistRemoteRef())
->setRemoteName($this->getOntoRemote());
}
}

View file

@ -270,8 +270,7 @@ final class ArcanistMercurialLandEngine
}
}
$remote_ref = id(new ArcanistRemoteRef())
->setRemoteName($this->getOntoRemote());
$remote_ref = $this->getOntoRemoteRef();
$markers = $api->newMarkerRefQuery()
->withRemotes(array($remote_ref))
@ -346,8 +345,8 @@ final class ArcanistMercurialLandEngine
"\n%!\n%W\n\n",
pht('CREATE %s BOOKMARK(S)', phutil_count($new_markers)),
pht(
'These %s symbol(s) do not exist in the remote. They will be created '.
'as new bookmarks:',
'These %s symbol(s) do not exist in the remote. They will be '.
'created as new bookmarks:',
phutil_count($new_markers)));
@ -357,6 +356,17 @@ final class ArcanistMercurialLandEngine
echo tsprintf("\n");
$is_hold = $this->getShouldHold();
if ($is_hold) {
echo tsprintf(
"%?\n",
pht(
'You are using "--hold", so execution will stop before the '.
'%s bookmark(s) are actually created. You will be given '.
'instructions to create the bookmarks.',
phutil_count($new_markers)));
}
$query = pht(
'Create %s new remote bookmark(s)?',
phutil_count($new_markers));

View file

@ -122,7 +122,59 @@ final class ArcanistGitRepositoryMarkerQuery
}
protected function newRemoteRefMarkers(ArcanistRemoteRef $remote) {
throw new PhutilMethodNotImplementedException();
$api = $this->getRepositoryAPI();
// NOTE: Since we only care about branches today, we only list branches.
$future = $api->newFuture(
'ls-remote --refs %s %s',
$remote->getRemoteName(),
'refs/heads/*');
list($stdout) = $future->resolve();
$branch_prefix = 'refs/heads/';
$branch_length = strlen($branch_prefix);
$pattern = '(^(?P<hash>\S+)\t(?P<ref>\S+)\z)';
$markers = array();
$lines = phutil_split_lines($stdout, false);
foreach ($lines as $line) {
$matches = null;
$ok = preg_match($pattern, $line, $matches);
if (!$ok) {
throw new Exception(
pht(
'Failed to match "ls-remote" pattern against line "%s".',
$line));
}
$hash = $matches['hash'];
$ref = $matches['ref'];
if (!strncmp($ref, $branch_prefix, $branch_length)) {
$type = ArcanistMarkerRef::TYPE_BRANCH;
$name = substr($ref, $branch_length);
} else {
// For now, discard other refs.
continue;
}
$marker = id(new ArcanistMarkerRef())
->setName($name)
->setMarkerType($type)
->setMarkerHash($hash)
->setCommitHash($hash);
$commit_ref = $api->newCommitRef()
->setCommitHash($hash);
$marker->attachCommitRef($commit_ref);
$markers[] = $marker;
}
return $markers;
}
}

View file

@ -51,6 +51,7 @@ function xsprintf_terminal($userdata, &$pattern, &$pos, &$value, &$length) {
case '?':
$value = tsprintf('<bg:green>** ? **</bg> %s', $value);
$value = PhutilTerminalString::escapeStringValue($value, false);
$value = phutil_console_wrap($value, 6, false);
$type = 's';
break;
case '>':