Skip to content

Commit 4a17770

Browse files
authored
Merge pull request #217 from akwodkiewicz/feature/ignore-errors-option
Add --ignore-errors option
2 parents 2f1c855 + a82bbed commit 4a17770

File tree

3 files changed

+144
-93
lines changed

3 files changed

+144
-93
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ Run `patch-package` without arguments to apply all patches in your project.
169169

170170
Specify the name for the directory in which the patch files are located
171171

172+
- `--ignore-errors`
173+
174+
Try to apply all of the patches, even if some of them fail.
175+
172176
#### Notes
173177

174178
To apply patches individually, you may use `git`:

src/applyPatches.ts

Lines changed: 98 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ function getInstalledPackageVersion({
6262
)
6363
}
6464

65-
exit()
65+
throw new Error("applyPatches")
6666
}
6767

6868
const { version } = require(join(packageDir, "package.json"))
@@ -78,7 +78,7 @@ function getInstalledPackageVersion({
7878
)}`,
7979
)
8080

81-
exit()
81+
throw new Error("applyPatches")
8282
}
8383

8484
return result as string
@@ -87,10 +87,12 @@ function getInstalledPackageVersion({
8787
export function applyPatchesForApp({
8888
appPath,
8989
reverse,
90+
ignoreErrors,
9091
patchDir,
9192
}: {
9293
appPath: string
9394
reverse: boolean
95+
ignoreErrors: boolean
9496
patchDir: string
9597
}): void {
9698
const patchesDirectory = join(appPath, patchDir)
@@ -101,91 +103,112 @@ export function applyPatchesForApp({
101103
return
102104
}
103105

104-
files.forEach(filename => {
105-
const packageDetails = getPackageDetailsFromPatchFilename(filename)
106+
let hasFailed = false
107+
files.forEach((filename, idx) => {
108+
try {
109+
const packageDetails = getPackageDetailsFromPatchFilename(filename)
106110

107-
if (!packageDetails) {
108-
console.warn(`Unrecognized patch file in patches directory ${filename}`)
109-
return
110-
}
111+
if (!packageDetails) {
112+
console.warn(`Unrecognized patch file in patches directory ${filename}`)
113+
return
114+
}
111115

112-
const {
113-
name,
114-
version,
115-
path,
116-
pathSpecifier,
117-
isDevOnly,
118-
patchFilename,
119-
} = packageDetails
120-
121-
const installedPackageVersion = getInstalledPackageVersion({
122-
appPath,
123-
path,
124-
pathSpecifier,
125-
isDevOnly:
126-
isDevOnly ||
127-
// check for direct-dependents in prod
128-
(process.env.NODE_ENV === "production" &&
129-
packageIsDevDependency({ appPath, packageDetails })),
130-
patchFilename,
131-
})
132-
if (!installedPackageVersion) {
133-
// it's ok we're in production mode and this is a dev only package
134-
console.log(
135-
`Skipping dev-only ${chalk.bold(pathSpecifier)}@${version} ${chalk.blue(
136-
"✔",
137-
)}`,
138-
)
139-
return
140-
}
116+
const {
117+
name,
118+
version,
119+
path,
120+
pathSpecifier,
121+
isDevOnly,
122+
patchFilename,
123+
} = packageDetails
141124

142-
if (
143-
applyPatch({
144-
patchFilePath: resolve(patchesDirectory, filename) as string,
145-
reverse,
146-
packageDetails,
147-
patchDir,
125+
const installedPackageVersion = getInstalledPackageVersion({
126+
appPath,
127+
path,
128+
pathSpecifier,
129+
isDevOnly:
130+
isDevOnly ||
131+
// check for direct-dependents in prod
132+
(process.env.NODE_ENV === "production" &&
133+
packageIsDevDependency({ appPath, packageDetails })),
134+
patchFilename,
148135
})
149-
) {
150-
// yay patch was applied successfully
151-
// print warning if version mismatch
152-
if (installedPackageVersion !== version) {
153-
printVersionMismatchWarning({
154-
packageName: name,
155-
actualVersion: installedPackageVersion,
156-
originalVersion: version,
157-
pathSpecifier,
158-
path,
159-
})
160-
} else {
136+
if (!installedPackageVersion) {
137+
// it's ok we're in production mode and this is a dev only package
161138
console.log(
162-
`${chalk.bold(pathSpecifier)}@${version} ${chalk.green("✔")}`,
139+
`Skipping dev-only ${chalk.bold(
140+
pathSpecifier,
141+
)}@${version} ${chalk.blue("✔")}`,
163142
)
143+
return
164144
}
165-
} else {
166-
// completely failed to apply patch
167-
// TODO: propagate useful error messages from patch application
168-
if (installedPackageVersion === version) {
169-
printBrokenPatchFileError({
170-
packageName: name,
171-
patchFileName: filename,
172-
pathSpecifier,
173-
path,
145+
146+
if (
147+
applyPatch({
148+
patchFilePath: resolve(patchesDirectory, filename) as string,
149+
reverse,
150+
packageDetails,
151+
patchDir,
174152
})
153+
) {
154+
// yay patch was applied successfully
155+
// print warning if version mismatch
156+
if (installedPackageVersion !== version) {
157+
printVersionMismatchWarning({
158+
packageName: name,
159+
actualVersion: installedPackageVersion,
160+
originalVersion: version,
161+
pathSpecifier,
162+
path,
163+
})
164+
} else {
165+
console.log(
166+
`${chalk.bold(pathSpecifier)}@${version} ${chalk.green("✔")}`,
167+
)
168+
}
175169
} else {
176-
printPatchApplictionFailureError({
177-
packageName: name,
178-
actualVersion: installedPackageVersion,
179-
originalVersion: version,
180-
patchFileName: filename,
181-
path,
182-
pathSpecifier,
183-
})
170+
// completely failed to apply patch
171+
// TODO: propagate useful error messages from patch application
172+
if (installedPackageVersion === version) {
173+
printBrokenPatchFileError({
174+
packageName: name,
175+
patchFileName: filename,
176+
pathSpecifier,
177+
path,
178+
})
179+
} else {
180+
printPatchApplictionFailureError({
181+
packageName: name,
182+
actualVersion: installedPackageVersion,
183+
originalVersion: version,
184+
patchFileName: filename,
185+
path,
186+
pathSpecifier,
187+
})
188+
}
189+
190+
throw new Error("applyPatches")
191+
}
192+
} catch (err) {
193+
if (err.message !== "applyPatches") {
194+
throw err
195+
}
196+
if (!ignoreErrors) {
197+
exit()
198+
}
199+
hasFailed = true
200+
if (idx < files.length - 1) {
201+
console.warn(
202+
`${chalk.yellow("Warning:")} Option ${chalk.bold(
203+
"--ignore-errors",
204+
)} was set, moving on to next patch.`,
205+
)
184206
}
185-
186-
exit()
187207
}
188208
})
209+
if (hasFailed) {
210+
exit()
211+
}
189212
}
190213

191214
export function applyPatch({

src/index.ts

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const argv = minimist(process.argv.slice(2), {
1616
boolean: [
1717
"use-yarn",
1818
"case-sensitive-path-filtering",
19+
"ignore-errors",
1920
"reverse",
2021
"help",
2122
"version",
@@ -69,7 +70,8 @@ if (argv.version || argv.v) {
6970
} else {
7071
console.log("Applying patches...")
7172
const reverse = !!argv["reverse"]
72-
applyPatchesForApp({ appPath, reverse, patchDir })
73+
const ignoreErrors = !!argv["ignore-errors"]
74+
applyPatchesForApp({ appPath, reverse, ignoreErrors, patchDir })
7375
}
7476
}
7577

@@ -89,6 +91,28 @@ Usage:
8991
9092
./patches/<package-name>+<version>.patch
9193
94+
Options:
95+
96+
${chalk.bold("--patch-dir <dirname>")}
97+
98+
Specify the name for the directory in which the patch files are located.
99+
100+
${chalk.bold("--ignore-errors")}
101+
102+
Try to apply all of the patches, even if some of them fail.
103+
104+
${chalk.bold("--reverse")}
105+
106+
Un-applies all patches.
107+
108+
Note that this will fail if the patched files have changed since being
109+
patched. In that case, you'll probably need to re-install 'node_modules'.
110+
111+
This option was added to help people using CircleCI avoid an issue around caching
112+
and patch file updates (https://github.com/ds300/patch-package/issues/37),
113+
but might be useful in other contexts too.
114+
115+
92116
2. Creating patch files
93117
=======================
94118
@@ -101,32 +125,32 @@ Usage:
101125
102126
Options:
103127
104-
${chalk.bold("--use-yarn")}
105-
106-
By default, patch-package checks whether you use npm or yarn based on
107-
which lockfile you have. If you have both, it uses npm by default.
108-
Set this option to override that default and always use yarn.
128+
${chalk.bold("--use-yarn")}
109129
110-
${chalk.bold("--exclude <regexp>")}
130+
By default, patch-package checks whether you use npm or yarn based on
131+
which lockfile you have. If you have both, it uses npm by default.
132+
Set this option to override that default and always use yarn.
111133
112-
Ignore paths matching the regexp when creating patch files.
113-
Paths are relative to the root dir of the package to be patched.
134+
${chalk.bold("--exclude <regexp>")}
114135
115-
Default: 'package\\.json$'
136+
Ignore paths matching the regexp when creating patch files.
137+
Paths are relative to the root dir of the package to be patched.
116138
117-
${chalk.bold("--include <regexp>")}
139+
Default: 'package\\.json$'
118140
119-
Only consider paths matching the regexp when creating patch files.
120-
Paths are relative to the root dir of the package to be patched.
141+
${chalk.bold("--include <regexp>")}
121142
122-
Default '.*'
143+
Only consider paths matching the regexp when creating patch files.
144+
Paths are relative to the root dir of the package to be patched.
123145
124-
${chalk.bold("--case-sensitive-path-filtering")}
146+
Default '.*'
125147
126-
Make regexps used in --include or --exclude filters case-sensitive.
148+
${chalk.bold("--case-sensitive-path-filtering")}
127149
128-
${chalk.bold("--patch-dir")}
150+
Make regexps used in --include or --exclude filters case-sensitive.
151+
152+
${chalk.bold("--patch-dir")}
129153
130-
Specify the name for the directory in which to put the patch files.
154+
Specify the name for the directory in which to put the patch files.
131155
`)
132156
}

0 commit comments

Comments
 (0)