From 259c2242a5b73105d471eb1bcbcaa4724f332d82 Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Thu, 14 Sep 2023 07:32:44 +0100
Subject: [PATCH] Issue #3386707 by alexpott, mondrake, longwave:
 DiffOpOutputBuilder does not correctly match the 10.0.x implementation and
 produces unexpected output (part 2)

---
 .../Component/Diff/DiffOpOutputBuilder.php     |  6 +-----
 .../Component/Diff/DiffOpOutputBuilderTest.php | 17 +++++++++++++----
 .../Component/Diff/Engine/DiffEngineTest.php   | 18 ++++++++++++++++++
 3 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/core/lib/Drupal/Component/Diff/DiffOpOutputBuilder.php b/core/lib/Drupal/Component/Diff/DiffOpOutputBuilder.php
index 72cc5805ae8a..41a850bb5dc1 100644
--- a/core/lib/Drupal/Component/Diff/DiffOpOutputBuilder.php
+++ b/core/lib/Drupal/Component/Diff/DiffOpOutputBuilder.php
@@ -61,12 +61,8 @@ public function toOpsArray(array $diff): array {
         if (count($hunkTarget) === 0) {
           $ops[] = $this->hunkOp(Differ::REMOVED, $hunkSource, $hunkTarget);
         }
-        elseif (count($hunkSource) >= count($hunkTarget)) {
-          $ops[] = $this->hunkOp(self::CHANGED, $hunkSource, $hunkTarget);
-        }
         else {
-          $ops[] = $this->hunkOp(self::CHANGED, $hunkSource, array_slice($hunkTarget, 0, count($hunkSource)));
-          $ops[] = $this->hunkOp(Differ::ADDED, array_slice($hunkTarget, count($hunkSource)), []);
+          $ops[] = $this->hunkOp(self::CHANGED, $hunkSource, $hunkTarget);
         }
         $hunkMode = NULL;
         $hunkSource = [];
diff --git a/core/tests/Drupal/Tests/Component/Diff/DiffOpOutputBuilderTest.php b/core/tests/Drupal/Tests/Component/Diff/DiffOpOutputBuilderTest.php
index 725e178a4742..53ada909fec2 100644
--- a/core/tests/Drupal/Tests/Component/Diff/DiffOpOutputBuilderTest.php
+++ b/core/tests/Drupal/Tests/Component/Diff/DiffOpOutputBuilderTest.php
@@ -73,6 +73,16 @@ public function provideTestDiff(): array {
         ['aa', 'bb', 'cc', 'd'],
         ['a', 'c', 'd'],
       ],
+      'copy-change-copy-change' => [
+        [
+          new DiffOpCopy(['a']),
+          new DiffOpChange(['bb'], ['b', 'c']),
+          new DiffOpCopy(['d']),
+          new DiffOpChange(['ee'], ['e']),
+        ],
+        ['a', 'bb', 'd', 'ee'],
+        ['a', 'b', 'c', 'd', 'e'],
+      ],
     ];
   }
 
@@ -111,12 +121,11 @@ public function testDiffInfiniteLoop(): void {
     $differ = new Differ($diffOpBuilder);
     $diff = $differ->diffToArray($from, $to);
     $diffOps = $diffOpBuilder->toOpsArray($diff);
-    $this->assertCount(5, $diffOps);
+    $this->assertCount(4, $diffOps);
     $this->assertEquals($diffOps[0], new DiffOpAdd(['    - image.style.max_325x325']));
     $this->assertEquals($diffOps[1], new DiffOpCopy(['    - image.style.max_650x650']));
-    $this->assertEquals($diffOps[2], new DiffOpChange(['    - image.style.max_325x325'], ['_core:']));
-    $this->assertEquals($diffOps[3], new DiffOpAdd(['  default_config_hash: 3mjM9p-kQ8syzH7N8T0L9OnCJDSPvHAZoi3q6jcXJKM']));
-    $this->assertEquals($diffOps[4], new DiffOpCopy(['fallback_image_style: max_325x325', '']));
+    $this->assertEquals($diffOps[2], new DiffOpChange(['    - image.style.max_325x325'], ['_core:', '  default_config_hash: 3mjM9p-kQ8syzH7N8T0L9OnCJDSPvHAZoi3q6jcXJKM']));
+    $this->assertEquals($diffOps[3], new DiffOpCopy(['fallback_image_style: max_325x325', '']));
   }
 
 }
diff --git a/core/tests/Drupal/Tests/Component/Diff/Engine/DiffEngineTest.php b/core/tests/Drupal/Tests/Component/Diff/Engine/DiffEngineTest.php
index 1020373e6ac6..70265df1f6a5 100644
--- a/core/tests/Drupal/Tests/Component/Diff/Engine/DiffEngineTest.php
+++ b/core/tests/Drupal/Tests/Component/Diff/Engine/DiffEngineTest.php
@@ -70,6 +70,24 @@ public function provideTestDiff() {
         ['a', 'b', 'd'],
         ['a'],
       ],
+      'change-copy' => [
+        [
+          DiffOpChange::class,
+          DiffOpCopy::class,
+        ],
+        ['aa', 'bb', 'cc', 'd'],
+        ['a', 'c', 'd'],
+      ],
+      'copy-change-copy-change' => [
+        [
+          DiffOpCopy::class,
+          DiffOpChange::class,
+          DiffOpCopy::class,
+          DiffOpChange::class,
+        ],
+        ['a', 'bb', 'd', 'ee'],
+        ['a', 'b', 'c', 'd', 'e'],
+      ],
     ];
   }
 
-- 
GitLab