Skip to content

Commit d84a530

Browse files
committed
Update parsePatch to output common diff format
This will now generate the same format as `structuredPatch` and `applyPatch` consumes this format as well.
1 parent 42fdc6a commit d84a530

File tree

3 files changed

+109
-120
lines changed

3 files changed

+109
-120
lines changed

src/patch/apply.js

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,50 @@ export function applyPatch(oldStr, uniDiff) {
1515

1616
// Apply the diff to the input
1717
let lines = oldStr.split('\n'),
18-
hunks = uniDiff.hunks;
18+
hunks = uniDiff.hunks,
19+
removeEOFNL,
20+
addEOFNL;
1921
for (let i = 0; i < hunks.length; i++) {
2022
let hunk = hunks[i],
21-
toPos = hunk.to.line - 1;
23+
toPos = hunk.newStart - 1;
2224

2325
// Sanity check the input string. Bail if we don't match.
2426
for (let j = 0; j < hunk.lines.length; j++) {
25-
let line = hunk.lines[j];
26-
if (line.operation === ' ' || line.operation === '-') {
27+
let line = hunk.lines[j],
28+
operation = line[0],
29+
content = line.substr(1);
30+
if (operation === ' ' || operation === '-') {
2731
// Context sanity check
28-
if (lines[toPos] !== line.content) {
32+
if (lines[toPos] !== content) {
2933
return false;
3034
}
3135
}
3236

33-
if (line.operation === ' ') {
37+
if (operation === ' ') {
3438
toPos++;
35-
} else if (line.operation === '-') {
39+
} else if (operation === '-') {
3640
lines.splice(toPos, 1);
3741
/* istanbul ignore else */
38-
} else if (line.operation === '+') {
39-
lines.splice(toPos, 0, line.content);
42+
} else if (operation === '+') {
43+
lines.splice(toPos, 0, content);
4044
toPos++;
45+
} else if (operation === '\\') {
46+
let previousOperation = hunk.lines[j - 1][0];
47+
if (previousOperation === '+') {
48+
removeEOFNL = true;
49+
} else if (previousOperation === '-') {
50+
addEOFNL = true;
51+
}
4152
}
4253
}
4354
}
4455

4556
// Handle EOFNL insertion/removal
46-
if (uniDiff.removeEOFNL) {
57+
if (removeEOFNL) {
4758
while (!lines[lines.length - 1]) {
4859
lines.pop();
4960
}
50-
} else if (uniDiff.addEOFNL) {
61+
} else if (addEOFNL) {
5162
lines.push('');
5263
}
5364
return lines.join('\n');

src/patch/parse.js

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export function parsePatch(uniDiff, options = {}) {
3030
if (/^Index:/.test(diffstr[i])) {
3131
break;
3232
} else if (/^@@/.test(diffstr[i])) {
33-
index.hunks.push(parseHunk(index));
33+
index.hunks.push(parseHunk());
3434
} else if (!diffstr[i]) {
3535
i++;
3636
} else {
@@ -44,75 +44,64 @@ export function parsePatch(uniDiff, options = {}) {
4444
function parseFileHeader(index) {
4545
let fileHeader = (/^(\-\-\-|\+\+\+)\s(\S+)\s?(.*)/.exec(diffstr[i]));
4646
if (fileHeader) {
47-
index[fileHeader[1] === '---' ? 'from' : 'to'] = {
48-
file: fileHeader[2],
49-
header: fileHeader[3]
50-
};
47+
let keyPrefix = fileHeader[1] === '---' ? 'old' : 'new';
48+
index[keyPrefix + 'FileName'] = fileHeader[2];
49+
index[keyPrefix + 'Header'] = fileHeader[3];
50+
5151
i++;
5252
}
5353
}
5454

5555
// Parses a hunk
5656
// This assumes that we are at the start of a hunk.
57-
function parseHunk(index) {
57+
function parseHunk() {
5858
let chunkHeaderIndex = i,
5959
chunkHeaderLine = diffstr[i++],
6060
chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
6161

6262
let hunk = {
63-
from: {
64-
line: +chunkHeader[1],
65-
count: +chunkHeader[2] || 1
66-
},
67-
to: {
68-
line: +chunkHeader[3],
69-
count: +chunkHeader[4] || 1
70-
},
63+
oldStart: +chunkHeader[1],
64+
oldLines: +chunkHeader[2] || 1,
65+
newStart: +chunkHeader[3],
66+
newLines: +chunkHeader[4] || 1,
7167
lines: []
7268
};
7369

7470
let addCount = 0,
7571
removeCount = 0;
7672
for (; i < diffstr.length; i++) {
77-
let operation = diffstr[i][0],
78-
content = diffstr[i].substr(1);
73+
let operation = diffstr[i][0];
7974

80-
if (operation === '+' || operation === '-' || operation === ' ') {
81-
hunk.lines.push({operation, content});
75+
if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') {
76+
hunk.lines.push(diffstr[i]);
8277

8378
if (operation === '+') {
8479
addCount++;
8580
} else if (operation === '-') {
8681
removeCount++;
87-
} else {
82+
} else if (operation === ' ') {
8883
addCount++;
8984
removeCount++;
9085
}
91-
} else if (operation === '\\') {
92-
if (diffstr[i - 1][0] === '+') {
93-
index.removeEOFNL = true;
94-
} else if (diffstr[i - 1][0] === '-') {
95-
index.addEOFNL = true;
96-
}
9786
} else {
9887
break;
9988
}
10089
}
10190

10291
// Handle the empty block count case
103-
if (!addCount && hunk.to.count === 1) {
104-
hunk.to.count = 0;
92+
if (!addCount && hunk.newLines === 1) {
93+
hunk.newLines = 0;
10594
}
106-
if (!removeCount && hunk.from.count === 1) {
107-
hunk.from.count = 0;
95+
if (!removeCount && hunk.oldLines === 1) {
96+
hunk.oldLines = 0;
10897
}
10998

11099
// Perform optional sanity checking
111100
if (options.strict) {
112-
if (addCount !== hunk.to.count) {
101+
if (addCount !== hunk.newLines) {
113102
throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
114103
}
115-
if (removeCount !== hunk.from.count) {
104+
if (removeCount !== hunk.oldLines) {
116105
throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
117106
}
118107
}

test/patch/parse.js

Lines changed: 67 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ describe('patch/parse', function() {
1414
.to.eql([{
1515
hunks: [
1616
{
17-
from: {line: 1, count: 3},
18-
to: {line: 1, count: 4},
17+
oldStart: 1, oldLines: 3,
18+
newStart: 1, newLines: 4,
1919
lines: [
20-
{operation: ' ', content: 'line2'},
21-
{operation: ' ', content: 'line3'},
22-
{operation: '+', content: 'line4'},
23-
{operation: ' ', content: 'line5'}
20+
' line2',
21+
' line3',
22+
'+line4',
23+
' line5'
2424
]
2525
}
2626
]
@@ -34,11 +34,11 @@ describe('patch/parse', function() {
3434
.to.eql([{
3535
hunks: [
3636
{
37-
from: {line: 1, count: 1},
38-
to: {line: 1, count: 1},
37+
oldStart: 1, oldLines: 1,
38+
newStart: 1, newLines: 1,
3939
lines: [
40-
{operation: '-', content: 'line3'},
41-
{operation: '+', content: 'line4'}
40+
'-line3',
41+
'+line4'
4242
]
4343
}
4444
]
@@ -59,23 +59,23 @@ describe('patch/parse', function() {
5959
.to.eql([{
6060
hunks: [
6161
{
62-
from: {line: 1, count: 3},
63-
to: {line: 1, count: 4},
62+
oldStart: 1, oldLines: 3,
63+
newStart: 1, newLines: 4,
6464
lines: [
65-
{operation: ' ', content: 'line2'},
66-
{operation: ' ', content: 'line3'},
67-
{operation: '+', content: 'line4'},
68-
{operation: ' ', content: 'line5'}
65+
' line2',
66+
' line3',
67+
'+line4',
68+
' line5'
6969
]
7070
},
7171
{
72-
from: {line: 4, count: 3},
73-
to: {line: 1, count: 4},
72+
oldStart: 4, oldLines: 3,
73+
newStart: 1, newLines: 4,
7474
lines: [
75-
{operation: ' ', content: 'line2'},
76-
{operation: ' ', content: 'line3'},
77-
{operation: '-', content: 'line4'},
78-
{operation: ' ', content: 'line5'}
75+
' line2',
76+
' line3',
77+
'-line4',
78+
' line5'
7979
]
8080
}
8181
]
@@ -94,23 +94,19 @@ describe('patch/parse', function() {
9494
line5`))
9595
.to.eql([{
9696
index: 'test',
97-
from: {
98-
file: 'from',
99-
header: 'header1'
100-
},
101-
to: {
102-
file: 'to',
103-
header: 'header2'
104-
},
97+
oldFileName: 'from',
98+
oldHeader: 'header1',
99+
newFileName: 'to',
100+
newHeader: 'header2',
105101
hunks: [
106102
{
107-
from: {line: 1, count: 3},
108-
to: {line: 1, count: 4},
103+
oldStart: 1, oldLines: 3,
104+
newStart: 1, newLines: 4,
109105
lines: [
110-
{operation: ' ', content: 'line2'},
111-
{operation: ' ', content: 'line3'},
112-
{operation: '+', content: 'line4'},
113-
{operation: ' ', content: 'line5'}
106+
' line2',
107+
' line3',
108+
'+line4',
109+
' line5'
114110
]
115111
}
116112
]
@@ -138,45 +134,37 @@ Index: test2
138134
line5`))
139135
.to.eql([{
140136
index: 'test',
141-
from: {
142-
file: 'from',
143-
header: 'header1'
144-
},
145-
to: {
146-
file: 'to',
147-
header: 'header2'
148-
},
137+
oldFileName: 'from',
138+
oldHeader: 'header1',
139+
newFileName: 'to',
140+
newHeader: 'header2',
149141
hunks: [
150142
{
151-
from: {line: 1, count: 3},
152-
to: {line: 1, count: 4},
143+
oldStart: 1, oldLines: 3,
144+
newStart: 1, newLines: 4,
153145
lines: [
154-
{operation: ' ', content: 'line2'},
155-
{operation: ' ', content: 'line3'},
156-
{operation: '+', content: 'line4'},
157-
{operation: ' ', content: 'line5'}
146+
' line2',
147+
' line3',
148+
'+line4',
149+
' line5'
158150
]
159151
}
160152
]
161153
}, {
162154
index: 'test2',
163-
from: {
164-
file: 'from',
165-
header: 'header1'
166-
},
167-
to: {
168-
file: 'to',
169-
header: 'header2'
170-
},
155+
oldFileName: 'from',
156+
oldHeader: 'header1',
157+
newFileName: 'to',
158+
newHeader: 'header2',
171159
hunks: [
172160
{
173-
from: {line: 1, count: 3},
174-
to: {line: 1, count: 4},
161+
oldStart: 1, oldLines: 3,
162+
newStart: 1, newLines: 4,
175163
lines: [
176-
{operation: ' ', content: 'line2'},
177-
{operation: ' ', content: 'line3'},
178-
{operation: '+', content: 'line4'},
179-
{operation: ' ', content: 'line5'}
164+
' line2',
165+
' line3',
166+
'+line4',
167+
' line5'
180168
]
181169
}
182170
]
@@ -191,14 +179,14 @@ Index: test2
191179
.to.eql([{
192180
hunks: [
193181
{
194-
from: {line: 1, count: 3},
195-
to: {line: 1, count: 4},
182+
oldStart: 1, oldLines: 3,
183+
newStart: 1, newLines: 4,
196184
lines: [
197-
{operation: '-', content: 'line5'}
185+
'-line5',
186+
'\\ No newline at end of file'
198187
]
199188
}
200-
],
201-
addEOFNL: true
189+
]
202190
}]);
203191
});
204192
it('should note removed EOFNL', function() {
@@ -209,14 +197,14 @@ Index: test2
209197
.to.eql([{
210198
hunks: [
211199
{
212-
from: {line: 1, count: 3},
213-
to: {line: 1, count: 4},
200+
oldStart: 1, oldLines: 3,
201+
newStart: 1, newLines: 4,
214202
lines: [
215-
{operation: '+', content: 'line5'}
203+
'+line5',
204+
'\\ No newline at end of file'
216205
]
217206
}
218-
],
219-
removeEOFNL: true
207+
]
220208
}]);
221209
});
222210
it('should ignore context no EOFNL', function() {
@@ -228,11 +216,12 @@ Index: test2
228216
.to.eql([{
229217
hunks: [
230218
{
231-
from: {line: 1, count: 3},
232-
to: {line: 1, count: 4},
219+
oldStart: 1, oldLines: 3,
220+
newStart: 1, newLines: 4,
233221
lines: [
234-
{operation: '+', content: 'line4'},
235-
{operation: ' ', content: 'line5'}
222+
'+line4',
223+
' line5',
224+
'\\ No newline at end of file'
236225
]
237226
}
238227
]

0 commit comments

Comments
 (0)