Skip to content

Commit 04e6c43

Browse files
authored
Merge pull request dnaumenko#37 from catbref/master
Fix for issue dnaumenko#20 correcting empty-context add-only patches
2 parents 8b1e374 + 8df661f commit 04e6c43

File tree

5 files changed

+138
-24
lines changed

5 files changed

+138
-24
lines changed

src/main/java/difflib/DiffUtils.java

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -201,25 +201,8 @@ public static Patch<String> parseUnifiedDiff(List<String> diff) {
201201
Matcher m = unifiedDiffChunkRe.matcher(line);
202202
if (m.find()) {
203203
// Process the lines in the previous chunk
204-
if (rawChunk.size() != 0) {
205-
List<String> oldChunkLines = new ArrayList<String>();
206-
List<String> newChunkLines = new ArrayList<String>();
207-
208-
for (String[] raw_line : rawChunk) {
209-
tag = raw_line[0];
210-
rest = raw_line[1];
211-
if (tag.equals(" ") || tag.equals("-")) {
212-
oldChunkLines.add(rest);
213-
}
214-
if (tag.equals(" ") || tag.equals("+")) {
215-
newChunkLines.add(rest);
216-
}
217-
}
218-
patch.addDelta(new ChangeDelta<String>(new Chunk<String>(
219-
old_ln - 1, oldChunkLines), new Chunk<String>(
220-
new_ln - 1, newChunkLines)));
221-
rawChunk.clear();
222-
}
204+
processRawChunk(rawChunk, patch, old_ln, new_ln);
205+
223206
// Parse the @@ header
224207
old_ln = m.group(1) == null ? 1 : Integer.parseInt(m.group(1));
225208
new_ln = m.group(3) == null ? 1 : Integer.parseInt(m.group(3));
@@ -244,6 +227,15 @@ public static Patch<String> parseUnifiedDiff(List<String> diff) {
244227
}
245228

246229
// Process the lines in the last chunk
230+
processRawChunk(rawChunk, patch, old_ln, new_ln);
231+
232+
return patch;
233+
}
234+
235+
public static void processRawChunk(List<String[]> rawChunk, Patch patch, int old_ln, int new_ln) {
236+
String tag;
237+
String rest;
238+
247239
if (rawChunk.size() != 0) {
248240
List<String> oldChunkLines = new ArrayList<String>();
249241
List<String> newChunkLines = new ArrayList<String>();
@@ -259,13 +251,21 @@ public static Patch<String> parseUnifiedDiff(List<String> diff) {
259251
}
260252
}
261253

262-
patch.addDelta(new ChangeDelta<String>(new Chunk<String>(
263-
old_ln - 1, oldChunkLines), new Chunk<String>(new_ln - 1,
264-
newChunkLines)));
254+
if (oldChunkLines.isEmpty()) {
255+
patch.addDelta(new InsertDelta<String>(new Chunk<String>(
256+
old_ln, oldChunkLines), new Chunk<String>(new_ln - 1,
257+
newChunkLines)));
258+
} else if (newChunkLines.isEmpty()) {
259+
patch.addDelta(new DeleteDelta<String>(new Chunk<String>(
260+
old_ln - 1, oldChunkLines), new Chunk<String>(new_ln,
261+
newChunkLines)));
262+
} else {
263+
patch.addDelta(new ChangeDelta<String>(new Chunk<String>(
264+
old_ln - 1, oldChunkLines), new Chunk<String>(
265+
new_ln - 1, newChunkLines)));
266+
}
265267
rawChunk.clear();
266268
}
267-
268-
return patch;
269269
}
270270

