Skip to content

Commit 9bfcf30

Browse files
committed
fix --reverse behavior
1 parent e941f97 commit 9bfcf30

File tree

3 files changed

+65
-20
lines changed

3 files changed

+65
-20
lines changed

integration-tests/apply-multiple-patches/apply-multiple-patches.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ then
3333
fi
3434
(>&2 echo "END SNAPSHOT")
3535

36+
3637
echo "SNAPSHOT: patch-package only applies the first patch if the second of three is invalid"
3738
if patch-package
3839
then

integration-tests/reverse-multiple-patches/__snapshots__/reverse-multiple-patches.test.ts.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ [email protected] (3 goodbye) ✔
2626
END SNAPSHOT"
2727
`;
2828

29-
exports[`Test reverse-multiple-patches: 03: if one of the patches fails then reverse only ondoes the ones that succeeded 1`] = `
30-
"SNAPSHOT: if one of the patches fails then reverse only ondoes the ones that succeeded
29+
exports[`Test reverse-multiple-patches: 03: if one of the patches fails then reverse only undoes the ones that succeeded 1`] = `
30+
"SNAPSHOT: if one of the patches fails then reverse only undoes the ones that succeeded
3131
patches/left-pad+1.3.0+003+goodbye.patch
3232
9: -'use schmorld';
3333
10: +'goodbye schmorld';

src/applyPatches.ts

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import { join, relative, resolve } from "./path"
1313
import {
1414
clearPatchApplicationState,
1515
getPatchApplicationState,
16-
PatchState,
1716
savePatchApplicationState,
1817
} from "./stateFile"
1918

@@ -118,8 +117,8 @@ export function applyPatchesForApp({
118117
)) {
119118
const state =
120119
patches.length > 1 ? getPatchApplicationState(patches[0]) : null
121-
let unappliedPatches = patches.slice(0)
122-
const newState: PatchState[] | null = patches.length > 1 ? [] : null
120+
const unappliedPatches = patches.slice(0)
121+
const appliedPatches: PatchedPackageDetails[] = []
123122
// if there are multiple patches to apply, we can't rely on the reverse-patch-dry-run behavior to make this operation
124123
// idempotent, so instead we need to check the state file to see whether we have already applied any of the patches
125124
// todo: once this is battle tested we might want to use the same approach for single patches as well, but it's not biggie since the dry run thing is fast
@@ -132,7 +131,7 @@ export function applyPatchesForApp({
132131
)
133132
if (patchThatWasApplied.patchContentHash === currentPatchHash) {
134133
// this patch was applied we can skip it
135-
unappliedPatches.shift()
134+
appliedPatches.push(unappliedPatches.shift()!)
136135
} else {
137136
console.error(
138137
chalk.red("Error:"),
@@ -144,14 +143,21 @@ export function applyPatchesForApp({
144143
}
145144
}
146145

147-
if (reverse) {
148-
unappliedPatches = patches
149-
.slice(0, patches.length - unappliedPatches.length)
150-
.reverse()
146+
if (reverse && state) {
147+
// if we are reversing the patches we need to make the unappliedPatches array
148+
// be the reversed version of the appliedPatches array.
149+
// The applied patches array should then be empty because it is used differently
150+
// when outputting the state file.
151+
unappliedPatches.length = 0
152+
unappliedPatches.push(...appliedPatches)
153+
unappliedPatches.reverse()
154+
appliedPatches.length = 0
151155
}
152-
if (unappliedPatches.length === 0) {
156+
if (appliedPatches.length) {
153157
// all patches have already been applied
154-
patches.forEach(logPatchApplication)
158+
appliedPatches.forEach(logPatchApplication)
159+
}
160+
if (!unappliedPatches.length) {
155161
continue
156162
}
157163
packageLoop: for (const patchDetails of unappliedPatches) {
@@ -191,11 +197,7 @@ export function applyPatchesForApp({
191197
cwd: process.cwd(),
192198
})
193199
) {
194-
newState?.push({
195-
patchFilename,
196-
patchContentHash: hashFile(join(appPath, patchDir, patchFilename)),
197-
didApply: true,
198-
})
200+
appliedPatches.push(patchDetails)
199201
// yay patch was applied successfully
200202
// print warning if version mismatch
201203
if (installedPackageVersion !== version) {
@@ -256,11 +258,53 @@ export function applyPatchesForApp({
256258
}
257259
}
258260

259-
if (newState) {
261+
if (patches.length > 1) {
260262
if (reverse) {
261-
clearPatchApplicationState(patches[0])
263+
if (!state) {
264+
throw new Error(
265+
"unexpected state: no state file found while reversing",
266+
)
267+
}
268+
// if we removed all the patches that were previously applied we can delete the state file
269+
if (appliedPatches.length === patches.length) {
270+
clearPatchApplicationState(patches[0])
271+
} else {
272+
// We failed while reversing patches and some are still in the applied state.
273+
// We need to update the state file to reflect that.
274+
// appliedPatches is currently the patches that were successfully reversed, in the order they were reversed
275+
// So we need to find the index of the last reversed patch in the original patches array
276+
// and then remove all the patches after that. Sorry for the confusing code.
277+
const lastReversedPatchIndex = patches.indexOf(
278+
appliedPatches[appliedPatches.length - 1],
279+
)
280+
if (lastReversedPatchIndex === -1) {
281+
throw new Error(
282+
"unexpected state: failed to find last reversed patch in original patches array",
283+
)
284+
}
285+
286+
savePatchApplicationState(
287+
patches[0],
288+
patches.slice(0, lastReversedPatchIndex).map((patch) => ({
289+
didApply: true,
290+
patchContentHash: hashFile(
291+
join(appPath, patchDir, patch.patchFilename),
292+
),
293+
patchFilename: patch.patchFilename,
294+
})),
295+
)
296+
}
262297
} else {
263-
savePatchApplicationState(patches[0], newState)
298+
savePatchApplicationState(
299+
patches[0],
300+
appliedPatches.map((patch) => ({
301+
didApply: true,
302+
patchContentHash: hashFile(
303+
join(appPath, patchDir, patch.patchFilename),
304+
),
305+
patchFilename: patch.patchFilename,
306+
})),
307+
)
264308
}
265309
}
266310
}

0 commit comments

Comments
 (0)