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

Use a hash-and-diff strategy to produce a diff layout for block-based documents

Summary:
Depends on D20835. Ref T13425. Ref T13414. When a document has a list of content blocks, we may not be able to diff it directly, but we can hash each block and then diff the hashes (internally "diff" also does approximately the same thing).

We could do this ourselves with slightly fewer layers of indirection, but: diff already exists; we already use it; we already have a bunch of abstractions on top of it; and it's likely much faster on large inputs than the best we can do in PHP.

Test Plan: {F6888169}

Maniphest Tasks: T13425, T13414

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

+115 -24
+6 -6
resources/celerity/map.php
··· 11 11 'conpherence.pkg.js' => '020aebcf', 12 12 'core.pkg.css' => '6a8c9533', 13 13 'core.pkg.js' => '6e5c894f', 14 - 'differential.pkg.css' => 'ce54994e', 14 + 'differential.pkg.css' => 'abd2c0d8', 15 15 'differential.pkg.js' => '68fa36fc', 16 16 'diffusion.pkg.css' => '42c75c37', 17 17 'diffusion.pkg.js' => 'a98c0bf7', ··· 61 61 'rsrc/css/application/dashboard/dashboard.css' => '5a205b9d', 62 62 'rsrc/css/application/diff/inline-comment-summary.css' => '81eb368d', 63 63 'rsrc/css/application/differential/add-comment.css' => '7e5900d9', 64 - 'rsrc/css/application/differential/changeset-view.css' => 'db306b82', 64 + 'rsrc/css/application/differential/changeset-view.css' => '5dda5e53', 65 65 'rsrc/css/application/differential/core.css' => '7300a73e', 66 66 'rsrc/css/application/differential/phui-inline-comment.css' => '48acce5b', 67 67 'rsrc/css/application/differential/revision-comment.css' => '7dbc8d1d', ··· 554 554 'conpherence-thread-manager' => 'aec8e38c', 555 555 'conpherence-transaction-css' => '3a3f5e7e', 556 556 'd3' => '9d068042', 557 - 'differential-changeset-view-css' => 'db306b82', 557 + 'differential-changeset-view-css' => '5dda5e53', 558 558 'differential-core-view-css' => '7300a73e', 559 559 'differential-revision-add-comment-css' => '7e5900d9', 560 560 'differential-revision-comment-css' => '7dbc8d1d', ··· 1457 1457 'javelin-dom', 1458 1458 'phuix-dropdown-menu', 1459 1459 ), 1460 + '5dda5e53' => array( 1461 + 'phui-inline-comment-view-css', 1462 + ), 1460 1463 '5faf27b9' => array( 1461 1464 'phuix-form-control-view', 1462 1465 ), ··· 2068 2071 'javelin-behavior', 2069 2072 'javelin-uri', 2070 2073 'phabricator-notification', 2071 - ), 2072 - 'db306b82' => array( 2073 - 'phui-inline-comment-view-css', 2074 2074 ), 2075 2075 'dfa1d313' => array( 2076 2076 'javelin-behavior',
+17 -2
src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php
··· 379 379 if ($old) { 380 380 $old_content = $old->newContentView(); 381 381 $old_key = $old->getBlockKey(); 382 - $old_classes = implode(' ', $old->getClasses()); 382 + 383 + $old_classes = $old->getClasses(); 384 + 385 + if ($old->getDifferenceType() === '-') { 386 + $old_classes[] = 'old'; 387 + $old_classes[] = 'old-full'; 388 + } 389 + 390 + $old_classes = implode(' ', $old_classes); 383 391 } else { 384 392 $old_content = null; 385 393 $old_key = null; ··· 389 397 if ($new) { 390 398 $new_content = $new->newContentView(); 391 399 $new_key = $new->getBlockKey(); 392 - $new_classes = implode(' ', $new->getClasses()); 400 + $new_classes = $new->getClasses(); 401 + 402 + if ($new->getDifferenceType() === '+') { 403 + $new_classes[] = 'new'; 404 + $new_classes[] = 'new-full'; 405 + } 406 + 407 + $new_classes = implode(' ', $new_classes); 393 408 } else { 394 409 $new_content = null; 395 410 $new_key = null;
+20
src/applications/files/diff/PhabricatorDocumentEngineBlock.php
··· 6 6 private $blockKey; 7 7 private $content; 8 8 private $classes = array(); 9 + private $differenceHash; 10 + private $differenceType; 9 11 10 12 public function setContent($content) { 11 13 $this->content = $content; ··· 36 38 37 39 public function getClasses() { 38 40 return $this->classes; 41 + } 42 + 43 + public function setDifferenceHash($difference_hash) { 44 + $this->differenceHash = $difference_hash; 45 + return $this; 46 + } 47 + 48 + public function getDifferenceHash() { 49 + return $this->differenceHash; 50 + } 51 + 52 + public function setDifferenceType($difference_type) { 53 + $this->differenceType = $difference_type; 54 + return $this; 55 + } 56 + 57 + public function getDifferenceType() { 58 + return $this->differenceType; 39 59 } 40 60 41 61 }
+62 -15
src/applications/files/diff/PhabricatorDocumentEngineBlocks.php
··· 20 20 $rows = array(); 21 21 $lists = $this->lists; 22 22 23 - $idx = 0; 24 - while (true) { 25 - $found_any = false; 23 + $specs = array(); 24 + foreach ($this->lists as $list) { 25 + $specs[] = $this->newDiffSpec($list['blocks']); 26 + } 27 + 28 + $old_map = $specs[0]['map']; 29 + $new_map = $specs[1]['map']; 30 + 31 + $old_list = $specs[0]['list']; 32 + $new_list = $specs[1]['list']; 33 + 34 + $changeset = id(new PhabricatorDifferenceEngine()) 35 + ->generateChangesetFromFileContent($old_list, $new_list); 36 + 37 + $hunk_parser = id(new DifferentialHunkParser()) 38 + ->parseHunksForLineData($changeset->getHunks()) 39 + ->reparseHunksForSpecialAttributes(); 40 + 41 + $old_lines = $hunk_parser->getOldLines(); 42 + $new_lines = $hunk_parser->getNewLines(); 26 43 27 - $row = array(); 28 - foreach ($lists as $list) { 29 - $blocks = $list['blocks']; 30 - $cell = idx($blocks, $idx); 44 + $rows = array(); 31 45 32 - if ($cell !== null) { 33 - $found_any = true; 34 - } 46 + $count = count($old_lines); 47 + for ($ii = 0; $ii < $count; $ii++) { 48 + $old_line = idx($old_lines, $ii); 49 + $new_line = idx($new_lines, $ii); 35 50 36 - $row[] = $cell; 51 + if ($old_line) { 52 + $old_hash = rtrim($old_line['text'], "\n"); 53 + $old_block = array_shift($old_map[$old_hash]); 54 + $old_block->setDifferenceType($old_line['type']); 55 + } else { 56 + $old_block = null; 37 57 } 38 58 39 - if (!$found_any) { 40 - break; 59 + if ($new_line) { 60 + $new_hash = rtrim($new_line['text'], "\n"); 61 + $new_block = array_shift($new_map[$new_hash]); 62 + $new_block->setDifferenceType($new_line['type']); 63 + } else { 64 + $new_block = null; 41 65 } 42 66 43 - $rows[] = $row; 44 - $idx++; 67 + $rows[] = array( 68 + $old_block, 69 + $new_block, 70 + ); 45 71 } 46 72 47 73 return $rows; ··· 79 105 return $rows; 80 106 } 81 107 108 + 109 + private function newDiffSpec(array $blocks) { 110 + $map = array(); 111 + $list = array(); 112 + 113 + foreach ($blocks as $block) { 114 + $hash = $block->getDifferenceHash(); 115 + 116 + if (!isset($map[$hash])) { 117 + $map[$hash] = array(); 118 + } 119 + $map[$hash][] = $block; 120 + 121 + $list[] = $hash; 122 + } 123 + 124 + return array( 125 + 'map' => $map, 126 + 'list' => implode("\n", $list)."\n", 127 + ); 128 + } 82 129 83 130 }
+3
src/applications/files/document/PhabricatorImageDocumentEngine.php
··· 55 55 'src' => $file->getBestURI(), 56 56 ))); 57 57 58 + $hash = $file->getContentHash(); 59 + 58 60 $blocks[] = id(new PhabricatorDocumentEngineBlock()) 59 61 ->setBlockKey('1') 60 62 ->addClass('diff-image-cell') 63 + ->setDifferenceHash($hash) 61 64 ->setContent($image_view); 62 65 63 66 return $blocks;
+5
src/applications/files/document/PhabricatorJupyterDocumentEngine.php
··· 82 82 ), 83 83 $notebook_table); 84 84 85 + $hash = PhabricatorHash::digestWithNamedKey( 86 + serialize($cell), 87 + 'document-engine.content-digest'); 88 + 85 89 $blocks[] = id(new PhabricatorDocumentEngineBlock()) 86 90 ->setBlockKey($idx) 91 + ->setDifferenceHash($hash) 87 92 ->setContent($container); 88 93 89 94 $idx++;
+2 -1
webroot/rsrc/css/application/differential/changeset-view.css
··· 282 282 font-weight: bold; 283 283 } 284 284 285 - .differential-diff .diff-image-cell { 285 + .differential-diff td.diff-image-cell { 286 + background-color: transparent; 286 287 background-image: url(/rsrc/image/checker_light.png); 287 288 padding: 8px; 288 289 }