diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -994,6 +994,7 @@ 'phutil_loggable_string' => 'utils/utils.php', 'phutil_microseconds_since' => 'utils/utils.php', 'phutil_parse_bytes' => 'utils/viewutils.php', + 'phutil_partition' => 'utils/utils.php', 'phutil_passthru' => 'future/exec/execx.php', 'phutil_person' => 'internationalization/pht.php', 'phutil_register_library' => 'init/lib/core.php', 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 @@ -169,41 +169,43 @@ ); } - $marker_layout = array(); + $items = array(); foreach ($object_layout as $layout) { $commit_ref = idx($layout, 'commit'); if (!$commit_ref) { - $marker_layout[] = $layout; + $items[] = $layout; continue; } $commit_hash = $commit_ref->getCommitHash(); $markers = idx($marker_refs, $commit_hash); if (!$markers) { - $marker_layout[] = $layout; + $items[] = $layout; continue; } $head_marker = array_shift($markers); $layout['marker'] = $head_marker; - $marker_layout[] = $layout; + $items[] = $layout; if (!$markers) { continue; } foreach ($markers as $marker) { - $marker_layout[] = array( + $items[] = array( 'marker' => $marker, ); } } - $marker_view = $this->drawMarkerCell($marker_layout); - $commits_view = $this->drawCommitsCell($marker_layout); - $status_view = $this->drawStatusCell($marker_layout); - $revisions_view = $this->drawRevisionsCell($marker_layout); - $messages_view = $this->drawMessagesCell($marker_layout); + $items = $this->collapseItems($items); + + $marker_view = $this->drawMarkerCell($items); + $commits_view = $this->drawCommitsCell($items); + $status_view = $this->drawStatusCell($items); + $revisions_view = $this->drawRevisionsCell($items); + $messages_view = $this->drawMessagesCell($items); return array( id(new ArcanistGridCell()) @@ -311,6 +313,12 @@ private function drawCommitsCell(array $items) { $cell = array(); foreach ($items as $item) { + $count = idx($item, 'collapseCount'); + if ($count) { + $cell[] = tsprintf(" : \n"); + continue; + } + $commit_ref = idx($item, 'commit'); if (!$commit_ref) { $cell[] = tsprintf("\n"); @@ -361,6 +369,16 @@ $cell = array(); foreach ($items as $item) { + $count = idx($item, 'collapseCount'); + if ($count) { + $cell[] = tsprintf( + "%s\n", + pht( + '<... %s more commits ...>', + new PhutilNumber($count))); + continue; + } + $revision_ref = idx($item, 'revision'); if ($revision_ref) { $cell[] = tsprintf("%s\n", $revision_ref->getName()); @@ -415,5 +433,46 @@ return tsprintf('%s', $status); } + private function collapseItems(array $items) { + $show_context = 3; + + $map = array(); + foreach ($items as $key => $item) { + $can_collapse = + (isset($item['commit'])) && + (!isset($item['revision'])) && + (!isset($item['marker'])); + $map[$key] = $can_collapse; + } + + $map = phutil_partition($map); + foreach ($map as $partition) { + $value = head($partition); + + if (!$value) { + break; + } + + $count = count($partition); + if ($count < ($show_context * 2) + 3) { + continue; + } + + $partition = array_slice($partition, $show_context, -$show_context, true); + + $is_first = true; + foreach ($partition as $key => $value) { + if ($is_first) { + $items[$key]['collapseCount'] = $count; + } else { + unset($items[$key]); + } + + $is_first = false; + } + } + + return $items; + } } diff --git a/src/utils/__tests__/PhutilUtilsTestCase.php b/src/utils/__tests__/PhutilUtilsTestCase.php --- a/src/utils/__tests__/PhutilUtilsTestCase.php +++ b/src/utils/__tests__/PhutilUtilsTestCase.php @@ -966,4 +966,38 @@ } } + public function testArrayPartition() { + $map = array( + 'empty' => array( + array(), + array(), + ), + 'unique' => array( + array('a' => 'a', 'b' => 'b', 'c' => 'c'), + array(array('a' => 'a'), array('b' => 'b'), array('c' => 'c')), + ), + 'xy' => array( + array('a' => 'x', 'b' => 'x', 'c' => 'y', 'd' => 'y'), + array( + array('a' => 'x', 'b' => 'x'), + array('c' => 'y', 'd' => 'y'), + ), + ), + 'multi' => array( + array('a' => true, 'b' => true, 'c' => false, 'd' => true), + array( + array('a' => true, 'b' => true), + array('c' => false), + array('d' => true), + ), + ), + ); + + foreach ($map as $name => $item) { + list($input, $expect) = $item; + $actual = phutil_partition($input); + $this->assertEqual($expect, $actual, pht('Partition of "%s"', $name)); + } + } + } diff --git a/src/utils/utils.php b/src/utils/utils.php --- a/src/utils/utils.php +++ b/src/utils/utils.php @@ -1974,3 +1974,32 @@ return array_select_keys($tmp, $keys); } + +function phutil_partition(array $map) { + $partitions = array(); + + $partition = array(); + $is_first = true; + $partition_value = null; + + foreach ($map as $key => $value) { + if (!$is_first) { + if ($partition_value === $value) { + $partition[$key] = $value; + continue; + } + + $partitions[] = $partition; + } + + $is_first = false; + $partition = array($key => $value); + $partition_value = $value; + } + + if ($partition) { + $partitions[] = $partition; + } + + return $partitions; +}