diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -49,12 +49,10 @@ '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 @@ '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 @@ '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 @@ 'ArcanistExternalLinterTestCase' => 'ArcanistLinterTestCase', 'ArcanistExtractUseXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistExtractUseXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', - 'ArcanistFeatureBaseWorkflow' => 'ArcanistArcWorkflow', - 'ArcanistFeatureWorkflow' => 'ArcanistFeatureBaseWorkflow', 'ArcanistFileConfigurationSource' => 'ArcanistFilesystemConfigurationSource', 'ArcanistFileDataRef' => 'Phobject', 'ArcanistFileRef' => array( diff --git a/src/config/arc/ArcanistArcConfigurationEngineExtension.php b/src/config/arc/ArcanistArcConfigurationEngineExtension.php --- a/src/config/arc/ArcanistArcConfigurationEngineExtension.php +++ b/src/config/arc/ArcanistArcConfigurationEngineExtension.php @@ -22,14 +22,6 @@ '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( diff --git a/src/configuration/ArcanistSettings.php b/src/configuration/ArcanistSettings.php --- a/src/configuration/ArcanistSettings.php +++ b/src/configuration/ArcanistSettings.php @@ -65,13 +65,6 @@ '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( diff --git a/src/repository/api/ArcanistGitAPI.php b/src/repository/api/ArcanistGitAPI.php --- a/src/repository/api/ArcanistGitAPI.php +++ b/src/repository/api/ArcanistGitAPI.php @@ -597,16 +597,16 @@ 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 @@ * * @return list> Dictionary of branch information. */ - public function getAllBranches() { + private function getAllBranches() { $field_list = array( '%(refname)', '%(objectname)', @@ -1102,26 +1102,6 @@ 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 @@ return new ArcanistGitRepositoryMarkerQuery(); } - } 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 @@ -49,12 +49,6 @@ } 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 @@ 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 @@ 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 @@ } - public function isHgSubversionRepo() { - return file_exists($this->getPath('.hg/svn/rev_map')); - } - public function getSubversionInfo() { $info = array(); $base_path = null; @@ -972,133 +889,16 @@ } public function getActiveBookmark() { - $bookmarks = $this->getBookmarks(); - foreach ($bookmarks as $bookmark) { - if ($bookmark['is_active']) { - return $bookmark['name']; - } - } - - 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)); - } + $bookmark = $this->newMarkerRefQuery() + ->withMarkerTypes(ArcanistMarkerRef::TYPE_BOOKMARK) + ->withIsActive(true) + ->executeOne(); - 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)); + if (!$bookmark) { + return null; } - 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() { diff --git a/src/repository/api/ArcanistRepositoryAPI.php b/src/repository/api/ArcanistRepositoryAPI.php --- a/src/repository/api/ArcanistRepositoryAPI.php +++ b/src/repository/api/ArcanistRepositoryAPI.php @@ -369,15 +369,6 @@ 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); } diff --git a/src/workflow/ArcanistBookmarkWorkflow.php b/src/workflow/ArcanistBookmarkWorkflow.php deleted file mode 100644 --- a/src/workflow/ArcanistBookmarkWorkflow.php +++ /dev/null @@ -1,10 +0,0 @@ -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(<<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( - "%s", $line['status']), - 'descr' => $line['desc'], - )); - } - - $table->draw(); - } - } - -} diff --git a/src/workflow/ArcanistFeatureWorkflow.php b/src/workflow/ArcanistFeatureWorkflow.php deleted file mode 100644 --- a/src/workflow/ArcanistFeatureWorkflow.php +++ /dev/null @@ -1,10 +0,0 @@ -