Skip to content

Commit 09b7efe

Browse files
committed
Split logic for fit candidates on an iterator
1 parent 3908658 commit 09b7efe

File tree

2 files changed

+72
-32
lines changed

2 files changed

+72
-32
lines changed

src/patch/apply.js

+50-31
Original file line numberDiff line numberDiff line change
@@ -51,50 +51,69 @@ export function applyPatch(source, uniDiff, options = {}) {
5151
return true;
5252
}
5353

54-
// Search best fit offsets for each hunk based on the previous ones
55-
for (let i = 0; i < hunks.length; i++) {
56-
let hunk = hunks[i],
54+
function distanceIterator(toPos, minLine, maxLine) {
55+
let wantForward = true,
5756
backwardExhausted = false,
5857
forwardExhausted = false,
59-
localOffset = 0,
60-
toPos = offset + hunk.oldStart - 1,
61-
maxLine = lines.length - hunk.oldLines,
62-
toCheck;
58+
localOffset = 1;
59+
60+
return function iterator() {
61+
if (wantForward && !forwardExhausted) {
62+
if (backwardExhausted) {
63+
localOffset++;
64+
} else {
65+
wantForward = false;
66+
}
67+
68+
// Check if trying to fit beyond text length, and if not, check it fits
69+
// after offset location (or desired location on first iteration)
70+
if (toPos + localOffset <= maxLine) {
71+
return localOffset;
72+
}
6373

64-
for (;;) {
65-
// Check if trying to fit beyond text length, and if not, check it fits
66-
// after offset location (or desired location on first iteration)
67-
toCheck = toPos + localOffset;
68-
if (maxLine < toCheck) {
6974
forwardExhausted = true;
70-
} else if (hunkFits(hunk, toCheck)) {
71-
hunk.offset = offset += localOffset;
72-
break;
7375
}
7476

75-
// If we tried to fit hunk before text beginning and beyond text lenght,
76-
// then hunk can't be fit on the text so we raise an error
77-
if (backwardExhausted && forwardExhausted) {
78-
return false;
79-
}
77+
if (!backwardExhausted) {
78+
if (!forwardExhausted) {
79+
wantForward = true;
80+
}
8081

81-
// Reset checks of trying to fit outside text limits and increase offset
82-
// of the current hunk relative to its desired location
83-
backwardExhausted = false;
84-
forwardExhausted = false;
85-
localOffset++;
82+
// Check if trying to fit before text beginning, and if not, check it fits
83+
// before offset location
84+
if (minLine <= toPos - localOffset) {
85+
return -localOffset++;
86+
}
8687

87-
// Check if trying to fit before text beginning, and if not, check it fits
88-
// before offset location
89-
toCheck = toPos - localOffset;
90-
if (toCheck < minLine) {
9188
backwardExhausted = true;
92-
} else if (hunkFits(hunk, toCheck)) {
93-
hunk.offset = offset -= localOffset;
89+
return iterator();
90+
}
91+
92+
// We tried to fit hunk before text beginning and beyond text lenght, then
93+
// hunk can't fit on the text. Return undefined
94+
};
95+
}
96+
97+
// Search best fit offsets for each hunk based on the previous ones
98+
for (let i = 0; i < hunks.length; i++) {
99+
let hunk = hunks[i],
100+
maxLine = lines.length - hunk.oldLines,
101+
localOffset = 0,
102+
toPos = offset + hunk.oldStart - 1;
103+
104+
let iterator = distanceIterator(toPos, minLine, maxLine);
105+
106+
for (; localOffset != undefined; localOffset = iterator()) {
107+
if (hunkFits(hunk, toPos + localOffset)) {
108+
hunk.offset = offset += localOffset;
94109
break;
95110
}
96111
}
97112

113+
if (localOffset == undefined) {
114+
return false;
115+
}
116+
98117
// Set lower text limit to end of the current hunk, so next ones don't try
99118
// to fit over already patched text
100119
minLine = hunk.offset + hunk.oldStart + hunk.oldLines;

test/patch/apply.js

+22-1
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ describe('patch/apply', function() {
374374
+ 'line5\n');
375375
});
376376

377-
it('should succeed when hunk has an offset', function() {
377+
it('should succeed when hunk needs a negative offset', function() {
378378
expect(applyPatch(
379379
'line1\n'
380380
+ 'line3\n'
@@ -395,6 +395,27 @@ describe('patch/apply', function() {
395395
+ 'line5\n');
396396
});
397397

398+
it('should succeed when hunk needs a positive offset', function() {
399+
expect(applyPatch(
400+
'line1\n'
401+
+ 'line2\n'
402+
+ 'line3\n'
403+
+ 'line5\n',
404+
405+
'--- test\theader1\n'
406+
+ '+++ test\theader2\n'
407+
+ '@@ -1,2 +1,3 @@\n'
408+
+ ' line3\n'
409+
+ '+line4\n'
410+
+ ' line5\n'))
411+
.to.equal(
412+
'line1\n'
413+
+ 'line2\n'
414+
+ 'line3\n'
415+
+ 'line4\n'
416+
+ 'line5\n');
417+
});
418+
398419
it('should allow custom line comparison', function() {
399420
expect(applyPatch(
400421
'line2\n'

0 commit comments

Comments
 (0)