diff --git a/src/repository/graph/view/ArcanistCommitGraphSetTreeView.php b/src/repository/graph/view/ArcanistCommitGraphSetTreeView.php --- a/src/repository/graph/view/ArcanistCommitGraphSetTreeView.php +++ b/src/repository/graph/view/ArcanistCommitGraphSetTreeView.php @@ -54,16 +54,6 @@ $view_root = $this->newSetViews($set); $view_list = $this->setViews; - foreach ($view_list as $view) { - $parent_view = $view->getParentView(); - if ($parent_view) { - $depth = $parent_view->getViewDepth() + 1; - } else { - $depth = 0; - } - $view->setViewDepth($depth); - } - $api = $this->getRepositoryAPI(); foreach ($view_list as $view) { @@ -81,6 +71,8 @@ ->setMarkerRefs($marker_refs); } + $view_list = $this->collapseViews($view_root, $view_list); + $rows = array(); foreach ($view_list as $view) { $rows[] = $view->newCellViews(); @@ -144,4 +136,111 @@ return $results; } + private function collapseViews($view_root, array $view_list) { + $this->groupViews($view_root); + + foreach ($view_list as $view) { + $group = $view->getGroupView(); + $group->addMemberView($view); + } + + foreach ($view_list as $view) { + $member_views = $view->getMemberViews(); + + // Break small groups apart. + $count = count($member_views); + if ($count > 1 && $count < 4) { + foreach ($member_views as $member_view) { + $member_view->setGroupView($member_view); + $member_view->setMemberViews(array($member_view)); + } + } + } + + foreach ($view_list as $view) { + $parent_view = $view->getParentView(); + if (!$parent_view) { + $depth = 0; + } else { + $parent_group = $parent_view->getGroupView(); + + $member_views = $parent_group->getMemberViews(); + if (count($member_views) > 1) { + $depth = $parent_group->getViewDepth() + 2; + } else { + $depth = $parent_group->getViewDepth() + 1; + } + } + + $view->setViewDepth($depth); + } + + foreach ($view_list as $key => $view) { + if (!$view->getMemberViews()) { + unset($view_list[$key]); + } + } + + return $view_list; + } + + private function groupViews($view) { + $group_view = $this->getGroupForView($view); + $view->setGroupView($group_view); + + + + $children = $view->getChildViews(); + foreach ($children as $child) { + $this->groupViews($child); + } + } + + private function getGroupForView($view) { + $revision_refs = $view->getRevisionRefs(); + if ($revision_refs) { + $has_unpublished_revision = false; + + foreach ($revision_refs as $revision_ref) { + if (!$revision_ref->isStatusPublished()) { + $has_unpublished_revision = true; + break; + } + } + + if ($has_unpublished_revision) { + return $view; + } + } + + $marker_lists = $view->getMarkerRefs(); + foreach ($marker_lists as $marker_refs) { + if ($marker_refs) { + return $view; + } + } + + // If a view has no children, it is never grouped with other views. + $children = $view->getChildViews(); + if (!$children) { + return $view; + } + + // If a view is a root, we can't group it. + $parent = $view->getParentView(); + if (!$parent) { + return $view; + } + + // If a view has siblings, we can't group it with other views. + $siblings = $parent->getChildViews(); + if (count($siblings) !== 1) { + return $view; + } + + // The view has no children and no other siblings, so add it to the + // parent's group. + return $parent->getGroupView(); + } + } diff --git a/src/repository/graph/view/ArcanistCommitGraphSetView.php b/src/repository/graph/view/ArcanistCommitGraphSetView.php --- a/src/repository/graph/view/ArcanistCommitGraphSetView.php +++ b/src/repository/graph/view/ArcanistCommitGraphSetView.php @@ -11,6 +11,8 @@ private $revisionRefs; private $markerRefs; private $viewDepth; + private $groupView; + private $memberViews = array(); public function setRepositoryAPI(ArcanistRepositoryAPI $repository_api) { $this->repositoryAPI = $repository_api; @@ -39,6 +41,29 @@ return $this->parentView; } + public function setGroupView(ArcanistCommitGraphSetView $group_view) { + $this->groupView = $group_view; + return $this; + } + + public function getGroupView() { + return $this->groupView; + } + + public function addMemberView(ArcanistCommitGraphSetView $member_view) { + $this->memberViews[] = $member_view; + return $this; + } + + public function getMemberViews() { + return $this->memberViews; + } + + public function setMemberViews(array $member_views) { + $this->memberViews = $member_views; + return $this; + } + public function addChildView(ArcanistCommitGraphSetView $child_view) { $this->childViews[] = $child_view; return $this; @@ -307,6 +332,17 @@ $is_first = false; } + $member_views = $this->getMemberViews(); + $member_count = count($member_views); + if ($member_count > 1) { + $cell[] = tsprintf( + "%s%s\n", + $empty_indent, + pht( + '- <... %s more revisions ...>', + new PhutilNumber($member_count - 1))); + } + return $cell; }