Merge "expandshortcommitquery" and "stablecommitnamequery" into "resolverefs"
Summary: Ref T1493. Diffusion has some garbagey behavior for things we can't resolve. Common cases are: - Looking at a branch that doesn't exist. - Looking at a repository with no branches. - Looking at a commit that doesn't exist. - Looking at an empty repository. In these cases, we generally fatal unhelpfully. I want to untangle this mess. This doesn't help much, but does clean things up a bit. We currently have two separate query paths, "stablecommitname" and "expandshortcommit". These are pretty much doing the same thing -- taking some ref like "master" or "default" or a tag name or part of a commit name, and turning it into a full commit name. Merge them into a single "resolverefs" method. This simplifies the code a fair bit, and gives us better error messages. They still aren't great, but they're like this now: Ref "7498aec194ecf2d333e0e2baddd9d5cdf922d7f1" is ambiguous or does not exist. ...instead of just: ERR-INVALID-COMMIT Test Plan: Looked at Git, Mercurial and Subversion repositories that were empty and non-empty. Looked at branches/heads. Tried to look at invalid commits. Looked at tags. All of this still works, and some behaviors are a bit better than they used to be. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T1493 Differential Revision: https://secure.phabricator.com/D7484
This commit is contained in:
parent
8f3ae81143
commit
4f20530856
|
@ -151,7 +151,6 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'DiffusionSSHWorkflow' => 'PhabricatorSSHWorkflow',
|
||||
'DiffusionSetPasswordPanel' => 'PhabricatorSettingsPanel',
|
||||
'DiffusionSetupException' => 'AphrontUsageException',
|
||||
'DiffusionStableCommitNameQuery' => 'DiffusionQuery',
|
||||
'DiffusionSvnCommitParentsQuery' => 'DiffusionCommitParentsQuery',
|
||||
'DiffusionSvnFileContentQuery' => 'DiffusionFileContentQuery',
|
||||
'DiffusionSvnRawDiffQuery' => 'DiffusionRawDiffQuery',
|
||||
'DiffusionSvnRequest' => 'DiffusionRequest',
|
||||
'DiffusionSvnStableCommitNameQuery' => 'DiffusionStableCommitNameQuery',
|
||||
'DiffusionSymbolController' => 'DiffusionController',
|
||||
'DiffusionSymbolQuery' => 'PhabricatorOffsetPagedQuery',
|
||||
'DiffusionTagListController' => 'DiffusionController',
|
||||
|
|
|
@ -198,7 +198,7 @@ final class ConduitAPI_diffusion_browsequery_Method
|
|||
|
||||
list($entire_manifest) = $repository->execxLocalCommand(
|
||||
'manifest --rev %s',
|
||||
$commit);
|
||||
hgsprintf('%s', $commit));
|
||||
$entire_manifest = explode("\n", $entire_manifest);
|
||||
|
||||
$results = array();
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
final class ConduitAPI_diffusion_expandshortcommitquery_Method
|
||||
extends ConduitAPI_diffusion_abstractquery_Method {
|
||||
|
||||
public function __construct() {
|
||||
$this->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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
final class ConduitAPI_diffusion_resolverefs_Method
|
||||
extends ConduitAPI_diffusion_abstractquery_Method {
|
||||
|
||||
public function getMethodDescription() {
|
||||
return pht('Resolve references into stable, canonical identifiers.');
|
||||
}
|
||||
|
||||
public function defineReturnType() {
|
||||
return 'dict<string, list<dict<string, wild>>>';
|
||||
}
|
||||
|
||||
protected function defineCustomParamTypes() {
|
||||
return array(
|
||||
'refs' => 'required list<string>',
|
||||
);
|
||||
}
|
||||
|
||||
protected function getResult(ConduitAPIRequest $request) {
|
||||
$refs = $request->getValue('refs');
|
||||
|
||||
return id(new DiffusionLowLevelResolveRefsQuery())
|
||||
->setRepository($this->getDiffusionRequest()->getRepository())
|
||||
->withRefs($refs)
|
||||
->execute();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
final class ConduitAPI_diffusion_stablecommitnamequery_Method
|
||||
extends ConduitAPI_diffusion_abstractquery_Method {
|
||||
|
||||
public function __construct() {
|
||||
$this->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();
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionExpandCommitQueryException extends Exception {
|
||||
const CODE_UNPARSEABLE = 'unparseable';
|
||||
const CODE_MISSING = 'missing';
|
||||
const CODE_INVALID = 'invalid';
|
||||
|
||||
private $statusCode;
|
||||
public function getStatusCode() {
|
||||
return $this->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);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
<?php
|
||||
|
||||
abstract class DiffusionExpandShortNameQuery extends DiffusionQuery {
|
||||
|
||||
private $commit;
|
||||
private $commitType = 'commit';
|
||||
private $tagContent;
|
||||
private $repository;
|
||||
|
||||
public function setCommit($commit) {
|
||||
$this->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);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionGitExpandShortNameQuery
|
||||
extends DiffusionExpandShortNameQuery {
|
||||
|
||||
protected function executeQuery() {
|
||||
$repository = $this->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);
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionMercurialExpandShortNameQuery
|
||||
extends DiffusionExpandShortNameQuery {
|
||||
|
||||
protected function executeQuery() {
|
||||
$repository = $this->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));
|
||||
}
|
||||
|
||||
}
|
|
@ -16,6 +16,10 @@ abstract class DiffusionLowLevelQuery extends Phobject {
|
|||
}
|
||||
|
||||
public function execute() {
|
||||
if (!$this->getRepository()) {
|
||||
throw new Exception("Call setRepository() before execute()!");
|
||||
}
|
||||
|
||||
return $this->executeQuery();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,225 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Resolves references (like short commit names, branch names, tag names, etc.)
|
||||
* into canonical, stable commit identifiers. This query works for all
|
||||
* repository types.
|
||||
*/
|
||||
final class DiffusionLowLevelResolveRefsQuery
|
||||
extends DiffusionLowLevelQuery {
|
||||
|
||||
private $refs;
|
||||
|
||||
public function withRefs(array $refs) {
|
||||
$this->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;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionGitStableCommitNameQuery
|
||||
extends DiffusionStableCommitNameQuery {
|
||||
|
||||
protected function executeQuery() {
|
||||
$repository = $this->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);
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionMercurialStableCommitNameQuery
|
||||
extends DiffusionStableCommitNameQuery {
|
||||
|
||||
protected function executeQuery() {
|
||||
$repository = $this->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;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
|
||||
abstract class DiffusionStableCommitNameQuery extends DiffusionQuery {
|
||||
|
||||
private $branch;
|
||||
private $repository;
|
||||
|
||||
public function setBranch($branch) {
|
||||
$this->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();
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionSvnStableCommitNameQuery
|
||||
extends DiffusionStableCommitNameQuery {
|
||||
|
||||
protected function executeQuery() {
|
||||
$repository = $this->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;
|
||||
}
|
||||
}
|
|
@ -18,7 +18,6 @@ abstract class DiffusionRequest {
|
|||
protected $symbolicCommit;
|
||||
protected $commit;
|
||||
protected $commitType = 'commit';
|
||||
protected $tagContent;
|
||||
protected $branch;
|
||||
protected $lint;
|
||||
|
||||
|
@ -263,10 +262,6 @@ abstract class DiffusionRequest {
|
|||
$this->getArcanistBranch());
|
||||
}
|
||||
|
||||
public function getTagContent() {
|
||||
return $this->tagContent;
|
||||
}
|
||||
|
||||
public function loadCommit() {
|
||||
if (empty($this->repositoryCommit)) {
|
||||
$repository = $this->getRepository();
|
||||
|
@ -624,26 +619,17 @@ abstract class DiffusionRequest {
|
|||
}
|
||||
|
||||
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 @@ abstract class DiffusionRequest {
|
|||
private function queryStableCommitName() {
|
||||
if ($this->commit) {
|
||||
$this->stableCommitName = $this->commit;
|
||||
} else if ($this->shouldInitFromConduit()) {
|
||||
$this->stableCommitName = DiffusionQuery::callConduitWithDiffusionRequest(
|
||||
$this->getUser(),
|
||||
$this,
|
||||
'diffusion.stablecommitnamequery',
|
||||
array(
|
||||
'branch' => $this->getBranch()
|
||||
));
|
||||
} else {
|
||||
$query = DiffusionStableCommitNameQuery::newFromRepository(
|
||||
$this->getRepository());
|
||||
$query->setBranch($this->getBranch());
|
||||
$this->stableCommitName = $query->load();
|
||||
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.resolverefs',
|
||||
array(
|
||||
'refs' => $refs,
|
||||
));
|
||||
} else {
|
||||
return id(new DiffusionLowLevelResolveRefsQuery())
|
||||
->setRepository($this->getRepository())
|
||||
->withRefs($refs)
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue