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

Modernize UI for "Compare" in Diffusion

Summary: Ref T929. We've made some UI updates since D15330.

Test Plan: {F2079125}

Reviewers: avivey, chad

Reviewed By: chad

Maniphest Tasks: T929

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

+270 -162
+16
src/applications/diffusion/controller/DiffusionBrowseController.php
··· 1651 1651 1652 1652 protected function buildCurtain(DiffusionRequest $drequest) { 1653 1653 $viewer = $this->getViewer(); 1654 + $repository = $drequest->getRepository(); 1654 1655 1655 1656 $curtain = $this->newCurtainView($drequest); 1656 1657 ··· 1666 1667 ->setIcon('fa-list')); 1667 1668 1668 1669 $behind_head = $drequest->getSymbolicCommit(); 1670 + 1671 + if ($repository->supportsBranchComparison()) { 1672 + $compare_uri = $drequest->generateURI( 1673 + array( 1674 + 'action' => 'compare', 1675 + )); 1676 + 1677 + $curtain->addAction( 1678 + id(new PhabricatorActionView()) 1679 + ->setName(pht('Compare Against...')) 1680 + ->setIcon('fa-code-fork') 1681 + ->setWorkflow(true) 1682 + ->setHref($compare_uri)); 1683 + } 1684 + 1669 1685 $head_uri = $drequest->generateURI( 1670 1686 array( 1671 1687 'commit' => '',
+224 -159
src/applications/diffusion/controller/DiffusionCompareController.php
··· 16 16 $drequest = $this->getDiffusionRequest(); 17 17 $repository = $drequest->getRepository(); 18 18 19 - $content = array(); 20 - 21 - $crumbs = $this->buildCrumbs(array('view' => 'compare')); 22 - 23 - $empty_title = null; 24 - $error_message = null; 25 - 26 - if ($repository->getVersionControlSystem() != 27 - PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) { 28 - $empty_title = pht('Not supported'); 29 - $error_message = pht( 30 - 'This feature is not yet supported for %s repositories.', 31 - $repository->getVersionControlSystem()); 32 - $content[] = id(new PHUIInfoView()) 33 - ->setTitle($empty_title) 34 - ->setSeverity(PHUIInfoView::SEVERITY_WARNING) 35 - ->setErrors(array($error_message)); 19 + if (!$repository->supportsBranchComparison()) { 20 + return $this->newDialog() 21 + ->setTitle(pht('Not Supported')) 22 + ->appendParagraph( 23 + pht( 24 + 'Branch comparison is not supported for this version control '. 25 + 'system.')) 26 + ->addCancelButton($this->getApplicationURI(), pht('Okay')); 36 27 } 37 28 38 29 $head_ref = $request->getStr('head'); 39 30 $against_ref = $request->getStr('against'); 40 31 41 - $refs = id(new DiffusionCachedResolveRefsQuery()) 42 - ->setRepository($repository) 43 - ->withRefs(array($head_ref, $against_ref)) 44 - ->execute(); 32 + $must_prompt = false; 33 + if (!$request->isFormPost()) { 34 + if (!strlen($head_ref)) { 35 + $head_ref = $drequest->getSymbolicCommit(); 36 + if (!strlen($head_ref)) { 37 + $head_ref = $drequest->getBranch(); 38 + } 39 + } 45 40 41 + if (!strlen($against_ref)) { 42 + $default_branch = $repository->getDefaultBranch(); 43 + if ($default_branch != $head_ref) { 44 + $against_ref = $default_branch; 46 45 47 - if (count($refs) == 2) { 48 - $content[] = $this->buildCompareContent($drequest); 49 - } else { 50 - $content[] = $this->buildCompareForm($request, $refs); 46 + // If we filled this in by default, we want to prompt the user to 47 + // confirm that this is really what they want. 48 + $must_prompt = true; 49 + } 50 + } 51 51 } 52 52 53 - 54 - return $this->newPage() 55 - ->setTitle( 53 + $refs = $drequest->resolveRefs( 54 + array_filter( 56 55 array( 57 - $repository->getName(), 58 - $repository->getDisplayName(), 59 - )) 60 - ->setCrumbs($crumbs) 61 - ->appendChild($content); 62 - } 63 - 64 - private function buildCompareForm(AphrontRequest $request, array $resolved) { 65 - $viewer = $this->getViewer(); 66 - 67 - $head_ref = $request->getStr('head'); 68 - $against_ref = $request->getStr('against'); 56 + $head_ref, 57 + $against_ref, 58 + ))); 69 59 70 - if (idx($resolved, $head_ref)) { 71 - $e_head = null; 60 + $identical = false; 61 + if ($head_ref === $against_ref) { 62 + $identical = true; 72 63 } else { 73 - $e_head = 'Not Found'; 64 + if (count($refs) == 2) { 65 + if ($refs[$head_ref] === $refs[$against_ref]) { 66 + $identical = true; 67 + } 68 + } 74 69 } 75 70 76 - if (idx($resolved, $against_ref)) { 77 - $e_against = null; 78 - } else { 79 - $e_against = 'Not Found'; 71 + if ($must_prompt || count($refs) != 2 || $identical) { 72 + return $this->buildCompareDialog( 73 + $head_ref, 74 + $against_ref, 75 + $refs, 76 + $identical); 80 77 } 81 78 82 - 83 - $form = id(new AphrontFormView()) 84 - ->setUser($viewer) 85 - ->setMethod('GET') 86 - ->appendControl( 87 - id(new AphrontFormTextControl()) 88 - ->setLabel(pht('Head')) 89 - ->setName('head') 90 - ->setError($e_head) 91 - ->setValue($head_ref)) 92 - ->appendControl( 93 - id(new AphrontFormTextControl()) 94 - ->setLabel(pht('Against')) 95 - ->setName('against') 96 - ->setError($e_against) 97 - ->setValue($against_ref)) 98 - ->appendControl( 99 - id(new AphrontFormSubmitControl()) 100 - ->setValue('Compare')); 101 - 102 - return $form; 103 - } 104 - 105 - private function buildCompareContent(DiffusionRequest $drequest) { 106 - $request = $this->getRequest(); 107 - $repository = $drequest->getRepository(); 79 + if ($request->isFormPost()) { 80 + // Redirect to a stable URI that can be copy/pasted. 81 + $compare_uri = $drequest->generateURI( 82 + array( 83 + 'action' => 'compare', 84 + 'head' => $head_ref, 85 + 'against' => $against_ref, 86 + )); 108 87 109 - $head_ref = $request->getStr('head'); 110 - $against_ref = $request->getStr('against'); 88 + return id(new AphrontRedirectResponse())->setURI($compare_uri); 89 + } 111 90 112 - $content = array(); 91 + $crumbs = $this->buildCrumbs( 92 + array( 93 + 'view' => 'compare', 94 + )); 113 95 114 96 $pager = id(new PHUIPagerView()) 115 97 ->readFromRequest($request); 116 98 99 + $history = null; 117 100 try { 118 101 $history_results = $this->callConduitWithDiffusionRequest( 119 102 'diffusion.historyquery', ··· 126 109 )); 127 110 $history = DiffusionPathChange::newFromConduit( 128 111 $history_results['pathChanges']); 129 - 130 112 $history = $pager->sliceResults($history); 131 113 132 - $history_exception = null; 114 + $history_view = $this->newHistoryView( 115 + $history_results, 116 + $history, 117 + $pager, 118 + $head_ref, 119 + $against_ref); 120 + 133 121 } catch (Exception $ex) { 134 - $history_results = null; 135 - $history = null; 136 - $history_exception = $ex; 122 + if ($repository->isImporting()) { 123 + $history_view = $this->renderStatusMessage( 124 + pht('Still Importing...'), 125 + pht( 126 + 'This repository is still importing. History is not yet '. 127 + 'available.')); 128 + } else { 129 + $history_view = $this->renderStatusMessage( 130 + pht('Unable to Retrieve History'), 131 + $ex->getMessage()); 132 + } 137 133 } 138 134 139 - if ($history_results) { 140 - $content[] = $this->buildCompareProperties($drequest, $history_results); 135 + $header = id(new PHUIHeaderView()) 136 + ->setHeader( 137 + pht( 138 + 'Changes on %s but not %s', 139 + phutil_tag('em', array(), $head_ref), 140 + phutil_tag('em', array(), $against_ref))); 141 + 142 + $curtain = $this->buildCurtain($head_ref, $against_ref); 143 + 144 + $column_view = id(new PHUITwoColumnView()) 145 + ->setHeader($header) 146 + ->setCurtain($curtain) 147 + ->setMainColumn( 148 + array( 149 + $history_view, 150 + )); 151 + 152 + return $this->newPage() 153 + ->setTitle( 154 + array( 155 + $repository->getName(), 156 + $repository->getDisplayName(), 157 + )) 158 + ->setCrumbs($crumbs) 159 + ->appendChild($column_view); 160 + } 161 + 162 + private function buildCompareDialog( 163 + $head_ref, 164 + $against_ref, 165 + array $resolved, 166 + $identical) { 167 + 168 + $viewer = $this->getViewer(); 169 + $request = $this->getRequest(); 170 + $drequest = $this->getDiffusionRequest(); 171 + $repository = $drequest->getRepository(); 172 + 173 + $e_head = null; 174 + $e_against = null; 175 + $errors = array(); 176 + if ($request->isFormPost()) { 177 + if (!strlen($head_ref)) { 178 + $e_head = pht('Required'); 179 + $errors[] = pht( 180 + 'You must provide two different commits to compare.'); 181 + } else if (!isset($resolved[$head_ref])) { 182 + $e_head = pht('Not Found'); 183 + $errors[] = pht( 184 + 'Commit "%s" is not a valid commit in this repository.', 185 + $head_ref); 186 + } 187 + 188 + if (!strlen($against_ref)) { 189 + $e_against = pht('Required'); 190 + $errors[] = pht( 191 + 'You must provide two different commits to compare.'); 192 + } else if (!isset($resolved[$against_ref])) { 193 + $e_against = pht('Not Found'); 194 + $errors[] = pht( 195 + 'Commit "%s" is not a valid commit in this repository.', 196 + $against_ref); 197 + } 198 + 199 + if ($identical) { 200 + $e_head = pht('Identical'); 201 + $e_against = pht('Identical'); 202 + $errors[] = pht( 203 + 'Both references identify the same commit. You can not compare a '. 204 + 'commit against itself.'); 205 + } 141 206 } 142 - $content[] = $this->buildCompareForm( 143 - $request, 144 - array($head_ref => true, $against_ref => true)); 145 207 146 - $content[] = $this->buildHistoryTable( 147 - $history_results, 148 - $history, 149 - $pager, 150 - $history_exception); 208 + $form = id(new AphrontFormView()) 209 + ->setViewer($viewer) 210 + ->appendControl( 211 + id(new AphrontFormTextControl()) 212 + ->setLabel(pht('Head')) 213 + ->setName('head') 214 + ->setError($e_head) 215 + ->setValue($head_ref)) 216 + ->appendControl( 217 + id(new AphrontFormTextControl()) 218 + ->setLabel(pht('Against')) 219 + ->setName('against') 220 + ->setError($e_against) 221 + ->setValue($against_ref)); 151 222 152 - $content[] = $this->renderTablePagerBox($pager); 223 + $cancel_uri = $repository->generateURI( 224 + array( 225 + 'action' => 'browse', 226 + )); 153 227 154 - return $content; 228 + return $this->newDialog() 229 + ->setTitle(pht('Compare Against')) 230 + ->setWidth(AphrontDialogView::WIDTH_FORM) 231 + ->setErrors($errors) 232 + ->appendForm($form) 233 + ->addSubmitButton(pht('Compare')) 234 + ->addCancelButton($cancel_uri, pht('Cancel')); 155 235 } 156 236 157 - private function buildCompareProperties($drequest, array $history_results) { 237 + private function buildCurtain($head_ref, $against_ref) { 158 238 $viewer = $this->getViewer(); 159 - 160 239 $request = $this->getRequest(); 240 + $drequest = $this->getDiffusionRequest(); 161 241 $repository = $drequest->getRepository(); 162 242 163 - $head_ref = $request->getStr('head'); 164 - $against_ref = $request->getStr('against'); 165 - 166 - $reverse_uri = $repository->getPathURI( 167 - "compare/?head=${against_ref}&against=${head_ref}"); 168 - $actions = id(new PhabricatorActionListView()); 169 - $actions->setUser($viewer); 243 + $curtain = $this->newCurtainView(null); 170 244 245 + $reverse_uri = $drequest->generateURI( 246 + array( 247 + 'action' => 'compare', 248 + 'head' => $against_ref, 249 + 'against' => $head_ref, 250 + )); 171 251 172 - $actions->addAction(id(new PhabricatorActionView()) 252 + $curtain->addAction( 253 + id(new PhabricatorActionView()) 173 254 ->setName(pht('Reverse Comparison')) 174 255 ->setHref($reverse_uri) 175 - ->setIcon('fa-list')); 256 + ->setIcon('fa-refresh')); 176 257 177 - $view = id(new PHUIPropertyListView()) 178 - ->setUser($viewer) 179 - ->setActionList($actions); 180 - 181 - $readme = 182 - 'These are the commits that are reachable from **Head** commit and not '. 183 - 'from the **Against** commit.'; 184 - $readme = new PHUIRemarkupView($viewer, $readme); 185 - $view->addTextContent($readme); 258 + $compare_uri = $drequest->generateURI( 259 + array( 260 + 'action' => 'compare', 261 + 'head' => $head_ref, 262 + )); 186 263 187 - $view->addProperty(pht('Head'), $head_ref); 188 - $view->addProperty(pht('Against'), $against_ref); 264 + $curtain->addAction( 265 + id(new PhabricatorActionView()) 266 + ->setName(pht('Compare Against...')) 267 + ->setIcon('fa-code-fork') 268 + ->setWorkflow(true) 269 + ->setHref($compare_uri)); 189 270 190 - $header = id(new PHUIHeaderView()) 191 - ->setUser($viewer) 192 - ->setPolicyObject($drequest->getRepository()); 271 + // TODO: Provide a "Show Diff" action. 193 272 194 - $box = id(new PHUIObjectBoxView()) 195 - ->setUser($viewer) 196 - ->setHeader($header) 197 - ->addPropertyList($view); 198 - return $box; 273 + return $curtain; 199 274 } 200 275 201 - private function buildHistoryTable( 202 - $history_results, 203 - $history, 204 - $pager, 205 - $history_exception) { 276 + private function newHistoryView( 277 + array $results, 278 + array $history, 279 + PHUIPagerView $pager, 280 + $head_ref, 281 + $against_ref) { 206 282 207 283 $request = $this->getRequest(); 208 - $viewer = $request->getUser(); 284 + $viewer = $this->getViewer(); 209 285 $drequest = $this->getDiffusionRequest(); 210 286 $repository = $drequest->getRepository(); 211 287 212 - if ($history_exception) { 213 - if ($repository->isImporting()) { 214 - return $this->renderStatusMessage( 215 - pht('Still Importing...'), 216 - pht( 217 - 'This repository is still importing. History is not yet '. 218 - 'available.')); 219 - } else { 220 - return $this->renderStatusMessage( 221 - pht('Unable to Retrieve History'), 222 - $history_exception->getMessage()); 223 - } 224 - } 225 - 226 288 if (!$history) { 227 289 return $this->renderStatusMessage( 228 - pht('Up to date'), 229 - new PHUIRemarkupView( 230 - $viewer, 231 - pht( 232 - '**Against** is strictly ahead of **Head** '. 233 - '- no commits are missing.'))); 290 + pht('Up To Date'), 291 + pht( 292 + 'There are no commits on %s that are not already on %s.', 293 + phutil_tag('strong', array(), $head_ref), 294 + phutil_tag('strong', array(), $against_ref))); 234 295 } 235 296 236 297 $history_table = id(new DiffusionHistoryTableView()) ··· 238 299 ->setDiffusionRequest($drequest) 239 300 ->setHistory($history); 240 301 241 - // TODO: Super sketchy? 242 302 $history_table->loadRevisions(); 243 303 244 - if ($history_results) { 245 - $history_table->setParents($history_results['parents']); 304 + if ($history) { 305 + $history_table->setParents($results['parents']); 246 306 $history_table->setIsHead(!$pager->getOffset()); 247 307 $history_table->setIsTail(!$pager->getHasMorePages()); 248 308 } 249 309 250 - // TODO also expose diff. 310 + $header = id(new PHUIHeaderView()) 311 + ->setHeader(pht('Commits')); 312 + 313 + $object_box = id(new PHUIObjectBoxView()) 314 + ->setHeader($header) 315 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 316 + ->setTable($history_table); 251 317 252 - $panel = new PHUIObjectBoxView(); 253 - $header = id(new PHUIHeaderView()) 254 - ->setHeader(pht('Missing Commits')); 255 - $panel->setHeader($header); 256 - $panel->setTable($history_table); 318 + $pager_box = $this->renderTablePagerBox($pager); 257 319 258 - return $panel; 320 + return array( 321 + $object_box, 322 + $pager_box, 323 + ); 259 324 } 260 325 }
+1 -1
src/applications/diffusion/request/DiffusionRequest.php
··· 644 644 return $match; 645 645 } 646 646 647 - private function resolveRefs(array $refs, array $types) { 647 + public function resolveRefs(array $refs, array $types = array()) { 648 648 // First, try to resolve refs from fast cache sources. 649 649 $cached_query = id(new DiffusionCachedResolveRefsQuery()) 650 650 ->setRepository($this->getRepository())
+29 -2
src/applications/repository/storage/PhabricatorRepository.php
··· 689 689 case 'lint': 690 690 case 'pathtree': 691 691 case 'refs': 692 + case 'compare': 692 693 break; 693 694 case 'branch': 694 695 // NOTE: This does not actually require a branch, and won't have one ··· 709 710 $branch = idx($params, 'branch'); 710 711 $commit = idx($params, 'commit'); 711 712 $line = idx($params, 'line'); 713 + 714 + $head = idx($params, 'head'); 715 + $against = idx($params, 'against'); 712 716 713 717 if ($req_commit && !strlen($commit)) { 714 718 throw new Exception( ··· 734 738 $path = phutil_escape_uri($path); 735 739 } 736 740 741 + $raw_branch = $branch; 737 742 if (strlen($branch)) { 738 743 $branch = phutil_escape_uri_path_component($branch); 739 744 $path = "{$branch}/{$path}"; 740 745 } 741 746 747 + $raw_commit = $commit; 742 748 if (strlen($commit)) { 743 749 $commit = str_replace('$', '$$', $commit); 744 750 $commit = ';'.phutil_escape_uri($commit); ··· 748 754 $line = '$'.phutil_escape_uri($line); 749 755 } 750 756 757 + $query = array(); 751 758 switch ($action) { 752 759 case 'change': 753 760 case 'history': ··· 760 767 case 'refs': 761 768 $uri = $this->getPathURI("/{$action}/{$path}{$commit}{$line}"); 762 769 break; 770 + case 'compare': 771 + $uri = $this->getPathURI("/{$action}/"); 772 + if (strlen($head)) { 773 + $query['head'] = $head; 774 + } else if (strlen($raw_commit)) { 775 + $query['commit'] = $raw_commit; 776 + } else if (strlen($raw_branch)) { 777 + $query['head'] = $raw_branch; 778 + } 779 + 780 + if (strlen($against)) { 781 + $query['against'] = $against; 782 + } 783 + break; 763 784 case 'branch': 764 785 if (strlen($path)) { 765 786 $uri = $this->getPathURI("/repository/{$path}"); ··· 791 812 ); 792 813 } 793 814 794 - if (idx($params, 'params')) { 795 - $uri->setQueryParams($params['params']); 815 + $query = idx($params, 'params', array()) + $query; 816 + 817 + if ($query) { 818 + $uri->setQueryParams($query); 796 819 } 797 820 798 821 return $uri; ··· 2064 2087 } 2065 2088 2066 2089 return $result; 2090 + } 2091 + 2092 + public function supportsBranchComparison() { 2093 + return $this->isGit(); 2067 2094 } 2068 2095 2069 2096 /* -( Repository URIs )---------------------------------------------------- */