@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+196 -4
+2
src/__phutil_library_map__.php
··· 577 577 'DiffusionRawDiffQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRawDiffQueryConduitAPIMethod.php', 578 578 'DiffusionReadmeView' => 'applications/diffusion/view/DiffusionReadmeView.php', 579 579 'DiffusionRefNotFoundException' => 'applications/diffusion/exception/DiffusionRefNotFoundException.php', 580 + 'DiffusionRefTableController' => 'applications/diffusion/controller/DiffusionRefTableController.php', 580 581 'DiffusionRefsQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRefsQueryConduitAPIMethod.php', 581 582 'DiffusionRenameHistoryQuery' => 'applications/diffusion/query/DiffusionRenameHistoryQuery.php', 582 583 'DiffusionRepositoryByIDRemarkupRule' => 'applications/diffusion/remarkup/DiffusionRepositoryByIDRemarkupRule.php', ··· 3789 3790 'DiffusionRawDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 3790 3791 'DiffusionReadmeView' => 'DiffusionView', 3791 3792 'DiffusionRefNotFoundException' => 'Exception', 3793 + 'DiffusionRefTableController' => 'DiffusionController', 3792 3794 'DiffusionRefsQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 3793 3795 'DiffusionRepositoryByIDRemarkupRule' => 'PhabricatorObjectRemarkupRule', 3794 3796 'DiffusionRepositoryController' => 'DiffusionController',
+1
src/applications/diffusion/application/PhabricatorDiffusionApplication.php
··· 76 76 'diff/' => 'DiffusionDiffController', 77 77 'tags/(?P<dblob>.*)' => 'DiffusionTagListController', 78 78 'branches/(?P<dblob>.*)' => 'DiffusionBranchTableController', 79 + 'refs/(?P<dblob>.*)' => 'DiffusionRefTableController', 79 80 'lint/(?P<dblob>.*)' => 'DiffusionLintController', 80 81 'commit/(?P<commit>[a-z0-9]+)/branches/' 81 82 => 'DiffusionCommitBranchesController',
+131
src/applications/diffusion/controller/DiffusionRefTableController.php
··· 1 + <?php 2 + 3 + final class DiffusionRefTableController extends DiffusionController { 4 + 5 + public function shouldAllowPublic() { 6 + return true; 7 + } 8 + 9 + protected function processDiffusionRequest(AphrontRequest $request) { 10 + $viewer = $this->getViewer(); 11 + 12 + $drequest = $this->getDiffusionRequest(); 13 + $repository = $drequest->getRepository(); 14 + 15 + if (!$drequest->supportsBranches()) { 16 + return $this->newDialog() 17 + ->setTitle(pht('No Ref Support')) 18 + ->appendParagraph( 19 + pht( 20 + 'The version control system this repository uses does not '. 21 + 'support named references, so you can not resolve or list '. 22 + 'repository refs in this repository.')) 23 + ->addCancelButton($repository->getURI()); 24 + } 25 + 26 + $ref_name = $drequest->getBranch(); 27 + 28 + $cache_query = id(new DiffusionCachedResolveRefsQuery()) 29 + ->setRepository($repository); 30 + if ($ref_name !== null) { 31 + $cache_query->withRefs(array($ref_name)); 32 + } 33 + $cache_refs = $cache_query->execute(); 34 + 35 + $vcs_refs = DiffusionQuery::callConduitWithDiffusionRequest( 36 + $viewer, 37 + $drequest, 38 + 'diffusion.resolverefs', 39 + array( 40 + 'refs' => array($ref_name), 41 + )); 42 + 43 + $all = array(); 44 + foreach ($cache_refs as $ref => $results) { 45 + foreach ($results as $result) { 46 + $id = $result['type'].'/'.$result['identifier']; 47 + $all[$ref][$id]['cache'] = $result; 48 + } 49 + } 50 + 51 + foreach ($vcs_refs as $ref => $results) { 52 + foreach ($results as $result) { 53 + $id = $result['type'].'/'.$result['identifier']; 54 + $all[$ref][$id]['vcs'] = $result; 55 + } 56 + } 57 + 58 + $rows = array(); 59 + foreach ($all as $ref => $results) { 60 + foreach ($results as $info) { 61 + $cache = idx($info, 'cache', array()); 62 + $vcs = idx($info, 'vcs', array()); 63 + 64 + $type = idx($vcs, 'type'); 65 + if (!$type) { 66 + $type = idx($cache, 'type'); 67 + } 68 + 69 + $identifier = idx($vcs, 'identifier'); 70 + if ($identifier !== null) { 71 + $identifier = DiffusionView::linkCommit( 72 + $repository, 73 + $identifier); 74 + } 75 + 76 + $cache_identifier = idx($cache, 'identifier'); 77 + if ($cache_identifier !== null) { 78 + $cache_identifier = DiffusionView::linkCommit( 79 + $repository, 80 + $cache_identifier); 81 + } 82 + 83 + $alternate = idx($vcs, 'alternate'); 84 + if ($alternate !== null) { 85 + $alternate = DiffusionView::linkCommit( 86 + $repository, 87 + $alternate); 88 + } 89 + 90 + $rows[] = array( 91 + $ref, 92 + $type, 93 + $identifier, 94 + $cache_identifier, 95 + $alternate, 96 + ); 97 + } 98 + } 99 + 100 + $table = id(new AphrontTableView($rows)) 101 + ->setHeaders( 102 + array( 103 + pht('Ref'), 104 + pht('Type'), 105 + pht('Identifier'), 106 + pht('Cached'), 107 + pht('Alternate'), 108 + )); 109 + 110 + $content = id(new PHUIObjectBoxView()) 111 + ->setHeaderText(pht('Ref "%s"', $ref_name)) 112 + ->appendChild($table); 113 + 114 + $crumbs = $this->buildCrumbs(array()); 115 + $crumbs->addTextCrumb(pht('Refs')); 116 + 117 + return $this->buildApplicationPage( 118 + array( 119 + $crumbs, 120 + $content, 121 + ), 122 + array( 123 + 'title' => array( 124 + pht('Refs'), 125 + $repository->getMonogram(), 126 + $ref_name, 127 + ), 128 + )); 129 + } 130 + 131 + }
+31 -1
src/applications/diffusion/controller/DiffusionRepositoryController.php
··· 303 303 304 304 $view->setActionList($actions); 305 305 306 - return id(new PHUIObjectBoxView()) 306 + $box = id(new PHUIObjectBoxView()) 307 307 ->setHeader($header) 308 308 ->addPropertyList($view); 309 309 310 + $info = null; 311 + $drequest = $this->getDiffusionRequest(); 312 + if ($drequest->getRefAlternatives()) { 313 + $message = array( 314 + pht( 315 + 'The ref "%s" is ambiguous in this repository.', 316 + $drequest->getBranch()), 317 + ' ', 318 + phutil_tag( 319 + 'a', 320 + array( 321 + 'href' => $drequest->generateURI( 322 + array( 323 + 'action' => 'refs', 324 + )), 325 + ), 326 + pht('View Alternatives')), 327 + ); 328 + 329 + $messages = array($message); 330 + 331 + $info = id(new PHUIInfoView()) 332 + ->setSeverity(PHUIInfoView::SEVERITY_WARNING) 333 + ->setErrors(array($message)); 334 + 335 + $box->setInfoView($info); 336 + } 337 + 338 + 339 + return $box; 310 340 } 311 341 312 342 private function buildBranchListTable(DiffusionRequest $drequest) {
+2
src/applications/diffusion/query/lowlevel/DiffusionLowLevelResolveRefsQuery.php
··· 45 45 private function resolveGitRefs() { 46 46 $repository = $this->getRepository(); 47 47 48 + // TODO: When refs are ambiguous (for example, tags and branches with 49 + // the same name) this will only resolve one of them. 48 50 $future = $repository->getLocalCommandFuture('cat-file --batch-check'); 49 51 $future->write(implode("\n", $this->refs)); 50 52 list($stdout) = $future->resolvex();
+29 -3
src/applications/diffusion/request/DiffusionRequest.php
··· 28 28 private $initFromConduit = true; 29 29 private $user; 30 30 private $branchObject = false; 31 + private $refAlternatives; 31 32 32 33 abstract public function supportsBranches(); 33 34 abstract protected function isStableCommit($symbol); ··· 528 529 case 'tags': 529 530 case 'branches': 530 531 case 'lint': 532 + case 'refs': 531 533 $req_callsign = true; 532 534 break; 533 535 case 'branch': ··· 559 561 case 'branches': 560 562 case 'lint': 561 563 case 'pathtree': 564 + case 'refs': 562 565 $uri = "/diffusion/{$callsign}{$action}/{$path}{$commit}{$line}"; 563 566 break; 564 567 case 'branch': ··· 728 731 $results = $this->resolveRefs(array($ref)); 729 732 730 733 $matches = idx($results, $ref, array()); 731 - if (count($matches) !== 1) { 732 - $message = pht('Ref "%s" is ambiguous or does not exist.', $ref); 734 + if (!$matches) { 735 + $message = pht( 736 + 'Ref "%s" does not exist in this repository.', 737 + $ref); 733 738 throw id(new DiffusionRefNotFoundException($message)) 734 739 ->setRef($ref); 735 740 } 736 741 737 - $match = head($matches); 742 + if (count($matches) > 1) { 743 + $match = $this->chooseBestRefMatch($ref, $matches); 744 + } else { 745 + $match = head($matches); 746 + } 738 747 739 748 $this->stableCommit = $match['identifier']; 740 749 $this->symbolicType = $match['type']; 750 + } 751 + 752 + public function getRefAlternatives() { 753 + // Make sure we've resolved the reference into a stable commit first. 754 + $this->getStableCommit(); 755 + return $this->refAlternatives; 756 + } 757 + 758 + private function chooseBestRefMatch($ref, array $results) { 759 + // TODO: Do a better job of selecting the best match. 760 + $match = head($results); 761 + 762 + // After choosing the best alternative, save all the alternatives so the 763 + // UI can show them to the user. 764 + $this->refAlternatives = $results; 765 + 766 + return $match; 741 767 } 742 768 743 769 protected function getResolvableBranchName($branch) {