lint-staged 17.0.7 → 17.1.0
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.
- package/README.md +14 -24
- package/bin/lint-staged.js +5 -5
- package/lib/colors.js +26 -8
- package/lib/debug.js +2 -2
- package/lib/execGit.js +3 -17
- package/lib/figures.js +9 -5
- package/lib/getFunctionTask.js +13 -4
- package/lib/getSpawnedTask.js +9 -9
- package/lib/getSpawnedTasks.js +3 -6
- package/lib/gitWorkflow.js +190 -113
- package/lib/index.js +14 -12
- package/lib/messages.js +36 -29
- package/lib/parseGitZOutput.js +1 -1
- package/lib/printTaskOutput.js +2 -2
- package/lib/runAll.js +103 -103
- package/lib/runParallelTasks.js +112 -0
- package/lib/state.js +14 -9
- package/lib/validateOptions.js +9 -0
- package/package.json +20 -25
- package/lib/getRenderer.js +0 -63
package/lib/parseGitZOutput.js
CHANGED
package/lib/printTaskOutput.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Handle logging of
|
|
3
|
-
* @param {Object} ctx - The
|
|
2
|
+
* Handle logging of task `ctx.output` to the specified `logger`
|
|
3
|
+
* @param {Object} ctx - The context
|
|
4
4
|
* @param {Object} logger - The logger
|
|
5
5
|
*/
|
|
6
6
|
export const printTaskOutput = (ctx = {}, logger) => {
|
package/lib/runAll.js
CHANGED
|
@@ -2,29 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
import path from 'node:path'
|
|
4
4
|
|
|
5
|
-
import { Listr } from 'listr2'
|
|
6
|
-
|
|
7
5
|
import { chunkFiles } from './chunkFiles.js'
|
|
8
6
|
import { dim } from './colors.js'
|
|
9
7
|
import { createDebug } from './debug.js'
|
|
10
8
|
import { execGit } from './execGit.js'
|
|
9
|
+
import * as figures from './figures.js'
|
|
11
10
|
import { generateTasks } from './generateTasks.js'
|
|
12
11
|
import { getAbortController } from './getAbortController.js'
|
|
13
12
|
import { getFunctionTask, isFunctionTask } from './getFunctionTask.js'
|
|
14
|
-
import { getRenderer } from './getRenderer.js'
|
|
15
13
|
import { getSpawnedTasks } from './getSpawnedTasks.js'
|
|
16
14
|
import { getStagedFiles } from './getStagedFiles.js'
|
|
17
15
|
import { GitWorkflow } from './gitWorkflow.js'
|
|
18
16
|
import { groupFilesByConfig } from './groupFilesByConfig.js'
|
|
19
17
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
SKIPPED_GIT_ERROR,
|
|
26
|
-
SKIPPING_HIDE_PARTIALLY_CHANGED,
|
|
18
|
+
deprecatedGitAdd,
|
|
19
|
+
failedGetStagedFiles,
|
|
20
|
+
noStagedFiles,
|
|
21
|
+
noTasks,
|
|
22
|
+
notGitRepo,
|
|
27
23
|
skippingBackup,
|
|
24
|
+
skippingHidePartiallyChanged,
|
|
28
25
|
} from './messages.js'
|
|
29
26
|
import { normalizePath } from './normalizePath.js'
|
|
30
27
|
import { resolveGitRepo } from './resolveGitRepo.js'
|
|
@@ -41,10 +38,24 @@ import {
|
|
|
41
38
|
shouldRestoreUntrackedFiles,
|
|
42
39
|
updateIndexSkipped,
|
|
43
40
|
} from './state.js'
|
|
44
|
-
import { ConfigNotFoundError, GetStagedFilesError,
|
|
41
|
+
import { ConfigNotFoundError, GetStagedFilesError, GitRepoError } from './symbols.js'
|
|
45
42
|
|
|
46
43
|
const debugLog = createDebug('lint-staged:runAll')
|
|
47
44
|
|
|
45
|
+
/**
|
|
46
|
+
* @param {Logger} logger
|
|
47
|
+
* @param {boolean} quiet
|
|
48
|
+
* @returns {Logger}
|
|
49
|
+
*/
|
|
50
|
+
const configureLogger = (logger, quiet) => {
|
|
51
|
+
if (quiet) {
|
|
52
|
+
const noop = () => {}
|
|
53
|
+
return { error: logger.error, log: noop, warn: noop }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return logger
|
|
57
|
+
}
|
|
58
|
+
|
|
48
59
|
/**
|
|
49
60
|
* @param {ReturnType<typeof getInitialState>} ctx context
|
|
50
61
|
* @param {unknown} cause error cause
|
|
@@ -57,13 +68,11 @@ const createError = (ctx, cause) =>
|
|
|
57
68
|
*
|
|
58
69
|
* @param {object} options
|
|
59
70
|
* @param {boolean} [options.allowEmpty] - Allow empty commits when tasks revert all staged changes
|
|
60
|
-
* @param {boolean} [options.color] - Enable or disable ANSI color codes in output.
|
|
61
71
|
* @param {boolean | number} [options.concurrent] - The number of tasks to run concurrently, or false to run tasks serially
|
|
62
72
|
* @param {Object} [options.configObject] - Explicit config object from the js API
|
|
63
73
|
* @param {string} [options.configPath] - Explicit path to a config file
|
|
64
74
|
* @param {boolean} [options.continueOnError] - Run all tasks to completion even if one fails
|
|
65
75
|
* @param {string} [options.cwd] - Current working directory
|
|
66
|
-
* @param {boolean} [options.debug] - Enable debug mode
|
|
67
76
|
* @param {string} [options.diff] - Override the default "--staged" flag of "git diff" to get list of files
|
|
68
77
|
* @param {string} [options.diffFilter] - Override the default "--diff-filter=ACMR" flag of "git diff" to get list of files
|
|
69
78
|
* @param {boolean} [options.failOnChanges] - Fail with exit code 1 when tasks modify tracked files
|
|
@@ -81,13 +90,11 @@ const createError = (ctx, cause) =>
|
|
|
81
90
|
export const runAll = async (
|
|
82
91
|
{
|
|
83
92
|
allowEmpty = false,
|
|
84
|
-
color = false,
|
|
85
93
|
concurrent = true,
|
|
86
94
|
configObject,
|
|
87
95
|
configPath,
|
|
88
96
|
continueOnError = false,
|
|
89
97
|
cwd,
|
|
90
|
-
debug = false,
|
|
91
98
|
diff,
|
|
92
99
|
diffFilter,
|
|
93
100
|
failOnChanges = false,
|
|
@@ -105,6 +112,8 @@ export const runAll = async (
|
|
|
105
112
|
},
|
|
106
113
|
logger = console
|
|
107
114
|
) => {
|
|
115
|
+
const thisLogger = configureLogger(logger, quiet)
|
|
116
|
+
|
|
108
117
|
debugLog('Running all linter scripts...')
|
|
109
118
|
|
|
110
119
|
// Resolve relative CWD option
|
|
@@ -123,7 +132,7 @@ export const runAll = async (
|
|
|
123
132
|
|
|
124
133
|
const { topLevelDir, gitConfigDir } = await resolveGitRepo(cwd)
|
|
125
134
|
if (!topLevelDir) {
|
|
126
|
-
if (!quiet) ctx.output.push(
|
|
135
|
+
if (!quiet) ctx.output.push(notGitRepo())
|
|
127
136
|
ctx.errors.add(GitRepoError)
|
|
128
137
|
throw createError(ctx, GitRepoError)
|
|
129
138
|
}
|
|
@@ -137,22 +146,22 @@ export const runAll = async (
|
|
|
137
146
|
// Lint-staged will create a backup stash only when there's an initial commit,
|
|
138
147
|
// and when using the default list of staged files by default
|
|
139
148
|
ctx.shouldBackup = hasInitialCommit && stash
|
|
140
|
-
if (!ctx.shouldBackup
|
|
141
|
-
|
|
149
|
+
if (!ctx.shouldBackup) {
|
|
150
|
+
thisLogger.warn(skippingBackup(hasInitialCommit, diff))
|
|
142
151
|
}
|
|
143
152
|
|
|
144
|
-
if (!ctx.shouldHidePartiallyStaged && !ctx.shouldHideUnstaged && !ctx.shouldHideAll
|
|
145
|
-
|
|
153
|
+
if (!ctx.shouldHidePartiallyStaged && !ctx.shouldHideUnstaged && !ctx.shouldHideAll) {
|
|
154
|
+
thisLogger.warn(skippingHidePartiallyChanged())
|
|
146
155
|
}
|
|
147
156
|
|
|
148
157
|
// Run staged files retrieval and config search in parallel since they're independent
|
|
149
158
|
const [stagedFiles, foundConfigs] = await Promise.all([
|
|
150
159
|
getStagedFiles({ cwd: topLevelDir, diff, diffFilter }),
|
|
151
|
-
searchConfigs({ configObject, configPath, cwd, topLevelDir },
|
|
160
|
+
searchConfigs({ configObject, configPath, cwd, topLevelDir }, thisLogger),
|
|
152
161
|
])
|
|
153
162
|
|
|
154
163
|
if (!stagedFiles) {
|
|
155
|
-
if (!quiet) ctx.output.push(
|
|
164
|
+
if (!quiet) ctx.output.push(failedGetStagedFiles())
|
|
156
165
|
ctx.errors.add(GetStagedFilesError)
|
|
157
166
|
throw createError(ctx, GetStagedFilesError)
|
|
158
167
|
}
|
|
@@ -160,7 +169,7 @@ export const runAll = async (
|
|
|
160
169
|
|
|
161
170
|
// If there are no files avoid executing any lint-staged logic
|
|
162
171
|
if (stagedFiles.length === 0) {
|
|
163
|
-
if (!quiet) ctx.output.push(
|
|
172
|
+
if (!quiet) ctx.output.push(noStagedFiles())
|
|
164
173
|
return ctx
|
|
165
174
|
}
|
|
166
175
|
|
|
@@ -184,14 +193,7 @@ export const runAll = async (
|
|
|
184
193
|
// Warn user when their command includes `git add`
|
|
185
194
|
let hasDeprecatedGitAdd = false
|
|
186
195
|
|
|
187
|
-
const
|
|
188
|
-
ctx,
|
|
189
|
-
exitOnError: false,
|
|
190
|
-
registerSignalListeners: false,
|
|
191
|
-
...getRenderer({ color, debug, quiet }, logger),
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const listrTasks = []
|
|
196
|
+
const tasks = []
|
|
195
197
|
|
|
196
198
|
// Set of all staged files that matched a task glob. Values in a set are unique.
|
|
197
199
|
/** @type {Set<import('./getStagedFiles.js').StagedFile>} */
|
|
@@ -215,13 +217,17 @@ export const runAll = async (
|
|
|
215
217
|
}
|
|
216
218
|
|
|
217
219
|
for (const [index, files] of stagedFileChunks.entries()) {
|
|
218
|
-
const
|
|
220
|
+
const taskChunk = await Promise.all(
|
|
219
221
|
generateTasks({ config, cwd: groupCwd, files, relative }).map((task) =>
|
|
220
222
|
(isFunctionTask(task.commands)
|
|
221
|
-
? getFunctionTask(
|
|
223
|
+
? getFunctionTask({
|
|
224
|
+
abortController,
|
|
225
|
+
command: task.commands,
|
|
226
|
+
continueOnError,
|
|
227
|
+
files: task.fileList,
|
|
228
|
+
})
|
|
222
229
|
: getSpawnedTasks({
|
|
223
230
|
abortController,
|
|
224
|
-
color,
|
|
225
231
|
commands: task.commands,
|
|
226
232
|
continueOnError,
|
|
227
233
|
cwd: groupCwd,
|
|
@@ -246,7 +252,7 @@ export const runAll = async (
|
|
|
246
252
|
})
|
|
247
253
|
|
|
248
254
|
hasDeprecatedGitAdd =
|
|
249
|
-
hasDeprecatedGitAdd || subTasks.some((subTask) => subTask.
|
|
255
|
+
hasDeprecatedGitAdd || subTasks.some((subTask) => subTask.title.includes('git add'))
|
|
250
256
|
|
|
251
257
|
const fileCount = task.fileList.length
|
|
252
258
|
|
|
@@ -254,17 +260,13 @@ export const runAll = async (
|
|
|
254
260
|
title: `${task.pattern}${dim(
|
|
255
261
|
` — ${fileCount} ${fileCount === 1 ? 'file' : 'files'}`
|
|
256
262
|
)}`,
|
|
257
|
-
task:
|
|
258
|
-
task.newListr(
|
|
259
|
-
subTasks,
|
|
260
|
-
// Subtasks should not run in parallel, and should exit on error
|
|
261
|
-
{ concurrent: false, exitOnError: !continueOnError }
|
|
262
|
-
),
|
|
263
|
+
task: subTasks,
|
|
263
264
|
skip: () => {
|
|
264
265
|
// Skip task when no files matched
|
|
265
266
|
if (fileCount === 0) {
|
|
266
267
|
return `${task.pattern}${dim(' — no files')}`
|
|
267
268
|
}
|
|
269
|
+
|
|
268
270
|
return false
|
|
269
271
|
},
|
|
270
272
|
}
|
|
@@ -272,33 +274,29 @@ export const runAll = async (
|
|
|
272
274
|
)
|
|
273
275
|
)
|
|
274
276
|
|
|
275
|
-
|
|
277
|
+
tasks.push({
|
|
276
278
|
title:
|
|
277
279
|
`${configName}${dim(` — ${files.length} ${files.length > 1 ? 'files' : 'file'}`)}` +
|
|
278
280
|
(chunkCount > 1 ? dim(` (chunk ${index + 1}/${chunkCount})...`) : ''),
|
|
279
|
-
task:
|
|
280
|
-
task.newListr(chunkListrTasks, { concurrent, exitOnError: !continueOnError }),
|
|
281
|
+
task: taskChunk,
|
|
281
282
|
skip: () => {
|
|
282
|
-
// Skip if the first step (backup) failed
|
|
283
|
-
if (ctx.errors.has(GitError)) return SKIPPED_GIT_ERROR
|
|
284
283
|
// Skip chunk when no every task is skipped (due to no matches)
|
|
285
|
-
if (
|
|
284
|
+
if (taskChunk.every((task) => task.skip())) {
|
|
286
285
|
return `${configName}${dim(' — no tasks to run')}`
|
|
287
286
|
}
|
|
287
|
+
|
|
288
288
|
return false
|
|
289
289
|
},
|
|
290
290
|
})
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
-
if (hasDeprecatedGitAdd
|
|
295
|
-
|
|
294
|
+
if (hasDeprecatedGitAdd) {
|
|
295
|
+
thisLogger.warn(deprecatedGitAdd())
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if (listrTasks.every((task) => task.skip())) {
|
|
301
|
-
if (!quiet) ctx.output.push(NO_TASKS)
|
|
298
|
+
if (tasks.every((task) => task.skip())) {
|
|
299
|
+
if (!quiet) ctx.output.push(noTasks())
|
|
302
300
|
return ctx
|
|
303
301
|
}
|
|
304
302
|
|
|
@@ -318,60 +316,62 @@ export const runAll = async (
|
|
|
318
316
|
diffFilter,
|
|
319
317
|
failOnChanges,
|
|
320
318
|
gitConfigDir,
|
|
319
|
+
logger: thisLogger,
|
|
321
320
|
matchedFileChunks,
|
|
322
321
|
topLevelDir,
|
|
323
322
|
})
|
|
324
323
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
324
|
+
await git.prepare(ctx)
|
|
325
|
+
|
|
326
|
+
if (shouldHidePartiallyStagedFiles(ctx)) {
|
|
327
|
+
await git.hidePartiallyStagedChanges(ctx)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (abortController.signal.aborted || ctx.errors.size > 0) {
|
|
331
|
+
thisLogger.log(`${figures.cancelled()} ${dim(`Skipped running tasks…`)}`)
|
|
332
|
+
} else {
|
|
333
|
+
await git.runTasks(ctx, tasks, { abortController, concurrent })
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (updateIndexSkipped(ctx)) {
|
|
337
|
+
thisLogger.log(`${figures.cancelled()} ${dim('Skipped staging changes from tasks…')}`)
|
|
338
|
+
} else {
|
|
339
|
+
await git.updateIndex(ctx)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (shouldRestoreUnstagedChanges(ctx)) {
|
|
343
|
+
if (restoreUnstagedChangesSkipped(ctx)) {
|
|
344
|
+
thisLogger.log(`${figures.cancelled()} ${dim('Skipped restoring unstaged changes…')}`)
|
|
345
|
+
} else {
|
|
346
|
+
await git.restoreUnstagedChanges(ctx)
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (shouldRestoreUntrackedFiles(ctx)) {
|
|
351
|
+
if (restoreUnstagedChangesSkipped(ctx)) {
|
|
352
|
+
thisLogger.log(`${figures.cancelled()} ${dim('Skipped restoring untracked files…')}`)
|
|
353
|
+
} else {
|
|
354
|
+
await git.restoreUntrackedFiles(ctx)
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (restoreOriginalStateEnabled(ctx)) {
|
|
359
|
+
if (restoreOriginalStateSkipped(ctx)) {
|
|
360
|
+
thisLogger.log(
|
|
361
|
+
`${figures.cancelled()} ${dim('Skipped reverting to original state because of errors…')}`
|
|
362
|
+
)
|
|
363
|
+
} else {
|
|
364
|
+
await git.restoreOriginalState(ctx)
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (cleanupEnabled(ctx)) {
|
|
369
|
+
if (cleanupSkipped(ctx)) {
|
|
370
|
+
thisLogger.log(`${figures.cancelled()} ${dim('Skipped cleaning up temporary files…')}`)
|
|
371
|
+
} else {
|
|
372
|
+
await git.cleanup(ctx)
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
375
|
|
|
376
376
|
if (ctx.errors.size > 0) {
|
|
377
377
|
throw createError(ctx)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import * as colors from './colors.js'
|
|
2
|
+
import { createDebug } from './debug.js'
|
|
3
|
+
import * as figures from './figures.js'
|
|
4
|
+
|
|
5
|
+
const debugLog = createDebug('lint-staged:runParallelTasks')
|
|
6
|
+
|
|
7
|
+
/** @param {Number | boolean} options.concurrent Boolean value for whether to run concurrently */
|
|
8
|
+
export const parseConcurrency = (concurrent) => {
|
|
9
|
+
if (concurrent === false || concurrent < 1 || Number.isNaN(concurrent)) {
|
|
10
|
+
return 1
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (concurrent === true) {
|
|
14
|
+
return Infinity
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return parseInt(concurrent)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {Object} ctx
|
|
22
|
+
* @param {Array} tasks
|
|
23
|
+
* @param {Object} options
|
|
24
|
+
* @param {AbortController} abortController
|
|
25
|
+
* @param {Number | boolean} [options.concurrent=true] Boolean value for whether to run concurrently,
|
|
26
|
+
* or a number value controls the number of concurrent executions
|
|
27
|
+
*/
|
|
28
|
+
export const runParallelTasks = async (
|
|
29
|
+
ctx,
|
|
30
|
+
tasks,
|
|
31
|
+
{ abortController, concurrent = true, logger }
|
|
32
|
+
) => {
|
|
33
|
+
const concurrency = parseConcurrency(concurrent)
|
|
34
|
+
|
|
35
|
+
debugLog('Running parallel tasks with concurrency:', concurrency)
|
|
36
|
+
|
|
37
|
+
const indent = tasks.length > 1 ? ' ' : ' '
|
|
38
|
+
const allPerGlobTasks = []
|
|
39
|
+
|
|
40
|
+
// the array of actual tasks is split per config and per glob
|
|
41
|
+
for (const perConfig of tasks) {
|
|
42
|
+
if (perConfig.skip()) {
|
|
43
|
+
debugLog('Skipped configuration:', perConfig.title)
|
|
44
|
+
} else {
|
|
45
|
+
debugLog('Running configuration:', perConfig.title)
|
|
46
|
+
|
|
47
|
+
if (tasks.length > 1) {
|
|
48
|
+
// display name of config only when there are multiple
|
|
49
|
+
logger?.log(colors.dim(`${indent}${perConfig.title}`))
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
for (const perGlob of perConfig.task) {
|
|
54
|
+
if (perGlob.skip()) {
|
|
55
|
+
debugLog('Skipped glob from configuration:', perConfig.title, perGlob.title)
|
|
56
|
+
continue
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (perConfig.skip()) {
|
|
60
|
+
continue // entire group is skipped, but debug logs still show above
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
debugLog('Running glob:', perGlob.title)
|
|
64
|
+
logger?.log(colors.dim(`${indent} ${perGlob.title}`))
|
|
65
|
+
|
|
66
|
+
for (const task of perGlob.task) {
|
|
67
|
+
debugLog('Running task:', task.title)
|
|
68
|
+
logger?.log(colors.dim(`${indent} ${figures.wip()} ${task.title}`))
|
|
69
|
+
}
|
|
70
|
+
// per-glob tasks run serially
|
|
71
|
+
allPerGlobTasks.push(perGlob.task)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
logger?.log('') // empty line before all tasks
|
|
76
|
+
|
|
77
|
+
const runSequential = async (tasks) => {
|
|
78
|
+
for (const { title, task } of tasks) {
|
|
79
|
+
if (abortController.signal.aborted) {
|
|
80
|
+
debugLog('Skipped task because aborted:', title)
|
|
81
|
+
// Log all aborted tasks without actually running them
|
|
82
|
+
logger?.warn(`${figures.cancelled()} ${title}`)
|
|
83
|
+
continue
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
debugLog('Running task:', title)
|
|
88
|
+
await task(ctx)
|
|
89
|
+
debugLog('Done running task:', title)
|
|
90
|
+
logger?.log(`${figures.done()} ${title}`)
|
|
91
|
+
} catch {
|
|
92
|
+
debugLog('Failed to run task:', title)
|
|
93
|
+
logger?.error(colors.red(`${figures.error()} ${title}`))
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
let next = 0
|
|
99
|
+
const worker = async () => {
|
|
100
|
+
while (next < allPerGlobTasks.length) {
|
|
101
|
+
const perGlobTasks = allPerGlobTasks[next++]
|
|
102
|
+
await runSequential(perGlobTasks)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const length = Math.min(allPerGlobTasks.length, concurrency)
|
|
107
|
+
debugLog('Running workers with concurrency:', length)
|
|
108
|
+
await Promise.all(Array.from({ length }, worker))
|
|
109
|
+
debugLog('Done running workers')
|
|
110
|
+
|
|
111
|
+
logger?.log('') // empty line after all tasks
|
|
112
|
+
}
|
package/lib/state.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { gitError, taskError } from './messages.js'
|
|
2
2
|
import {
|
|
3
3
|
FailOnChangesError,
|
|
4
4
|
GitError,
|
|
@@ -56,31 +56,31 @@ export const updateIndexSkipped = (ctx) => {
|
|
|
56
56
|
|
|
57
57
|
// Should be skipped in case of git errors
|
|
58
58
|
if (ctx.errors.has(GitError)) {
|
|
59
|
-
return
|
|
59
|
+
return gitError()
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
// Should be skipped when tasks fail
|
|
63
63
|
if (ctx.errors.has(TaskError)) {
|
|
64
|
-
return
|
|
64
|
+
return taskError()
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
export const restoreUnstagedChangesSkipped = (ctx) => {
|
|
69
69
|
// Should be skipped in case of git errors
|
|
70
70
|
if (ctx.errors.has(GitError)) {
|
|
71
|
-
return
|
|
71
|
+
return gitError()
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
// When complete reverting to original state is skipped,
|
|
75
75
|
// we can still restore unstaged changes to make it easier
|
|
76
76
|
// to do manually.
|
|
77
77
|
if (!ctx.shouldRevert) {
|
|
78
|
-
false
|
|
78
|
+
return false
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
// Should be skipped when tasks fail
|
|
82
82
|
if (ctx.errors.has(TaskError)) {
|
|
83
|
-
return
|
|
83
|
+
return taskError()
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -94,7 +94,7 @@ export const restoreOriginalStateEnabled = (ctx) =>
|
|
|
94
94
|
export const restoreOriginalStateSkipped = (ctx) => {
|
|
95
95
|
// Should be skipped in case of unknown git errors
|
|
96
96
|
if (ctx.errors.has(GitError) && !ctx.errors.has(RestoreUnstagedChangesError)) {
|
|
97
|
-
return
|
|
97
|
+
return gitError()
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -106,13 +106,18 @@ export const cleanupSkipped = (ctx) => {
|
|
|
106
106
|
return true
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
/** Failed to restore hidden unstaged changes, shouldn't drop stash, @see restoreUnstagedChangesSkipped */
|
|
110
|
+
if (ctx.errors.has(RestoreUnstagedChangesError) && !ctx.shouldRevert) {
|
|
111
|
+
return gitError()
|
|
112
|
+
}
|
|
113
|
+
|
|
109
114
|
// Should be skipped in case of unknown git errors
|
|
110
115
|
if (restoreOriginalStateSkipped(ctx)) {
|
|
111
|
-
return
|
|
116
|
+
return gitError()
|
|
112
117
|
}
|
|
113
118
|
|
|
114
119
|
// Should be skipped when reverting to original state fails
|
|
115
120
|
if (ctx.errors.has(RestoreOriginalStateError)) {
|
|
116
|
-
return
|
|
121
|
+
return gitError()
|
|
117
122
|
}
|
|
118
123
|
}
|
package/lib/validateOptions.js
CHANGED
|
@@ -17,6 +17,15 @@ const debugLog = createDebug('lint-staged:validateOptions')
|
|
|
17
17
|
export const validateOptions = async (options = {}, logger) => {
|
|
18
18
|
debugLog('Validating options...')
|
|
19
19
|
|
|
20
|
+
if (
|
|
21
|
+
options.concurrent !== undefined &&
|
|
22
|
+
typeof options.concurrent !== 'boolean' &&
|
|
23
|
+
(!Number.isInteger(options.concurrent) || Number.isNaN(options.concurrent))
|
|
24
|
+
) {
|
|
25
|
+
logger.error(invalidOption('concurrent', `${options.concurrent}`, 'Must be boolean or integer'))
|
|
26
|
+
throw InvalidOptionsError
|
|
27
|
+
}
|
|
28
|
+
|
|
20
29
|
/** Ensure the passed cwd option exists; it might also be relative */
|
|
21
30
|
if (typeof options.cwd === 'string') {
|
|
22
31
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lint-staged",
|
|
3
|
-
"version": "17.0
|
|
3
|
+
"version": "17.1.0",
|
|
4
4
|
"description": "Lint files staged by git",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"MIGRATION.md"
|
|
45
45
|
],
|
|
46
46
|
"scripts": {
|
|
47
|
-
"lint": "
|
|
47
|
+
"lint": "oxfmt && oxlint",
|
|
48
48
|
"test": "vitest",
|
|
49
49
|
"typecheck": "tsc",
|
|
50
50
|
"version": "npx changeset version",
|
|
@@ -52,8 +52,7 @@
|
|
|
52
52
|
"tag": "npx changeset tag"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"
|
|
56
|
-
"picomatch": "^4.0.4",
|
|
55
|
+
"picomatch": "^4.0.5",
|
|
57
56
|
"string-argv": "^0.3.2",
|
|
58
57
|
"tinyexec": "^1.2.4"
|
|
59
58
|
},
|
|
@@ -62,36 +61,32 @@
|
|
|
62
61
|
},
|
|
63
62
|
"devDependencies": {
|
|
64
63
|
"@changesets/changelog-github": "0.7.0",
|
|
65
|
-
"@changesets/cli": "2.31.
|
|
66
|
-
"@commitlint/cli": "21.
|
|
67
|
-
"@commitlint/config-conventional": "21.0
|
|
68
|
-
"@
|
|
69
|
-
"@vitest/coverage-istanbul": "4.1.7",
|
|
70
|
-
"@vitest/eslint-plugin": "1.6.18",
|
|
64
|
+
"@changesets/cli": "2.31.1",
|
|
65
|
+
"@commitlint/cli": "21.2.1",
|
|
66
|
+
"@commitlint/config-conventional": "21.2.0",
|
|
67
|
+
"@vitest/coverage-istanbul": "4.1.10",
|
|
71
68
|
"consolemock": "1.1.0",
|
|
72
69
|
"cross-env": "10.1.0",
|
|
73
|
-
"eslint": "10.4.1",
|
|
74
|
-
"eslint-config-prettier": "10.1.8",
|
|
75
|
-
"eslint-plugin-n": "18.0.1",
|
|
76
|
-
"eslint-plugin-prettier": "5.5.6",
|
|
77
|
-
"eslint-plugin-simple-import-sort": "13.0.0",
|
|
78
70
|
"husky": "9.1.7",
|
|
79
71
|
"mock-stdin": "1.0.0",
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
72
|
+
"oxfmt": "0.59.0",
|
|
73
|
+
"oxlint": "1.74.0",
|
|
74
|
+
"semver": "7.8.5",
|
|
75
|
+
"vitest": "4.1.10"
|
|
83
76
|
},
|
|
84
77
|
"keywords": [
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"staged",
|
|
78
|
+
"check",
|
|
79
|
+
"code",
|
|
88
80
|
"eslint",
|
|
81
|
+
"format",
|
|
82
|
+
"git",
|
|
83
|
+
"lint",
|
|
84
|
+
"oxlint",
|
|
85
|
+
"oxfmt",
|
|
89
86
|
"prettier",
|
|
90
|
-
"stylelint",
|
|
91
|
-
"code",
|
|
92
87
|
"quality",
|
|
93
|
-
"
|
|
94
|
-
"
|
|
88
|
+
"staged",
|
|
89
|
+
"stylelint",
|
|
95
90
|
"validate"
|
|
96
91
|
]
|
|
97
92
|
}
|