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

Introduce "DiffusionCommitGraphView", which unifies "HistoryListView" and "HistoryTableView"

Summary:
Ref T13552. Currently, commit lists are sometimes rendered as an object list and sometimes rendered as a table. There are two separate views for table rendering.

Add a fourth view ("list, with a graph") with the eventual intent of unifying all the other views. For now, this only replaces "HistoryListView" -- and needs some more work to really be a convincing replacement.

Test Plan:
- Looked at "History" in Diffusion, saw an ugly view with all the information we want.
- Grepped for "HistoryListView", no hits.

Maniphest Tasks: T13552

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

+440 -176
+2 -2
src/__phutil_library_map__.php
··· 770 770 'DiffusionCommitEditEngine' => 'applications/diffusion/editor/DiffusionCommitEditEngine.php', 771 771 'DiffusionCommitFerretEngine' => 'applications/repository/search/DiffusionCommitFerretEngine.php', 772 772 'DiffusionCommitFulltextEngine' => 'applications/repository/search/DiffusionCommitFulltextEngine.php', 773 + 'DiffusionCommitGraphView' => 'applications/diffusion/view/DiffusionCommitGraphView.php', 773 774 'DiffusionCommitHasPackageEdgeType' => 'applications/diffusion/edge/DiffusionCommitHasPackageEdgeType.php', 774 775 'DiffusionCommitHasRevisionEdgeType' => 'applications/diffusion/edge/DiffusionCommitHasRevisionEdgeType.php', 775 776 'DiffusionCommitHasRevisionRelationship' => 'applications/diffusion/relationships/DiffusionCommitHasRevisionRelationship.php', ··· 862 863 'DiffusionGitWireProtocolRef' => 'applications/diffusion/protocol/DiffusionGitWireProtocolRef.php', 863 864 'DiffusionGitWireProtocolRefList' => 'applications/diffusion/protocol/DiffusionGitWireProtocolRefList.php', 864 865 'DiffusionHistoryController' => 'applications/diffusion/controller/DiffusionHistoryController.php', 865 - 'DiffusionHistoryListView' => 'applications/diffusion/view/DiffusionHistoryListView.php', 866 866 'DiffusionHistoryQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionHistoryQueryConduitAPIMethod.php', 867 867 'DiffusionHistoryTableView' => 'applications/diffusion/view/DiffusionHistoryTableView.php', 868 868 'DiffusionHistoryView' => 'applications/diffusion/view/DiffusionHistoryView.php', ··· 6860 6860 'DiffusionCommitEditEngine' => 'PhabricatorEditEngine', 6861 6861 'DiffusionCommitFerretEngine' => 'PhabricatorFerretEngine', 6862 6862 'DiffusionCommitFulltextEngine' => 'PhabricatorFulltextEngine', 6863 + 'DiffusionCommitGraphView' => 'DiffusionView', 6863 6864 'DiffusionCommitHasPackageEdgeType' => 'PhabricatorEdgeType', 6864 6865 'DiffusionCommitHasRevisionEdgeType' => 'PhabricatorEdgeType', 6865 6866 'DiffusionCommitHasRevisionRelationship' => 'DiffusionCommitRelationship', ··· 6955 6956 'DiffusionGitWireProtocolRef' => 'Phobject', 6956 6957 'DiffusionGitWireProtocolRefList' => 'Phobject', 6957 6958 'DiffusionHistoryController' => 'DiffusionController', 6958 - 'DiffusionHistoryListView' => 'DiffusionHistoryView', 6959 6959 'DiffusionHistoryQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 6960 6960 'DiffusionHistoryTableView' => 'DiffusionHistoryView', 6961 6961 'DiffusionHistoryView' => 'DiffusionView',
+23 -2
src/applications/diffusion/controller/DiffusionHistoryController.php
··· 35 35 36 36 $history = $pager->sliceResults($history); 37 37 38 - $history_list = id(new DiffusionHistoryListView()) 38 + $identifiers = array(); 39 + foreach ($history as $item) { 40 + $identifiers[] = $item->getCommitIdentifier(); 41 + } 42 + 43 + if ($identifiers) { 44 + $commits = id(new DiffusionCommitQuery()) 45 + ->setViewer($viewer) 46 + ->withRepositoryPHIDs(array($repository->getPHID())) 47 + ->withIdentifiers($identifiers) 48 + ->needCommitData(true) 49 + ->needIdentities(true) 50 + ->execute(); 51 + } else { 52 + $commits = array(); 53 + } 54 + 55 + $history_list = id(new DiffusionCommitGraphView()) 39 56 ->setViewer($viewer) 57 + ->setParents($history_results['parents']) 58 + ->setIsHead(!$pager->getOffset()) 59 + ->setIsTail(!$pager->getHasMorePages()) 40 60 ->setDiffusionRequest($drequest) 41 - ->setHistory($history); 61 + ->setHistory($history) 62 + ->setCommits($commits); 42 63 43 64 $header = $this->buildHeader($drequest); 44 65
+415
src/applications/diffusion/view/DiffusionCommitGraphView.php
··· 1 + <?php 2 + 3 + final class DiffusionCommitGraphView 4 + extends DiffusionView { 5 + 6 + private $history; 7 + private $commits = array(); 8 + private $isHead; 9 + private $isTail; 10 + private $parents; 11 + private $filterParents; 12 + 13 + private $commitMap = array(); 14 + private $buildableMap; 15 + private $revisionMap; 16 + 17 + public function setHistory(array $history) { 18 + assert_instances_of($history, 'DiffusionPathChange'); 19 + $this->history = $history; 20 + return $this; 21 + } 22 + 23 + public function getHistory() { 24 + return $this->history; 25 + } 26 + 27 + public function setCommits(array $commits) { 28 + assert_instances_of($commits, 'PhabricatorRepositoryCommit'); 29 + $this->commits = $commits; 30 + $this->commitMap = mpull($commits, null, 'getCommitIdentifier'); 31 + return $this; 32 + } 33 + 34 + public function getCommits() { 35 + return $this->commits; 36 + } 37 + 38 + public function setParents(array $parents) { 39 + $this->parents = $parents; 40 + return $this; 41 + } 42 + 43 + public function getParents() { 44 + return $this->parents; 45 + } 46 + 47 + public function setIsHead($is_head) { 48 + $this->isHead = $is_head; 49 + return $this; 50 + } 51 + 52 + public function getIsHead() { 53 + return $this->isHead; 54 + } 55 + 56 + public function setIsTail($is_tail) { 57 + $this->isTail = $is_tail; 58 + return $this; 59 + } 60 + 61 + public function getIsTail() { 62 + return $this->isTail; 63 + } 64 + 65 + public function setFilterParents($filter_parents) { 66 + $this->filterParents = $filter_parents; 67 + return $this; 68 + } 69 + 70 + public function getFilterParents() { 71 + return $this->filterParents; 72 + } 73 + 74 + private function getRepository() { 75 + $drequest = $this->getDiffusionRequest(); 76 + 77 + if (!$drequest) { 78 + return null; 79 + } 80 + 81 + return $drequest->getRepository(); 82 + } 83 + 84 + public function render() { 85 + $viewer = $this->getUser(); 86 + 87 + $drequest = $this->getDiffusionRequest(); 88 + $repository = $drequest->getRepository(); 89 + 90 + require_celerity_resource('diffusion-css'); 91 + Javelin::initBehavior('phabricator-tooltips'); 92 + 93 + $show_builds = $this->shouldShowBuilds(); 94 + $show_revisions = $this->shouldShowRevisions(); 95 + 96 + $items = $this->newHistoryItems(); 97 + 98 + $rows = array(); 99 + $last_date = null; 100 + foreach ($items as $item) { 101 + $content = array(); 102 + 103 + $item_epoch = $item['epoch']; 104 + $item_hash = $item['hash']; 105 + $commit = $item['commit']; 106 + 107 + $item_date = phabricator_date($item_epoch, $viewer); 108 + if ($item_date !== $last_date) { 109 + $last_date = $item_date; 110 + $content[] = $item_date; 111 + } 112 + 113 + $commit_description = $this->getCommitDescription($commit); 114 + $commit_link = $this->getCommitURI($commit, $item_hash); 115 + 116 + $short_hash = $this->getCommitObjectName($commit, $item_hash); 117 + $is_disabled = $this->getCommitIsDisabled($commit); 118 + 119 + $author_view = $this->getCommitAuthorView($commit); 120 + 121 + $item_view = id(new PHUIObjectItemView()) 122 + ->setHeader($commit_description) 123 + ->setObjectName($short_hash) 124 + ->setHref($commit_link) 125 + ->setDisabled($is_disabled); 126 + 127 + if ($author_view !== null) { 128 + $item_view->addAttribute($author_view); 129 + } 130 + 131 + $browse_button = $this->newBrowseButton($item_hash); 132 + 133 + $build_view = null; 134 + if ($show_builds) { 135 + $build_view = $this->newBuildView($item_hash); 136 + } 137 + 138 + $item_view->setSideColumn( 139 + array( 140 + $build_view, 141 + $browse_button, 142 + )); 143 + 144 + $revision_view = null; 145 + if ($show_revisions) { 146 + $revision_view = $this->newRevisionView($item_hash); 147 + } 148 + 149 + if ($revision_view !== null) { 150 + $item_view->addAttribute($revision_view); 151 + } 152 + 153 + $view = id(new PHUIObjectItemListView()) 154 + ->setFlush(true) 155 + ->addItem($item_view); 156 + 157 + $content[] = $view; 158 + 159 + $rows[] = array( 160 + $content, 161 + ); 162 + } 163 + 164 + $graph = $this->newGraphView(); 165 + if ($graph) { 166 + $idx = 0; 167 + foreach ($rows as $key => $row) { 168 + array_unshift($row, $graph[$idx++]); 169 + $rows[$key] = $row; 170 + } 171 + } 172 + 173 + foreach ($rows as $key => $row) { 174 + $cells = array(); 175 + foreach ($row as $cell) { 176 + $cells[] = phutil_tag('td', array(), $cell); 177 + } 178 + $rows[$key] = phutil_tag('tr', array(), $cells); 179 + } 180 + 181 + $table = phutil_tag('table', array(), $rows); 182 + 183 + return $table; 184 + } 185 + 186 + private function newGraphView() { 187 + if (!$this->getParents()) { 188 + return null; 189 + } 190 + 191 + $parents = $this->getParents(); 192 + 193 + // If we're filtering parents, remove relationships which point to 194 + // commits that are not part of the visible graph. Otherwise, we get 195 + // a big tree of nonsense when viewing release branches like "stable" 196 + // versus "master". 197 + if ($this->getFilterParents()) { 198 + foreach ($parents as $key => $nodes) { 199 + foreach ($nodes as $nkey => $node) { 200 + if (empty($parents[$node])) { 201 + unset($parents[$key][$nkey]); 202 + } 203 + } 204 + } 205 + } 206 + 207 + return id(new PHUIDiffGraphView()) 208 + ->setIsHead($this->getIsHead()) 209 + ->setIsTail($this->getIsTail()) 210 + ->renderGraph($parents); 211 + } 212 + 213 + private function shouldShowBuilds() { 214 + $viewer = $this->getViewer(); 215 + 216 + $show_builds = PhabricatorApplication::isClassInstalledForViewer( 217 + 'PhabricatorHarbormasterApplication', 218 + $this->getUser()); 219 + 220 + return $show_builds; 221 + } 222 + 223 + private function shouldShowRevisions() { 224 + $viewer = $this->getViewer(); 225 + 226 + $show_revisions = PhabricatorApplication::isClassInstalledForViewer( 227 + 'PhabricatorDifferentialApplication', 228 + $viewer); 229 + 230 + return $show_revisions; 231 + } 232 + 233 + private function newHistoryItems() { 234 + $items = array(); 235 + 236 + $commits = $this->getCommits(); 237 + $commit_map = mpull($commits, null, 'getCommitIdentifier'); 238 + 239 + $history = $this->getHistory(); 240 + if ($history !== null) { 241 + foreach ($history as $history_item) { 242 + $commit_hash = $history_item->getCommitIdentifier(); 243 + 244 + $items[] = array( 245 + 'epoch' => $history_item->getEpoch(), 246 + 'hash' => $commit_hash, 247 + 'commit' => idx($commit_map, $commit_hash), 248 + ); 249 + } 250 + } else { 251 + foreach ($commits as $commit) { 252 + $items[] = array( 253 + 'epoch' => $commit->getEpoch(), 254 + 'hash' => $commit->getCommitIdentifier(), 255 + 'commit' => $commit, 256 + ); 257 + } 258 + } 259 + 260 + return $items; 261 + } 262 + 263 + private function getCommitDescription($commit) { 264 + if (!$commit) { 265 + return phutil_tag('em', array(), pht("Discovering\xE2\x80\xA6")); 266 + } 267 + 268 + // We can show details once the message and change have been imported. 269 + $partial_import = PhabricatorRepositoryCommit::IMPORTED_MESSAGE | 270 + PhabricatorRepositoryCommit::IMPORTED_CHANGE; 271 + if (!$commit->isPartiallyImported($partial_import)) { 272 + return phutil_tag('em', array(), pht("Importing\xE2\x80\xA6")); 273 + } 274 + 275 + return $commit->getCommitData()->getSummary(); 276 + } 277 + 278 + private function getCommitURI($commit, $hash) { 279 + $repository = $this->getRepository(); 280 + 281 + if ($repository) { 282 + return $repository->getCommitURI($hash); 283 + } 284 + 285 + return $commit->getURI(); 286 + } 287 + 288 + private function getCommitObjectName($commit, $hash) { 289 + $repository = $this->getRepository(); 290 + 291 + if ($repository) { 292 + return $repository->formatCommitName( 293 + $hash, 294 + $is_local = true); 295 + } 296 + 297 + return $commit->getDisplayName(); 298 + } 299 + 300 + private function getCommitIsDisabled($commit) { 301 + if (!$commit) { 302 + return true; 303 + } 304 + 305 + if ($commit->isUnreachable()) { 306 + return true; 307 + } 308 + 309 + return false; 310 + } 311 + 312 + private function getCommitAuthorView($commit) { 313 + if (!$commit) { 314 + return null; 315 + } 316 + 317 + $viewer = $this->getViewer(); 318 + 319 + return $commit->newCommitAuthorView($viewer); 320 + } 321 + 322 + private function newBrowseButton($hash) { 323 + $commit = $this->getCommit($hash); 324 + 325 + return $this->linkBrowse( 326 + '/', 327 + array( 328 + 'commit' => $hash, 329 + ), 330 + $as_button = true); 331 + } 332 + 333 + private function getCommit($hash) { 334 + $commit_map = $this->getCommitMap(); 335 + return idx($commit_map, $hash); 336 + } 337 + 338 + private function getCommitMap() { 339 + return $this->commitMap; 340 + } 341 + 342 + private function newBuildView($hash) { 343 + $commit = $this->getCommit($hash); 344 + if (!$commit) { 345 + return null; 346 + } 347 + 348 + $buildable = $this->getBuildable($commit); 349 + if (!$buildable) { 350 + return null; 351 + } 352 + 353 + return $this->renderBuildable($buildable, 'button'); 354 + } 355 + 356 + private function getBuildable(PhabricatorRepositoryCommit $commit) { 357 + $buildable_map = $this->getBuildableMap(); 358 + return idx($buildable_map, $commit->getPHID()); 359 + } 360 + 361 + private function getBuildableMap() { 362 + if ($this->buildableMap === null) { 363 + $commits = $this->getCommits(); 364 + $buildables = $this->loadBuildables($commits); 365 + $this->buildableMap = $buildables; 366 + } 367 + 368 + return $this->buildableMap; 369 + } 370 + 371 + private function newRevisionView($hash) { 372 + $commit = $this->getCommit($hash); 373 + if (!$commit) { 374 + return null; 375 + } 376 + 377 + $revisions = $this->getRevisions($commit); 378 + if (!$revisions) { 379 + return null; 380 + } 381 + 382 + $revision = head($revisions); 383 + 384 + return id(new PHUITagView()) 385 + ->setName($revision->getMonogram()) 386 + ->setType(PHUITagView::TYPE_SHADE) 387 + ->setColor(PHUITagView::COLOR_BLUE) 388 + ->setHref($revision->getURI()) 389 + ->setBorder(PHUITagView::BORDER_NONE) 390 + ->setSlimShady(true); 391 + } 392 + 393 + private function getRevisions(PhabricatorRepositoryCommit $commit) { 394 + $revision_map = $this->getRevisionMap(); 395 + return idx($revision_map, $commit->getPHID(), array()); 396 + } 397 + 398 + private function getRevisionMap() { 399 + if ($this->revisionMap === null) { 400 + $this->revisionMap = $this->newRevisionMap(); 401 + } 402 + 403 + return $this->revisionMap; 404 + } 405 + 406 + private function newRevisionMap() { 407 + $viewer = $this->getViewer(); 408 + $commits = $this->getCommits(); 409 + 410 + return DiffusionCommitRevisionQuery::loadRevisionMapForCommits( 411 + $viewer, 412 + $commits); 413 + } 414 + 415 + }
-172
src/applications/diffusion/view/DiffusionHistoryListView.php
··· 1 - <?php 2 - 3 - final class DiffusionHistoryListView extends DiffusionHistoryView { 4 - 5 - public function render() { 6 - $drequest = $this->getDiffusionRequest(); 7 - $viewer = $this->getUser(); 8 - $repository = $drequest->getRepository(); 9 - 10 - require_celerity_resource('diffusion-css'); 11 - Javelin::initBehavior('phabricator-tooltips'); 12 - 13 - $buildables = $this->loadBuildables( 14 - mpull($this->getHistory(), 'getCommit')); 15 - 16 - $show_revisions = PhabricatorApplication::isClassInstalledForViewer( 17 - 'PhabricatorDifferentialApplication', 18 - $viewer); 19 - 20 - $handles = $viewer->loadHandles($this->getRequiredHandlePHIDs()); 21 - 22 - $show_builds = PhabricatorApplication::isClassInstalledForViewer( 23 - 'PhabricatorHarbormasterApplication', 24 - $this->getUser()); 25 - 26 - $cur_date = null; 27 - $view = array(); 28 - foreach ($this->getHistory() as $history) { 29 - $epoch = $history->getEpoch(); 30 - $new_date = phabricator_date($history->getEpoch(), $viewer); 31 - if ($cur_date !== $new_date) { 32 - $date = ucfirst( 33 - phabricator_relative_date($history->getEpoch(), $viewer)); 34 - $header = id(new PHUIHeaderView()) 35 - ->setHeader($date); 36 - $list = id(new PHUIObjectItemListView()) 37 - ->setFlush(true) 38 - ->addClass('diffusion-history-list'); 39 - 40 - $view[] = id(new PHUIObjectBoxView()) 41 - ->setHeader($header) 42 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 43 - ->addClass('diffusion-mobile-view') 44 - ->setObjectList($list); 45 - } 46 - 47 - if ($epoch) { 48 - $committed = $viewer->formatShortDateTime($epoch); 49 - } else { 50 - $committed = null; 51 - } 52 - 53 - $data = $history->getCommitData(); 54 - $author_phid = $committer = $committer_phid = null; 55 - if ($data) { 56 - $author_phid = $data->getCommitDetail('authorPHID'); 57 - $committer_phid = $data->getCommitDetail('committerPHID'); 58 - $committer = $data->getCommitDetail('committer'); 59 - } 60 - 61 - if ($author_phid && isset($handles[$author_phid])) { 62 - $author_name = $handles[$author_phid]->renderLink(); 63 - $author_image = $handles[$author_phid]->getImageURI(); 64 - } else { 65 - $author_name = self::renderName($history->getAuthorName()); 66 - $author_image = 67 - celerity_get_resource_uri('/rsrc/image/people/user0.png'); 68 - } 69 - 70 - $different_committer = false; 71 - if ($committer_phid) { 72 - $different_committer = ($committer_phid != $author_phid); 73 - } else if ($committer != '') { 74 - $different_committer = ($committer != $history->getAuthorName()); 75 - } 76 - if ($different_committer) { 77 - if ($committer_phid && isset($handles[$committer_phid])) { 78 - $committer = $handles[$committer_phid]->renderLink(); 79 - } else { 80 - $committer = self::renderName($committer); 81 - } 82 - $author_name = hsprintf('%s / %s', $author_name, $committer); 83 - } 84 - 85 - // We can show details once the message and change have been imported. 86 - $partial_import = PhabricatorRepositoryCommit::IMPORTED_MESSAGE | 87 - PhabricatorRepositoryCommit::IMPORTED_CHANGE; 88 - 89 - $commit = $history->getCommit(); 90 - if ($commit && $commit->isPartiallyImported($partial_import) && $data) { 91 - $commit_desc = $history->getSummary(); 92 - } else { 93 - $commit_desc = phutil_tag('em', array(), pht("Importing\xE2\x80\xA6")); 94 - } 95 - 96 - $browse_button = $this->linkBrowse( 97 - $history->getPath(), 98 - array( 99 - 'commit' => $history->getCommitIdentifier(), 100 - 'branch' => $drequest->getBranch(), 101 - 'type' => $history->getFileType(), 102 - ), 103 - true); 104 - 105 - $diff_tag = null; 106 - if ($show_revisions && $commit) { 107 - $revisions = $this->getRevisionsForCommit($commit); 108 - if ($revisions) { 109 - $revision = head($revisions); 110 - $diff_tag = id(new PHUITagView()) 111 - ->setName($revision->getMonogram()) 112 - ->setType(PHUITagView::TYPE_SHADE) 113 - ->setColor(PHUITagView::COLOR_BLUE) 114 - ->setHref($revision->getURI()) 115 - ->setBorder(PHUITagView::BORDER_NONE) 116 - ->setSlimShady(true); 117 - } 118 - } 119 - 120 - $build_view = null; 121 - if ($show_builds) { 122 - $buildable = idx($buildables, $commit->getPHID()); 123 - if ($buildable !== null) { 124 - $build_view = $this->renderBuildable($buildable, 'button'); 125 - } 126 - } 127 - 128 - $message = null; 129 - $commit_link = $repository->getCommitURI( 130 - $history->getCommitIdentifier()); 131 - 132 - $commit_name = $repository->formatCommitName( 133 - $history->getCommitIdentifier(), $local = true); 134 - 135 - $committed = phabricator_datetime($commit->getEpoch(), $viewer); 136 - $author_name = phutil_tag( 137 - 'strong', 138 - array( 139 - 'class' => 'diffusion-history-author-name', 140 - ), 141 - $author_name); 142 - $authored = pht('%s on %s.', $author_name, $committed); 143 - 144 - $commit_tag = id(new PHUITagView()) 145 - ->setName($commit_name) 146 - ->setType(PHUITagView::TYPE_SHADE) 147 - ->setColor(PHUITagView::COLOR_INDIGO) 148 - ->setBorder(PHUITagView::BORDER_NONE) 149 - ->setSlimShady(true); 150 - 151 - $item = id(new PHUIObjectItemView()) 152 - ->setHeader($commit_desc) 153 - ->setHref($commit_link) 154 - ->setDisabled($commit->isUnreachable()) 155 - ->setDescription($message) 156 - ->setImageURI($author_image) 157 - ->addAttribute(array($commit_tag, ' ', $diff_tag)) // For Copy Pasta 158 - ->addAttribute($authored) 159 - ->setSideColumn(array( 160 - $build_view, 161 - $browse_button, 162 - )); 163 - 164 - $list->addItem($item); 165 - $cur_date = $new_date; 166 - } 167 - 168 - 169 - return $view; 170 - } 171 - 172 - }