diff --git a/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php b/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php --- a/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php +++ b/src/applications/differential/render/DifferentialChangesetTwoUpRenderer.php @@ -379,7 +379,15 @@ if ($old) { $old_content = $old->newContentView(); $old_key = $old->getBlockKey(); - $old_classes = implode(' ', $old->getClasses()); + + $old_classes = $old->getClasses(); + + if ($old->getDifferenceType() === '-') { + $old_classes[] = 'old'; + $old_classes[] = 'old-full'; + } + + $old_classes = implode(' ', $old_classes); } else { $old_content = null; $old_key = null; @@ -389,7 +397,14 @@ if ($new) { $new_content = $new->newContentView(); $new_key = $new->getBlockKey(); - $new_classes = implode(' ', $new->getClasses()); + $new_classes = $new->getClasses(); + + if ($new->getDifferenceType() === '+') { + $new_classes[] = 'new'; + $new_classes[] = 'new-full'; + } + + $new_classes = implode(' ', $new_classes); } else { $new_content = null; $new_key = null; diff --git a/src/applications/files/diff/PhabricatorDocumentEngineBlock.php b/src/applications/files/diff/PhabricatorDocumentEngineBlock.php --- a/src/applications/files/diff/PhabricatorDocumentEngineBlock.php +++ b/src/applications/files/diff/PhabricatorDocumentEngineBlock.php @@ -6,6 +6,8 @@ private $blockKey; private $content; private $classes = array(); + private $differenceHash; + private $differenceType; public function setContent($content) { $this->content = $content; @@ -38,4 +40,22 @@ return $this->classes; } + public function setDifferenceHash($difference_hash) { + $this->differenceHash = $difference_hash; + return $this; + } + + public function getDifferenceHash() { + return $this->differenceHash; + } + + public function setDifferenceType($difference_type) { + $this->differenceType = $difference_type; + return $this; + } + + public function getDifferenceType() { + return $this->differenceType; + } + } diff --git a/src/applications/files/diff/PhabricatorDocumentEngineBlocks.php b/src/applications/files/diff/PhabricatorDocumentEngineBlocks.php --- a/src/applications/files/diff/PhabricatorDocumentEngineBlocks.php +++ b/src/applications/files/diff/PhabricatorDocumentEngineBlocks.php @@ -20,28 +20,54 @@ $rows = array(); $lists = $this->lists; - $idx = 0; - while (true) { - $found_any = false; + $specs = array(); + foreach ($this->lists as $list) { + $specs[] = $this->newDiffSpec($list['blocks']); + } - $row = array(); - foreach ($lists as $list) { - $blocks = $list['blocks']; - $cell = idx($blocks, $idx); + $old_map = $specs[0]['map']; + $new_map = $specs[1]['map']; - if ($cell !== null) { - $found_any = true; - } + $old_list = $specs[0]['list']; + $new_list = $specs[1]['list']; + + $changeset = id(new PhabricatorDifferenceEngine()) + ->generateChangesetFromFileContent($old_list, $new_list); + + $hunk_parser = id(new DifferentialHunkParser()) + ->parseHunksForLineData($changeset->getHunks()) + ->reparseHunksForSpecialAttributes(); + + $old_lines = $hunk_parser->getOldLines(); + $new_lines = $hunk_parser->getNewLines(); - $row[] = $cell; + $rows = array(); + + $count = count($old_lines); + for ($ii = 0; $ii < $count; $ii++) { + $old_line = idx($old_lines, $ii); + $new_line = idx($new_lines, $ii); + + if ($old_line) { + $old_hash = rtrim($old_line['text'], "\n"); + $old_block = array_shift($old_map[$old_hash]); + $old_block->setDifferenceType($old_line['type']); + } else { + $old_block = null; } - if (!$found_any) { - break; + if ($new_line) { + $new_hash = rtrim($new_line['text'], "\n"); + $new_block = array_shift($new_map[$new_hash]); + $new_block->setDifferenceType($new_line['type']); + } else { + $new_block = null; } - $rows[] = $row; - $idx++; + $rows[] = array( + $old_block, + $new_block, + ); } return $rows; @@ -80,4 +106,25 @@ } + private function newDiffSpec(array $blocks) { + $map = array(); + $list = array(); + + foreach ($blocks as $block) { + $hash = $block->getDifferenceHash(); + + if (!isset($map[$hash])) { + $map[$hash] = array(); + } + $map[$hash][] = $block; + + $list[] = $hash; + } + + return array( + 'map' => $map, + 'list' => implode("\n", $list)."\n", + ); + } + } diff --git a/src/applications/files/document/PhabricatorJupyterDocumentEngine.php b/src/applications/files/document/PhabricatorJupyterDocumentEngine.php --- a/src/applications/files/document/PhabricatorJupyterDocumentEngine.php +++ b/src/applications/files/document/PhabricatorJupyterDocumentEngine.php @@ -82,8 +82,13 @@ ), $notebook_table); + $hash = PhabricatorHash::digestWithNamedKey( + serialize($cell), + 'document-engine.content-digest'); + $blocks[] = id(new PhabricatorDocumentEngineBlock()) ->setBlockKey($idx) + ->setDifferenceHash($hash) ->setContent($container); $idx++;