271271
/**
@@ -426,6 +426,14 @@ private static List<String> processDeltas(List<String> origLines,
426426
revTotal++;
427427
}
428428

429+
// In case of empty chunk and context
430+
if (origTotal == 0 && origStart > 1)
431+
--origStart;
432+
433+
// In case of empty chunk and context
434+
if (revTotal == 0 && revStart > 1)
435+
--revStart;
436+
429437
// Create and insert the block header, conforming to the Unified Diff
430438
// standard
431439
StringBuffer header = new StringBuffer();
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package diffutils;
2+
3+
import java.io.BufferedReader;
4+
import java.io.FileReader;
5+
import java.io.IOException;
6+
import java.util.LinkedList;
7+
import java.util.List;
8+
9+
import difflib.DiffUtils;
10+
import difflib.Patch;
11+
import difflib.PatchFailedException;
12+
13+
import junit.framework.TestCase;
14+
15+
public class EmptyContextUnifiedDiffTest extends TestCase {
16+
17+
public List<String> fileToLines(String filename) {
18+
List<String> lines = new LinkedList<String>();
19+
String line = "";
20+
BufferedReader in = null;
21+
try {
22+
in = new BufferedReader(new FileReader(filename));
23+
while ((line = in.readLine()) != null) {
24+
lines.add(line);
25+
}
26+
} catch (IOException e) {
27+
e.printStackTrace();
28+
fail(e.getMessage());
29+
} finally {
30+
if (in != null) {
31+
try {
32+
in.close();
33+
} catch (IOException e) {
34+
// ignore ... any errors should already have been
35+
// reported via an IOException from the final flush.
36+
}
37+
}
38+
}
39+
return lines;
40+
}
41+
42+
public void testEmptyUnifiedContextPatch() {
43+
List<String> origLines = fileToLines(TestConstants.MOCK_FOLDER + "unified_empty_context_original.txt");
44+
List<String> revLines = fileToLines(TestConstants.MOCK_FOLDER + "unified_empty_context_revised.txt");
45+
List<String> unifiedDiff = fileToLines(TestConstants.MOCK_FOLDER + "unified_empty_context_patch.txt");
46+
47+
List<String> patchedLines = null;
48+
Patch patch = DiffUtils.parseUnifiedDiff(unifiedDiff);
49+
50+
try {
51+
patchedLines = (List<String>) patch.applyTo(origLines);
52+
} catch (PatchFailedException e) {
53+
fail(e.getMessage());
54+
}
55+
56+
verifyLinesEqual(patchedLines, revLines);
57+
}
58+
59+
public void testEmptyUnifiedContextDiff() {
60+
List<String> origLines = fileToLines(TestConstants.MOCK_FOLDER + "unified_empty_context_original.txt");
61+
List<String> revLines = fileToLines(TestConstants.MOCK_FOLDER + "unified_empty_context_revised.txt");
62+
63+
List<String> patchedLines = null;
64+
65+
// Generate a 0-context diff then reapply
66+
Patch generatedPatch = DiffUtils.diff(origLines, revLines);
67+
List<String> generatedDiff = DiffUtils.generateUnifiedDiff("original", "revised", origLines, generatedPatch, 0);
68+
Patch newPatch = DiffUtils.parseUnifiedDiff(generatedDiff);
69+
70+
try {
71+
patchedLines = (List<String>) newPatch.applyTo(origLines);
72+
} catch (PatchFailedException e) {
73+
fail(e.getMessage());
74+
}
75+
76+
verifyLinesEqual(patchedLines, revLines);
77+
}
78+
79+
public void verifyLinesEqual(List<String> patchedLines, List<String> revLines) {
80+
assertTrue(revLines.size() == patchedLines.size());
81+
for (int i = 0; i < revLines.size(); i++) {
82+
String l1 = revLines.get(i);
83+
String l2 = patchedLines.get(i);
84+
if (!l1.equals(l2)) {
85+
fail("Line " + (i + 1) + " of the patched file did not match the revised original");
86+
}
87+
}
88+
}
89+
90+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
This
2+
is
3+
a
4+
test
5+
file
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
--- uc_original.txt 2011-06-14 16:21:56.578627000 +0300
2+
+++ uc_insert_revised.txt 2011-06-14 16:20:37.654820000 +0300
3+
@@ -2,0 +3 @@
4+
+not
5+
@@ -5 +5,0 @@
6+
-file
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
This
2+
is
3+
not
4+
a
5+
test

0 commit comments

Comments
 (0)