diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -149,7 +149,7 @@ 'rsrc/css/phui/phui-profile-menu.css' => '7e92a89a', 'rsrc/css/phui/phui-property-list-view.css' => '27b2849e', 'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591', - 'rsrc/css/phui/phui-segment-bar-view.css' => '46342871', + 'rsrc/css/phui/phui-segment-bar-view.css' => '8ce8eba3', 'rsrc/css/phui/phui-spacing.css' => '042804d6', 'rsrc/css/phui/phui-status.css' => '888cedb8', 'rsrc/css/phui/phui-tag-view.css' => '9d5d4400', @@ -835,7 +835,7 @@ 'phui-profile-menu-css' => '7e92a89a', 'phui-property-list-view-css' => '27b2849e', 'phui-remarkup-preview-css' => '1a8f2591', - 'phui-segment-bar-view-css' => '46342871', + 'phui-segment-bar-view-css' => '8ce8eba3', 'phui-spacing-css' => '042804d6', 'phui-status-list-view-css' => '888cedb8', 'phui-tag-view-css' => '9d5d4400', diff --git a/src/applications/diffusion/controller/DiffusionLastModifiedController.php b/src/applications/diffusion/controller/DiffusionLastModifiedController.php --- a/src/applications/diffusion/controller/DiffusionLastModifiedController.php +++ b/src/applications/diffusion/controller/DiffusionLastModifiedController.php @@ -71,8 +71,11 @@ } $lint = $lint_query->execute(); + + $coverage = $this->loadCoverageForPaths($branch, array_keys($commits)); } else { $lint = array(); + $coverage = array(); } $output = array(); @@ -84,7 +87,8 @@ $prequest, $handles, $commit, - idx($lint, $path)); + idx($lint, $path), + idx($coverage, $path)); } return id(new AphrontAjaxResponse())->setContent($output); @@ -94,7 +98,8 @@ DiffusionRequest $drequest, array $handles, PhabricatorRepositoryCommit $commit = null, - $lint = null) { + $lint = null, + $coverage = null) { assert_instances_of($handles, 'PhabricatorObjectHandle'); $viewer = $this->getRequest()->getUser(); @@ -156,6 +161,10 @@ number_format($lint)); } + if ($coverage !== null) { + $return['coverage'] = $coverage; + } + // The client treats these results as markup, so make sure they have been // escaped correctly. foreach ($return as $key => $value) { @@ -165,4 +174,113 @@ return $return; } + private function loadCoverageForPaths($branch, array $paths) { + if (!$paths) { + return array(); + } + + $drequest = $this->getDiffusionRequest(); + $commit = $drequest->loadCommit(); + + $path_map = id(new DiffusionPathIDQuery($paths)) + ->loadPathIDs(); + $path_map = array_flip($path_map); + + $coverage_rows = queryfx_all( + id(new PhabricatorRepository())->establishConnection('r'), + 'SELECT * FROM %T + WHERE branchID = %d + AND pathID IN (%Ld) + AND commitID = %d', + PhabricatorRepository::TABLE_COVERAGE, + $branch->getID(), + array_keys($path_map), + $commit->getID()); + + $coverage_map = array(); + foreach ($coverage_rows as $coverage_row) { + if (empty($path_map[$coverage_row['pathID']])) { + continue; + } + + $covered_path = $path_map[$coverage_row['pathID']]; + $coverage_map[$covered_path] = $coverage_row['coverage']; + } + + if (!$coverage_map) { + return array(); + } + + $maximum = 0; + $grand_total = 0; + foreach ($coverage_map as $path => $coverage) { + $stats = $this->getCoverageStatistics($coverage); + $maximum = max($maximum, $stats['U'] + $stats['C']); + $grand_total += $stats['U'] + $stats['C']; + $coverage_map[$path] = $stats; + } + + $log_base = 3; + $log_maximum = log($maximum + 1, $log_base); + + $coverage_bars = array(); + foreach ($coverage_map as $path => $stats) { + $total = $stats['U'] + $stats['C']; + $log_total = log($total + 1, $log_base); + + $bar_size = $log_total / $log_maximum; + $bar_full = $stats['C'] / $total; + + $tip = pht( + "%s / %s Lines\n%s of Total Lines\n%s Covered", + new PhutilNumber($stats['C']), + new PhutilNumber($total), + sprintf('%.1f%%', 100 * ($total / $grand_total)), + sprintf('%.1f%%', 100 * $bar_full)); + + $bar = new PHUISegmentBarView(); + + $bar->newSegment() + ->setWidth($bar_full) + ->setColor('blue'); + + $coverage_bars[$path] = javelin_tag( + 'div', + array( + 'class' => 'diffusion-coverage', + 'style' => sprintf('width: %.2f%%', 100 * $bar_size), + 'sigil' => 'has-tooltip', + 'meta' => array( + 'tip' => $tip, + 'align' => 'E', + 'size' => 300, + ), + ), + $bar); + } + + return $coverage_bars; + } + + private function getCoverageStatistics($coverage) { + $defaults = array( + 'U' => 0, + 'C' => 0, + ); + + // If this is JSON-encoded aggregate data, we're just going to decode it. + if (!strncmp($coverage, '+J', 2)) { + $stats = phutil_json_decode(substr($coverage, 2)); + return $stats + $defaults; + } + + // Otherwise, count the lines. + $map = array(); + foreach ($defaults as $char => $count) { + $map[$char] = substr_count($coverage, $char); + } + + return $map; + } + } diff --git a/src/applications/diffusion/view/DiffusionBrowseTableView.php b/src/applications/diffusion/view/DiffusionBrowseTableView.php --- a/src/applications/diffusion/view/DiffusionBrowseTableView.php +++ b/src/applications/diffusion/view/DiffusionBrowseTableView.php @@ -74,6 +74,7 @@ $dict = array( 'lint' => celerity_generate_unique_node_id(), + 'coverage' => celerity_generate_unique_node_id(), 'commit' => celerity_generate_unique_node_id(), 'date' => celerity_generate_unique_node_id(), 'author' => celerity_generate_unique_node_id(), @@ -88,8 +89,9 @@ $rows[] = array( $history_link, $browse_link, - idx($dict, 'lint'), $dict['commit'], + idx($dict, 'lint'), + $dict['coverage'], $dict['author'], $dict['details'], $dict['date'], @@ -112,14 +114,16 @@ $branch = $this->getDiffusionRequest()->loadBranch(); $show_lint = ($branch && $branch->getLintCommit()); $lint = $request->getLint(); + $show_coverage = $this->getDiffusionRequest()->loadCoverage(); $view = new AphrontTableView($rows); $view->setHeaders( array( null, pht('Path'), - ($lint ? $lint : pht('Lint')), pht('Modified'), + ($lint ? $lint : pht('Lint')), + pht('Coverage'), pht('Author/Committer'), pht('Details'), pht('Committed'), @@ -131,6 +135,7 @@ '', '', '', + '', 'wide', '', )); @@ -138,8 +143,9 @@ array( true, true, - $show_lint, true, + $show_lint, + $show_coverage, true, true, true, @@ -149,9 +155,10 @@ array( true, true, - false, true, false, + false, + false, true, false, )); diff --git a/webroot/rsrc/css/phui/phui-segment-bar-view.css b/webroot/rsrc/css/phui/phui-segment-bar-view.css --- a/webroot/rsrc/css/phui/phui-segment-bar-view.css +++ b/webroot/rsrc/css/phui/phui-segment-bar-view.css @@ -21,6 +21,10 @@ height: 8px; } +.diffusion-coverage .phui-segment-bar-segments { + background: {$greyborder}; +} + .phui-segment-bar-segment-view { position: absolute; top: 0;