Skip to content

Commit

Permalink
add --partial option
Browse files Browse the repository at this point in the history
  • Loading branch information
ds300 committed Jul 27, 2023
1 parent 1981d42 commit cced41a
Show file tree
Hide file tree
Showing 17 changed files with 293 additions and 37 deletions.
21 changes: 19 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,17 @@ Then, update your hash key to include a checksum of that file:
```yaml
- restore_cache:
key:
app-node_modules-v1-{{ checksum "yarn.lock" }}-{{ checksum "patches.hash" }}
app-node_modules-v1-{{ checksum "yarn.lock" }}-{{ checksum "patches.hash"
}}
```
As well as the save_cache
```yaml
- save_cache:
key:
app-node_modules-v1-{{ checksum "yarn.lock" }}-{{ checksum "patches.hash" }}
app-node_modules-v1-{{ checksum "yarn.lock" }}-{{ checksum "patches.hash"
}}
paths:
- ./node_modules
```
Expand Down Expand Up @@ -342,6 +344,21 @@ If you deleted one of the patch files other than the last one, you don't need to
update the sequence numbers in the successive patch file names, but you might
want to do so to keep things tidy.

#### Partially applying a broken patch file

Normally patch application is atomic per patch file. i.e. if a patch file
contains an error anywhere then none of the changes in the patch file will be
applied and saved to disk.

This can be problematic if you have a patch with many changes and you want to
keep some of them and update others.

In this case you can use the `--partial` option. Patch-package will apply as
many of the changes as it can and then leave it to you to fix the rest.

Any errors encountered will be written to a file `./patch-package-errors.log` to
help you keep track of what needs fixing.

## Benefits of patching over forking

- Sometimes forks need extra build steps, e.g. with react-native for Android.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Test partial-apply: 00: patch-package fails when one of the patches in the sequence fails 1`] = `
"SNAPSHOT: patch-package fails when one of the patches in the sequence fails
patch-package 0.0.0
Applying patches...
left-pad@1.3.0 (1 hello) ✔
⛔ ERROR
Failed to apply patch file left-pad+1.3.0+002+world.patch.
If this patch file is no longer useful, delete it and run
patch-package
To partially apply the patch (if possible) and output a log of errors to fix, run
patch-package --partial
After which you should make any required changes inside node_modules/left-pad, and finally run
patch-package left-pad
to update the patch file.
END SNAPSHOT"
`;

exports[`Test partial-apply: 01: patch-package --partial saves a log 1`] = `
"SNAPSHOT: patch-package --partial saves a log
patch-package 0.0.0
Applying patches...
left-pad@1.3.0 (1 hello) ✔
Saving errors to ./patch-package-errors.log
patch-package-errors.log
Cannot apply hunk 0 for file node_modules/left-pad/index.js
\`\`\`diff
@@ -3,7 +3,7 @@
* and/or modify it under the terms of the Do What The Fuck You Want
* To Public License, Version 2, as published by Sam Hocevar. See
* http://www.wtfpl.net/ for more details. */
-'use oops';
+'use world';
module.exports = leftPad;
var cache = [
\`\`\`
END SNAPSHOT"
`;
22 changes: 22 additions & 0 deletions integration-tests/partial-apply/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions integration-tests/partial-apply/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "partial-apply",
"version": "1.0.0",
"description": "integration test for patch-package",
"main": "index.js",
"author": "",
"license": "ISC",
"dependencies": {
"left-pad": "^1.3.0"
}
}
26 changes: 26 additions & 0 deletions integration-tests/partial-apply/partial-apply.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash
# make sure errors stop the script
set -e

npm install

echo "add patch-package"
npm add $1

function patch-package {
./node_modules/.bin/patch-package "$@"
}

echo "SNAPSHOT: patch-package fails when one of the patches in the sequence fails"
if patch-package
then
exit 1
fi
echo "END SNAPSHOT"


