@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
at recaptime-dev/main 136 lines 3.9 kB view raw
1<?php 2 3final class DiffusionBranchQueryConduitAPIMethod 4 extends DiffusionQueryConduitAPIMethod { 5 6 public function getAPIMethodName() { 7 return 'diffusion.branchquery'; 8 } 9 10 public function getMethodDescription() { 11 return pht('Determine what branches exist for a repository.'); 12 } 13 14 protected function defineReturnType() { 15 return 'list<dict>'; 16 } 17 18 protected function defineCustomParamTypes() { 19 return array( 20 'closed' => 'optional bool', 21 'limit' => 'optional int', 22 'offset' => 'optional int', 23 'contains' => 'optional string', 24 'patterns' => 'optional list<string>', 25 ); 26 } 27 28 protected function getGitResult(ConduitAPIRequest $request) { 29 $drequest = $this->getDiffusionRequest(); 30 $repository = $drequest->getRepository(); 31 32 $contains = $request->getValue('contains'); 33 if (phutil_nonempty_string($contains)) { 34 35 // See PHI958 (and, earlier, PHI720). If "patterns" are provided, pass 36 // them to "git branch ..." to let callers test for reachability from 37 // particular branch heads. 38 $patterns_argv = $request->getValue('patterns', array()); 39 PhutilTypeSpec::checkMap( 40 array( 41 'patterns' => $patterns_argv, 42 ), 43 array( 44 'patterns' => 'list<string>', 45 )); 46 47 // NOTE: We can't use DiffusionLowLevelGitRefQuery here because 48 // `git for-each-ref` does not support `--contains`. 49 list($stdout) = $repository->execxLocalCommand( 50 'branch --verbose --no-abbrev --contains %s -- %Ls', 51 $contains, 52 $patterns_argv); 53 $ref_map = DiffusionGitBranch::parseLocalBranchOutput( 54 $stdout); 55 56 $refs = array(); 57 foreach ($ref_map as $ref => $commit) { 58 $refs[] = id(new DiffusionRepositoryRef()) 59 ->setShortName((string)$ref) 60 ->setCommitIdentifier($commit); 61 } 62 } else { 63 $refs = id(new DiffusionLowLevelGitRefQuery()) 64 ->setRepository($repository) 65 ->withRefTypes( 66 array( 67 PhabricatorRepositoryRefCursor::TYPE_BRANCH, 68 )) 69 ->execute(); 70 } 71 72 return $this->processBranchRefs($request, $refs); 73 } 74 75 protected function getMercurialResult(ConduitAPIRequest $request) { 76 $drequest = $this->getDiffusionRequest(); 77 $repository = $drequest->getRepository(); 78 79 $query = id(new DiffusionLowLevelMercurialBranchesQuery()) 80 ->setRepository($repository); 81 82 $contains = $request->getValue('contains'); 83 if (phutil_nonempty_string($contains)) { 84 $query->withContainsCommit($contains); 85 } 86 87 $refs = $query->execute(); 88 89 return $this->processBranchRefs($request, $refs); 90 } 91 92 protected function getSVNResult(ConduitAPIRequest $request) { 93 // Since SVN doesn't have meaningful branches, just return nothing for all 94 // queries. 95 return array(); 96 } 97 98 private function processBranchRefs(ConduitAPIRequest $request, array $refs) { 99 $drequest = $this->getDiffusionRequest(); 100 $repository = $drequest->getRepository(); 101 $offset = $request->getValue('offset'); 102 $limit = $request->getValue('limit'); 103 104 foreach ($refs as $key => $ref) { 105 if (!$repository->shouldTrackBranch($ref->getShortName())) { 106 unset($refs[$key]); 107 } 108 } 109 110 $with_closed = $request->getValue('closed'); 111 if ($with_closed !== null) { 112 foreach ($refs as $key => $ref) { 113 $fields = $ref->getRawFields(); 114 if (idx($fields, 'closed') != $with_closed) { 115 unset($refs[$key]); 116 } 117 } 118 } 119 120 // NOTE: We can't apply the offset or limit until here, because we may have 121 // filtered untrackable branches out of the result set. 122 123 if ($offset) { 124 $refs = array_slice($refs, $offset); 125 } 126 127 if ($limit) { 128 $refs = array_slice($refs, 0, $limit); 129 } 130 131 $refs = array_values($refs); 132 133 return mpull($refs, 'toDictionary'); 134 } 135 136}