@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.

Merge `diffusion.commitbranchesquery` into `diffusion.branchquery`

Summary:
Ref T4327. This is general cleanup since I was in this area of the code. Primarily, the Mercurial implementation here was completely broken and wrong:

- It returned only one branch, but a commit can be present on many branches.
- It did not account for multiple branch heads.
- It returned a result implying the branch head pointed at the queried commit, which is no consistent or accurate.

Simplify the amount of API we're dealing with by collapsing this method into the very similar `diffusion.branchquery` method.

Test Plan: Looked at mercurial and git repositories and commits, branch information seemed correct.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T4327

Differential Revision: https://secure.phabricator.com/D8003

+75 -84
-2
src/__phutil_library_map__.php
··· 155 155 'ConduitAPI_diffusion_abstractquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_abstractquery_Method.php', 156 156 'ConduitAPI_diffusion_branchquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_branchquery_Method.php', 157 157 'ConduitAPI_diffusion_browsequery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_browsequery_Method.php', 158 - 'ConduitAPI_diffusion_commitbranchesquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_commitbranchesquery_Method.php', 159 158 'ConduitAPI_diffusion_commitparentsquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_commitparentsquery_Method.php', 160 159 'ConduitAPI_diffusion_createcomment_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_createcomment_Method.php', 161 160 'ConduitAPI_diffusion_diffquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_diffquery_Method.php', ··· 2615 2614 'ConduitAPI_diffusion_abstractquery_Method' => 'ConduitAPI_diffusion_Method', 2616 2615 'ConduitAPI_diffusion_branchquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 2617 2616 'ConduitAPI_diffusion_browsequery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 2618 - 'ConduitAPI_diffusion_commitbranchesquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 2619 2617 'ConduitAPI_diffusion_commitparentsquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 2620 2618 'ConduitAPI_diffusion_createcomment_Method' => 'ConduitAPI_diffusion_Method', 2621 2619 'ConduitAPI_diffusion_diffquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
+66 -11
src/applications/diffusion/conduit/ConduitAPI_diffusion_branchquery_Method.php
··· 1 1 <?php 2 2 3 - /** 4 - * @group conduit 5 - */ 6 3 final class ConduitAPI_diffusion_branchquery_Method 7 4 extends ConduitAPI_diffusion_abstractquery_Method { 8 5 9 6 public function getMethodDescription() { 10 - return 'Determine what branches exist for a repository.'; 7 + return pht('Determine what branches exist for a repository.'); 11 8 } 12 9 13 10 public function defineReturnType() { 14 - return 'array'; 11 + return 'list<dict>'; 15 12 } 16 13 17 14 protected function defineCustomParamTypes() { 18 15 return array( 19 16 'limit' => 'optional int', 20 - 'offset' => 'optional int' 17 + 'offset' => 'optional int', 18 + 'contains' => 'optional string', 21 19 ); 22 20 } 23 21 24 - 25 22 protected function getGitResult(ConduitAPIRequest $request) { 26 23 $drequest = $this->getDiffusionRequest(); 27 24 $repository = $drequest->getRepository(); 28 25 29 - $refs = id(new DiffusionLowLevelGitRefQuery()) 30 - ->setRepository($repository) 31 - ->withIsOriginBranch(true) 32 - ->execute(); 26 + $contains = $request->getValue('contains'); 27 + if (strlen($contains)) { 28 + // NOTE: We can't use DiffusionLowLevelGitRefQuery here because 29 + // `git for-each-ref` does not support `--contains`. 30 + if ($repository->isWorkingCopyBare()) { 31 + list($stdout) = $repository->execxLocalCommand( 32 + 'branch --verbose --no-abbrev --contains %s --', 33 + $contains); 34 + $ref_map = DiffusionGitBranch::parseLocalBranchOutput( 35 + $stdout); 36 + } else { 37 + list($stdout) = $repository->execxLocalCommand( 38 + 'branch -r --verbose --no-abbrev --contains %s --', 39 + $contains); 40 + $ref_map = DiffusionGitBranch::parseRemoteBranchOutput( 41 + $stdout, 42 + DiffusionGitBranch::DEFAULT_GIT_REMOTE); 43 + } 44 + 45 + $refs = array(); 46 + foreach ($ref_map as $ref => $commit) { 47 + $refs[] = id(new DiffusionRepositoryRef()) 48 + ->setShortName($ref) 49 + ->setCommitIdentifier($commit); 50 + } 51 + } else { 52 + $refs = id(new DiffusionLowLevelGitRefQuery()) 53 + ->setRepository($repository) 54 + ->withIsOriginBranch(true) 55 + ->execute(); 56 + } 33 57 34 58 return $this->processBranchRefs($request, $refs); 35 59 } ··· 41 65 $refs = id(new DiffusionLowLevelMercurialBranchesQuery()) 42 66 ->setRepository($repository) 43 67 ->execute(); 68 + 69 + // If we have a 'contains' query, filter these branches down to just the 70 + // ones which contain the commit. 71 + $contains = $request->getValue('contains'); 72 + if (strlen($contains)) { 73 + list($branches_raw) = $repository->execxLocalCommand( 74 + 'log --template %s --limit 1 --rev %s --', 75 + '{branches}', 76 + hgsprintf('%s', $contains)); 77 + 78 + $branches_raw = trim($branches_raw); 79 + if (!strlen($branches_raw)) { 80 + $containing_branches = array('default'); 81 + } else { 82 + $containing_branches = explode(' ', $branches_raw); 83 + } 84 + 85 + $containing_branches = array_fuse($containing_branches); 86 + 87 + // NOTE: We get this very slightly wrong: a branch may have multiple 88 + // heads and we'll keep all of the heads of the branch, even if the 89 + // commit is only on some of the heads. This should be rare, is probably 90 + // more clear to users as is, and would potentially be expensive to get 91 + // right since we'd have to do additional checks. 92 + 93 + foreach ($refs as $key => $ref) { 94 + if (empty($containing_branches[$ref->getShortName()])) { 95 + unset($refs[$key]); 96 + } 97 + } 98 + } 44 99 45 100 return $this->processBranchRefs($request, $refs); 46 101 }
-66
src/applications/diffusion/conduit/ConduitAPI_diffusion_commitbranchesquery_Method.php
··· 1 - <?php 2 - 3 - /** 4 - * @group conduit 5 - */ 6 - final class ConduitAPI_diffusion_commitbranchesquery_Method 7 - extends ConduitAPI_diffusion_abstractquery_Method { 8 - 9 - public function getMethodDescription() { 10 - return 'Determine what branches contain a commit in a repository.'; 11 - } 12 - 13 - public function defineReturnType() { 14 - return 'array'; 15 - } 16 - 17 - protected function defineCustomParamTypes() { 18 - return array( 19 - 'commit' => 'required string', 20 - ); 21 - } 22 - 23 - protected function getGitResult(ConduitAPIRequest $request) { 24 - $drequest = $this->getDiffusionRequest(); 25 - $repository = $drequest->getRepository(); 26 - $commit = $request->getValue('commit'); 27 - 28 - // NOTE: We can't use DiffusionLowLevelGitRefQuery here because 29 - // `git for-each-ref` does not support `--contains`. 30 - if ($repository->isWorkingCopyBare()) { 31 - list($contains) = $repository->execxLocalCommand( 32 - 'branch --verbose --no-abbrev --contains %s', 33 - $commit); 34 - return DiffusionGitBranch::parseLocalBranchOutput( 35 - $contains); 36 - } else { 37 - list($contains) = $repository->execxLocalCommand( 38 - 'branch -r --verbose --no-abbrev --contains %s', 39 - $commit); 40 - return DiffusionGitBranch::parseRemoteBranchOutput( 41 - $contains, 42 - DiffusionGitBranch::DEFAULT_GIT_REMOTE); 43 - } 44 - } 45 - 46 - protected function getMercurialResult(ConduitAPIRequest $request) { 47 - $drequest = $this->getDiffusionRequest(); 48 - $repository = $drequest->getRepository(); 49 - $commit = $request->getValue('commit'); 50 - 51 - // TODO: This should use `branches`. Also, this entire method's API needs 52 - // to be fixed to support multiple branch heads in Mercurial. We should 53 - // probably return `DiffusionRepositoryRefs` and probably merge this into 54 - // `diffusion.branchesquery`. 55 - 56 - list($contains) = $repository->execxLocalCommand( 57 - 'log --template %s --limit 1 --rev %s --', 58 - '{branch}', 59 - $commit); 60 - 61 - return array( 62 - trim($contains) => $commit, 63 - ); 64 - 65 - } 66 - }
+9 -5
src/applications/diffusion/controller/DiffusionCommitBranchesController.php
··· 17 17 $branches = array(); 18 18 try { 19 19 $branches = $this->callConduitWithDiffusionRequest( 20 - 'diffusion.commitbranchesquery', 21 - array('commit' => $request->getCommit())); 20 + 'diffusion.branchquery', 21 + array( 22 + 'contains' => $request->getCommit(), 23 + )); 22 24 } catch (ConduitException $ex) { 23 25 if ($ex->getMessage() != 'ERR-UNSUPPORTED-VCS') { 24 26 throw $ex; 25 27 } 26 28 } 27 29 30 + $branches = DiffusionRepositoryRef::loadAllFromDictionaries($branches); 31 + 28 32 $branch_links = array(); 29 - foreach ($branches as $branch => $commit) { 33 + foreach ($branches as $branch) { 30 34 $branch_links[] = phutil_tag( 31 35 'a', 32 36 array( 33 37 'href' => $request->generateURI( 34 38 array( 35 39 'action' => 'browse', 36 - 'branch' => $branch, 40 + 'branch' => $branch->getShortName(), 37 41 )), 38 42 ), 39 - $branch); 43 + $branch->getShortName()); 40 44 } 41 45 42 46 return id(new AphrontAjaxResponse())