|
1 | | -export function applyPatch(oldStr, uniDiff) { |
2 | | - let diffstr = uniDiff.split('\n'), |
3 | | - hunks = [], |
4 | | - i = 0, |
5 | | - remEOFNL = false, |
6 | | - addEOFNL = false; |
| 1 | +import {parsePatch} from './parse'; |
7 | 2 |
|
8 | | - // Skip to the first change hunk |
9 | | - while (i < diffstr.length && !(/^@@/.test(diffstr[i]))) { |
10 | | - i++; |
| 3 | +export function applyPatch(oldStr, uniDiff) { |
| 4 | + if (typeof uniDiff === 'string') { |
| 5 | + uniDiff = parsePatch(uniDiff); |
11 | 6 | } |
12 | 7 |
|
13 | | - // Parse the unified diff |
14 | | - for (; i < diffstr.length; i++) { |
15 | | - if (diffstr[i][0] === '@') { |
16 | | - let chnukHeader = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/); |
17 | | - hunks.unshift({ |
18 | | - start: chnukHeader[3], |
19 | | - oldlength: +chnukHeader[2], |
20 | | - removed: [], |
21 | | - newlength: chnukHeader[4], |
22 | | - added: [] |
23 | | - }); |
24 | | - } else if (diffstr[i][0] === '+') { |
25 | | - hunks[0].added.push(diffstr[i].substr(1)); |
26 | | - } else if (diffstr[i][0] === '-') { |
27 | | - hunks[0].removed.push(diffstr[i].substr(1)); |
28 | | - } else if (diffstr[i][0] === ' ') { |
29 | | - hunks[0].added.push(diffstr[i].substr(1)); |
30 | | - hunks[0].removed.push(diffstr[i].substr(1)); |
31 | | - } else if (diffstr[i][0] === '\\') { |
32 | | - if (diffstr[i - 1][0] === '+') { |
33 | | - remEOFNL = true; |
34 | | - } else if (diffstr[i - 1][0] === '-') { |
35 | | - addEOFNL = true; |
36 | | - } |
| 8 | + if (Array.isArray(uniDiff)) { |
| 9 | + if (uniDiff.length > 1) { |
| 10 | + throw new Error('applyPatch only works with a single input.'); |
37 | 11 | } |
| 12 | + |
| 13 | + uniDiff = uniDiff[0]; |
38 | 14 | } |
39 | 15 |
|
40 | 16 | // Apply the diff to the input |
41 | | - let lines = oldStr.split('\n'); |
42 | | - for (i = hunks.length - 1; i >= 0; i--) { |
43 | | - let hunk = hunks[i]; |
| 17 | + let lines = oldStr.split('\n'), |
| 18 | + hunks = uniDiff.hunks; |
| 19 | + for (let i = 0; i < hunks.length; i++) { |
| 20 | + let hunk = hunks[i], |
| 21 | + toPos = hunk.to.line - 1; |
| 22 | + |
44 | 23 | // Sanity check the input string. Bail if we don't match. |
45 | | - for (let j = 0; j < hunk.oldlength; j++) { |
46 | | - if (lines[hunk.start - 1 + j] !== hunk.removed[j]) { |
47 | | - return false; |
| 24 | + for (let j = 0; j < hunk.lines.length; j++) { |
| 25 | + let line = hunk.lines[j]; |
| 26 | + if (line.operation === ' ' || line.operation === '-') { |
| 27 | + // Context sanity check |
| 28 | + if (lines[toPos] !== line.content) { |
| 29 | + return false; |
| 30 | + } |
| 31 | + } |
| 32 | + |
| 33 | + if (line.operation === ' ') { |
| 34 | + toPos++; |
| 35 | + } else if (line.operation === '-') { |
| 36 | + lines.splice(toPos, 1); |
| 37 | + /* istanbul ignore else */ |
| 38 | + } else if (line.operation === '+') { |
| 39 | + lines.splice(toPos, 0, line.content); |
| 40 | + toPos++; |
48 | 41 | } |
49 | 42 | } |
50 | | - Array.prototype.splice.apply(lines, [hunk.start - 1, hunk.oldlength].concat(hunk.added)); |
51 | 43 | } |
52 | 44 |
|
53 | 45 | // Handle EOFNL insertion/removal |
54 | | - if (remEOFNL) { |
| 46 | + if (uniDiff.removeEOFNL) { |
55 | 47 | while (!lines[lines.length - 1]) { |
56 | 48 | lines.pop(); |
57 | 49 | } |
58 | | - } else if (addEOFNL) { |
| 50 | + } else if (uniDiff.addEOFNL) { |
59 | 51 | lines.push(''); |
60 | 52 | } |
61 | 53 | return lines.join('\n'); |
|
0 commit comments