[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class ReleephWorkNextRequestConduitAPIMethod 4 extends ReleephConduitAPIMethod { 5 6 private $project; 7 private $branch; 8 9 public function getAPIMethodName() { 10 return 'releephwork.nextrequest'; 11 } 12 13 public function getMethodStatus() { 14 return self::METHOD_STATUS_UNSTABLE; 15 } 16 17 public function getMethodDescription() { 18 return 19 'Return info required to cut a branch, '. 20 'and pick and revert ReleephRequests'; 21 } 22 23 public function defineParamTypes() { 24 return array( 25 'branchPHID' => 'required phid', 26 'seen' => 'required map<string, bool>', 27 ); 28 } 29 30 public function defineReturnType() { 31 return ''; 32 } 33 34 public function defineErrorTypes() { 35 return array( 36 'ERR-NOT-PUSHER' => 37 'You are not listed as a pusher for thie Releeph project!', 38 ); 39 } 40 41 protected function execute(ConduitAPIRequest $request) { 42 $viewer = $request->getUser(); 43 $seen = $request->getValue('seen'); 44 45 $branch = id(new ReleephBranchQuery()) 46 ->setViewer($viewer) 47 ->withPHIDs(array($request->getValue('branchPHID'))) 48 ->executeOne(); 49 50 $project = $branch->getProduct(); 51 52 $needs_pick = array(); 53 $needs_revert = array(); 54 55 // Load every request ever made for this branch...?!!! 56 $releeph_requests = id(new ReleephRequestQuery()) 57 ->setViewer($viewer) 58 ->withBranchIDs(array($branch->getID())) 59 ->execute(); 60 61 foreach ($releeph_requests as $candidate) { 62 $phid = $candidate->getPHID(); 63 if (idx($seen, $phid)) { 64 continue; 65 } 66 67 $should = $candidate->shouldBeInBranch(); 68 $in = $candidate->getInBranch(); 69 if ($should && !$in) { 70 $needs_pick[] = $candidate; 71 } 72 if (!$should && $in) { 73 $needs_revert[] = $candidate; 74 } 75 } 76 77 /** 78 * Sort both needs_pick and needs_revert in ascending commit order, as 79 * discovered by Phabricator (using the `id` column to perform that 80 * ordering). 81 * 82 * This is easy for $needs_pick as the ordinal is stored. It is hard for 83 * reverts, as we have to look that information up. 84 */ 85 $needs_pick = $this->sortPicks($needs_pick); 86 $needs_revert = $this->sortReverts($needs_revert); 87 88 /** 89 * Do reverts first in reverse order, then the picks in original-commit 90 * order. 91 * 92 * This seems like the correct thing to do, but there may be a better 93 * algorithm for the releephwork.nextrequest Conduit call that orders 94 * things better. 95 * 96 * We could also button-mash our way through everything that failed (at the 97 * end of the run) to try failed things again. 98 */ 99 $releeph_request = null; 100 $action = null; 101 if ($needs_revert) { 102 $releeph_request = last($needs_revert); 103 $action = 'revert'; 104 $commit_id = $releeph_request->getCommitIdentifier(); 105 $commit_phid = $releeph_request->getCommitPHID(); 106 } else if ($needs_pick) { 107 $releeph_request = head($needs_pick); 108 $action = 'pick'; 109 $commit = $releeph_request->loadPhabricatorRepositoryCommit(); 110 $commit_id = $commit->getCommitIdentifier(); 111 $commit_phid = $commit->getPHID(); 112 } else { 113 // Return early if there's nothing to do! 114 return array(); 115 } 116 117 // Build the response 118 $phids = array(); 119 $phids[] = $commit_phid; 120 121 $diff_phid = null; 122 $diff_rev_id = null; 123 124 $requested_object = $releeph_request->getRequestedObject(); 125 if ($requested_object instanceof DifferentialRevision) { 126 $diff_rev = $requested_object; 127 } else { 128 $diff_rev = null; 129 } 130 131 if ($diff_rev) { 132 $diff_phid = $diff_rev->getPHID(); 133 $phids[] = $diff_phid; 134 $diff_rev_id = $diff_rev->getID(); 135 } 136 137 $phids[] = $releeph_request->getPHID(); 138 $handles = id(new PhabricatorHandleQuery()) 139 ->setViewer($request->getUser()) 140 ->withPHIDs($phids) 141 ->execute(); 142 143 $diff_name = null; 144 if ($diff_rev) { 145 $diff_name = $handles[$diff_phid]->getName(); 146 } 147 148 $new_author_phid = null; 149 if ($diff_rev) { 150 $new_author_phid = $diff_rev->getAuthorPHID(); 151 } else { 152 $pr_commit = $releeph_request->loadPhabricatorRepositoryCommit(); 153 if ($pr_commit) { 154 $new_author_phid = $pr_commit->getAuthorPHID(); 155 } 156 } 157 158 return array( 159 'requestID' => $releeph_request->getID(), 160 'requestPHID' => $releeph_request->getPHID(), 161 'requestName' => $handles[$releeph_request->getPHID()]->getName(), 162 'requestorPHID' => $releeph_request->getRequestUserPHID(), 163 'action' => $action, 164 'diffRevID' => $diff_rev_id, 165 'diffName' => $diff_name, 166 'commitIdentifier' => $commit_id, 167 'commitPHID' => $commit_phid, 168 'commitName' => $handles[$commit_phid]->getName(), 169 'needsRevert' => mpull($needs_revert, 'getID'), 170 'needsPick' => mpull($needs_pick, 'getID'), 171 'newAuthorPHID' => $new_author_phid, 172 ); 173 } 174 175 private function sortPicks(array $releeph_requests) { 176 $surrogate = array(); 177 foreach ($releeph_requests as $rq) { 178 // TODO: it's likely that relying on the `id` column to provide 179 // trunk-commit-order is thoroughly broken. 180 $ordinal = (int) $rq->loadPhabricatorRepositoryCommit()->getID(); 181 $surrogate[$ordinal] = $rq; 182 } 183 ksort($surrogate); 184 return $surrogate; 185 } 186 187 /** 188 * Sort an array of ReleephRequests, that have been picked into a branch, in 189 * the order in which they were picked to the branch. 190 */ 191 private function sortReverts(array $releeph_requests) { 192 if (!$releeph_requests) { 193 return array(); 194 } 195 196 // ReleephRequests, keyed by <branch-commit-id> 197 $releeph_requests = mpull($releeph_requests, null, 'getCommitIdentifier'); 198 199 $commits = id(new PhabricatorRepositoryCommit()) 200 ->loadAllWhere( 201 'commitIdentifier IN (%Ls)', 202 mpull($releeph_requests, 'getCommitIdentifier')); 203 204 // A map of <branch-commit-id> => <branch-commit-ordinal> 205 $surrogate = mpull($commits, 'getID', 'getCommitIdentifier'); 206 207 $unparsed = array(); 208 $result = array(); 209 210 foreach ($releeph_requests as $commit_id => $releeph_request) { 211 $ordinal = idx($surrogate, $commit_id); 212 if ($ordinal) { 213 $result[$ordinal] = $releeph_request; 214 } else { 215 $unparsed[] = $releeph_request; 216 } 217 } 218 219 // Sort $result in ascending order 220 ksort($result); 221 222 // Unparsed commits we'll just have to guess, based on time 223 $unparsed = msort($unparsed, 'getDateModified'); 224 225 return array_merge($result, $unparsed); 226 } 227 228 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |