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

Remove "arc feature", "arc branch", "arc bookmark", and significant chunks of obsolete marker code

Summary: Ref T13546. Moves away from the older workflows in favor of "arc branches", "arc bookmarks", and "arc work".

Test Plan: Grepped for affected symbols, didn't find any callers.

Maniphest Tasks: T13546

Differential Revision: https://secure.phabricator.com/D21337
This commit is contained in:
epriestley 2020-06-08 11:05:08 -07:00
parent 3d64140ff3
commit b003cf9310
10 changed files with 12 additions and 581 deletions

View file

@ -49,12 +49,10 @@ phutil_register_library_map(array(
'ArcanistBlacklistedFunctionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistBlacklistedFunctionXHPASTLinterRule.php',
'ArcanistBlacklistedFunctionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistBlacklistedFunctionXHPASTLinterRuleTestCase.php',
'ArcanistBlindlyTrustHTTPEngineExtension' => 'configuration/ArcanistBlindlyTrustHTTPEngineExtension.php',
'ArcanistBookmarkWorkflow' => 'workflow/ArcanistBookmarkWorkflow.php',
'ArcanistBookmarksWorkflow' => 'workflow/ArcanistBookmarksWorkflow.php',
'ArcanistBoolConfigOption' => 'config/option/ArcanistBoolConfigOption.php',
'ArcanistBraceFormattingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistBraceFormattingXHPASTLinterRule.php',
'ArcanistBraceFormattingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistBraceFormattingXHPASTLinterRuleTestCase.php',
'ArcanistBranchWorkflow' => 'workflow/ArcanistBranchWorkflow.php',
'ArcanistBranchesWorkflow' => 'workflow/ArcanistBranchesWorkflow.php',
'ArcanistBrowseCommitHardpointQuery' => 'browse/query/ArcanistBrowseCommitHardpointQuery.php',
'ArcanistBrowseCommitURIHardpointQuery' => 'browse/query/ArcanistBrowseCommitURIHardpointQuery.php',
@ -194,8 +192,6 @@ phutil_register_library_map(array(
'ArcanistExternalLinterTestCase' => 'lint/linter/__tests__/ArcanistExternalLinterTestCase.php',
'ArcanistExtractUseXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistExtractUseXHPASTLinterRule.php',
'ArcanistExtractUseXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistExtractUseXHPASTLinterRuleTestCase.php',
'ArcanistFeatureBaseWorkflow' => 'workflow/ArcanistFeatureBaseWorkflow.php',
'ArcanistFeatureWorkflow' => 'workflow/ArcanistFeatureWorkflow.php',
'ArcanistFileConfigurationSource' => 'config/source/ArcanistFileConfigurationSource.php',
'ArcanistFileDataRef' => 'upload/ArcanistFileDataRef.php',
'ArcanistFileRef' => 'ref/file/ArcanistFileRef.php',
@ -1068,12 +1064,10 @@ phutil_register_library_map(array(
'ArcanistBlacklistedFunctionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistBlacklistedFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistBlindlyTrustHTTPEngineExtension' => 'PhutilHTTPEngineExtension',
'ArcanistBookmarkWorkflow' => 'ArcanistFeatureBaseWorkflow',
'ArcanistBookmarksWorkflow' => 'ArcanistMarkersWorkflow',
'ArcanistBoolConfigOption' => 'ArcanistSingleSourceConfigOption',
'ArcanistBraceFormattingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistBraceFormattingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistBranchWorkflow' => 'ArcanistFeatureBaseWorkflow',
'ArcanistBranchesWorkflow' => 'ArcanistMarkersWorkflow',
'ArcanistBrowseCommitHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
'ArcanistBrowseCommitURIHardpointQuery' => 'ArcanistBrowseURIHardpointQuery',
@ -1224,8 +1218,6 @@ phutil_register_library_map(array(
'ArcanistExternalLinterTestCase' => 'ArcanistLinterTestCase',
'ArcanistExtractUseXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistExtractUseXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistFeatureBaseWorkflow' => 'ArcanistArcWorkflow',
'ArcanistFeatureWorkflow' => 'ArcanistFeatureBaseWorkflow',
'ArcanistFileConfigurationSource' => 'ArcanistFilesystemConfigurationSource',
'ArcanistFileDataRef' => 'Phobject',
'ArcanistFileRef' => array(

View file

@ -22,14 +22,6 @@ final class ArcanistArcConfigurationEngineExtension
'default' => array(),
'example' => '["/var/arc/customlib/src"]',
),
'arc.feature.start.default' => array(
'type' => 'string',
'help' => pht(
'The name of the default branch to create the new feature branch '.
'off of.'),
'example' => '"develop"',
),
'editor' => array(
'type' => 'string',
'help' => pht(

View file

@ -65,13 +65,6 @@ final class ArcanistSettings extends Phobject {
'engine is specified by the current project.'),
'example' => '"ExampleUnitTestEngine"',
),
'arc.feature.start.default' => array(
'type' => 'string',
'help' => pht(
'The name of the default branch to create the new feature branch '.
'off of.'),
'example' => '"develop"',
),
'arc.land.onto.default' => array(
'type' => 'string',
'help' => pht(

View file

@ -597,16 +597,16 @@ final class ArcanistGitAPI extends ArcanistRepositoryAPI {
public function getCanonicalRevisionName($string) {
$match = null;
if (preg_match('/@([0-9]+)$/', $string, $match)) {
$stdout = $this->getHashFromFromSVNRevisionNumber($match[1]);
} else {
list($stdout) = $this->execxLocal(
phutil_is_windows()
? 'show -s --format=%C %s --'
: 'show -s --format=%s %s --',
'show -s --format=%s %s --',
'%H',
$string);
}
return rtrim($stdout);
}
@ -1056,7 +1056,7 @@ final class ArcanistGitAPI extends ArcanistRepositoryAPI {
*
* @return list<dict<string, string>> Dictionary of branch information.
*/
public function getAllBranches() {
private function getAllBranches() {
$field_list = array(
'%(refname)',
'%(objectname)',
@ -1102,26 +1102,6 @@ final class ArcanistGitAPI extends ArcanistRepositoryAPI {
return $result;
}
public function getAllBranchRefs() {
$branches = $this->getAllBranches();
$refs = array();
foreach ($branches as $branch) {
$commit_ref = $this->newCommitRef()
->setCommitHash($branch['hash'])
->setTreeHash($branch['tree'])
->setCommitEpoch($branch['epoch'])
->attachMessage($branch['text']);
$refs[] = $this->newMarkerRef()
->setName($branch['name'])
->setIsActive($branch['current'])
->attachCommitRef($commit_ref);
}
return $refs;
}
public function getBaseCommitRef() {
$base_commit = $this->getBaseCommit();
@ -1783,5 +1763,4 @@ final class ArcanistGitAPI extends ArcanistRepositoryAPI {
return new ArcanistGitRepositoryMarkerQuery();
}
}

View file

@ -49,12 +49,6 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
}
public function getCanonicalRevisionName($string) {
$match = null;
if ($this->isHgSubversionRepo() &&
preg_match('/@([0-9]+)$/', $string, $match)) {
$string = hgsprintf('svnrev(%s)', $match[1]);
}
list($stdout) = $this->execxLocal(
'log -l 1 --template %s -r %s --',
'{node}',
@ -63,32 +57,6 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
return $stdout;
}
public function getHashFromFromSVNRevisionNumber($revision_id) {
$matches = array();
$string = hgsprintf('svnrev(%s)', $revision_id);
list($stdout) = $this->execxLocal(
'log -l 1 --template %s -r %s --',
'{node}',
$string);
if (!$stdout) {
throw new ArcanistUsageException(
pht('Cannot find the HG equivalent of %s given.', $revision_id));
}
return $stdout;
}
public function getSVNRevisionNumberFromHash($hash) {
$matches = array();
list($stdout) = $this->execxLocal(
'log -r %s --template {svnrev}', $hash);
if (!$stdout) {
throw new ArcanistUsageException(
pht('Cannot find the SVN equivalent of %s given.', $hash));
}
return $stdout;
}
public function getSourceControlPath() {
return '/';
}
@ -505,53 +473,6 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
return true;
}
public function getAllBranches() {
// TODO: This is wrong, and returns bookmarks.
list($branch_info) = $this->execxLocal('bookmarks');
if (trim($branch_info) == 'no bookmarks set') {
return array();
}
$matches = null;
preg_match_all(
'/^\s*(\*?)\s*(.+)\s(\S+)$/m',
$branch_info,
$matches,
PREG_SET_ORDER);
$return = array();
foreach ($matches as $match) {
list(, $current, $name, $hash) = $match;
list($id, $hash) = explode(':', $hash);
$return[] = array(
'current' => (bool)$current,
'name' => rtrim($name),
'hash' => $hash,
);
}
return $return;
}
public function getAllBranchRefs() {
$branches = $this->getAllBranches();
$refs = array();
foreach ($branches as $branch) {
$commit_ref = $this->newCommitRef()
->setCommitHash($branch['hash']);
$refs[] = $this->newMarkerRef()
->setBranchName($branch['name'])
->setIsCurrentBranch($branch['current'])
->attachCommitRef($commit_ref);
}
return $refs;
}
public function getBaseCommitRef() {
$base_commit = $this->getBaseCommit();
@ -937,10 +858,6 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
}
public function isHgSubversionRepo() {
return file_exists($this->getPath('.hg/svn/rev_map'));
}
public function getSubversionInfo() {
$info = array();
$base_path = null;
@ -972,133 +889,16 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI {
}
public function getActiveBookmark() {
$bookmarks = $this->getBookmarks();
foreach ($bookmarks as $bookmark) {
if ($bookmark['is_active']) {
return $bookmark['name'];
}
}
$bookmark = $this->newMarkerRefQuery()
->withMarkerTypes(ArcanistMarkerRef::TYPE_BOOKMARK)
->withIsActive(true)
->executeOne();
if (!$bookmark) {
return null;
}
public function isBookmark($name) {
$bookmarks = $this->getBookmarks();
foreach ($bookmarks as $bookmark) {
if ($bookmark['name'] === $name) {
return true;
}
}
return false;
}
public function isBranch($name) {
$branches = $this->getBranches();
foreach ($branches as $branch) {
if ($branch['name'] === $name) {
return true;
}
}
return false;
}
public function getBranches() {
list($stdout) = $this->execxLocal('--debug branches');
$lines = ArcanistMercurialParser::parseMercurialBranches($stdout);
$branches = array();
foreach ($lines as $name => $spec) {
$branches[] = array(
'name' => $name,
'revision' => $spec['rev'],
);
}
return $branches;
}
public function getBookmarks() {
$bookmarks = array();
list($raw_output) = $this->execxLocal('bookmarks');
$raw_output = trim($raw_output);
if ($raw_output !== 'no bookmarks set') {
foreach (explode("\n", $raw_output) as $line) {
// example line: * mybook 2:6b274d49be97
list($name, $revision) = $this->splitBranchOrBookmarkLine($line);
$is_active = false;
if ('*' === $name[0]) {
$is_active = true;
$name = substr($name, 2);
}
$bookmarks[] = array(
'is_active' => $is_active,
'name' => $name,
'revision' => $revision,
);
}
}
return $bookmarks;
}
public function getBookmarkCommitHash($name) {
// TODO: Cache this.
$bookmarks = $this->getBookmarks($name);
$bookmarks = ipull($bookmarks, null, 'name');
foreach ($bookmarks as $bookmark) {
if ($bookmark['name'] === $name) {
return $bookmark['revision'];
}
}
throw new Exception(pht('No bookmark "%s".', $name));
}
public function getBranchCommitHash($name) {
// TODO: Cache this.
// TODO: This won't work when there are multiple branch heads with the
// same name.
$branches = $this->getBranches($name);
$heads = array();
foreach ($branches as $branch) {
if ($branch['name'] === $name) {
$heads[] = $branch;
}
}
if (count($heads) === 1) {
return idx(head($heads), 'revision');
}
if (!$heads) {
throw new Exception(pht('No branch "%s".', $name));
}
throw new Exception(pht('Too many branch heads for "%s".', $name));
}
private function splitBranchOrBookmarkLine($line) {
// branches and bookmarks are printed in the format:
// default 0:a5ead76cdf85 (inactive)
// * mybook 2:6b274d49be97
// this code divides the name half from the revision half
// it does not parse the * and (inactive) bits
$colon_index = strrpos($line, ':');
$before_colon = substr($line, 0, $colon_index);
$start_rev_index = strrpos($before_colon, ' ');
$name = substr($line, 0, $start_rev_index);
$rev = substr($line, $start_rev_index);
return array(trim($name), trim($rev));
return $bookmark->getName();
}
public function getRemoteURI() {

View file

@ -369,15 +369,6 @@ abstract class ArcanistRepositoryAPI extends Phobject {
throw new ArcanistCapabilityNotSupportedException($this);
}
public function getAllBranches() {
// TODO: Implement for Mercurial/SVN and make abstract.
return array();
}
public function getAllBranchRefs() {
throw new ArcanistCapabilityNotSupportedException($this);
}
public function getBaseCommitRef() {
throw new ArcanistCapabilityNotSupportedException($this);
}

View file

@ -1,10 +0,0 @@
<?php
final class ArcanistBookmarkWorkflow
extends ArcanistFeatureBaseWorkflow {
public function getWorkflowName() {
return 'bookmark';
}
}

View file

@ -1,10 +0,0 @@
<?php
final class ArcanistBranchWorkflow
extends ArcanistFeatureBaseWorkflow {
public function getWorkflowName() {
return 'branch';
}
}

View file

@ -1,286 +0,0 @@
<?php
abstract class ArcanistFeatureBaseWorkflow
extends ArcanistArcWorkflow {
private $branches;
public function getWorkflowArguments() {
return array(
$this->newWorkflowArgument('view-all')
->setHelp(pht('Include closed and abandoned revisions.')),
$this->newWorkflowArgument('by-status')
->setParameter('status')
->setHelp(pht('Sort branches by status instead of time.')),
$this->newWorkflowArgument('output')
->setParameter('format')
->setHelp(
pht(
'With "json", show features in machine-readable JSON format.')),
$this->newWorkflowArgument('branch')
->setWildcard(true),
);
}
public function getWorkflowInformation() {
return $this->newWorkflowInformation()
->setSynopsis(pht('Wrapper on "git branch" or "hg bookmark".'))
->addExample(pht('**%s** [__options__]', $this->getWorkflowName()))
->addExample(pht('**%s** __name__ [__start__]', $this->getWorkflowName()))
->setHelp(
pht(<<<EOHELP
A wrapper on 'git branch' or 'hg bookmark'.
Without __name__, it lists the available branches and their revision status.
With __name__, it creates or checks out a branch. If the branch __name__
doesn't exist and is in format D123 then the branch of revision D123 is
checked out. Use __start__ to specify where the new branch will start. Use
'arc.feature.start.default' to set the default feature start location.
EOHELP
));
}
public function runWorkflow() {
$repository_api = $this->getRepositoryAPI();
if (!$repository_api) {
throw new PhutilArgumentUsageException(
pht(
'This command must be run in a Git or Mercurial working copy.'));
}
$names = $this->getArgument('branch');
if ($names) {
if (count($names) > 2) {
throw new ArcanistUsageException(pht('Specify only one branch.'));
}
return $this->checkoutBranch($names);
}
// TODO: Everything in this whole workflow that says "branch" means
// "bookmark" in Mercurial.
$branches = $repository_api->getAllBranchRefs();
if (!$branches) {
throw new ArcanistUsageException(
pht('No branches in this working copy.'));
}
$states = array();
foreach ($branches as $branch_key => $branch) {
$state_ref = id(new ArcanistWorkingCopyStateRef())
->setCommitRef($branch->getCommitRef());
$states[] = array(
'branch' => $branch,
'state' => $state_ref,
);
}
$this->loadHardpoints(
ipull($states, 'state'),
ArcanistWorkingCopyStateRef::HARDPOINT_REVISIONREFS);
$this->printBranches($states);
return 0;
}
private function checkoutBranch(array $names) {
$api = $this->getRepositoryAPI();
if ($api instanceof ArcanistMercurialAPI) {
$command = 'update %s';
} else {
$command = 'checkout %s';
}
$err = 1;
$name = $names[0];
if (isset($names[1])) {
$start = $names[1];
} else {
$start = $this->getConfigFromAnySource('arc.feature.start.default');
}
$branches = $api->getAllBranches();
if (in_array($name, ipull($branches, 'name'))) {
list($err, $stdout, $stderr) = $api->execManualLocal($command, $name);
}
if ($err) {
$match = null;
if (preg_match('/^D(\d+)$/', $name, $match)) {
$diff = $this->getConduitEngine()->resolveCall(
'differential.querydiffs',
array(
'revisionIDs' => array($match[1]),
));
$diff = head($diff);
if ($diff['branch'] != '') {
$name = $diff['branch'];
list($err, $stdout, $stderr) = $api->execManualLocal(
$command,
$name);
}
}
}
if ($err) {
if ($api instanceof ArcanistMercurialAPI) {
$rev = '';
if ($start) {
$rev = csprintf('-r %s', $start);
}
$exec = $api->execManualLocal('bookmark %C %s', $rev, $name);
if (!$exec[0] && $start) {
$api->execxLocal('update %s', $name);
}
} else {
$startarg = $start ? csprintf('%s', $start) : '';
$exec = $api->execManualLocal(
'checkout --track -b %s %C',
$name,
$startarg);
}
list($err, $stdout, $stderr) = $exec;
}
echo $stdout;
fprintf(STDERR, '%s', $stderr);
return $err;
}
private function printBranches(array $states) {
static $color_map = array(
'Closed' => 'cyan',
'Needs Review' => 'magenta',
'Needs Revision' => 'red',
'Accepted' => 'green',
'No Revision' => 'blue',
'Abandoned' => 'default',
);
static $ssort_map = array(
'Closed' => 1,
'No Revision' => 2,
'Needs Review' => 3,
'Needs Revision' => 4,
'Accepted' => 5,
);
$out = array();
foreach ($states as $objects) {
$state = $objects['state'];
$branch = $objects['branch'];
$revision = null;
if ($state->hasAmbiguousRevisionRefs()) {
$status = pht('Ambiguous Revision');
} else {
$revision = $state->getRevisionRef();
if ($revision) {
$status = $revision->getStatusDisplayName();
} else {
$status = pht('No Revision');
}
}
if (!$this->getArgument('view-all') && !$branch->getIsActive()) {
if ($status == 'Closed' || $status == 'Abandoned') {
continue;
}
}
$commit = $branch->getCommitRef();
$epoch = $commit->getCommitEpoch();
$color = idx($color_map, $status, 'default');
$epoch_vector = id(new PhutilSortVector())
->addInt($epoch);
$status_vector = id(new PhutilSortVector())
->addInt(idx($ssort_map, $status, 0))
->addInt($epoch);
if ($revision) {
$desc = $revision->getFullName();
} else {
$desc = $commit->getSummary();
}
$out[] = array(
'name' => $branch->getName(),
'current' => $branch->getIsActive(),
'status' => $status,
'desc' => $desc,
'revision' => $revision ? $revision->getID() : null,
'color' => $color,
'epoch' => $epoch,
'esort' => $epoch_vector,
'ssort' => $status_vector,
);
}
if (!$out) {
// All of the revisions are closed or abandoned.
return;
}
$len_name = max(array_map('strlen', ipull($out, 'name'))) + 2;
$len_status = max(array_map('strlen', ipull($out, 'status'))) + 2;
// Sort the list in natural order first. When we apply a stable sort to
// the list below, branches which were last updated at the same time will
// retain this ordering. This allows "feature1", "feature2", etc., to
// display in the correct order if they were touched at the same second,
// which is common when "arc land" performs a cascading rebase.
$name_map = ipull($out, 'name');
natcasesort($name_map);
$out = array_select_keys($out, array_keys($name_map));
if ($this->getArgument('by-status')) {
$vectors = ipull($out, 'ssort');
} else {
$vectors = ipull($out, 'esort');
}
$vectors = msortv($vectors, 'getSelf');
$out = array_select_keys($out, array_keys($vectors));
if ($this->getArgument('output') == 'json') {
foreach ($out as &$feature) {
unset($feature['color'], $feature['ssort'], $feature['esort']);
}
echo json_encode(ipull($out, null, 'name'))."\n";
} else {
$table = id(new PhutilConsoleTable())
->setShowHeader(false)
->addColumn('current', array('title' => ''))
->addColumn('name', array('title' => pht('Name')))
->addColumn('status', array('title' => pht('Status')))
->addColumn('descr', array('title' => pht('Description')));
foreach ($out as $line) {
$table->addRow(array(
'current' => $line['current'] ? '*' : '',
'name' => tsprintf('**%s**', $line['name']),
'status' => tsprintf(
"<fg:{$line['color']}>%s</fg>", $line['status']),
'descr' => $line['desc'],
));
}
$table->draw();
}
}
}

View file

@ -1,10 +0,0 @@
<?php
final class ArcanistFeatureWorkflow
extends ArcanistFeatureBaseWorkflow {
public function getWorkflowName() {
return 'feature';
}
}