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

Improve "thread" rendering of unusually-shaped graphs

Summary:
Ref T4788. This fixes all the bugs I was immediately able to catch:

- "Directory-Like" graph shapes could draw too many vertical lines.
- "Reverse-Directory-Like" graph shapes could draw too few vertical lines.
- Terminated, branched graph shapes drew the very last line to the wrong place.

This covers the behavior with tests, so we should be able to fix more stuff later without breaking anything.

Test Plan:
- Added failing tests and made them pass.

{F1708158}

{F1708159}

{F1708160}

{F1708161}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T4788

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

+135 -14
+8 -8
resources/celerity/map.php
··· 13 13 'differential.pkg.css' => '3e81ae60', 14 14 'differential.pkg.js' => '634399e9', 15 15 'diffusion.pkg.css' => '91c5d3a6', 16 - 'diffusion.pkg.js' => '3a9a8bfa', 16 + 'diffusion.pkg.js' => '84c8f8fd', 17 17 'maniphest.pkg.css' => '4845691a', 18 18 'maniphest.pkg.js' => '949a7498', 19 19 'rsrc/css/aphront/aphront-bars.css' => '231ac33c', ··· 394 394 'rsrc/js/application/diffusion/DiffusionLocateFileSource.js' => 'b42eddc7', 395 395 'rsrc/js/application/diffusion/behavior-audit-preview.js' => 'd835b03a', 396 396 'rsrc/js/application/diffusion/behavior-commit-branches.js' => 'bdaf4d04', 397 - 'rsrc/js/application/diffusion/behavior-commit-graph.js' => '5a0b1a64', 397 + 'rsrc/js/application/diffusion/behavior-commit-graph.js' => '49ae8328', 398 398 'rsrc/js/application/diffusion/behavior-diffusion-browse-file.js' => '054a0f0b', 399 399 'rsrc/js/application/diffusion/behavior-jump-to.js' => '73d09eef', 400 400 'rsrc/js/application/diffusion/behavior-load-blame.js' => '42126667', ··· 619 619 'javelin-behavior-differential-user-select' => 'a8d8459d', 620 620 'javelin-behavior-diffusion-browse-file' => '054a0f0b', 621 621 'javelin-behavior-diffusion-commit-branches' => 'bdaf4d04', 622 - 'javelin-behavior-diffusion-commit-graph' => '5a0b1a64', 622 + 'javelin-behavior-diffusion-commit-graph' => '49ae8328', 623 623 'javelin-behavior-diffusion-jump-to' => '73d09eef', 624 624 'javelin-behavior-diffusion-locate-file' => '6d3e1947', 625 625 'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc', ··· 1217 1217 'javelin-uri', 1218 1218 'phabricator-notification', 1219 1219 ), 1220 + '49ae8328' => array( 1221 + 'javelin-behavior', 1222 + 'javelin-dom', 1223 + 'javelin-stratcom', 1224 + ), 1220 1225 '4b700e9e' => array( 1221 1226 'javelin-behavior', 1222 1227 'javelin-dom', ··· 1342 1347 'javelin-stratcom', 1343 1348 'javelin-vector', 1344 1349 'javelin-dom', 1345 - ), 1346 - '5a0b1a64' => array( 1347 - 'javelin-behavior', 1348 - 'javelin-dom', 1349 - 'javelin-stratcom', 1350 1350 ), 1351 1351 '5a13c79f' => array( 1352 1352 'javelin-install',
+2
src/__phutil_library_map__.php
··· 1602 1602 'PHUICurtainPanelView' => 'view/layout/PHUICurtainPanelView.php', 1603 1603 'PHUICurtainView' => 'view/layout/PHUICurtainView.php', 1604 1604 'PHUIDiffGraphView' => 'infrastructure/diff/view/PHUIDiffGraphView.php', 1605 + 'PHUIDiffGraphViewTestCase' => 'infrastructure/diff/view/__tests__/PHUIDiffGraphViewTestCase.php', 1605 1606 'PHUIDiffInlineCommentDetailView' => 'infrastructure/diff/view/PHUIDiffInlineCommentDetailView.php', 1606 1607 'PHUIDiffInlineCommentEditView' => 'infrastructure/diff/view/PHUIDiffInlineCommentEditView.php', 1607 1608 'PHUIDiffInlineCommentRowScaffold' => 'infrastructure/diff/view/PHUIDiffInlineCommentRowScaffold.php', ··· 6139 6140 'PHUICurtainPanelView' => 'AphrontTagView', 6140 6141 'PHUICurtainView' => 'AphrontTagView', 6141 6142 'PHUIDiffGraphView' => 'Phobject', 6143 + 'PHUIDiffGraphViewTestCase' => 'PhabricatorTestCase', 6142 6144 'PHUIDiffInlineCommentDetailView' => 'PHUIDiffInlineCommentView', 6143 6145 'PHUIDiffInlineCommentEditView' => 'PHUIDiffInlineCommentView', 6144 6146 'PHUIDiffInlineCommentRowScaffold' => 'AphrontView',
+29 -6
src/infrastructure/diff/view/PHUIDiffGraphView.php
··· 23 23 return $this->isTail; 24 24 } 25 25 26 - public function renderGraph(array $parents) { 26 + public function renderRawGraph(array $parents) { 27 27 // This keeps our accumulated information about each line of the 28 28 // merge/branch graph. 29 29 $graph = array(); ··· 47 47 $line = ''; 48 48 $found = false; 49 49 $pos = count($threads); 50 - for ($n = 0; $n < $count; $n++) { 50 + 51 + $thread_count = $pos; 52 + for ($n = 0; $n < $thread_count; $n++) { 53 + 51 54 if (empty($threads[$n])) { 52 55 $line .= ' '; 53 56 continue; ··· 147 150 $line = $graph[$key]['line']; 148 151 $len = strlen($line); 149 152 for ($ii = 0; $ii < $len; $ii++) { 150 - if (isset($terminated[$ii])) { 151 - continue; 152 - } 153 - 154 153 $c = $line[$ii]; 155 154 if ($c == 'o') { 155 + // If we've already terminated this thread, we don't need to add 156 + // a terminator. 157 + if (isset($terminated[$ii])) { 158 + continue; 159 + } 160 + 156 161 $terminated[$ii] = true; 162 + 163 + // If this thread is joinining some other node here, we don't want 164 + // to terminate it. 165 + if (isset($graph[$key + 1])) { 166 + $joins = $graph[$key + 1]['join']; 167 + if (in_array($ii, $joins)) { 168 + continue; 169 + } 170 + } 171 + 157 172 $graph[$key]['line'][$ii] = 'x'; 158 173 } else if ($c != ' ') { 159 174 $terminated[$ii] = true; 175 + } else { 176 + unset($terminated[$ii]); 160 177 } 161 178 } 162 179 } ··· 165 182 $last['line'] = str_replace('^', 'X', $last['line']); 166 183 $graph[] = $last; 167 184 } 185 + 186 + return array($graph, $count); 187 + } 188 + 189 + public function renderGraph(array $parents) { 190 + list($graph, $count) = $this->renderRawGraph($parents); 168 191 169 192 // Render into tags for the behavior. 170 193
+94
src/infrastructure/diff/view/__tests__/PHUIDiffGraphViewTestCase.php
··· 1 + <?php 2 + 3 + final class PHUIDiffGraphViewTestCase extends PhabricatorTestCase { 4 + 5 + public function testTailTermination() { 6 + $nodes = array( 7 + 'A' => array('B'), 8 + 'B' => array('C', 'D', 'E'), 9 + 'E' => array(), 10 + 'D' => array(), 11 + 'C' => array('F', 'G'), 12 + 'G' => array(), 13 + 'F' => array(), 14 + ); 15 + 16 + $graph = $this->newGraph($nodes); 17 + 18 + $picture = array( 19 + '^', 20 + 'o', 21 + '||x', 22 + '|x ', 23 + 'o ', 24 + '|x ', 25 + 'x ', 26 + ); 27 + 28 + $this->assertGraph($picture, $graph, pht('Terminating Tree')); 29 + } 30 + 31 + public function testReverseTree() { 32 + $nodes = array( 33 + 'A' => array('B'), 34 + 'C' => array('B'), 35 + 'B' => array('D'), 36 + 'E' => array('D'), 37 + 'F' => array('D'), 38 + 'D' => array('G'), 39 + 'G' => array(), 40 + ); 41 + 42 + $graph = $this->newGraph($nodes); 43 + 44 + $picture = array( 45 + '^', 46 + '|^', 47 + 'o ', 48 + '|^', 49 + '||^', 50 + 'o ', 51 + 'x', 52 + ); 53 + 54 + $this->assertGraph($picture, $graph, pht('Reverse Tree')); 55 + } 56 + 57 + public function testJoinTerminateTree() { 58 + $nodes = array( 59 + 'A' => array('D'), 60 + 'B' => array('C'), 61 + 'C' => array('D'), 62 + 'D' => array(), 63 + ); 64 + 65 + $graph = $this->newGraph($nodes); 66 + 67 + $picture = array( 68 + '^', 69 + '|^', 70 + '|o', 71 + 'x ', 72 + ); 73 + 74 + $this->assertGraph($picture, $graph, pht('Reverse Tree')); 75 + } 76 + 77 + private function newGraph(array $nodes) { 78 + return id(new PHUIDiffGraphView()) 79 + ->setIsHead(true) 80 + ->setIsTail(true) 81 + ->renderRawGraph($nodes); 82 + } 83 + 84 + private function assertGraph($picture, $graph, $label) { 85 + list($data, $count) = $graph; 86 + $lines = ipull($data, 'line'); 87 + 88 + $picture = implode("\n", $picture); 89 + $lines = implode("\n", $lines); 90 + 91 + $this->assertEqual($picture, $lines, $label); 92 + } 93 + 94 + }
+2
webroot/rsrc/js/application/diffusion/behavior-commit-graph.js
··· 79 79 c = data.line.charAt(jj); 80 80 switch (c) { 81 81 case 'o': 82 + case 'x': 82 83 case '^': 83 84 origin = xpos(jj); 84 85 break; ··· 91 92 for (jj = 0; jj < data.join.length; jj++) { 92 93 var join = data.join[jj]; 93 94 x = xpos(join); 95 + 94 96 cxt.beginPath(); 95 97 cxt.moveTo(x, 0); 96 98 cxt.bezierCurveTo(x, h/4, origin, h/4, origin, h/2);