lint-staged 16.2.4 → 16.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import spawn from 'nano-spawn'
1
+ import spawn, { SubprocessError } from 'nano-spawn'
2
2
  import pidtree from 'pidtree'
3
3
  import { parseArgsStringToArgv } from 'string-argv'
4
4
 
@@ -30,11 +30,17 @@ const handleOutput = (command, result, ctx, isError = false) => {
30
30
  const outputTitle = isError ? red(`${error} ${command}:`) : `${info} ${command}:`
31
31
  const output = [...(ctx.quiet ? [] : ['', outputTitle]), result.output]
32
32
  ctx.output.push(output.join('\n'))
33
+ }
34
+
35
+ if (ctx.quiet) return
36
+
37
+ if (result instanceof SubprocessError) {
38
+ ctx.output.push(red(`\n${error} ${command} failed to spawn:`), result.message, result.cause)
33
39
  } else if (isError) {
34
40
  // Show generic error when task had no output
35
41
  const tag = getTag(result)
36
42
  const message = red(`\n${error} ${command} failed without output (${tag}).`)
37
- if (!ctx.quiet) ctx.output.push(message)
43
+ ctx.output.push(message)
38
44
  }
39
45
  }
40
46
 
@@ -43,7 +49,13 @@ const handleOutput = (command, result, ctx, isError = false) => {
43
49
  * @param {import('nano-spawn').Subprocess} subprocess
44
50
  */
45
51
  const killSubprocess = async (subprocess) => {
46
- const childProcess = await subprocess.nodeChildProcess
52
+ let childProcess
53
+
54
+ try {
55
+ childProcess = await subprocess.nodeChildProcess
56
+ } catch {
57
+ /** ignore internal nano-spawn errors, if child process isn't available it can't be killed */
58
+ }
47
59
 
48
60
  if (childProcess?.pid !== undefined) {
49
61
  try {
@@ -62,7 +74,7 @@ const killSubprocess = async (subprocess) => {
62
74
  }
63
75
 
64
76
  // The child process is terminated separately in order to get the `KILLED` status.
65
- childProcess.kill('SIGKILL')
77
+ childProcess?.kill('SIGKILL')
66
78
  }
67
79
 
68
80
  /**
@@ -117,6 +129,7 @@ export const makeErr = (command, error, ctx) => {
117
129
  * @param {Object} options
118
130
  * @param {boolean} [options.color]
119
131
  * @param {string} options.command — Linter task
132
+ * @param {string} [options.continueOnError]
120
133
  * @param {string} [options.cwd]
121
134
  * @param {String} options.topLevelDir - Current git repo top-level path
122
135
  * @param {Boolean} options.isFn - Whether the linter task is a function
@@ -127,6 +140,7 @@ export const makeErr = (command, error, ctx) => {
127
140
  export const getSpawnedTask = ({
128
141
  color,
129
142
  command,
143
+ continueOnError = false,
130
144
  cwd = process.cwd(),
131
145
  files,
132
146
  topLevelDir,
@@ -149,11 +163,13 @@ export const getSpawnedTask = ({
149
163
  debugLog('Spawn options:', spawnOptions)
150
164
 
151
165
  return async (ctx = getInitialState()) => {
152
- const subprocess = spawn(cmd, isFn ? args : args.concat(files), spawnOptions)
153
-
154
- const quitInterruptCheck = interruptExecutionOnError(ctx, subprocess)
166
+ let quitInterruptCheck
155
167
 
156
168
  try {
169
+ const subprocess = spawn(cmd, isFn ? args : args.concat(files), spawnOptions)
170
+ if (!continueOnError) {
171
+ quitInterruptCheck = interruptExecutionOnError(ctx, subprocess)
172
+ }
157
173
  const result = await subprocess
158
174
  if (verbose) {
159
175
  handleOutput(command, result, ctx)
@@ -161,7 +177,9 @@ export const getSpawnedTask = ({
161
177
  } catch (error) {
162
178
  throw makeErr(command, error, ctx)
163
179
  } finally {
164
- await quitInterruptCheck()
180
+ if (quitInterruptCheck) {
181
+ await quitInterruptCheck()
182
+ }
165
183
  }
166
184
  }
167
185
  }
@@ -10,12 +10,21 @@ const debugLog = createDebug('lint-staged:getSpawnedTasks')
10
10
  * @param {object} options
11
11
  * @param {boolean} [options.color]
12
12
  * @param {Array<string|Function>|string|Function} options.commands
13
+ * @param {string} options.continueOnError
13
14
  * @param {string} options.cwd
14
15
  * @param {import('./getStagedFiles.js').StagedFile[]} options.files
15
16
  * @param {string} options.topLevelDir
16
17
  * @param {Boolean} verbose
17
18
  */
18
- export const getSpawnedTasks = async ({ color, commands, cwd, files, topLevelDir, verbose }) => {
19
+ export const getSpawnedTasks = async ({
20
+ color,
21
+ commands,
22
+ continueOnError,
23
+ cwd,
24
+ files,
25
+ topLevelDir,
26
+ verbose,
27
+ }) => {
19
28
  debugLog('Creating Listr tasks for commands %o', commands)
20
29
  const cmdTasks = []
21
30
 
@@ -48,6 +57,7 @@ export const getSpawnedTasks = async ({ color, commands, cwd, files, topLevelDir
48
57
  const task = getSpawnedTask({
49
58
  color,
50
59
  command,
60
+ continueOnError,
51
61
  cwd,
52
62
  files: filepaths,
53
63
  topLevelDir,
package/lib/runAll.js CHANGED
@@ -224,6 +224,7 @@ export const runAll = async (
224
224
  : getSpawnedTasks({
225
225
  color,
226
226
  commands: task.commands,
227
+ continueOnError,
227
228
  cwd: groupCwd,
228
229
  files: task.fileList,
229
230
  topLevelDir,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lint-staged",
3
- "version": "16.2.4",
3
+ "version": "16.2.6",
4
4
  "description": "Lint files staged by git",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "commander": "^14.0.1",
52
- "listr2": "^9.0.4",
52
+ "listr2": "^9.0.5",
53
53
  "micromatch": "^4.0.8",
54
54
  "nano-spawn": "^2.0.0",
55
55
  "pidtree": "^0.6.0",
@@ -61,12 +61,12 @@
61
61
  "@changesets/cli": "2.29.7",
62
62
  "@commitlint/cli": "20.1.0",
63
63
  "@commitlint/config-conventional": "20.0.0",
64
- "@eslint/js": "9.37.0",
65
- "@vitest/coverage-v8": "3.2.4",
66
- "@vitest/eslint-plugin": "1.3.16",
64
+ "@eslint/js": "9.38.0",
65
+ "@vitest/coverage-v8": "4.0.1",
66
+ "@vitest/eslint-plugin": "1.3.23",
67
67
  "consolemock": "1.1.0",
68
68
  "cross-env": "10.1.0",
69
- "eslint": "9.37.0",
69
+ "eslint": "9.38.0",
70
70
  "eslint-config-prettier": "10.1.8",
71
71
  "eslint-plugin-n": "17.23.1",
72
72
  "eslint-plugin-prettier": "5.5.4",
@@ -76,7 +76,7 @@
76
76
  "prettier": "3.6.2",
77
77
  "semver": "7.7.3",
78
78
  "typescript": "5.9.3",
79
- "vitest": "3.2.4"
79
+ "vitest": "4.0.1"
80
80
  },
81
81
  "keywords": [
82
82
  "lint",