mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-31 08:58:20 +01:00
Add a "refs" table to Diffusion
Summary: Ref T7100. When a user navigates to a branch like "default" which is ambiguous: - don't fatal; - choose one alternative to resolve it to (currently more or less at random); - sometimes show what we did in the UI. Also, add a new table to show the alternatives. This will get refined in followup changes. Test Plan: {F384335} {F384336} Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T7100 Differential Revision: https://secure.phabricator.com/D12547
This commit is contained in:
parent
55ff197f2a
commit
7f43cde82d
6 changed files with 196 additions and 4 deletions
|
@ -577,6 +577,7 @@ phutil_register_library_map(array(
|
||||||
'DiffusionRawDiffQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRawDiffQueryConduitAPIMethod.php',
|
'DiffusionRawDiffQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRawDiffQueryConduitAPIMethod.php',
|
||||||
'DiffusionReadmeView' => 'applications/diffusion/view/DiffusionReadmeView.php',
|
'DiffusionReadmeView' => 'applications/diffusion/view/DiffusionReadmeView.php',
|
||||||
'DiffusionRefNotFoundException' => 'applications/diffusion/exception/DiffusionRefNotFoundException.php',
|
'DiffusionRefNotFoundException' => 'applications/diffusion/exception/DiffusionRefNotFoundException.php',
|
||||||
|
'DiffusionRefTableController' => 'applications/diffusion/controller/DiffusionRefTableController.php',
|
||||||
'DiffusionRefsQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRefsQueryConduitAPIMethod.php',
|
'DiffusionRefsQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRefsQueryConduitAPIMethod.php',
|
||||||
'DiffusionRenameHistoryQuery' => 'applications/diffusion/query/DiffusionRenameHistoryQuery.php',
|
'DiffusionRenameHistoryQuery' => 'applications/diffusion/query/DiffusionRenameHistoryQuery.php',
|
||||||
'DiffusionRepositoryByIDRemarkupRule' => 'applications/diffusion/remarkup/DiffusionRepositoryByIDRemarkupRule.php',
|
'DiffusionRepositoryByIDRemarkupRule' => 'applications/diffusion/remarkup/DiffusionRepositoryByIDRemarkupRule.php',
|
||||||
|
@ -3789,6 +3790,7 @@ phutil_register_library_map(array(
|
||||||
'DiffusionRawDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
|
'DiffusionRawDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
|
||||||
'DiffusionReadmeView' => 'DiffusionView',
|
'DiffusionReadmeView' => 'DiffusionView',
|
||||||
'DiffusionRefNotFoundException' => 'Exception',
|
'DiffusionRefNotFoundException' => 'Exception',
|
||||||
|
'DiffusionRefTableController' => 'DiffusionController',
|
||||||
'DiffusionRefsQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
|
'DiffusionRefsQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
|
||||||
'DiffusionRepositoryByIDRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
'DiffusionRepositoryByIDRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
||||||
'DiffusionRepositoryController' => 'DiffusionController',
|
'DiffusionRepositoryController' => 'DiffusionController',
|
||||||
|
|
|
@ -76,6 +76,7 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication {
|
||||||
'diff/' => 'DiffusionDiffController',
|
'diff/' => 'DiffusionDiffController',
|
||||||
'tags/(?P<dblob>.*)' => 'DiffusionTagListController',
|
'tags/(?P<dblob>.*)' => 'DiffusionTagListController',
|
||||||
'branches/(?P<dblob>.*)' => 'DiffusionBranchTableController',
|
'branches/(?P<dblob>.*)' => 'DiffusionBranchTableController',
|
||||||
|
'refs/(?P<dblob>.*)' => 'DiffusionRefTableController',
|
||||||
'lint/(?P<dblob>.*)' => 'DiffusionLintController',
|
'lint/(?P<dblob>.*)' => 'DiffusionLintController',
|
||||||
'commit/(?P<commit>[a-z0-9]+)/branches/'
|
'commit/(?P<commit>[a-z0-9]+)/branches/'
|
||||||
=> 'DiffusionCommitBranchesController',
|
=> 'DiffusionCommitBranchesController',
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class DiffusionRefTableController extends DiffusionController {
|
||||||
|
|
||||||
|
public function shouldAllowPublic() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processDiffusionRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$drequest = $this->getDiffusionRequest();
|
||||||
|
$repository = $drequest->getRepository();
|
||||||
|
|
||||||
|
if (!$drequest->supportsBranches()) {
|
||||||
|
return $this->newDialog()
|
||||||
|
->setTitle(pht('No Ref Support'))
|
||||||
|
->appendParagraph(
|
||||||
|
pht(
|
||||||
|
'The version control system this repository uses does not '.
|
||||||
|
'support named references, so you can not resolve or list '.
|
||||||
|
'repository refs in this repository.'))
|
||||||
|
->addCancelButton($repository->getURI());
|
||||||
|
}
|
||||||
|
|
||||||
|
$ref_name = $drequest->getBranch();
|
||||||
|
|
||||||
|
$cache_query = id(new DiffusionCachedResolveRefsQuery())
|
||||||
|
->setRepository($repository);
|
||||||
|
if ($ref_name !== null) {
|
||||||
|
$cache_query->withRefs(array($ref_name));
|
||||||
|
}
|
||||||
|
$cache_refs = $cache_query->execute();
|
||||||
|
|
||||||
|
$vcs_refs = DiffusionQuery::callConduitWithDiffusionRequest(
|
||||||
|
$viewer,
|
||||||
|
$drequest,
|
||||||
|
'diffusion.resolverefs',
|
||||||
|
array(
|
||||||
|
'refs' => array($ref_name),
|
||||||
|
));
|
||||||
|
|
||||||
|
$all = array();
|
||||||
|
foreach ($cache_refs as $ref => $results) {
|
||||||
|
foreach ($results as $result) {
|
||||||
|
$id = $result['type'].'/'.$result['identifier'];
|
||||||
|
$all[$ref][$id]['cache'] = $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($vcs_refs as $ref => $results) {
|
||||||
|
foreach ($results as $result) {
|
||||||
|
$id = $result['type'].'/'.$result['identifier'];
|
||||||
|
$all[$ref][$id]['vcs'] = $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows = array();
|
||||||
|
foreach ($all as $ref => $results) {
|
||||||
|
foreach ($results as $info) {
|
||||||
|
$cache = idx($info, 'cache', array());
|
||||||
|
$vcs = idx($info, 'vcs', array());
|
||||||
|
|
||||||
|
$type = idx($vcs, 'type');
|
||||||
|
if (!$type) {
|
||||||
|
$type = idx($cache, 'type');
|
||||||
|
}
|
||||||
|
|
||||||
|
$identifier = idx($vcs, 'identifier');
|
||||||
|
if ($identifier !== null) {
|
||||||
|
$identifier = DiffusionView::linkCommit(
|
||||||
|
$repository,
|
||||||
|
$identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
$cache_identifier = idx($cache, 'identifier');
|
||||||
|
if ($cache_identifier !== null) {
|
||||||
|
$cache_identifier = DiffusionView::linkCommit(
|
||||||
|
$repository,
|
||||||
|
$cache_identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
$alternate = idx($vcs, 'alternate');
|
||||||
|
if ($alternate !== null) {
|
||||||
|
$alternate = DiffusionView::linkCommit(
|
||||||
|
$repository,
|
||||||
|
$alternate);
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = array(
|
||||||
|
$ref,
|
||||||
|
$type,
|
||||||
|
$identifier,
|
||||||
|
$cache_identifier,
|
||||||
|
$alternate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = id(new AphrontTableView($rows))
|
||||||
|
->setHeaders(
|
||||||
|
array(
|
||||||
|
pht('Ref'),
|
||||||
|
pht('Type'),
|
||||||
|
pht('Identifier'),
|
||||||
|
pht('Cached'),
|
||||||
|
pht('Alternate'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$content = id(new PHUIObjectBoxView())
|
||||||
|
->setHeaderText(pht('Ref "%s"', $ref_name))
|
||||||
|
->appendChild($table);
|
||||||
|
|
||||||
|
$crumbs = $this->buildCrumbs(array());
|
||||||
|
$crumbs->addTextCrumb(pht('Refs'));
|
||||||
|
|
||||||
|
return $this->buildApplicationPage(
|
||||||
|
array(
|
||||||
|
$crumbs,
|
||||||
|
$content,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'title' => array(
|
||||||
|
pht('Refs'),
|
||||||
|
$repository->getMonogram(),
|
||||||
|
$ref_name,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -303,10 +303,40 @@ final class DiffusionRepositoryController extends DiffusionController {
|
||||||
|
|
||||||
$view->setActionList($actions);
|
$view->setActionList($actions);
|
||||||
|
|
||||||
return id(new PHUIObjectBoxView())
|
$box = id(new PHUIObjectBoxView())
|
||||||
->setHeader($header)
|
->setHeader($header)
|
||||||
->addPropertyList($view);
|
->addPropertyList($view);
|
||||||
|
|
||||||
|
$info = null;
|
||||||
|
$drequest = $this->getDiffusionRequest();
|
||||||
|
if ($drequest->getRefAlternatives()) {
|
||||||
|
$message = array(
|
||||||
|
pht(
|
||||||
|
'The ref "%s" is ambiguous in this repository.',
|
||||||
|
$drequest->getBranch()),
|
||||||
|
' ',
|
||||||
|
phutil_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => $drequest->generateURI(
|
||||||
|
array(
|
||||||
|
'action' => 'refs',
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
pht('View Alternatives')),
|
||||||
|
);
|
||||||
|
|
||||||
|
$messages = array($message);
|
||||||
|
|
||||||
|
$info = id(new PHUIInfoView())
|
||||||
|
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
|
||||||
|
->setErrors(array($message));
|
||||||
|
|
||||||
|
$box->setInfoView($info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $box;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildBranchListTable(DiffusionRequest $drequest) {
|
private function buildBranchListTable(DiffusionRequest $drequest) {
|
||||||
|
|
|
@ -45,6 +45,8 @@ final class DiffusionLowLevelResolveRefsQuery
|
||||||
private function resolveGitRefs() {
|
private function resolveGitRefs() {
|
||||||
$repository = $this->getRepository();
|
$repository = $this->getRepository();
|
||||||
|
|
||||||
|
// TODO: When refs are ambiguous (for example, tags and branches with
|
||||||
|
// the same name) this will only resolve one of them.
|
||||||
$future = $repository->getLocalCommandFuture('cat-file --batch-check');
|
$future = $repository->getLocalCommandFuture('cat-file --batch-check');
|
||||||
$future->write(implode("\n", $this->refs));
|
$future->write(implode("\n", $this->refs));
|
||||||
list($stdout) = $future->resolvex();
|
list($stdout) = $future->resolvex();
|
||||||
|
|
|
@ -28,6 +28,7 @@ abstract class DiffusionRequest {
|
||||||
private $initFromConduit = true;
|
private $initFromConduit = true;
|
||||||
private $user;
|
private $user;
|
||||||
private $branchObject = false;
|
private $branchObject = false;
|
||||||
|
private $refAlternatives;
|
||||||
|
|
||||||
abstract public function supportsBranches();
|
abstract public function supportsBranches();
|
||||||
abstract protected function isStableCommit($symbol);
|
abstract protected function isStableCommit($symbol);
|
||||||
|
@ -528,6 +529,7 @@ abstract class DiffusionRequest {
|
||||||
case 'tags':
|
case 'tags':
|
||||||
case 'branches':
|
case 'branches':
|
||||||
case 'lint':
|
case 'lint':
|
||||||
|
case 'refs':
|
||||||
$req_callsign = true;
|
$req_callsign = true;
|
||||||
break;
|
break;
|
||||||
case 'branch':
|
case 'branch':
|
||||||
|
@ -559,6 +561,7 @@ abstract class DiffusionRequest {
|
||||||
case 'branches':
|
case 'branches':
|
||||||
case 'lint':
|
case 'lint':
|
||||||
case 'pathtree':
|
case 'pathtree':
|
||||||
|
case 'refs':
|
||||||
$uri = "/diffusion/{$callsign}{$action}/{$path}{$commit}{$line}";
|
$uri = "/diffusion/{$callsign}{$action}/{$path}{$commit}{$line}";
|
||||||
break;
|
break;
|
||||||
case 'branch':
|
case 'branch':
|
||||||
|
@ -728,18 +731,41 @@ abstract class DiffusionRequest {
|
||||||
$results = $this->resolveRefs(array($ref));
|
$results = $this->resolveRefs(array($ref));
|
||||||
|
|
||||||
$matches = idx($results, $ref, array());
|
$matches = idx($results, $ref, array());
|
||||||
if (count($matches) !== 1) {
|
if (!$matches) {
|
||||||
$message = pht('Ref "%s" is ambiguous or does not exist.', $ref);
|
$message = pht(
|
||||||
|
'Ref "%s" does not exist in this repository.',
|
||||||
|
$ref);
|
||||||
throw id(new DiffusionRefNotFoundException($message))
|
throw id(new DiffusionRefNotFoundException($message))
|
||||||
->setRef($ref);
|
->setRef($ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
$match = head($matches);
|
if (count($matches) > 1) {
|
||||||
|
$match = $this->chooseBestRefMatch($ref, $matches);
|
||||||
|
} else {
|
||||||
|
$match = head($matches);
|
||||||
|
}
|
||||||
|
|
||||||
$this->stableCommit = $match['identifier'];
|
$this->stableCommit = $match['identifier'];
|
||||||
$this->symbolicType = $match['type'];
|
$this->symbolicType = $match['type'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getRefAlternatives() {
|
||||||
|
// Make sure we've resolved the reference into a stable commit first.
|
||||||
|
$this->getStableCommit();
|
||||||
|
return $this->refAlternatives;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function chooseBestRefMatch($ref, array $results) {
|
||||||
|
// TODO: Do a better job of selecting the best match.
|
||||||
|
$match = head($results);
|
||||||
|
|
||||||
|
// After choosing the best alternative, save all the alternatives so the
|
||||||
|
// UI can show them to the user.
|
||||||
|
$this->refAlternatives = $results;
|
||||||
|
|
||||||
|
return $match;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getResolvableBranchName($branch) {
|
protected function getResolvableBranchName($branch) {
|
||||||
return $branch;
|
return $branch;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue