From 784ae1884abea583ae690d729a70a0c01b1517dd Mon Sep 17 00:00:00 2001 From: andyjy Date: Sat, 1 Apr 2023 16:20:06 +0100 Subject: [PATCH 1/3] Add --ignore-missing flag to continue without error on missing packages --- README.md | 8 ++++++++ .../__snapshots__/ignore-missing.test.ts.snap | 18 ++++++++++++++++++ .../ignore-missing/ignore-missing.sh | 17 +++++++++++++++++ .../ignore-missing/ignore-missing.test.ts | 5 +++++ integration-tests/ignore-missing/package.json | 11 +++++++++++ .../patches/left-pad+1.1.3.patch | 13 +++++++++++++ .../patches/missing-package+1.0.0.patch | 13 +++++++++++++ integration-tests/ignore-missing/yarn.lock | 8 ++++++++ src/applyPatches.ts | 12 ++++++++++-- src/index.ts | 16 ++++++++++++++-- 10 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 integration-tests/ignore-missing/__snapshots__/ignore-missing.test.ts.snap create mode 100755 integration-tests/ignore-missing/ignore-missing.sh create mode 100644 integration-tests/ignore-missing/ignore-missing.test.ts create mode 100644 integration-tests/ignore-missing/package.json create mode 100644 integration-tests/ignore-missing/patches/left-pad+1.1.3.patch create mode 100644 integration-tests/ignore-missing/patches/missing-package+1.0.0.patch create mode 100644 integration-tests/ignore-missing/yarn.lock diff --git a/README.md b/README.md index c3a910b0..1a01f25e 100644 --- a/README.md +++ b/README.md @@ -229,6 +229,14 @@ Run `patch-package` without arguments to apply all patches in your project. Specify the name for the directory in which the patch files are located +- `--ignore-missing` + + Ignores patches for packages that are not present in node_modules. + This is useful when working with monorepos and wanting to install sub-packages + separately from the root package, with pruned dependencies. + + See https://github.com/ds300/patch-package/issues/339 for background. + #### Notes To apply patches individually, you may use `git`: diff --git a/integration-tests/ignore-missing/__snapshots__/ignore-missing.test.ts.snap b/integration-tests/ignore-missing/__snapshots__/ignore-missing.test.ts.snap new file mode 100644 index 00000000..a8ea141e --- /dev/null +++ b/integration-tests/ignore-missing/__snapshots__/ignore-missing.test.ts.snap @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test ignore-missing: patch-package returns 1 on missing package 1`] = ` +"SNAPSHOT: patch-package returns 1 on missing package +Error: Patch file found for package missing-package which is not present at node_modules/missing-package +--- +patch-package finished with 1 error(s). +END SNAPSHOT" +`; + +exports[`Test ignore-missing: adding --ignore-missing forces patch-package to return 0 1`] = ` +"SNAPSHOT: adding --ignore-missing forces patch-package to return 0 +patch-package 0.0.0 +Applying patches... +left-pad@1.1.3 ✔ +Skipping missing missing-package@1.0.0 ✔ +END SNAPSHOT" +`; diff --git a/integration-tests/ignore-missing/ignore-missing.sh b/integration-tests/ignore-missing/ignore-missing.sh new file mode 100755 index 00000000..39a4c35d --- /dev/null +++ b/integration-tests/ignore-missing/ignore-missing.sh @@ -0,0 +1,17 @@ +# make sure errors stop the script +set -e + +echo "add patch-package" +yarn add $1 +alias patch-package=./node_modules/.bin/patch-package + +(>&2 echo "SNAPSHOT: patch-package returns 1 on missing package") +if patch-package; +then + exit 1 +fi +(>&2 echo "END SNAPSHOT") + +echo "SNAPSHOT: adding --ignore-missing forces patch-package to return 0" +patch-package --ignore-missing; +echo "END SNAPSHOT" diff --git a/integration-tests/ignore-missing/ignore-missing.test.ts b/integration-tests/ignore-missing/ignore-missing.test.ts new file mode 100644 index 00000000..5b5b8717 --- /dev/null +++ b/integration-tests/ignore-missing/ignore-missing.test.ts @@ -0,0 +1,5 @@ +import { runIntegrationTest } from "../runIntegrationTest" +runIntegrationTest({ + projectName: "ignore-missing", + shouldProduceSnapshots: true, +}) diff --git a/integration-tests/ignore-missing/package.json b/integration-tests/ignore-missing/package.json new file mode 100644 index 00000000..287cde3b --- /dev/null +++ b/integration-tests/ignore-missing/package.json @@ -0,0 +1,11 @@ +{ + "name": "ignore-missing", + "version": "1.0.0", + "description": "integration test for patch-package", + "main": "index.js", + "author": "", + "license": "ISC", + "dependencies": { + "left-pad": "1.1.3" + } +} diff --git a/integration-tests/ignore-missing/patches/left-pad+1.1.3.patch b/integration-tests/ignore-missing/patches/left-pad+1.1.3.patch new file mode 100644 index 00000000..0600ef9f --- /dev/null +++ b/integration-tests/ignore-missing/patches/left-pad+1.1.3.patch @@ -0,0 +1,13 @@ +diff --git a/node_modules/left-pad/index.js b/node_modules/left-pad/index.js +index 26f73ff..60f3f56 100644 +--- a/node_modules/left-pad/index.js ++++ b/node_modules/left-pad/index.js +@@ -4,7 +4,7 @@ + * To Public License, Version 2, as published by Sam Hocevar. See + * http://www.wtfpl.net/ for more details. */ + 'use strict'; +-module.exports = leftPad; ++module.exports = patch-package; + + var cache = [ + '', diff --git a/integration-tests/ignore-missing/patches/missing-package+1.0.0.patch b/integration-tests/ignore-missing/patches/missing-package+1.0.0.patch new file mode 100644 index 00000000..e294d98b --- /dev/null +++ b/integration-tests/ignore-missing/patches/missing-package+1.0.0.patch @@ -0,0 +1,13 @@ +diff --git a/node_modules/left-pad/index.js b/node_modules/left-pad/index.js +index 26f73ff..60f3f56 100644 +--- a/node_modules/left-pad/index.js ++++ b/node_modules/left-pad/index.js +@@ -7,7 +7,7 @@ + module.exports = leftPad; + + var cache = [ +- '', ++ "", + ' ', + ' ', + ' ', \ No newline at end of file diff --git a/integration-tests/ignore-missing/yarn.lock b/integration-tests/ignore-missing/yarn.lock new file mode 100644 index 00000000..392d269a --- /dev/null +++ b/integration-tests/ignore-missing/yarn.lock @@ -0,0 +1,8 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +left-pad@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.1.3.tgz#612f61c033f3a9e08e939f1caebeea41b6f3199a" + integrity sha1-YS9hwDPzqeCOk58crr7qQbbzGZo= diff --git a/src/applyPatches.ts b/src/applyPatches.ts index 1a50d094..91207615 100644 --- a/src/applyPatches.ts +++ b/src/applyPatches.ts @@ -31,18 +31,23 @@ function getInstalledPackageVersion({ pathSpecifier, isDevOnly, patchFilename, + ignoreMissing, }: { appPath: string path: string pathSpecifier: string isDevOnly: boolean patchFilename: string + ignoreMissing: boolean }): null | string { const packageDir = join(appPath, path) if (!existsSync(packageDir)) { if (process.env.NODE_ENV === "production" && isDevOnly) { return null } + if (ignoreMissing) { + return null + } let err = `${chalk.red("Error:")} Patch file found for package ${posix.basename( @@ -98,6 +103,7 @@ export function applyPatchesForApp({ shouldExitWithError, shouldExitWithWarning, bestEffort, + ignoreMissing, }: { appPath: string reverse: boolean @@ -105,6 +111,7 @@ export function applyPatchesForApp({ shouldExitWithError: boolean shouldExitWithWarning: boolean bestEffort: boolean + ignoreMissing: boolean }): void { const patchesDirectory = join(appPath, patchDir) const groupedPatches = getGroupedPatches(patchesDirectory) @@ -245,11 +252,12 @@ export function applyPatchesForPackage({ patchDetails, })), patchFilename, + ignoreMissing, }) if (!installedPackageVersion) { - // it's ok we're in production mode and this is a dev only package + // it's ok we're ignoring missing packages OR in production mode and this is a dev only package console.log( - `Skipping dev-only ${chalk.bold( + `Skipping ${ignoreMissing ? "missing" : "dev-only"} ${chalk.bold( pathSpecifier, )}@${version} ${chalk.blue("✔")}`, ) diff --git a/src/index.ts b/src/index.ts index 8ee449a9..948d8607 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,6 +26,7 @@ const argv = minimist(process.argv.slice(2), { "create-issue", "partial", "", + "ignore-missing", ], string: ["patch-dir", "append", "rebase"], }) @@ -115,6 +116,8 @@ if (argv.version || argv.v) { const shouldExitWithWarning = !!argv["error-on-warn"] + const ignoreMissing = !!argv["ignore-missing"] + applyPatchesForApp({ appPath, reverse, @@ -122,6 +125,7 @@ if (argv.version || argv.v) { shouldExitWithError, shouldExitWithWarning, bestEffort: argv.partial, + ignoreMissing, }) } } @@ -178,13 +182,21 @@ Usage: and patch file updates (https://github.com/ds300/patch-package/issues/37), but might be useful in other contexts too. + ${chalk.bold("--ignore-missing")} + + Ignores patches for packages that are not present in node_modules. + This is useful when working with monorepos and wanting to install sub-packages + separately from the root package, with pruned dependencies. + + See https://github.com/ds300/patch-package/issues/339 for background. + 2. Creating patch files ======================= ${chalk.bold("patch-package")} ${chalk.italic( - "[ ]", - )} + "[ ]", + )} When given package names as arguments, patch-package will create patch files based on any changes you've made to the versions installed by yarn/npm. From bf1c9e3ced629e5cfbad152aca6ebfb8a4d7ce4e Mon Sep 17 00:00:00 2001 From: andyjy Date: Wed, 5 Jul 2023 15:27:20 +0100 Subject: [PATCH 2/3] add support for PATCH_PACKAGE_IGNORE_MISSING env var --- .../__snapshots__/ignore-missing.test.ts.snap | 9 +++++++++ integration-tests/ignore-missing/ignore-missing.sh | 5 +++++ src/index.ts | 10 +++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/integration-tests/ignore-missing/__snapshots__/ignore-missing.test.ts.snap b/integration-tests/ignore-missing/__snapshots__/ignore-missing.test.ts.snap index a8ea141e..a1b3ff33 100644 --- a/integration-tests/ignore-missing/__snapshots__/ignore-missing.test.ts.snap +++ b/integration-tests/ignore-missing/__snapshots__/ignore-missing.test.ts.snap @@ -16,3 +16,12 @@ left-pad@1.1.3 ✔ Skipping missing missing-package@1.0.0 ✔ END SNAPSHOT" `; + +exports[`Test ignore-missing: setting PATCH_PACKAGE_IGNORE_MISSING=1 forces patch-package to return 0 1`] = ` +"SNAPSHOT: setting PATCH_PACKAGE_IGNORE_MISSING=1 forces patch-package to return 0 +patch-package 0.0.0 +Applying patches... +left-pad@1.1.3 ✔ +Skipping missing missing-package@1.0.0 ✔ +END SNAPSHOT" +`; diff --git a/integration-tests/ignore-missing/ignore-missing.sh b/integration-tests/ignore-missing/ignore-missing.sh index 39a4c35d..b44f60f5 100755 --- a/integration-tests/ignore-missing/ignore-missing.sh +++ b/integration-tests/ignore-missing/ignore-missing.sh @@ -15,3 +15,8 @@ fi echo "SNAPSHOT: adding --ignore-missing forces patch-package to return 0" patch-package --ignore-missing; echo "END SNAPSHOT" + +export PATCH_PACKAGE_IGNORE_MISSING=1 +echo "SNAPSHOT: setting PATCH_PACKAGE_IGNORE_MISSING=1 forces patch-package to return 0" +patch-package; +echo "END SNAPSHOT" diff --git a/src/index.ts b/src/index.ts index 948d8607..b2ac0c24 100644 --- a/src/index.ts +++ b/src/index.ts @@ -116,7 +116,8 @@ if (argv.version || argv.v) { const shouldExitWithWarning = !!argv["error-on-warn"] - const ignoreMissing = !!argv["ignore-missing"] + const ignoreMissing = + !!argv["ignore-missing"] || !!process.env.PATCH_PACKAGE_IGNORE_MISSING applyPatchesForApp({ appPath, @@ -188,6 +189,13 @@ Usage: This is useful when working with monorepos and wanting to install sub-packages separately from the root package, with pruned dependencies. + This option is can also be set via the environment variable + PATCH_PACKAGE_IGNORE_MISSING=1. Setting this env variable during the deployment + build process is recommended instead of using the --ignore-missing command option + when we want to ignore missing packages during deployment (of a monorepo with + pruned dependencies), but ensure we fail loudly during development if any + dependencies are moved or removed without updating the patches accordingly. + See https://github.com/ds300/patch-package/issues/339 for background. From 732fd0f8f2db7d25041da8c867579e3f21fdc8fa Mon Sep 17 00:00:00 2001 From: andyjy Date: Sat, 2 May 2026 21:36:40 +0100 Subject: [PATCH 3/3] fix patch for upstream v8.0.1 --- src/applyPatches.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/applyPatches.ts b/src/applyPatches.ts index 91207615..8627ff62 100644 --- a/src/applyPatches.ts +++ b/src/applyPatches.ts @@ -135,6 +135,7 @@ export function applyPatchesForApp({ warnings, errors, bestEffort, + ignoreMissing, }) } @@ -177,6 +178,7 @@ export function applyPatchesForPackage({ warnings, errors, bestEffort, + ignoreMissing, }: { patches: PatchedPackageDetails[] appPath: string @@ -185,6 +187,7 @@ export function applyPatchesForPackage({ warnings: string[] errors: string[] bestEffort: boolean + ignoreMissing: boolean }) { const pathSpecifier = patches[0].pathSpecifier const state = patches.length > 1 ? getPatchApplicationState(patches[0]) : null