Index: src/__phutil_library_map__.php =================================================================== --- src/__phutil_library_map__.php +++ src/__phutil_library_map__.php @@ -151,7 +151,6 @@ 'ConduitAPI_diffusion_createcomment_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_createcomment_Method.php', 'ConduitAPI_diffusion_diffquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_diffquery_Method.php', 'ConduitAPI_diffusion_existsquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_existsquery_Method.php', - 'ConduitAPI_diffusion_expandshortcommitquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_expandshortcommitquery_Method.php', 'ConduitAPI_diffusion_filecontentquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_filecontentquery_Method.php', 'ConduitAPI_diffusion_findsymbols_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_findsymbols_Method.php', 'ConduitAPI_diffusion_getcommits_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_getcommits_Method.php', @@ -164,8 +163,8 @@ 'ConduitAPI_diffusion_rawdiffquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_rawdiffquery_Method.php', 'ConduitAPI_diffusion_readmequery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_readmequery_Method.php', 'ConduitAPI_diffusion_refsquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_refsquery_Method.php', + 'ConduitAPI_diffusion_resolverefs_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_resolverefs_Method.php', 'ConduitAPI_diffusion_searchquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_searchquery_Method.php', - 'ConduitAPI_diffusion_stablecommitnamequery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_stablecommitnamequery_Method.php', 'ConduitAPI_diffusion_tagsquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_tagsquery_Method.php', 'ConduitAPI_feed_Method' => 'applications/feed/conduit/ConduitAPI_feed_Method.php', 'ConduitAPI_feed_publish_Method' => 'applications/feed/conduit/ConduitAPI_feed_publish_Method.php', @@ -472,20 +471,16 @@ 'DiffusionDiffController' => 'applications/diffusion/controller/DiffusionDiffController.php', 'DiffusionDoorkeeperCommitFeedStoryPublisher' => 'applications/diffusion/doorkeeper/DiffusionDoorkeeperCommitFeedStoryPublisher.php', 'DiffusionEmptyResultView' => 'applications/diffusion/view/DiffusionEmptyResultView.php', - 'DiffusionExpandCommitQueryException' => 'applications/diffusion/exception/DiffusionExpandCommitQueryException.php', - 'DiffusionExpandShortNameQuery' => 'applications/diffusion/query/expandshortname/DiffusionExpandShortNameQuery.php', 'DiffusionExternalController' => 'applications/diffusion/controller/DiffusionExternalController.php', 'DiffusionFileContent' => 'applications/diffusion/data/DiffusionFileContent.php', 'DiffusionFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionFileContentQuery.php', 'DiffusionGitBranch' => 'applications/diffusion/data/DiffusionGitBranch.php', 'DiffusionGitBranchTestCase' => 'applications/diffusion/data/__tests__/DiffusionGitBranchTestCase.php', 'DiffusionGitCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionGitCommitParentsQuery.php', - 'DiffusionGitExpandShortNameQuery' => 'applications/diffusion/query/expandshortname/DiffusionGitExpandShortNameQuery.php', 'DiffusionGitFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionGitFileContentQuery.php', 'DiffusionGitRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionGitRawDiffQuery.php', 'DiffusionGitRequest' => 'applications/diffusion/request/DiffusionGitRequest.php', 'DiffusionGitResponse' => 'applications/diffusion/response/DiffusionGitResponse.php', - 'DiffusionGitStableCommitNameQuery' => 'applications/diffusion/query/stablecommitname/DiffusionGitStableCommitNameQuery.php', 'DiffusionHistoryController' => 'applications/diffusion/controller/DiffusionHistoryController.php', 'DiffusionHistoryTableView' => 'applications/diffusion/view/DiffusionHistoryTableView.php', 'DiffusionHovercardEventListener' => 'applications/diffusion/events/DiffusionHovercardEventListener.php', @@ -498,12 +493,11 @@ 'DiffusionLowLevelGitRefQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelGitRefQuery.php', 'DiffusionLowLevelMercurialBranchesQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelMercurialBranchesQuery.php', 'DiffusionLowLevelQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelQuery.php', + 'DiffusionLowLevelResolveRefsQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelResolveRefsQuery.php', 'DiffusionMercurialCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionMercurialCommitParentsQuery.php', - 'DiffusionMercurialExpandShortNameQuery' => 'applications/diffusion/query/expandshortname/DiffusionMercurialExpandShortNameQuery.php', 'DiffusionMercurialFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionMercurialFileContentQuery.php', 'DiffusionMercurialRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionMercurialRawDiffQuery.php', 'DiffusionMercurialRequest' => 'applications/diffusion/request/DiffusionMercurialRequest.php', - 'DiffusionMercurialStableCommitNameQuery' => 'applications/diffusion/query/stablecommitname/DiffusionMercurialStableCommitNameQuery.php', 'DiffusionPathChange' => 'applications/diffusion/data/DiffusionPathChange.php', 'DiffusionPathChangeQuery' => 'applications/diffusion/query/pathchange/DiffusionPathChangeQuery.php', 'DiffusionPathCompleteController' => 'applications/diffusion/controller/DiffusionPathCompleteController.php', @@ -542,12 +536,10 @@ 'DiffusionSSHWorkflow' => 'applications/diffusion/ssh/DiffusionSSHWorkflow.php', 'DiffusionSetPasswordPanel' => 'applications/diffusion/panel/DiffusionSetPasswordPanel.php', 'DiffusionSetupException' => 'applications/diffusion/exception/DiffusionSetupException.php', - 'DiffusionStableCommitNameQuery' => 'applications/diffusion/query/stablecommitname/DiffusionStableCommitNameQuery.php', 'DiffusionSvnCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionSvnCommitParentsQuery.php', 'DiffusionSvnFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionSvnFileContentQuery.php', 'DiffusionSvnRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionSvnRawDiffQuery.php', 'DiffusionSvnRequest' => 'applications/diffusion/request/DiffusionSvnRequest.php', - 'DiffusionSvnStableCommitNameQuery' => 'applications/diffusion/query/stablecommitname/DiffusionSvnStableCommitNameQuery.php', 'DiffusionSymbolController' => 'applications/diffusion/controller/DiffusionSymbolController.php', 'DiffusionSymbolQuery' => 'applications/diffusion/query/DiffusionSymbolQuery.php', 'DiffusionTagListController' => 'applications/diffusion/controller/DiffusionTagListController.php', @@ -2366,7 +2358,6 @@ 'ConduitAPI_diffusion_createcomment_Method' => 'ConduitAPI_diffusion_Method', 'ConduitAPI_diffusion_diffquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 'ConduitAPI_diffusion_existsquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', - 'ConduitAPI_diffusion_expandshortcommitquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 'ConduitAPI_diffusion_filecontentquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 'ConduitAPI_diffusion_findsymbols_Method' => 'ConduitAPI_diffusion_Method', 'ConduitAPI_diffusion_getcommits_Method' => 'ConduitAPI_diffusion_Method', @@ -2379,8 +2370,8 @@ 'ConduitAPI_diffusion_rawdiffquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 'ConduitAPI_diffusion_readmequery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 'ConduitAPI_diffusion_refsquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', + 'ConduitAPI_diffusion_resolverefs_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 'ConduitAPI_diffusion_searchquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', - 'ConduitAPI_diffusion_stablecommitnamequery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 'ConduitAPI_diffusion_tagsquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 'ConduitAPI_feed_Method' => 'ConduitAPIMethod', 'ConduitAPI_feed_publish_Method' => 'ConduitAPI_feed_Method', @@ -2681,18 +2672,14 @@ 'DiffusionDiffController' => 'DiffusionController', 'DiffusionDoorkeeperCommitFeedStoryPublisher' => 'DoorkeeperFeedStoryPublisher', 'DiffusionEmptyResultView' => 'DiffusionView', - 'DiffusionExpandCommitQueryException' => 'Exception', - 'DiffusionExpandShortNameQuery' => 'DiffusionQuery', 'DiffusionExternalController' => 'DiffusionController', 'DiffusionFileContentQuery' => 'DiffusionQuery', 'DiffusionGitBranchTestCase' => 'PhabricatorTestCase', 'DiffusionGitCommitParentsQuery' => 'DiffusionCommitParentsQuery', - 'DiffusionGitExpandShortNameQuery' => 'DiffusionExpandShortNameQuery', 'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery', 'DiffusionGitRawDiffQuery' => 'DiffusionRawDiffQuery', 'DiffusionGitRequest' => 'DiffusionRequest', 'DiffusionGitResponse' => 'AphrontResponse', - 'DiffusionGitStableCommitNameQuery' => 'DiffusionStableCommitNameQuery', 'DiffusionHistoryController' => 'DiffusionController', 'DiffusionHistoryTableView' => 'DiffusionView', 'DiffusionHovercardEventListener' => 'PhabricatorEventListener', @@ -2704,12 +2691,11 @@ 'DiffusionLowLevelGitRefQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelMercurialBranchesQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelQuery' => 'Phobject', + 'DiffusionLowLevelResolveRefsQuery' => 'DiffusionLowLevelQuery', 'DiffusionMercurialCommitParentsQuery' => 'DiffusionCommitParentsQuery', - 'DiffusionMercurialExpandShortNameQuery' => 'DiffusionExpandShortNameQuery', 'DiffusionMercurialFileContentQuery' => 'DiffusionFileContentQuery', 'DiffusionMercurialRawDiffQuery' => 'DiffusionRawDiffQuery', 'DiffusionMercurialRequest' => 'DiffusionRequest', - 'DiffusionMercurialStableCommitNameQuery' => 'DiffusionStableCommitNameQuery', 'DiffusionPathCompleteController' => 'DiffusionController', 'DiffusionPathQueryTestCase' => 'PhabricatorTestCase', 'DiffusionPathValidateController' => 'DiffusionController', @@ -2743,12 +2729,10 @@ 'DiffusionSSHWorkflow' => 'PhabricatorSSHWorkflow', 'DiffusionSetPasswordPanel' => 'PhabricatorSettingsPanel', 'DiffusionSetupException' => 'AphrontUsageException', - 'DiffusionStableCommitNameQuery' => 'DiffusionQuery', 'DiffusionSvnCommitParentsQuery' => 'DiffusionCommitParentsQuery', 'DiffusionSvnFileContentQuery' => 'DiffusionFileContentQuery', 'DiffusionSvnRawDiffQuery' => 'DiffusionRawDiffQuery', 'DiffusionSvnRequest' => 'DiffusionRequest', - 'DiffusionSvnStableCommitNameQuery' => 'DiffusionStableCommitNameQuery', 'DiffusionSymbolController' => 'DiffusionController', 'DiffusionSymbolQuery' => 'PhabricatorOffsetPagedQuery', 'DiffusionTagListController' => 'DiffusionController', Index: src/applications/diffusion/conduit/ConduitAPI_diffusion_browsequery_Method.php =================================================================== --- src/applications/diffusion/conduit/ConduitAPI_diffusion_browsequery_Method.php +++ src/applications/diffusion/conduit/ConduitAPI_diffusion_browsequery_Method.php @@ -198,7 +198,7 @@ list($entire_manifest) = $repository->execxLocalCommand( 'manifest --rev %s', - $commit); + hgsprintf('%s', $commit)); $entire_manifest = explode("\n", $entire_manifest); $results = array(); Index: src/applications/diffusion/conduit/ConduitAPI_diffusion_expandshortcommitquery_Method.php =================================================================== --- src/applications/diffusion/conduit/ConduitAPI_diffusion_expandshortcommitquery_Method.php +++ /dev/null @@ -1,70 +0,0 @@ -setShouldCreateDiffusionRequest(false); - } - - public function getMethodDescription() { - return - 'Expands a short commit name to its full glory.'; - } - - public function defineReturnType() { - return 'array'; - } - - protected function defineCustomParamTypes() { - return array( - 'commit' => 'required string', - ); - } - - protected function defineCustomErrorTypes() { - return array( - 'ERR-MISSING-COMMIT' => pht( - 'Bad commit.'), - 'ERR-INVALID-COMMIT' => pht( - 'Invalid object name.'), - 'ERR-UNPARSEABLE-OUTPUT' => pht( - 'Unparseable output from cat-file.') - ); - } - - protected function getGitResult(ConduitAPIRequest $request) { - return $this->getGitOrMercurialResult($request); - } - protected function getMercurialResult(ConduitAPIRequest $request) { - return $this->getGitOrMercurialResult($request); - } - - private function getGitOrMercurialResult(ConduitAPIRequest $request) { - $repository = $this->getRepository($request); - $query = DiffusionExpandShortNameQuery::newFromRepository($repository); - $query->setCommit($request->getValue('commit')); - try { - $result = $query->expand(); - return $result; - } catch (DiffusionExpandCommitQueryException $e) { - switch ($e->getStatusCode()) { - case DiffusionExpandCommitQueryException::CODE_INVALID: - throw id(new ConduitException('ERR-INVALID-COMMIT')) - ->setErrorDescription($e->getMessage()); - break; - case DiffusionExpandCommitQueryException::CODE_MISSING: - throw id(new ConduitException('ERR-MISSING-COMMIT')) - ->setErrorDescription($e->getMessage()); - break; - case DiffusionExpandCommitQueryException::CODE_UNPARSEABLE: - throw id(new ConduitException('ERR-UNPARSEABLE-OUTPUT')) - ->setErrorDescription($e->getMessage()); - break; - } - } - } -} Index: src/applications/diffusion/conduit/ConduitAPI_diffusion_resolverefs_Method.php =================================================================== --- /dev/null +++ src/applications/diffusion/conduit/ConduitAPI_diffusion_resolverefs_Method.php @@ -0,0 +1,29 @@ +>>'; + } + + protected function defineCustomParamTypes() { + return array( + 'refs' => 'required list', + ); + } + + protected function getResult(ConduitAPIRequest $request) { + $refs = $request->getValue('refs'); + + return id(new DiffusionLowLevelResolveRefsQuery()) + ->setRepository($this->getDiffusionRequest()->getRepository()) + ->withRefs($refs) + ->execute(); + } + +} Index: src/applications/diffusion/conduit/ConduitAPI_diffusion_stablecommitnamequery_Method.php =================================================================== --- src/applications/diffusion/conduit/ConduitAPI_diffusion_stablecommitnamequery_Method.php +++ /dev/null @@ -1,35 +0,0 @@ -setShouldCreateDiffusionRequest(false); - } - - public function getMethodDescription() { - return - 'Identifies the latest commit in a repository. Repositories with '. - 'branch support must specify which branch to look at.'; - } - - public function defineReturnType() { - return 'string'; - } - - protected function defineCustomParamTypes() { - return array( - 'branch' => 'required string', - ); - } - - protected function getResult(ConduitAPIRequest $request) { - $repository = $this->getRepository($request); - $query = DiffusionStableCommitNameQuery::newFromRepository($repository); - $query->setBranch($request->getValue('branch')); - return $query->load(); - } -} Index: src/applications/diffusion/exception/DiffusionExpandCommitQueryException.php =================================================================== --- src/applications/diffusion/exception/DiffusionExpandCommitQueryException.php +++ /dev/null @@ -1,21 +0,0 @@ -statusCode; - } - - public function __construct($status_code /* ... */) { - $args = func_get_args(); - $this->statusCode = $args[0]; - - $args = array_slice($args, 1); - call_user_func_array(array('parent', '__construct'), $args); - } - -} Index: src/applications/diffusion/query/expandshortname/DiffusionExpandShortNameQuery.php =================================================================== --- src/applications/diffusion/query/expandshortname/DiffusionExpandShortNameQuery.php +++ /dev/null @@ -1,51 +0,0 @@ -commit = $commit; - } - public function getCommit() { - return $this->commit; - } - - public function setRepository(PhabricatorRepository $repository) { - $this->repository = $repository; - return $this; - } - public function getRepository() { - return $this->repository; - } - - protected function setCommitType($type) { - $this->commitType = $type; - return $this; - } - protected function setTagContent($content) { - $this->tagContent = $content; - return $this; - } - - final public static function newFromRepository( - PhabricatorRepository $repository) { - - $obj = parent::initQueryObject(__CLASS__, $repository); - $obj->setRepository($repository); - return $obj; - } - - final public function expand() { - $this->executeQuery(); - - return array( - 'commit' => $this->commit, - 'commitType' => $this->commitType, - 'tagContent' => $this->tagContent); - } - -} Index: src/applications/diffusion/query/expandshortname/DiffusionGitExpandShortNameQuery.php =================================================================== --- src/applications/diffusion/query/expandshortname/DiffusionGitExpandShortNameQuery.php +++ /dev/null @@ -1,52 +0,0 @@ -getRepository(); - $commit = $this->getCommit(); - - $future = $repository->getLocalCommandFuture( - 'cat-file --batch'); - $future->write($commit); - list($stdout) = $future->resolvex(); - - list($hash, $type) = explode(' ', $stdout); - if ($type == 'missing') { - throw new DiffusionExpandCommitQueryException( - DiffusionExpandCommitQueryException::CODE_MISSING, - "Bad commit '{$commit}'."); - } - - switch ($type) { - case 'tag': - $this->setCommitType('tag'); - - $matches = null; - $ok = preg_match( - '/^object ([a-f0-9]+)$.*?\n\n(.*)$/sm', - $stdout, - $matches); - if (!$ok) { - throw new DiffusionExpandCommitQueryException( - DiffusionExpandCommitQueryException::CODE_UNPARSEABLE, - "Unparseable output from cat-file: {$stdout}"); - } - - $hash = $matches[1]; - $this->setTagContent(trim($matches[2])); - break; - case 'commit': - break; - default: - throw new DiffusionExpandCommitQueryException( - DiffusionExpandCommitQueryException::CODE_INVALID, - "The reference '{$commit}' does not name a valid ". - 'commit or a tag in this repository.'); - break; - } - - $this->setCommit($hash); - } -} Index: src/applications/diffusion/query/expandshortname/DiffusionMercurialExpandShortNameQuery.php =================================================================== --- src/applications/diffusion/query/expandshortname/DiffusionMercurialExpandShortNameQuery.php +++ /dev/null @@ -1,23 +0,0 @@ -getRepository(); - $commit = $this->getCommit(); - - list($full_hash) = $repository->execxLocalCommand( - 'log --template=%s --rev %s', - '{node}', - $commit); - - $full_hash = explode("\n", trim($full_hash)); - - // TODO: Show "multiple matching commits" if count is larger than 1. For - // now, pick the first one. - - $this->setCommit(head($full_hash)); - } - -} Index: src/applications/diffusion/query/lowlevel/DiffusionLowLevelQuery.php =================================================================== --- src/applications/diffusion/query/lowlevel/DiffusionLowLevelQuery.php +++ src/applications/diffusion/query/lowlevel/DiffusionLowLevelQuery.php @@ -16,6 +16,10 @@ } public function execute() { + if (!$this->getRepository()) { + throw new Exception("Call setRepository() before execute()!"); + } + return $this->executeQuery(); } Index: src/applications/diffusion/query/lowlevel/DiffusionLowLevelResolveRefsQuery.php =================================================================== --- /dev/null +++ src/applications/diffusion/query/lowlevel/DiffusionLowLevelResolveRefsQuery.php @@ -0,0 +1,225 @@ +refs = $refs; + return $this; + } + + public function executeQuery() { + if (!$this->refs) { + return array(); + } + + switch ($this->getRepository()->getVersionControlSystem()) { + case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: + $result = $this->resolveGitRefs(); + break; + case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: + $result = $this->resolveMercurialRefs(); + break; + case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: + $result = $this->resolveSubversionRefs(); + break; + default: + throw new Exception("Unsupported repository type!"); + } + + return $result; + } + + private function resolveGitRefs() { + $repository = $this->getRepository(); + + $future = $repository->getLocalCommandFuture('cat-file --batch-check'); + $future->write(implode("\n", $this->refs)); + list($stdout) = $future->resolvex(); + + $lines = explode("\n", rtrim($stdout, "\n")); + if (count($lines) !== count($this->refs)) { + throw new Exception("Unexpected line count from `git cat-file`!"); + } + + $hits = array(); + $tags = array(); + + $lines = array_combine($this->refs, $lines); + foreach ($lines as $ref => $line) { + $parts = explode(' ', $line); + if (count($parts) < 2) { + throw new Exception("Failed to parse `git cat-file` output: {$line}"); + } + list($identifier, $type) = $parts; + + if ($type == 'missing') { + // This is either an ambiguous reference which resolves to several + // objects, or an invalid reference. For now, always treat it as + // invalid. It would be nice to resolve all possibilities for + // ambiguous references at some point, although the strategy for doing + // so isn't clear to me. + continue; + } + + switch ($type) { + case 'commit': + break; + case 'tag': + $tags[] = $identifier; + break; + default: + throw new Exception( + "Unexpected object type from `git cat-file`: {$line}"); + } + + $hits[] = array( + 'ref' => $ref, + 'type' => $type, + 'identifier' => $identifier, + ); + } + + $tag_map = array(); + if ($tags) { + // If some of the refs were tags, just load every tag in order to figure + // out which commits they map to. This might be somewhat inefficient in + // repositories with a huge number of tags. + $tag_refs = id(new DiffusionLowLevelGitRefQuery()) + ->setRepository($repository) + ->withIsTag(true) + ->executeQuery(); + foreach ($tag_refs as $tag_ref) { + $tag_map[$tag_ref->getShortName()] = $tag_ref->getCommitIdentifier(); + } + } + + $results = array(); + foreach ($hits as $hit) { + $type = $hit['type']; + $ref = $hit['ref']; + + $alternate = null; + if ($type == 'tag') { + $alternate = $identifier; + $identifier = idx($tag_map, $ref); + if (!$identifier) { + throw new Exception("Failed to look up tag '{$ref}'!"); + } + } + + $result = array( + 'type' => $type, + 'identifier' => $identifier, + ); + + if ($alternate !== null) { + $result['alternate'] = $alternate; + } + + $results[$ref][] = $result; + } + + return $results; + } + + private function resolveMercurialRefs() { + $repository = $this->getRepository(); + + $futures = array(); + foreach ($this->refs as $ref) { + // TODO: There was a note about `--rev 'a b'` not working for branches + // with spaces in their names in older code, but I suspect this was + // misidentified and resulted from the branch name being interpeted as + // a revset. Use hgsprintf() to avoid that. If this doesn't break for a + // bit, remove this comment. Otherwise, consider `-b %s --limit 1`. + + $futures[$ref] = $repository->getLocalCommandFuture( + 'log --template=%s --rev %s', + '{node}', + hgsprintf('%s', $ref)); + } + + $results = array(); + foreach (Futures($futures) as $ref => $future) { + try { + list($stdout) = $future->resolvex(); + } catch (CommandException $ex) { + if (preg_match('/ambiguous identifier/', $ex->getStdErr())) { + // This indicates that the ref ambiguously matched several things. + // Eventually, it would be nice to return all of them, but it is + // unclear how to best do that. For now, treat it as a miss instead. + continue; + } + throw $ex; + } + + // It doesn't look like we can figure out the type (commit/branch/rev) + // from this output very easily. For now, just call everything a commit. + $type = 'commit'; + + $results[$ref][] = array( + 'type' => $type, + 'identifier' => trim($stdout), + ); + } + + return $results; + } + + private function resolveSubversionRefs() { + $repository = $this->getRepository(); + + $max_commit = id(new PhabricatorRepositoryCommit()) + ->loadOneWhere( + 'repositoryID = %d ORDER BY epoch DESC, id DESC LIMIT 1', + $repository->getID()); + if (!$max_commit) { + // This repository is empty or hasn't parsed yet, so none of the refs are + // going to resolve. + return array(); + } + + $max_commit_id = (int)$max_commit->getCommitIdentifier(); + + $results = array(); + foreach ($this->refs as $ref) { + if ($ref == 'HEAD') { + // Resolve "HEAD" to mean "the most recent commit". + $results[$ref][] = array( + 'type' => 'commit', + 'identifier' => $max_commit_id, + ); + continue; + } + + if (!preg_match('/^\d+$/', $ref)) { + // This ref is non-numeric, so it doesn't resolve to anything. + continue; + } + + // Resolve other commits if we can deduce their existence. + + // TODO: When we import only part of a repository, we won't necessarily + // have all of the smaller commits. Should we fail to resolve them here + // for repositories with a subpath? It might let us simplify other things + // elsewhere. + if ((int)$ref <= $max_commit_id) { + $results[$ref][] = array( + 'type' => 'commit', + 'identifier' => (int)$ref, + ); + } + } + + return $results; + } + +} Index: src/applications/diffusion/query/stablecommitname/DiffusionGitStableCommitNameQuery.php =================================================================== --- src/applications/diffusion/query/stablecommitname/DiffusionGitStableCommitNameQuery.php +++ /dev/null @@ -1,24 +0,0 @@ -getRepository(); - $branch = $this->getBranch(); - - if ($repository->isWorkingCopyBare()) { - list($stdout) = $repository->execxLocalCommand( - 'rev-parse --verify %s', - $branch); - } else { - list($stdout) = $repository->execxLocalCommand( - 'rev-parse --verify %s/%s', - DiffusionBranchInformation::DEFAULT_GIT_REMOTE, - $branch); - } - - $commit = trim($stdout); - return substr($commit, 0, 16); - } -} Index: src/applications/diffusion/query/stablecommitname/DiffusionMercurialStableCommitNameQuery.php =================================================================== --- src/applications/diffusion/query/stablecommitname/DiffusionMercurialStableCommitNameQuery.php +++ /dev/null @@ -1,30 +0,0 @@ -getRepository(); - - // NOTE: For branches with spaces in their name like "a b", this - // does not work properly: - // - // $ hg log --rev 'a b' - // - // We can use revsets instead: - // - // $ hg log --rev branch('a b') - // - // ...but they require a somewhat newer version of Mercurial. Instead, - // use "-b" flag with limit 1 for greatest compatibility across - // versions. - - list($stable_commit_name) = $repository->execxLocalCommand( - 'log --template=%s -b %s --limit 1', - '{node}', - $this->getBranch()); - - return $stable_commit_name; - } - -} Index: src/applications/diffusion/query/stablecommitname/DiffusionStableCommitNameQuery.php =================================================================== --- src/applications/diffusion/query/stablecommitname/DiffusionStableCommitNameQuery.php +++ /dev/null @@ -1,35 +0,0 @@ -branch = $branch; - return $this; - } - public function getBranch() { - return $this->branch; - } - - public function setRepository(PhabricatorRepository $repository) { - $this->repository = $repository; - return $this; - } - public function getRepository() { - return $this->repository; - } - - final public static function newFromRepository( - PhabricatorRepository $repository) { - - $obj = parent::initQueryObject(__CLASS__, $repository); - $obj->setRepository($repository); - return $obj; - } - - final public function load() { - return $this->executeQuery(); - } -} Index: src/applications/diffusion/query/stablecommitname/DiffusionSvnStableCommitNameQuery.php =================================================================== --- src/applications/diffusion/query/stablecommitname/DiffusionSvnStableCommitNameQuery.php +++ /dev/null @@ -1,23 +0,0 @@ -getRepository(); - - $commit = id(new PhabricatorRepositoryCommit()) - ->loadOneWhere( - 'repositoryID = %d ORDER BY epoch DESC LIMIT 1', - $repository->getID()); - if ($commit) { - $stable_commit_name = $commit->getCommitIdentifier(); - } else { - // For new repositories, we may not have parsed any commits yet. Call - // the stable commit "1" and avoid fataling. - $stable_commit_name = 1; - } - - return $stable_commit_name; - } -} Index: src/applications/diffusion/request/DiffusionRequest.php =================================================================== --- src/applications/diffusion/request/DiffusionRequest.php +++ src/applications/diffusion/request/DiffusionRequest.php @@ -18,7 +18,6 @@ protected $symbolicCommit; protected $commit; protected $commitType = 'commit'; - protected $tagContent; protected $branch; protected $lint; @@ -263,10 +262,6 @@ $this->getArcanistBranch()); } - public function getTagContent() { - return $this->tagContent; - } - public function loadCommit() { if (empty($this->repositoryCommit)) { $repository = $this->getRepository(); @@ -624,26 +619,17 @@ } final protected function expandCommitName() { - if ($this->shouldInitFromConduit()) { - $commit_data = DiffusionQuery::callConduitWithDiffusionRequest( - $this->getUser(), - $this, - 'diffusion.expandshortcommitquery', - array( - 'commit' => $this->commit - )); - } else { - $repository = $this->getRepository(); - $this->validateWorkingCopy($repository->getLocalPath()); - $query = DiffusionExpandShortNameQuery::newFromRepository( - $repository); - $query->setCommit($this->commit); - $commit_data = $query->expand(); + $results = $this->resolveRefs(array($this->commit)); + $matches = idx($results, $this->commit, array()); + if (count($results) !== 1) { + throw new Exception( + pht('Ref "%s" is ambiguous or does not exist.', $this->commit)); } - $this->commit = $commit_data['commit']; - $this->commitType = $commit_data['commitType']; - $this->tagContent = $commit_data['tagContent']; + $match = head($matches); + + $this->commit = $match['identifier']; + $this->commitType = $match['type']; } public function getCommitType() { @@ -653,20 +639,43 @@ private function queryStableCommitName() { if ($this->commit) { $this->stableCommitName = $this->commit; - } else if ($this->shouldInitFromConduit()) { - $this->stableCommitName = DiffusionQuery::callConduitWithDiffusionRequest( + return $this->stableCommitName; + } + + if ($this->getSupportsBranches()) { + $branch = $this->getBranch(); + } else { + $branch = 'HEAD'; + } + + $results = $this->resolveRefs(array($branch)); + + $matches = idx($results, $branch, array()); + if (count($matches) !== 1) { + throw new Exception( + pht('Ref "%s" is ambiguous or does not exist.', $branch)); + } + + $this->stableCommitName = idx(head($matches), 'identifier'); + return $this->stableCommitName; + } + + private function resolveRefs(array $refs) { + if ($this->shouldInitFromConduit()) { + return DiffusionQuery::callConduitWithDiffusionRequest( $this->getUser(), $this, - 'diffusion.stablecommitnamequery', + 'diffusion.resolverefs', array( - 'branch' => $this->getBranch() + 'refs' => $refs, )); } else { - $query = DiffusionStableCommitNameQuery::newFromRepository( - $this->getRepository()); - $query->setBranch($this->getBranch()); - $this->stableCommitName = $query->load(); + return id(new DiffusionLowLevelResolveRefsQuery()) + ->setRepository($this->getRepository()) + ->withRefs($refs) + ->execute(); } - return $this->stableCommitName; } + + }