@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 309 lines 8.5 kB view raw
1<?php 2 3final class DiffusionCompareController extends DiffusionController { 4 5 public function shouldAllowPublic() { 6 return true; 7 } 8 9 public function handleRequest(AphrontRequest $request) { 10 $response = $this->loadDiffusionContext(); 11 if ($response) { 12 return $response; 13 } 14 15 $viewer = $this->getViewer(); 16 $drequest = $this->getDiffusionRequest(); 17 $repository = $drequest->getRepository(); 18 require_celerity_resource('diffusion-css'); 19 20 if (!$repository->supportsBranchComparison()) { 21 return $this->newDialog() 22 ->setTitle(pht('Not Supported')) 23 ->appendParagraph( 24 pht( 25 'Branch comparison is not supported for this version control '. 26 'system.')) 27 ->addCancelButton($this->getApplicationURI(), pht('Okay')); 28 } 29 30 $head_ref = $request->getStr('head', ''); 31 $against_ref = $request->getStr('against', ''); 32 33 $must_prompt = false; 34 if (!$request->isFormPost()) { 35 if (!strlen($head_ref)) { 36 $head_ref = $drequest->getSymbolicCommit(); 37 if (!phutil_nonempty_string($head_ref)) { 38 $head_ref = $drequest->getBranch(); 39 } 40 } 41 42 if (!strlen($against_ref)) { 43 $default_branch = $repository->getDefaultBranch(); 44 if ($default_branch != $head_ref) { 45 $against_ref = $default_branch; 46 47 // If we filled this in by default, we want to prompt the user to 48 // confirm that this is really what they want. 49 $must_prompt = true; 50 } 51 } 52 } 53 54 $refs = $drequest->resolveRefs( 55 array_filter( 56 array( 57 $head_ref, 58 $against_ref, 59 ))); 60 61 $identical = false; 62 if ($head_ref === $against_ref) { 63 $identical = true; 64 } else { 65 if (count($refs) == 2) { 66 if ($refs[$head_ref] === $refs[$against_ref]) { 67 $identical = true; 68 } 69 } 70 } 71 72 if ($must_prompt || count($refs) != 2 || $identical) { 73 return $this->buildCompareDialog( 74 $head_ref, 75 $against_ref, 76 $refs, 77 $identical); 78 } 79 80 if ($request->isFormPost()) { 81 // Redirect to a stable URI that can be copy/pasted. 82 $compare_uri = $drequest->generateURI( 83 array( 84 'action' => 'compare', 85 'head' => $head_ref, 86 'against' => $against_ref, 87 )); 88 89 return id(new AphrontRedirectResponse())->setURI($compare_uri); 90 } 91 92 $crumbs = $this->buildCrumbs( 93 array( 94 'view' => 'compare', 95 )); 96 $crumbs->setBorder(true); 97 98 $pager = id(new PHUIPagerView()) 99 ->readFromRequest($request); 100 101 $history = null; 102 try { 103 $history_results = $this->callConduitWithDiffusionRequest( 104 'diffusion.historyquery', 105 array( 106 'commit' => $head_ref, 107 'against' => $against_ref, 108 'path' => $drequest->getPath(), 109 'offset' => $pager->getOffset(), 110 'limit' => $pager->getPageSize() + 1, 111 )); 112 $history = DiffusionPathChange::newFromConduit( 113 $history_results['pathChanges']); 114 $history = $pager->sliceResults($history); 115 116 $history_view = $this->newHistoryView( 117 $history_results, 118 $history, 119 $pager, 120 $head_ref, 121 $against_ref); 122 123 } catch (Exception $ex) { 124 if ($repository->isImporting()) { 125 $history_view = $this->renderStatusMessage( 126 pht('Still Importing...'), 127 pht( 128 'This repository is still importing. History is not yet '. 129 'available.')); 130 } else { 131 $history_view = $this->renderStatusMessage( 132 pht('Unable to Retrieve History'), 133 $ex->getMessage()); 134 } 135 } 136 137 $header = id(new PHUIHeaderView()) 138 ->setHeader( 139 pht( 140 'Changes on %s but not %s', 141 phutil_tag('em', array(), $head_ref), 142 phutil_tag('em', array(), $against_ref))); 143 144 $curtain = $this->buildCurtain($head_ref, $against_ref); 145 146 $column_view = id(new PHUITwoColumnView()) 147 ->setHeader($header) 148 ->setCurtain($curtain) 149 ->setMainColumn( 150 array( 151 $history_view, 152 )); 153 154 return $this->newPage() 155 ->setTitle( 156 array( 157 $repository->getName(), 158 $repository->getDisplayName(), 159 )) 160 ->setCrumbs($crumbs) 161 ->appendChild($column_view); 162 } 163 164 private function buildCompareDialog( 165 $head_ref, 166 $against_ref, 167 array $resolved, 168 $identical) { 169 170 $viewer = $this->getViewer(); 171 $request = $this->getRequest(); 172 $drequest = $this->getDiffusionRequest(); 173 $repository = $drequest->getRepository(); 174 175 $e_head = null; 176 $e_against = null; 177 $errors = array(); 178 if ($request->isFormPost()) { 179 if (!strlen($head_ref)) { 180 $e_head = pht('Required'); 181 $errors[] = pht( 182 'You must provide two different commits to compare.'); 183 } else if (!isset($resolved[$head_ref])) { 184 $e_head = pht('Not Found'); 185 $errors[] = pht( 186 'Commit "%s" is not a valid commit in this repository.', 187 $head_ref); 188 } 189 190 if (!strlen($against_ref)) { 191 $e_against = pht('Required'); 192 $errors[] = pht( 193 'You must provide two different commits to compare.'); 194 } else if (!isset($resolved[$against_ref])) { 195 $e_against = pht('Not Found'); 196 $errors[] = pht( 197 'Commit "%s" is not a valid commit in this repository.', 198 $against_ref); 199 } 200 201 if ($identical) { 202 $e_head = pht('Identical'); 203 $e_against = pht('Identical'); 204 $errors[] = pht( 205 'Both references identify the same commit. You can not compare a '. 206 'commit against itself.'); 207 } 208 } 209 210 $form = id(new AphrontFormView()) 211 ->setViewer($viewer) 212 ->appendControl( 213 id(new AphrontFormTextControl()) 214 ->setLabel(pht('Head')) 215 ->setName('head') 216 ->setError($e_head) 217 ->setValue($head_ref)) 218 ->appendControl( 219 id(new AphrontFormTextControl()) 220 ->setLabel(pht('Against')) 221 ->setName('against') 222 ->setError($e_against) 223 ->setValue($against_ref)); 224 225 $cancel_uri = $repository->generateURI( 226 array( 227 'action' => 'browse', 228 )); 229 230 return $this->newDialog() 231 ->setTitle(pht('Compare Against')) 232 ->setWidth(AphrontDialogView::WIDTH_FORM) 233 ->setErrors($errors) 234 ->appendForm($form) 235 ->addSubmitButton(pht('Compare')) 236 ->addCancelButton($cancel_uri, pht('Cancel')); 237 } 238 239 private function buildCurtain($head_ref, $against_ref) { 240 $viewer = $this->getViewer(); 241 $request = $this->getRequest(); 242 $drequest = $this->getDiffusionRequest(); 243 $repository = $drequest->getRepository(); 244 245 $curtain = $this->newCurtainView(null); 246 247 $reverse_uri = $drequest->generateURI( 248 array( 249 'action' => 'compare', 250 'head' => $against_ref, 251 'against' => $head_ref, 252 )); 253 254 $curtain->addAction( 255 id(new PhabricatorActionView()) 256 ->setName(pht('Reverse Comparison')) 257 ->setHref($reverse_uri) 258 ->setIcon('fa-refresh')); 259 260 $compare_uri = $drequest->generateURI( 261 array( 262 'action' => 'compare', 263 'head' => $head_ref, 264 )); 265 266 $curtain->addAction( 267 id(new PhabricatorActionView()) 268 ->setName(pht('Compare Against...')) 269 ->setIcon('fa-code-fork') 270 ->setWorkflow(true) 271 ->setHref($compare_uri)); 272 273 // TODO: Provide a "Show Diff" action. 274 275 return $curtain; 276 } 277 278 private function newHistoryView( 279 array $results, 280 array $history, 281 PHUIPagerView $pager, 282 $head_ref, 283 $against_ref) { 284 285 $request = $this->getRequest(); 286 $viewer = $this->getViewer(); 287 $drequest = $this->getDiffusionRequest(); 288 289 if (!$history) { 290 return $this->renderStatusMessage( 291 pht('Up To Date'), 292 pht( 293 'There are no commits on %s that are not already on %s.', 294 phutil_tag('strong', array(), $head_ref), 295 phutil_tag('strong', array(), $against_ref))); 296 } 297 298 $history_view = id(new DiffusionCommitGraphView()) 299 ->setViewer($viewer) 300 ->setDiffusionRequest($drequest) 301 ->setHistory($history) 302 ->setParents($results['parents']) 303 ->setFilterParents(true) 304 ->setIsHead(!$pager->getOffset()) 305 ->setIsTail(!$pager->getHasMorePages()); 306 307 return $history_view; 308 } 309}