echo "SNAPSHOT: patch-package --partial saves a log"
patch-package --partial
echo 'patch-package-errors.log'
cat patch-package-errors.log
echo "END SNAPSHOT"
5 changes: 5 additions & 0 deletions integration-tests/partial-apply/partial-apply.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { runIntegrationTest } from "../runIntegrationTest"
runIntegrationTest({
projectName: "partial-apply",
shouldProduceSnapshots: true,
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/node_modules/left-pad/index.js b/node_modules/left-pad/index.js
index e90aec3..1a2ec5f 100644
--- a/node_modules/left-pad/index.js
+++ b/node_modules/left-pad/index.js
@@ -3,7 +3,7 @@
* and/or modify it under the terms of the Do What The Fuck You Want
* To Public License, Version 2, as published by Sam Hocevar. See
* http://www.wtfpl.net/ for more details. */
-'use strict';
+'use hello';
module.exports = leftPad;

var cache = [
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/node_modules/left-pad/index.js b/node_modules/left-pad/index.js
index 1a2ec5f..5aa41be 100644
--- a/node_modules/left-pad/index.js
+++ b/node_modules/left-pad/index.js
@@ -3,7 +3,7 @@
* and/or modify it under the terms of the Do What The Fuck You Want
* To Public License, Version 2, as published by Sam Hocevar. See
* http://www.wtfpl.net/ for more details. */
-'use oops';
+'use world';
module.exports = leftPad;

var cache = [
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/node_modules/left-pad/index.js b/node_modules/left-pad/index.js
index 5aa41be..5ee751b 100644
--- a/node_modules/left-pad/index.js
+++ b/node_modules/left-pad/index.js
@@ -3,7 +3,7 @@
* and/or modify it under the terms of the Do What The Fuck You Want
* To Public License, Version 2, as published by Sam Hocevar. See
* http://www.wtfpl.net/ for more details. */
-'use world';
+'goodbye world';
module.exports = leftPad;

var cache = [
4 changes: 2 additions & 2 deletions property-based-tests/executeTestCase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export function executeTestCase(testCase: TestCase) {
fs.setWorkingFiles({ ...testCase.cleanFiles })
reportingFailures(() => {
const effects = parsePatchFile(patchFileContents)
executeEffects(effects, { dryRun: false })
executeEffects(effects, { dryRun: false, bestEffort: false })
expect(fs.getWorkingFiles()).toEqual(testCase.modifiedFiles)
})
})
Expand All @@ -141,7 +141,7 @@ export function executeTestCase(testCase: TestCase) {
fs.setWorkingFiles({ ...testCase.modifiedFiles })
reportingFailures(() => {
const effects = reversePatch(parsePatchFile(patchFileContents))
executeEffects(effects, { dryRun: false })
executeEffects(effects, { dryRun: false, bestEffort: false })
expect(fs.getWorkingFiles()).toEqual(testCase.cleanFiles)
})
})
Expand Down
25 changes: 23 additions & 2 deletions src/applyPatches.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import chalk from "chalk"
import { writeFileSync } from "fs"
import { existsSync } from "fs-extra"
import { posix } from "path"
import semver from "semver"
Expand Down Expand Up @@ -96,12 +97,14 @@ export function applyPatchesForApp({
patchDir,
shouldExitWithError,
shouldExitWithWarning,
bestEffort,
}: {
appPath: string
reverse: boolean
patchDir: string
shouldExitWithError: boolean
shouldExitWithWarning: boolean
bestEffort: boolean
}): void {
const patchesDirectory = join(appPath, patchDir)
const groupedPatches = getGroupedPatches(patchesDirectory)
Expand All @@ -124,6 +127,7 @@ export function applyPatchesForApp({
reverse,
warnings,
errors,
bestEffort,
})
}

Expand Down Expand Up @@ -165,13 +169,15 @@ export function applyPatchesForPackage({
reverse,
warnings,
errors,
bestEffort,
}: {
patches: PatchedPackageDetails[]
appPath: string
patchDir: string
reverse: boolean
warnings: string[]
errors: string[]
bestEffort: boolean
}) {
const pathSpecifier = patches[0].pathSpecifier
const state = patches.length > 1 ? getPatchApplicationState(patches[0]) : null
Expand Down Expand Up @@ -257,6 +263,7 @@ export function applyPatchesForPackage({
patchDetails,
patchDir,
cwd: process.cwd(),
bestEffort,
})
) {
appliedPatches.push(patchDetails)
Expand Down Expand Up @@ -397,12 +404,14 @@ export function applyPatch({
patchDetails,
patchDir,
cwd,
bestEffort,
}: {
patchFilePath: string
reverse: boolean
patchDetails: PackageDetails
patchDir: string
cwd: string
bestEffort: boolean
}): boolean {
const patch = readPatch({
patchFilePath,
Expand All @@ -412,14 +421,26 @@ export function applyPatch({

const forward = reverse ? reversePatch(patch) : patch
try {
executeEffects(forward, { dryRun: true, cwd })
executeEffects(forward, { dryRun: false, cwd })
if (!bestEffort) {
executeEffects(forward, { dryRun: true, cwd, bestEffort: false })
}
const errors: string[] | undefined = bestEffort ? [] : undefined
executeEffects(forward, { dryRun: false, cwd, bestEffort, errors })
if (errors?.length) {
console.log(
"Saving errors to",
chalk.cyan.bold("./patch-package-errors.log"),
)
writeFileSync("patch-package-errors.log", errors.join("\n\n"))
process.exit(0)
}
} catch (e) {
try {
const backward = reverse ? patch : reversePatch(patch)
executeEffects(backward, {
dryRun: true,
cwd,
bestEffort: false,
})
} catch (e) {
return false
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const argv = minimist(process.argv.slice(2), {
"error-on-fail",
"error-on-warn",
"create-issue",
"partial",
"",
],
string: ["patch-dir", "append", "rebase"],
Expand Down Expand Up @@ -120,6 +121,7 @@ if (argv.version || argv.v) {
patchDir,
shouldExitWithError,
shouldExitWithWarning,
bestEffort: argv.partial,
})
}
}
Expand Down
16 changes: 11 additions & 5 deletions src/makePatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ export function makePatch({
})
} catch (e) {
// try again while ignoring scripts in case the script depends on
// an implicit context which we havn't reproduced
// an implicit context which we haven't reproduced
spawnSafeSync(
`yarn`,
["install", "--ignore-engines", "--ignore-scripts"],
Expand All @@ -238,7 +238,7 @@ export function makePatch({
})
} catch (e) {
// try again while ignoring scripts in case the script depends on
// an implicit context which we havn't reproduced
// an implicit context which we haven't reproduced
spawnSafeSync(`npm`, ["i", "--ignore-scripts", "--force"], {
cwd: tmpRepoNpmRoot,
stdio: "ignore",
Expand Down Expand Up @@ -278,6 +278,7 @@ export function makePatch({
patchFilePath: join(appPath, patchDir, patchDetails.patchFilename),
reverse: false,
cwd: tmpRepo.name,
bestEffort: false,
})
) {
// TODO: add better error message once --rebase is implemented
Expand Down Expand Up @@ -498,6 +499,7 @@ export function makePatch({
patchFilePath,
reverse: false,
cwd: process.cwd(),
bestEffort: false,
})
) {
didFailWhileFinishingRebase = true
Expand Down Expand Up @@ -587,10 +589,14 @@ Failed to apply patch file ${chalk.bold(patchDetails.patchFilename)}.
If this patch file is no longer useful, delete it and run
${chalk.bold(`patch-package`)}
Otherwise you should open ${
To partially apply the patch (if possible) and output a log of errors to fix, run
${chalk.bold(`patch-package --partial`)}
After which you should make any required changes inside ${
patchDetails.path
}, manually apply the changes from the patch file, and run
}, and finally run
${chalk.bold(`patch-package ${patchDetails.pathSpecifier}`)}
Expand Down
Loading

0 comments on commit cced41a

Please sign in to comment.