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

Provide a rough, unstable API for reporting coverage into Diffusion

Summary:
Ref T4994. This stuff works:

- You can dump a blob of coverage information into `diffusion.updatecoverage`. This wipes existing coverage information and replaces it.
- It shows up when viewing files.
- It shows up when viewing commits.

This stuff does not work:

- When viewing files, the Javascript hover interaction isn't tied in yet.
- We always show this information, even if you're behind the commit where it was generated.
- You can't do incremental updates.
- There's no aggregation at the file (this file has 90% coverage), diff (the changes in this commit are 90% covered), or directory (the code in this directory has 90% coverage) levels yet.
- This is probably not the final form of the UI, storage, or API, so you should expect occasional changes over time. I've marked the method as "Unstable" for now.

Test Plan:
- Ran `save_lint.php` to check for collateral damage; it worked fine.
- Ran `save_lint.php` on a new branch to check creation.
- Published some fake coverage information.
- Viewed an affected commit.
- Viewed an affected file.

{F151915}

{F151916}

Reviewers: chad, btrahan

Reviewed By: btrahan

Subscribers: jhurwitz, epriestley, zeeg

Maniphest Tasks: T5044, T4994

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

+226 -21
+3 -3
resources/celerity/map.php
··· 10 10 'core.pkg.css' => '59ea1706', 11 11 'core.pkg.js' => 'b2ed04a2', 12 12 'darkconsole.pkg.js' => 'ca8671ce', 13 - 'differential.pkg.css' => '4b8686e3', 13 + 'differential.pkg.css' => '382ca868', 14 14 'differential.pkg.js' => '36bec171', 15 15 'diffusion.pkg.css' => '3783278d', 16 16 'diffusion.pkg.js' => '077e3ad0', ··· 55 55 'rsrc/css/application/dashboard/dashboard.css' => '2b41640b', 56 56 'rsrc/css/application/diff/inline-comment-summary.css' => '8cfd34e8', 57 57 'rsrc/css/application/differential/add-comment.css' => 'c478bcaa', 58 - 'rsrc/css/application/differential/changeset-view.css' => '1570a1ff', 58 + 'rsrc/css/application/differential/changeset-view.css' => 'c45747f0', 59 59 'rsrc/css/application/differential/core.css' => '7ac3cabc', 60 60 'rsrc/css/application/differential/results-table.css' => '239924f9', 61 61 'rsrc/css/application/differential/revision-comment.css' => '48186045', ··· 514 514 'conpherence-notification-css' => '403cf598', 515 515 'conpherence-update-css' => '1099a660', 516 516 'conpherence-widget-pane-css' => 'bf275a6c', 517 - 'differential-changeset-view-css' => '1570a1ff', 517 + 'differential-changeset-view-css' => 'c45747f0', 518 518 'differential-core-view-css' => '7ac3cabc', 519 519 'differential-inline-comment-editor' => 'f2441746', 520 520 'differential-results-table-css' => '239924f9',
+8
resources/sql/autopatches/20140509.coverage.1.sql
··· 1 + CREATE TABLE {$NAMESPACE}_repository.repository_coverage ( 2 + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 + branchID INT UNSIGNED NOT NULL, 4 + commitID INT UNSIGNED NOT NULL, 5 + pathID INT UNSIGNED NOT NULL, 6 + coverage LONGTEXT NOT NULL COLLATE latin1_bin, 7 + KEY `key_path` (branchID, pathID, commitID) 8 + ) ENGINE=InnoDB, COLLATE utf8_general_ci;
+2
src/__phutil_library_map__.php
··· 178 178 'ConduitAPI_diffusion_resolverefs_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_resolverefs_Method.php', 179 179 'ConduitAPI_diffusion_searchquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_searchquery_Method.php', 180 180 'ConduitAPI_diffusion_tagsquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_tagsquery_Method.php', 181 + 'ConduitAPI_diffusion_updatecoverage_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_updatecoverage_Method.php', 181 182 'ConduitAPI_feed_Method' => 'applications/feed/conduit/ConduitAPI_feed_Method.php', 182 183 'ConduitAPI_feed_publish_Method' => 'applications/feed/conduit/ConduitAPI_feed_publish_Method.php', 183 184 'ConduitAPI_feed_query_Method' => 'applications/feed/conduit/ConduitAPI_feed_query_Method.php', ··· 2838 2839 'ConduitAPI_diffusion_resolverefs_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 2839 2840 'ConduitAPI_diffusion_searchquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 2840 2841 'ConduitAPI_diffusion_tagsquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method', 2842 + 'ConduitAPI_diffusion_updatecoverage_Method' => 'ConduitAPI_diffusion_Method', 2841 2843 'ConduitAPI_feed_Method' => 'ConduitAPIMethod', 2842 2844 'ConduitAPI_feed_publish_Method' => 'ConduitAPI_feed_Method', 2843 2845 'ConduitAPI_feed_query_Method' => 'ConduitAPI_feed_Method',
+5 -10
src/applications/diffusion/DiffusionLintSaveRunner.php
··· 66 66 } 67 67 68 68 $branch_name = $api->getBranchName(); 69 - $this->branch = new PhabricatorRepositoryBranch(); 70 - $this->conn = $this->branch->establishConnection('w'); 71 - $this->branch = $this->branch->loadOneWhere( 72 - 'repositoryID = %d AND name = %s', 69 + 70 + $this->branch = PhabricatorRepositoryBranch::loadOrCreateBranch( 73 71 $project->getRepositoryID(), 74 72 $branch_name); 73 + $this->conn = $this->branch->establishConnection('w'); 75 74 76 75 $this->lintCommit = null; 77 - if (!$this->branch) { 78 - $this->branch = id(new PhabricatorRepositoryBranch()) 79 - ->setRepositoryID($project->getRepositoryID()) 80 - ->setName($branch_name) 81 - ->save(); 82 - } else if (!$this->all) { 76 + if (!$this->all) { 83 77 $this->lintCommit = $this->branch->getLintCommit(); 84 78 } 85 79 ··· 94 88 $this->lintCommit = null; 95 89 } 96 90 } 91 + 97 92 98 93 if (!$this->lintCommit) { 99 94 $where = ($this->svnRoot
+97
src/applications/diffusion/conduit/ConduitAPI_diffusion_updatecoverage_Method.php
··· 1 + <?php 2 + 3 + final class ConduitAPI_diffusion_updatecoverage_Method 4 + extends ConduitAPI_diffusion_Method { 5 + 6 + public function getMethodStatus() { 7 + return self::METHOD_STATUS_UNSTABLE; 8 + } 9 + 10 + public function getMethodDescription() { 11 + return pht('Publish coverage information for a repository.'); 12 + } 13 + 14 + public function defineReturnType() { 15 + return 'void'; 16 + } 17 + 18 + public function defineParamTypes() { 19 + return array( 20 + 'repositoryPHID' => 'required phid', 21 + 'branch' => 'required string', 22 + 'commit' => 'required string', 23 + 'coverage' => 'required map<string, string>', 24 + ); 25 + } 26 + 27 + public function defineErrorTypes() { 28 + return array(); 29 + } 30 + 31 + protected function execute(ConduitAPIRequest $request) { 32 + $viewer = $request->getUser(); 33 + 34 + $repository_phid = $request->getValue('repositoryPHID'); 35 + $repository = id(new PhabricatorRepositoryQuery()) 36 + ->setViewer($viewer) 37 + ->withPHIDs(array($repository_phid)) 38 + ->executeOne(); 39 + 40 + if (!$repository) { 41 + throw new Exception( 42 + pht('No repository exists with PHID "%s".', $repository_phid)); 43 + } 44 + 45 + $commit_name = $request->getValue('commit'); 46 + $commit = id(new DiffusionCommitQuery()) 47 + ->setViewer($viewer) 48 + ->withRepository($repository) 49 + ->withIdentifiers(array($commit_name)) 50 + ->executeOne(); 51 + if (!$commit) { 52 + throw new Exception( 53 + pht('No commit exists with identifier "%s".', $commit_name)); 54 + } 55 + 56 + $branch = PhabricatorRepositoryBranch::loadOrCreateBranch( 57 + $repository->getID(), 58 + $request->getValue('branch')); 59 + 60 + $coverage = $request->getValue('coverage'); 61 + $path_map = id(new DiffusionPathIDQuery(array_keys($coverage))) 62 + ->loadPathIDs(); 63 + 64 + $conn = $repository->establishConnection('w'); 65 + 66 + $sql = array(); 67 + foreach ($coverage as $path => $coverage_info) { 68 + $sql[] = qsprintf( 69 + $conn, 70 + '(%d, %d, %d, %s)', 71 + $branch->getID(), 72 + $path_map[$path], 73 + $commit->getID(), 74 + $coverage_info); 75 + } 76 + 77 + $table_name = 'repository_coverage'; 78 + 79 + $conn->openTransaction(); 80 + queryfx( 81 + $conn, 82 + 'DELETE FROM %T WHERE branchID = %d', 83 + $table_name, 84 + $branch->getID()); 85 + 86 + foreach (PhabricatorLiskDAO::chunkSQL($sql) as $chunk) { 87 + queryfx( 88 + $conn, 89 + 'INSERT INTO %T (branchID, pathID, commitID, coverage) VALUES %Q', 90 + $table_name, 91 + $chunk); 92 + } 93 + $conn->saveTransaction(); 94 + } 95 + 96 + 97 + }
+43 -4
src/applications/diffusion/controller/DiffusionBrowseFileController.php
··· 4 4 5 5 private $lintCommit; 6 6 private $lintMessages; 7 + private $coverage; 7 8 8 9 public function processRequest() { 9 10 $request = $this->getRequest(); ··· 68 69 } 69 70 70 71 $this->loadLintMessages(); 72 + $this->coverage = $drequest->loadCoverage(); 71 73 72 74 $binary_uri = null; 73 75 if (ArcanistDiffUtils::isHeuristicBinaryFile($data)) { ··· 625 627 626 628 $rows = $this->renderInlines( 627 629 idx($inlines, 0, array()), 628 - ($show_blame), 630 + $show_blame, 631 + (bool)$this->coverage, 629 632 $engine); 630 633 631 634 foreach ($display as $line) { ··· 789 792 phutil_safe_html(str_replace("\t", ' ', $line['data'])), 790 793 )); 791 794 795 + if ($this->coverage) { 796 + require_celerity_resource('differential-changeset-view-css'); 797 + $cov_index = $line['line'] - 1; 798 + 799 + if (isset($this->coverage[$cov_index])) { 800 + $cov_class = $this->coverage[$cov_index]; 801 + } else { 802 + $cov_class = 'N'; 803 + } 804 + 805 + $blame[] = phutil_tag( 806 + 'td', 807 + array( 808 + 'class' => 'cov cov-'.$cov_class, 809 + ), 810 + ''); 811 + } 812 + 792 813 $rows[] = phutil_tag( 793 814 'tr', 794 815 array( ··· 800 821 801 822 $cur_inlines = $this->renderInlines( 802 823 idx($inlines, $line['line'], array()), 803 - ($show_blame), 824 + $show_blame, 825 + $this->coverage, 804 826 $engine); 805 827 foreach ($cur_inlines as $cur_inline) { 806 828 $rows[] = $cur_inline; ··· 810 832 return $rows; 811 833 } 812 834 813 - private function renderInlines(array $inlines, $needs_blame, $engine) { 835 + private function renderInlines( 836 + array $inlines, 837 + $needs_blame, 838 + $has_coverage, 839 + $engine) { 840 + 814 841 $rows = array(); 815 842 foreach ($inlines as $inline) { 816 843 $inline_view = id(new DifferentialInlineCommentView()) 817 844 ->setMarkupEngine($engine) 818 845 ->setInlineComment($inline) 819 846 ->render(); 820 - $row = array_fill(0, ($needs_blame ? 5 : 1), phutil_tag('th')); 847 + 848 + $row = array_fill(0, ($needs_blame ? 3 : 1), phutil_tag('th')); 849 + 821 850 $row[] = phutil_tag('td', array(), $inline_view); 851 + 852 + if ($has_coverage) { 853 + $row[] = phutil_tag( 854 + 'td', 855 + array( 856 + 'class' => 'cov cov-I', 857 + )); 858 + } 859 + 822 860 $rows[] = phutil_tag('tr', array('class' => 'inline'), $row); 823 861 } 862 + 824 863 return $rows; 825 864 } 826 865
+5
src/applications/diffusion/controller/DiffusionDiffController.php
··· 68 68 array( 69 69 'action' => 'rendering-ref'))); 70 70 71 + $coverage = $drequest->loadCoverage(); 72 + if ($coverage) { 73 + $parser->setCoverage($coverage); 74 + } 75 + 71 76 $pquery = new DiffusionPathIDQuery(array($changeset->getFilename())); 72 77 $ids = $pquery->loadPathIDs(); 73 78 $path_id = $ids[$changeset->getFilename()];
+36 -4
src/applications/diffusion/request/DiffusionRequest.php
··· 26 26 27 27 private $initFromConduit = true; 28 28 private $user; 29 + private $branchObject = false; 29 30 30 31 abstract protected function getSupportsBranches(); 31 32 abstract protected function isStableCommit($symbol); ··· 338 339 } 339 340 340 341 public function loadBranch() { 341 - return id(new PhabricatorRepositoryBranch())->loadOneWhere( 342 - 'repositoryID = %d AND name = %s', 343 - $this->getRepository()->getID(), 344 - $this->getArcanistBranch()); 342 + // TODO: Get rid of this and do real Queries on real objects. 343 + 344 + if ($this->branchObject === false) { 345 + $this->branchObject = PhabricatorRepositoryBranch::loadBranch( 346 + $this->getRepository()->getID(), 347 + $this->getArcanistBranch()); 348 + } 349 + 350 + return $this->branchObject; 351 + } 352 + 353 + public function loadCoverage() { 354 + // TODO: This should also die. 355 + $branch = $this->loadBranch(); 356 + if (!$branch) { 357 + return; 358 + } 359 + 360 + $path = $this->getPath(); 361 + $path_map = id(new DiffusionPathIDQuery(array($path)))->loadPathIDs(); 362 + 363 + $coverage_row = queryfx_one( 364 + id(new PhabricatorRepository())->establishConnection('r'), 365 + 'SELECT * FROM %T WHERE branchID = %d AND pathID = %d 366 + ORDER BY commitID DESC LIMIT 1', 367 + 'repository_coverage', 368 + $branch->getID(), 369 + $path_map[$path]); 370 + 371 + if (!$coverage_row) { 372 + return null; 373 + } 374 + 375 + return idx($coverage_row, 'coverage'); 345 376 } 377 + 346 378 347 379 public function loadCommit() { 348 380 if (empty($this->repositoryCommit)) {
+19
src/applications/repository/storage/PhabricatorRepositoryBranch.php
··· 6 6 protected $name; 7 7 protected $lintCommit; 8 8 9 + public static function loadBranch($repository_id, $branch_name) { 10 + return id(new PhabricatorRepositoryBranch())->loadOneWhere( 11 + 'repositoryID = %d AND name = %s', 12 + $repository_id, 13 + $branch_name); 14 + } 15 + 16 + public static function loadOrCreateBranch($repository_id, $branch_name) { 17 + $branch = self::loadBranch($repository_id, $branch_name); 18 + if ($branch) { 19 + return $branch; 20 + } 21 + 22 + return id(new PhabricatorRepositoryBranch()) 23 + ->setRepositoryID($repository_id) 24 + ->setName($branch_name) 25 + ->save(); 26 + } 27 + 9 28 }
+8
webroot/rsrc/css/application/differential/changeset-view.css
··· 136 136 padding: 0; 137 137 } 138 138 139 + .diffusion-source td.cov { 140 + padding: 0 8px; 141 + } 142 + 139 143 td.cov-U { 140 144 background: #dd8866; 141 145 } ··· 150 154 151 155 td.cov-X { 152 156 background: #aa00aa; 157 + } 158 + 159 + td.cov-I { 160 + background: {$lightgreybackground}; 153 161 } 154 162 155 163 .differential-diff td.source-cov-C,