Skip to content

Commit

Permalink
Fix hunk/ldiff unified diff against empty files
Browse files Browse the repository at this point in the history
The ldiff bin (and it's underlying implementation) behaves weirdly when
given an empty file as one of its operand (old or new file).

This is particularly painful when doing diff for new or deleted files,
especially as one could think it is a simple case as the whole content
should be considered either added or removed.

To demonstrate the issue, I'm adding test cases to demonstrate
how ldiff behaves when a 4-lines file is compared to empty, using all
supported formats and in both directions.

The expected result has been collected using GNU diff 3.10.
  • Loading branch information
Annih committed Feb 3, 2025
1 parent d26482c commit cdc3a64
Show file tree
Hide file tree
Showing 14 changed files with 61 additions and 1 deletion.
2 changes: 2 additions & 0 deletions lib/diff/lcs/hunk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,10 @@ def context_range(mode, op)
def unified_range(mode)
case mode
when :old
return "0,0" if @old_empty
s, e = (@start_old + 1), (@end_old + 1)
when :new
return "0,0" if @new_empty
s, e = (@start_new + 1), (@end_new + 1)
end

Expand Down
Empty file added spec/fixtures/empty
Empty file.
5 changes: 5 additions & 0 deletions spec/fixtures/ldiff/output.diff.empty.vs.four_lines
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
0a1,4
> one
> two
> three
> four
9 changes: 9 additions & 0 deletions spec/fixtures/ldiff/output.diff.empty.vs.four_lines-c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
*** spec/fixtures/empty 2025-01-31 12:14:52.856031635 +0100
--- spec/fixtures/four_lines 2025-01-31 12:13:45.476036544 +0100
***************
*** 0 ****
--- 1,4 ----
+ one
+ two
+ three
+ four
6 changes: 6 additions & 0 deletions spec/fixtures/ldiff/output.diff.empty.vs.four_lines-e
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
0a
one
two
three
four
.
6 changes: 6 additions & 0 deletions spec/fixtures/ldiff/output.diff.empty.vs.four_lines-f
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
a0
one
two
three
four
.
7 changes: 7 additions & 0 deletions spec/fixtures/ldiff/output.diff.empty.vs.four_lines-u
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
--- spec/fixtures/empty 2025-01-31 12:14:52.856031635 +0100
+++ spec/fixtures/four_lines 2025-01-31 12:13:45.476036544 +0100
@@ -0,0 +1,4 @@
+one
+two
+three
+four
5 changes: 5 additions & 0 deletions spec/fixtures/ldiff/output.diff.four_lines.vs.empty
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
1,4d0
< one
< two
< three
< four
9 changes: 9 additions & 0 deletions spec/fixtures/ldiff/output.diff.four_lines.vs.empty-c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
*** spec/fixtures/four_lines 2025-01-31 12:13:45.476036544 +0100
--- spec/fixtures/empty 2025-01-31 12:14:52.856031635 +0100
***************
*** 1,4 ****
- one
- two
- three
- four
--- 0 ----
1 change: 1 addition & 0 deletions spec/fixtures/ldiff/output.diff.four_lines.vs.empty-e
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1,4d
1 change: 1 addition & 0 deletions spec/fixtures/ldiff/output.diff.four_lines.vs.empty-f
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
d1 4
7 changes: 7 additions & 0 deletions spec/fixtures/ldiff/output.diff.four_lines.vs.empty-u
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
--- spec/fixtures/four_lines 2025-01-31 12:13:45.476036544 +0100
+++ spec/fixtures/empty 2025-01-31 12:14:52.856031635 +0100
@@ -1,4 +0,0 @@
-one
-two
-three
-four
2 changes: 1 addition & 1 deletion spec/hunk_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@

it "produces a unified diff" do
expected = <<-EXPECTED.gsub(/^\s+/, "").encode("UTF-16LE").chomp
@@ -1 +1,2 @@
@@ -0,0 +1 @@
+Tu a un carte avec {count} items
EXPECTED

Expand Down
2 changes: 2 additions & 0 deletions spec/ldiff_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
{:name => "diff.missing_new_line1", :left => "four_lines", :right => "four_lines_with_missing_new_line", :diff => 1},
{:name => "diff.missing_new_line2", :left => "four_lines_with_missing_new_line", :right => "four_lines", :diff => 1},
{:name => "diff.issue95_trailing_context", :left => "123_x", :right => "456_x", :diff => 1},
{:name => "diff.four_lines.vs.empty", :left => "four_lines", :right => "empty", :diff => 1},
{:name => "diff.empty.vs.four_lines", :left => "empty", :right => "four_lines", :diff => 1},
{:name => "diff.bin1", :left => "file1.bin", :right => "file1.bin", :diff => 0},
{:name => "diff.bin2", :left => "file1.bin", :right => "file2.bin", :diff => 1},
{:name => "diff.chef", :left => "old-chef", :right => "new-chef", :diff => 1},
Expand Down

0 comments on commit cdc3a64

Please sign in to comment.