@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 111 lines 3.2 kB view raw
1<?php 2 3final class DiffusionMergedCommitsQueryConduitAPIMethod 4 extends DiffusionQueryConduitAPIMethod { 5 6 public function getAPIMethodName() { 7 return 'diffusion.mergedcommitsquery'; 8 } 9 10 public function getMethodDescription() { 11 return pht( 12 'Merged commit information for a specific commit in a repository.'); 13 } 14 15 protected function defineReturnType() { 16 return 'array'; 17 } 18 19 protected function defineCustomParamTypes() { 20 return array( 21 'commit' => 'required string', 22 'limit' => 'optional int', 23 ); 24 } 25 26 private function getLimit(ConduitAPIRequest $request) { 27 // TODO: Paginate this sensibly at some point. 28 return $request->getValue('limit', 4096); 29 } 30 31 protected function getGitResult(ConduitAPIRequest $request) { 32 $drequest = $this->getDiffusionRequest(); 33 $repository = $drequest->getRepository(); 34 $commit = $request->getValue('commit'); 35 $limit = $this->getLimit($request); 36 37 list($parents) = $repository->execxLocalCommand( 38 'log -n 1 %s %s --', 39 '--format=%P', 40 gitsprintf('%s', $commit)); 41 42 $parents = preg_split('/\s+/', trim($parents)); 43 if (count($parents) < 2) { 44 // This is not a merge commit, so it doesn't merge anything. 45 return array(); 46 } 47 48 // Get all of the commits which are not reachable from the first parent. 49 // These are the commits this change merges. 50 51 $first_parent = head($parents); 52 list($logs) = $repository->execxLocalCommand( 53 'log -n %d %s %s %s --', 54 // NOTE: "+ 1" accounts for the merge commit itself. 55 $limit + 1, 56 '--format=%H', 57 gitsprintf('%s', $commit), 58 gitsprintf('%s', '^'.$first_parent)); 59 60 $hashes = explode("\n", trim($logs)); 61 62 // Remove the merge commit. 63 $hashes = array_diff($hashes, array($commit)); 64 65 $history = DiffusionQuery::loadHistoryForCommitIdentifiers( 66 $hashes, 67 $drequest); 68 return mpull($history, 'toDictionary'); 69 } 70 71 protected function getMercurialResult(ConduitAPIRequest $request) { 72 $drequest = $this->getDiffusionRequest(); 73 $repository = $drequest->getRepository(); 74 $commit = $request->getValue('commit'); 75 $limit = $this->getLimit($request); 76 77 list($parents) = $repository->execxLocalCommand( 78 'parents --template=%s --rev %s', 79 '{node}\\n', 80 hgsprintf('%s', $commit)); 81 $parents = explode("\n", trim($parents)); 82 83 if (count($parents) < 2) { 84 // Not a merge commit. 85 return array(); 86 } 87 88 // NOTE: In Git, the first parent is the "mainline". In Mercurial, the 89 // second parent is the "mainline" (the way 'git merge' and 'hg merge' 90 // work is also reversed). 91 92 $last_parent = last($parents); 93 list($logs) = $repository->execxLocalCommand( 94 'log --template=%s --follow --limit %d --rev %s:0 --prune %s --', 95 '{node}\\n', 96 $limit + 1, 97 $commit, 98 $last_parent); 99 100 $hashes = explode("\n", trim($logs)); 101 102 // Remove the merge commit. 103 $hashes = array_diff($hashes, array($commit)); 104 105 $history = DiffusionQuery::loadHistoryForCommitIdentifiers( 106 $hashes, 107 $drequest); 108 return mpull($history, 'toDictionary'); 109 } 110 111}