lint-staged 16.1.6 → 16.2.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 +88 -22
- package/bin/lint-staged.js +84 -67
- package/lib/chunkFiles.js +2 -3
- package/lib/colors.js +106 -0
- package/lib/debug.js +27 -0
- package/lib/execGit.js +3 -2
- package/lib/figures.js +5 -4
- package/lib/file.js +2 -2
- package/lib/generateTasks.js +2 -2
- package/lib/getFunctionTask.js +2 -3
- package/lib/getRenderer.js +7 -8
- package/lib/getSpawnedTask.js +9 -6
- package/lib/getSpawnedTasks.js +14 -5
- package/lib/gitWorkflow.js +96 -55
- package/lib/groupFilesByConfig.js +2 -2
- package/lib/index.d.ts +20 -5
- package/lib/index.js +25 -8
- package/lib/loadConfig.js +6 -22
- package/lib/messages.js +18 -19
- package/lib/resolveGitRepo.js +2 -3
- package/lib/runAll.js +43 -23
- package/lib/searchConfigs.js +95 -56
- package/lib/state.js +20 -7
- package/lib/symbols.js +2 -0
- package/lib/validateConfig.js +2 -3
- package/lib/validateOptions.js +2 -3
- package/package.json +19 -25
package/lib/resolveGitRepo.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
|
|
3
|
+
import { createDebug } from './debug.js'
|
|
5
4
|
import { execGit } from './execGit.js'
|
|
6
5
|
import { normalizePath } from './normalizePath.js'
|
|
7
6
|
|
|
8
|
-
const debugLog =
|
|
7
|
+
const debugLog = createDebug('lint-staged:resolveGitRepo')
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* Relative path up to the repo top-level directory
|
package/lib/runAll.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import path from 'node:path'
|
|
4
4
|
|
|
5
|
-
import chalk from 'chalk'
|
|
6
|
-
import debug from 'debug'
|
|
7
5
|
import { Listr } from 'listr2'
|
|
8
6
|
|
|
9
7
|
import { chunkFiles } from './chunkFiles.js'
|
|
8
|
+
import { blackBright } from './colors.js'
|
|
9
|
+
import { createDebug } from './debug.js'
|
|
10
10
|
import { execGit } from './execGit.js'
|
|
11
11
|
import { generateTasks } from './generateTasks.js'
|
|
12
12
|
import { getFunctionTask, isFunctionTask } from './getFunctionTask.js'
|
|
@@ -36,11 +36,11 @@ import {
|
|
|
36
36
|
restoreOriginalStateEnabled,
|
|
37
37
|
restoreOriginalStateSkipped,
|
|
38
38
|
restoreUnstagedChangesSkipped,
|
|
39
|
-
|
|
39
|
+
shouldHideUnstagedFiles,
|
|
40
40
|
} from './state.js'
|
|
41
41
|
import { ConfigNotFoundError, GetStagedFilesError, GitError, GitRepoError } from './symbols.js'
|
|
42
42
|
|
|
43
|
-
const debugLog =
|
|
43
|
+
const debugLog = createDebug('lint-staged:runAll')
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* @param {ReturnType<typeof getInitialState>} ctx context
|
|
@@ -54,15 +54,20 @@ const createError = (ctx, cause) =>
|
|
|
54
54
|
*
|
|
55
55
|
* @param {object} options
|
|
56
56
|
* @param {boolean} [options.allowEmpty] - Allow empty commits when tasks revert all staged changes
|
|
57
|
+
* @param {Object} [options.color] - Enable ANSI colors in output
|
|
57
58
|
* @param {boolean | number} [options.concurrent] - The number of tasks to run concurrently, or false to run tasks serially
|
|
58
59
|
* @param {Object} [options.configObject] - Explicit config object from the js API
|
|
59
60
|
* @param {string} [options.configPath] - Explicit path to a config file
|
|
61
|
+
* @param {boolean} [options.continueOnError] - Run all tasks to completion even if one fails
|
|
60
62
|
* @param {string} [options.cwd] - Current working directory
|
|
61
63
|
* @param {boolean} [options.debug] - Enable debug mode
|
|
62
64
|
* @param {string} [options.diff] - Override the default "--staged" flag of "git diff" to get list of files
|
|
63
65
|
* @param {string} [options.diffFilter] - Override the default "--diff-filter=ACMR" flag of "git diff" to get list of files
|
|
66
|
+
* @param {boolean} [options.failOnChanges] - Fail with exit code 1 when tasks modify tracked files
|
|
67
|
+
* @param {boolean} [options.hidePartiallyStaged] - Whether to hide unstaged changes from partially staged files before running tasks
|
|
68
|
+
* @param {boolean} [options.hideUnstaged] - Whether to hide all unstaged changes before running tasks
|
|
64
69
|
* @param {number} [options.maxArgLength] - Maximum argument string length
|
|
65
|
-
* @param {boolean} [options.quiet] - Disable lint-staged
|
|
70
|
+
* @param {boolean} [options.quiet] - Disable lint-staged's own console output
|
|
66
71
|
* @param {boolean} [options.relative] - Pass relative filepaths to tasks
|
|
67
72
|
* @param {boolean} [options.revert] - revert to original state in case of errors
|
|
68
73
|
* @param {boolean} [options.stash] - Enable the backup stash, and revert in case of errors
|
|
@@ -73,13 +78,18 @@ const createError = (ctx, cause) =>
|
|
|
73
78
|
export const runAll = async (
|
|
74
79
|
{
|
|
75
80
|
allowEmpty = false,
|
|
81
|
+
color = false,
|
|
76
82
|
concurrent = true,
|
|
77
83
|
configObject,
|
|
78
84
|
configPath,
|
|
85
|
+
continueOnError = false,
|
|
79
86
|
cwd,
|
|
80
87
|
debug = false,
|
|
81
88
|
diff,
|
|
82
89
|
diffFilter,
|
|
90
|
+
failOnChanges = false,
|
|
91
|
+
hidePartiallyStaged = true,
|
|
92
|
+
hideUnstaged = false,
|
|
83
93
|
maxArgLength,
|
|
84
94
|
quiet = false,
|
|
85
95
|
relative = false,
|
|
@@ -87,7 +97,6 @@ export const runAll = async (
|
|
|
87
97
|
stash = diff === undefined,
|
|
88
98
|
// Cannot revert to original state without stash
|
|
89
99
|
revert = stash,
|
|
90
|
-
hidePartiallyStaged = true,
|
|
91
100
|
verbose = false,
|
|
92
101
|
},
|
|
93
102
|
logger = console
|
|
@@ -99,7 +108,12 @@ export const runAll = async (
|
|
|
99
108
|
cwd = hasExplicitCwd ? path.resolve(cwd) : process.cwd()
|
|
100
109
|
debugLog('Using working directory `%s`', cwd)
|
|
101
110
|
|
|
102
|
-
const ctx = getInitialState({
|
|
111
|
+
const ctx = getInitialState({
|
|
112
|
+
hidePartiallyStaged,
|
|
113
|
+
hideUnstaged,
|
|
114
|
+
quiet,
|
|
115
|
+
revert,
|
|
116
|
+
})
|
|
103
117
|
|
|
104
118
|
const { topLevelDir, gitConfigDir } = await resolveGitRepo(cwd)
|
|
105
119
|
if (!topLevelDir) {
|
|
@@ -121,12 +135,16 @@ export const runAll = async (
|
|
|
121
135
|
logger.warn(skippingBackup(hasInitialCommit, diff))
|
|
122
136
|
}
|
|
123
137
|
|
|
124
|
-
ctx.shouldHidePartiallyStaged = hidePartiallyStaged
|
|
125
138
|
if (!ctx.shouldHidePartiallyStaged && !quiet) {
|
|
126
139
|
logger.warn(SKIPPING_HIDE_PARTIALLY_CHANGED)
|
|
127
140
|
}
|
|
128
141
|
|
|
129
|
-
|
|
142
|
+
// Run staged files retrieval and config search in parallel since they're independent
|
|
143
|
+
const [stagedFiles, foundConfigs] = await Promise.all([
|
|
144
|
+
getStagedFiles({ cwd: topLevelDir, diff, diffFilter }),
|
|
145
|
+
searchConfigs({ configObject, configPath, cwd, topLevelDir }, logger),
|
|
146
|
+
])
|
|
147
|
+
|
|
130
148
|
if (!stagedFiles) {
|
|
131
149
|
if (!quiet) ctx.output.push(FAILED_GET_STAGED_FILES)
|
|
132
150
|
ctx.errors.add(GetStagedFilesError)
|
|
@@ -140,7 +158,6 @@ export const runAll = async (
|
|
|
140
158
|
return ctx
|
|
141
159
|
}
|
|
142
160
|
|
|
143
|
-
const foundConfigs = await searchConfigs({ configObject, configPath, cwd, topLevelDir }, logger)
|
|
144
161
|
const numberOfConfigs = Object.keys(foundConfigs).length
|
|
145
162
|
|
|
146
163
|
// Throw if no configurations were found
|
|
@@ -165,7 +182,7 @@ export const runAll = async (
|
|
|
165
182
|
ctx,
|
|
166
183
|
exitOnError: false,
|
|
167
184
|
registerSignalListeners: false,
|
|
168
|
-
...getRenderer({ debug, quiet }, logger),
|
|
185
|
+
...getRenderer({ color, debug, quiet }, logger),
|
|
169
186
|
}
|
|
170
187
|
|
|
171
188
|
/**
|
|
@@ -203,6 +220,7 @@ export const runAll = async (
|
|
|
203
220
|
(isFunctionTask(task.commands)
|
|
204
221
|
? getFunctionTask(task.commands, task.fileList)
|
|
205
222
|
: getSpawnedTasks({
|
|
223
|
+
color,
|
|
206
224
|
commands: task.commands,
|
|
207
225
|
cwd: groupCwd,
|
|
208
226
|
files: task.fileList,
|
|
@@ -231,19 +249,19 @@ export const runAll = async (
|
|
|
231
249
|
const fileCount = task.fileList.length
|
|
232
250
|
|
|
233
251
|
return {
|
|
234
|
-
title: `${task.pattern}${
|
|
252
|
+
title: `${task.pattern}${blackBright(
|
|
235
253
|
` — ${fileCount} ${fileCount === 1 ? 'file' : 'files'}`
|
|
236
254
|
)}`,
|
|
237
255
|
task: async (ctx, task) =>
|
|
238
256
|
task.newListr(
|
|
239
257
|
subTasks,
|
|
240
258
|
// Subtasks should not run in parallel, and should exit on error
|
|
241
|
-
{ concurrent: false, exitOnError:
|
|
259
|
+
{ concurrent: false, exitOnError: !continueOnError }
|
|
242
260
|
),
|
|
243
261
|
skip: () => {
|
|
244
262
|
// Skip task when no files matched
|
|
245
263
|
if (fileCount === 0) {
|
|
246
|
-
return `${task.pattern}${
|
|
264
|
+
return `${task.pattern}${blackBright(' — no files')}`
|
|
247
265
|
}
|
|
248
266
|
return false
|
|
249
267
|
},
|
|
@@ -256,15 +274,16 @@ export const runAll = async (
|
|
|
256
274
|
|
|
257
275
|
listrTasks.push({
|
|
258
276
|
title:
|
|
259
|
-
`${configName}${
|
|
260
|
-
(chunkCount > 1 ?
|
|
261
|
-
task: (ctx, task) =>
|
|
277
|
+
`${configName}${blackBright(` — ${files.length} ${files.length > 1 ? 'files' : 'file'}`)}` +
|
|
278
|
+
(chunkCount > 1 ? blackBright(` (chunk ${index + 1}/${chunkCount})...`) : ''),
|
|
279
|
+
task: (ctx, task) =>
|
|
280
|
+
task.newListr(chunkListrTasks, { concurrent, exitOnError: !continueOnError }),
|
|
262
281
|
skip: () => {
|
|
263
282
|
// Skip if the first step (backup) failed
|
|
264
283
|
if (ctx.errors.has(GitError)) return SKIPPED_GIT_ERROR
|
|
265
284
|
// Skip chunk when no every task is skipped (due to no matches)
|
|
266
285
|
if (chunkListrTasks.every((task) => task.skip())) {
|
|
267
|
-
return `${configName}${
|
|
286
|
+
return `${configName}${blackBright(' — no tasks to run')}`
|
|
268
287
|
}
|
|
269
288
|
return false
|
|
270
289
|
},
|
|
@@ -295,11 +314,12 @@ export const runAll = async (
|
|
|
295
314
|
|
|
296
315
|
const git = new GitWorkflow({
|
|
297
316
|
allowEmpty,
|
|
298
|
-
gitConfigDir,
|
|
299
|
-
topLevelDir,
|
|
300
|
-
matchedFileChunks,
|
|
301
317
|
diff,
|
|
302
318
|
diffFilter,
|
|
319
|
+
failOnChanges,
|
|
320
|
+
gitConfigDir,
|
|
321
|
+
matchedFileChunks,
|
|
322
|
+
topLevelDir,
|
|
303
323
|
})
|
|
304
324
|
|
|
305
325
|
const runner = new Listr(
|
|
@@ -311,7 +331,7 @@ export const runAll = async (
|
|
|
311
331
|
{
|
|
312
332
|
title: 'Hiding unstaged changes to partially staged files...',
|
|
313
333
|
task: (ctx) => git.hideUnstagedChanges(ctx),
|
|
314
|
-
enabled:
|
|
334
|
+
enabled: shouldHideUnstagedFiles,
|
|
315
335
|
},
|
|
316
336
|
{
|
|
317
337
|
title: `Running tasks for ${diff ? 'changed' : 'staged'} files...`,
|
|
@@ -326,7 +346,7 @@ export const runAll = async (
|
|
|
326
346
|
{
|
|
327
347
|
title: 'Restoring unstaged changes to partially staged files...',
|
|
328
348
|
task: (ctx) => git.restoreUnstagedChanges(ctx),
|
|
329
|
-
enabled:
|
|
349
|
+
enabled: shouldHideUnstagedFiles,
|
|
330
350
|
skip: restoreUnstagedChangesSkipped,
|
|
331
351
|
},
|
|
332
352
|
{
|
package/lib/searchConfigs.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/** @typedef {import('./index').Logger} Logger */
|
|
2
2
|
|
|
3
|
+
import fs, { constants } from 'node:fs/promises'
|
|
3
4
|
import path from 'node:path'
|
|
4
5
|
|
|
5
|
-
import debug from 'debug'
|
|
6
|
-
|
|
7
6
|
import { CONFIG_FILE_NAMES } from './configFiles.js'
|
|
7
|
+
import { createDebug } from './debug.js'
|
|
8
8
|
import { execGit } from './execGit.js'
|
|
9
9
|
import { loadConfig } from './loadConfig.js'
|
|
10
10
|
import { normalizePath } from './normalizePath.js'
|
|
11
11
|
import { parseGitZOutput } from './parseGitZOutput.js'
|
|
12
12
|
import { validateConfig } from './validateConfig.js'
|
|
13
13
|
|
|
14
|
-
const debugLog =
|
|
14
|
+
const debugLog = createDebug('lint-staged:searchConfigs')
|
|
15
15
|
|
|
16
16
|
const EXEC_GIT = ['ls-files', '-z', '--full-name', '-t']
|
|
17
17
|
|
|
@@ -21,6 +21,87 @@ const numberOfLevels = (file) => file.split('/').length
|
|
|
21
21
|
|
|
22
22
|
const sortDeepestParth = (a, b) => (numberOfLevels(a) > numberOfLevels(b) ? -1 : 1)
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Get all possible config files from git
|
|
26
|
+
*
|
|
27
|
+
* @param {object} options
|
|
28
|
+
* @param {string} options.cwd
|
|
29
|
+
* @param {string} options.topLevelDir
|
|
30
|
+
* @returns {Promise<string[]>}
|
|
31
|
+
*/
|
|
32
|
+
const listConfigFilesFromGit = async ({ cwd, topLevelDir }) =>
|
|
33
|
+
execGit(
|
|
34
|
+
[
|
|
35
|
+
...EXEC_GIT,
|
|
36
|
+
'--cached', // show all tracked files
|
|
37
|
+
'--others', // show untracked files
|
|
38
|
+
'--exclude-standard', // apply standard git exclusions (.gitignore, etc.)
|
|
39
|
+
'--',
|
|
40
|
+
...CONFIG_PATHSPEC,
|
|
41
|
+
],
|
|
42
|
+
{ cwd }
|
|
43
|
+
)
|
|
44
|
+
.then(parseGitZOutput)
|
|
45
|
+
.then((lines) => {
|
|
46
|
+
const possibleConfigFiles = lines
|
|
47
|
+
.flatMap((line) => {
|
|
48
|
+
/**
|
|
49
|
+
* Leave out lines starting with "S " to ignore not-checked-out files in a sparse repo.
|
|
50
|
+
* The "S" status means a tracked file that is "skip-worktree"
|
|
51
|
+
* @see https://git-scm.com/docs/git-ls-files#Documentation/git-ls-files.txt--t
|
|
52
|
+
*/
|
|
53
|
+
if (line.startsWith('S ')) {
|
|
54
|
+
return []
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const relativePath = line.replace(/^[HSMRCK?U] /, '')
|
|
58
|
+
const absolutePath = normalizePath(path.join(topLevelDir, relativePath))
|
|
59
|
+
return [absolutePath]
|
|
60
|
+
})
|
|
61
|
+
.sort(sortDeepestParth)
|
|
62
|
+
|
|
63
|
+
debugLog('Found possible config files from git:', possibleConfigFiles)
|
|
64
|
+
|
|
65
|
+
return possibleConfigFiles
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get all possible config files from filesystem, starting from `cwd` and
|
|
70
|
+
* moving upwards if nothing is found.
|
|
71
|
+
*
|
|
72
|
+
* @param {object} options
|
|
73
|
+
* @param {string} options.cwd
|
|
74
|
+
* @param {string[]} [possibleConfigFiles]
|
|
75
|
+
* @returns {Promise<string[]>}
|
|
76
|
+
*/
|
|
77
|
+
export const listConfigFilesFromFs = async ({ cwd }) => {
|
|
78
|
+
debugLog('Listing possible configs from filesystem starting from "%s"...', cwd)
|
|
79
|
+
|
|
80
|
+
const results = await Promise.allSettled(
|
|
81
|
+
CONFIG_FILE_NAMES.map(async (f) => {
|
|
82
|
+
const filepath = path.join(cwd, f)
|
|
83
|
+
await fs.access(filepath, constants.F_OK)
|
|
84
|
+
return filepath
|
|
85
|
+
})
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
const possibleConfigFiles = results.flatMap((r) =>
|
|
89
|
+
r.status === 'fulfilled' ? [normalizePath(r.value)] : []
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
if (possibleConfigFiles.length > 0) {
|
|
93
|
+
debugLog('Found possible config files from filesystem:', possibleConfigFiles)
|
|
94
|
+
return possibleConfigFiles.sort((a, b) => a.localeCompare(b))
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const parentDir = path.dirname(cwd)
|
|
98
|
+
if (parentDir === cwd) {
|
|
99
|
+
return [] /** Root-level / */
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return listConfigFilesFromFs({ cwd: parentDir })
|
|
103
|
+
}
|
|
104
|
+
|
|
24
105
|
/**
|
|
25
106
|
* Search all config files from the git repository, preferring those inside `cwd`.
|
|
26
107
|
*
|
|
@@ -28,6 +109,7 @@ const sortDeepestParth = (a, b) => (numberOfLevels(a) > numberOfLevels(b) ? -1 :
|
|
|
28
109
|
* @param {Object} [options.configObject] - Explicit config object from the js API
|
|
29
110
|
* @param {string} [options.configPath] - Explicit path to a config file
|
|
30
111
|
* @param {string} [options.cwd] - Current working directory
|
|
112
|
+
* @param {string} [options.topLevelDir] - Top-level directory of the git repo
|
|
31
113
|
* @param {Logger} logger
|
|
32
114
|
*
|
|
33
115
|
* @returns {Promise<{ [key: string]: { config: *, files: string[] } }>} found configs with filepath as key, and config as value
|
|
@@ -55,40 +137,10 @@ export const searchConfigs = async (
|
|
|
55
137
|
return { [configPath]: validateConfig(config, filepath, logger) }
|
|
56
138
|
}
|
|
57
139
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
'--cached', // show all tracked files
|
|
63
|
-
'--others', // show untracked files
|
|
64
|
-
'--exclude-standard', // apply standard git exclusions (.gitignore, etc.)
|
|
65
|
-
'--',
|
|
66
|
-
...CONFIG_PATHSPEC,
|
|
67
|
-
],
|
|
68
|
-
{ cwd }
|
|
69
|
-
).then(parseGitZOutput)
|
|
70
|
-
|
|
71
|
-
debugLog('Git listed files matching config files:', gitListedFiles)
|
|
72
|
-
|
|
73
|
-
/** Sort possible config files so that deepest is first */
|
|
74
|
-
const possibleConfigFiles = gitListedFiles
|
|
75
|
-
.flatMap((line) => {
|
|
76
|
-
/**
|
|
77
|
-
* Leave out lines starting with "S " to ignore not-checked-out files in a sparse repo.
|
|
78
|
-
* The "S" status means a tracked file that is "skip-worktree"
|
|
79
|
-
* @see https://git-scm.com/docs/git-ls-files#Documentation/git-ls-files.txt--t
|
|
80
|
-
*/
|
|
81
|
-
if (line.startsWith('S ')) {
|
|
82
|
-
return []
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const relativePath = line.replace(/^[HSMRCK?U] /, '')
|
|
86
|
-
const absolutePath = normalizePath(path.join(topLevelDir, relativePath))
|
|
87
|
-
return [absolutePath]
|
|
88
|
-
})
|
|
89
|
-
.sort(sortDeepestParth)
|
|
90
|
-
|
|
91
|
-
debugLog('Found possible config files:', possibleConfigFiles)
|
|
140
|
+
let possibleConfigFiles = await listConfigFilesFromGit({ cwd, topLevelDir })
|
|
141
|
+
if (possibleConfigFiles.length === 0) {
|
|
142
|
+
possibleConfigFiles = await listConfigFilesFromFs({ cwd })
|
|
143
|
+
}
|
|
92
144
|
|
|
93
145
|
/** Create object with key as config file, and value as null */
|
|
94
146
|
const configs = possibleConfigFiles.reduce(
|
|
@@ -112,26 +164,13 @@ export const searchConfigs = async (
|
|
|
112
164
|
)
|
|
113
165
|
|
|
114
166
|
/** Get validated configs from the above object, without any `null` values (not found) */
|
|
115
|
-
const foundConfigs = Object.entries(configs)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Try to find a single config from parent directories
|
|
121
|
-
* to match old behavior before monorepo support
|
|
122
|
-
*/
|
|
123
|
-
if (!Object.keys(foundConfigs).length) {
|
|
124
|
-
debugLog('Could not find config files inside "%s"', cwd)
|
|
125
|
-
|
|
126
|
-
const { config, filepath } = await loadConfig({ cwd }, logger)
|
|
127
|
-
if (config) {
|
|
128
|
-
debugLog('Found parent configuration file from "%s"', filepath)
|
|
129
|
-
|
|
130
|
-
foundConfigs[filepath] = validateConfig(config, filepath, logger)
|
|
131
|
-
} else {
|
|
132
|
-
debugLog('Could not find parent configuration files from "%s"', cwd)
|
|
167
|
+
const foundConfigs = Object.entries(configs).reduce((acc, [key, value]) => {
|
|
168
|
+
if (value) {
|
|
169
|
+
Object.assign(acc, { [key]: value })
|
|
133
170
|
}
|
|
134
|
-
|
|
171
|
+
|
|
172
|
+
return acc
|
|
173
|
+
}, {})
|
|
135
174
|
|
|
136
175
|
debugLog('Found %d config files', Object.keys(foundConfigs).length)
|
|
137
176
|
|
package/lib/state.js
CHANGED
|
@@ -2,27 +2,34 @@ import EventEmitter from 'events'
|
|
|
2
2
|
|
|
3
3
|
import { GIT_ERROR, TASK_ERROR } from './messages.js'
|
|
4
4
|
import {
|
|
5
|
+
ExitCodeError,
|
|
5
6
|
GitError,
|
|
6
7
|
RestoreOriginalStateError,
|
|
7
8
|
RestoreUnstagedChangesError,
|
|
8
9
|
TaskError,
|
|
9
10
|
} from './symbols.js'
|
|
10
11
|
|
|
11
|
-
export const getInitialState = ({
|
|
12
|
+
export const getInitialState = ({
|
|
13
|
+
hidePartiallyStaged = true,
|
|
14
|
+
hideUnstaged = false,
|
|
15
|
+
quiet = false,
|
|
16
|
+
revert = true,
|
|
17
|
+
} = {}) => ({
|
|
12
18
|
backupHash: null,
|
|
13
19
|
errors: new Set([]),
|
|
14
20
|
events: new EventEmitter(),
|
|
15
|
-
|
|
21
|
+
hasFilesToHide: null,
|
|
16
22
|
output: [],
|
|
17
23
|
quiet,
|
|
18
24
|
shouldBackup: null,
|
|
19
|
-
shouldHidePartiallyStaged:
|
|
25
|
+
shouldHidePartiallyStaged: hidePartiallyStaged,
|
|
26
|
+
shouldHideUnstaged: hideUnstaged,
|
|
20
27
|
shouldRevert: revert,
|
|
21
28
|
unstagedPatch: null,
|
|
22
29
|
})
|
|
23
30
|
|
|
24
|
-
export const
|
|
25
|
-
ctx.
|
|
31
|
+
export const shouldHideUnstagedFiles = (ctx) =>
|
|
32
|
+
(ctx.shouldHideUnstaged || ctx.shouldHidePartiallyStaged) && ctx.hasFilesToHide
|
|
26
33
|
|
|
27
34
|
export const applyModificationsSkipped = (ctx) => {
|
|
28
35
|
// Always apply back unstaged modifications when skipping revert or backup
|
|
@@ -52,11 +59,17 @@ export const restoreUnstagedChangesSkipped = (ctx) => {
|
|
|
52
59
|
export const restoreOriginalStateEnabled = (ctx) =>
|
|
53
60
|
!!ctx.shouldRevert &&
|
|
54
61
|
!!ctx.shouldBackup &&
|
|
55
|
-
(ctx.errors.has(
|
|
62
|
+
(ctx.errors.has(ExitCodeError) ||
|
|
63
|
+
ctx.errors.has(TaskError) ||
|
|
64
|
+
ctx.errors.has(RestoreUnstagedChangesError))
|
|
56
65
|
|
|
57
66
|
export const restoreOriginalStateSkipped = (ctx) => {
|
|
58
67
|
// Should be skipped in case of unknown git errors
|
|
59
|
-
if (
|
|
68
|
+
if (
|
|
69
|
+
ctx.errors.has(GitError) &&
|
|
70
|
+
!ctx.errors.has(RestoreUnstagedChangesError) &&
|
|
71
|
+
!ctx.errors.has(ExitCodeError)
|
|
72
|
+
) {
|
|
60
73
|
return GIT_ERROR
|
|
61
74
|
}
|
|
62
75
|
}
|
package/lib/symbols.js
CHANGED
|
@@ -25,3 +25,5 @@ export const RestoreOriginalStateError = Symbol('RestoreOriginalStateError')
|
|
|
25
25
|
export const RestoreUnstagedChangesError = Symbol('RestoreUnstagedChangesError')
|
|
26
26
|
|
|
27
27
|
export const TaskError = Symbol('TaskError')
|
|
28
|
+
|
|
29
|
+
export const ExitCodeError = Symbol('ExitCodeError')
|
package/lib/validateConfig.js
CHANGED
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
import { inspect } from 'node:util'
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
|
|
5
|
+
import { createDebug } from './debug.js'
|
|
7
6
|
import { configurationError, failedToParseConfig } from './messages.js'
|
|
8
7
|
import { ConfigEmptyError, ConfigFormatError } from './symbols.js'
|
|
9
8
|
import { validateBraces } from './validateBraces.js'
|
|
10
9
|
|
|
11
|
-
const debugLog =
|
|
10
|
+
const debugLog = createDebug('lint-staged:validateConfig')
|
|
12
11
|
|
|
13
12
|
export const validateConfigLogic = (config, configPath, logger) => {
|
|
14
13
|
debugLog('Validating config from `%s`...', configPath)
|
package/lib/validateOptions.js
CHANGED
|
@@ -2,12 +2,11 @@ import { constants } from 'node:fs'
|
|
|
2
2
|
import fs from 'node:fs/promises'
|
|
3
3
|
import path from 'node:path'
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
|
|
5
|
+
import { createDebug } from './debug.js'
|
|
7
6
|
import { invalidOption } from './messages.js'
|
|
8
7
|
import { InvalidOptionsError } from './symbols.js'
|
|
9
8
|
|
|
10
|
-
const debugLog =
|
|
9
|
+
const debugLog = createDebug('lint-staged:validateOptions')
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* Validate lint-staged options, either from the Node.js API or the command line flags.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lint-staged",
|
|
3
|
-
"version": "16.
|
|
3
|
+
"version": "16.2.0",
|
|
4
4
|
"description": "Lint files staged by git",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -13,8 +13,6 @@
|
|
|
13
13
|
},
|
|
14
14
|
"author": "Andrey Okonetchnikov <andrey@okonet.ru>",
|
|
15
15
|
"maintainers": [
|
|
16
|
-
"Lufty Wiranda <lufty.wiranda@gmail.com>",
|
|
17
|
-
"Suhas Karanth <sudo.suhas@gmail.com>",
|
|
18
16
|
"Iiro Jäppinen <iiro@jappinen.fi> (https://iiro.fi)"
|
|
19
17
|
],
|
|
20
18
|
"funding": {
|
|
@@ -42,47 +40,43 @@
|
|
|
42
40
|
"MIGRATION.md"
|
|
43
41
|
],
|
|
44
42
|
"scripts": {
|
|
45
|
-
"lint": "eslint
|
|
46
|
-
"test": "
|
|
47
|
-
"
|
|
48
|
-
"typecheck": "tsc --noEmit --strict test/types/index.ts",
|
|
43
|
+
"lint": "eslint",
|
|
44
|
+
"test": "vitest",
|
|
45
|
+
"typecheck": "tsc",
|
|
49
46
|
"version": "npx changeset version",
|
|
50
47
|
"postversion": "npm i --package-lock-only && git commit -am \"chore(changeset): release\"",
|
|
51
48
|
"tag": "npx changeset tag"
|
|
52
49
|
},
|
|
53
50
|
"dependencies": {
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"pidtree": "^0.6.0",
|
|
62
|
-
"string-argv": "^0.3.2",
|
|
63
|
-
"yaml": "^2.8.1"
|
|
51
|
+
"commander": "14.0.1",
|
|
52
|
+
"listr2": "9.0.4",
|
|
53
|
+
"micromatch": "4.0.8",
|
|
54
|
+
"nano-spawn": "1.0.3",
|
|
55
|
+
"pidtree": "0.6.0",
|
|
56
|
+
"string-argv": "0.3.2",
|
|
57
|
+
"yaml": "2.8.1"
|
|
64
58
|
},
|
|
65
59
|
"devDependencies": {
|
|
66
60
|
"@changesets/changelog-github": "0.5.1",
|
|
67
|
-
"@changesets/cli": "2.29.
|
|
61
|
+
"@changesets/cli": "2.29.7",
|
|
68
62
|
"@commitlint/cli": "19.8.1",
|
|
69
63
|
"@commitlint/config-conventional": "19.8.1",
|
|
70
|
-
"@eslint/js": "9.
|
|
64
|
+
"@eslint/js": "9.35.0",
|
|
65
|
+
"@vitest/coverage-v8": "3.2.4",
|
|
66
|
+
"@vitest/eslint-plugin": "1.3.12",
|
|
71
67
|
"consolemock": "1.1.0",
|
|
72
68
|
"cross-env": "10.0.0",
|
|
73
|
-
"eslint": "9.
|
|
69
|
+
"eslint": "9.35.0",
|
|
74
70
|
"eslint-config-prettier": "10.1.8",
|
|
75
|
-
"eslint-plugin-
|
|
76
|
-
"eslint-plugin-n": "17.21.3",
|
|
71
|
+
"eslint-plugin-n": "17.23.1",
|
|
77
72
|
"eslint-plugin-prettier": "5.5.4",
|
|
78
73
|
"eslint-plugin-simple-import-sort": "12.1.1",
|
|
79
74
|
"husky": "9.1.7",
|
|
80
|
-
"jest": "30.1.1",
|
|
81
|
-
"jest-snapshot-serializer-ansi": "2.2.1",
|
|
82
75
|
"mock-stdin": "1.0.0",
|
|
83
76
|
"prettier": "3.6.2",
|
|
84
77
|
"semver": "7.7.2",
|
|
85
|
-
"typescript": "5.9.2"
|
|
78
|
+
"typescript": "5.9.2",
|
|
79
|
+
"vitest": "3.2.4"
|
|
86
80
|
},
|
|
87
81
|
"keywords": [
|
|
88
82
|
"lint",
|