Verified Commit e5dd1330 authored by Andrei Mateescu's avatar Andrei Mateescu
Browse files

fix: #3389715 Diffs with different line endings leads to Invalid $mode 3 specified

By: mstrelan
By: larowlan
By: mondrake
By: atropoides
By: longwave
By: amateescu
(cherry picked from commit cc28583d)
parent ca32739c
Loading
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -46,6 +46,14 @@ public function toOpsArray(array $diff): array {

    for ($i = 0; $i < count($diff); $i++) {

      // Differ prepends a warning pseudo-line when source and target use
      // different end of line markings. Skip it: no DiffOp represents a
      // warning, and keeping it would output a line absent from both inputs.
      // The lines it warns about are still reported as changes below.
      if ($diff[$i][1] === Differ::DIFF_LINE_END_WARNING) {
        continue;
      }

      // Handle a sequence of removals + additions as a sequence of changes, and
      // manages the tail if required.
      if ($diff[$i][1] === Differ::REMOVED) {
+18 −0
Original line number Diff line number Diff line
@@ -42,6 +42,24 @@ public static function provideTestDiff(): array {
        ['line1', 'line2', 'line2a', 'line3'],
        ['line1', 'line2', 'line2b', 'line3'],
      ],
      // Lines are compared including their end of line markings, so lines
      // differing only by those are a change. Differ's mismatched line ending
      // warning is not part of the output.
      'change, line endings differ' => [
        "1c1\n< foo\r\n\n---\n> foo\n\n",
        ["foo\r\n"],
        ["foo\n"],
      ],
      'change, line endings differ on multiple lines' => [
        "1,2c1,2\n< line1\r\n\n< line2\r\n\n---\n> line1\n\n> line2\n\n",
        ["line1\r\n", "line2\r\n"],
        ["line1\n", "line2\n"],
      ],
      'copy, line endings match' => [
        '',
        ["foo\r\n"],
        ["foo\r\n"],
      ],
    ];
  }

+19 −0
Original line number Diff line number Diff line
@@ -88,6 +88,25 @@ public static function provideTestDiff(): array {
        ['a', 'bb', 'd', 'ee'],
        ['a', 'b', 'c', 'd', 'e'],
      ],
      // Differ prepends a line end warning when source and target use
      // different end of line markings. It is skipped, the lines are a change.
      'line end warning' => [
        [new DiffOpChange(["foo\r\n"], ["foo\n"])],
        ["foo\r\n"],
        ["foo\n"],
      ],
      'line end warning, multiple lines' => [
        [new DiffOpChange(["line1\r\n", "line2\r\n"], ["line1\n", "line2\n"])],
        ["line1\r\n", "line2\r\n"],
        ["line1\n", "line2\n"],
      ],
      // No warning is raised when both sides use the same end of line
      // markings.
      'consistent line ends' => [
        [new DiffOpCopy(["foo\r\n"])],
        ["foo\r\n"],
        ["foo\r\n"],
      ],
    ];
  }