lint-staged 12.2.1 → 12.3.2
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 +13 -15
- package/bin/lint-staged.js +8 -6
- package/lib/getConfigGroups.js +48 -16
- package/lib/index.js +2 -2
- package/lib/resolveGitRepo.js +2 -1
- package/lib/runAll.js +7 -3
- package/lib/validateOptions.js +13 -0
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -81,38 +81,36 @@ See [Releases](https://github.com/okonet/lint-staged/releases).
|
|
|
81
81
|
|
|
82
82
|
## Command line flags
|
|
83
83
|
|
|
84
|
-
```
|
|
84
|
+
```
|
|
85
85
|
❯ npx lint-staged --help
|
|
86
86
|
Usage: lint-staged [options]
|
|
87
87
|
|
|
88
88
|
Options:
|
|
89
89
|
-V, --version output the version number
|
|
90
|
-
--allow-empty allow empty commits when tasks revert all staged changes
|
|
91
|
-
|
|
90
|
+
--allow-empty allow empty commits when tasks revert all staged changes (default: false)
|
|
91
|
+
-p, --concurrent <number|boolean> the number of tasks to run concurrently, or false for serial (default: true)
|
|
92
92
|
-c, --config [path] path to configuration file, or - to read from stdin
|
|
93
|
+
--cwd [path] run all tasks in specific directory, instead of the current
|
|
93
94
|
-d, --debug print additional debug information (default: false)
|
|
94
|
-
--no-stash disable the backup stash, and do not revert in case of
|
|
95
|
-
errors
|
|
96
|
-
-p, --concurrent <parallel tasks> the number of tasks to run concurrently, or false to run
|
|
97
|
-
tasks serially (default: true)
|
|
95
|
+
--no-stash disable the backup stash, and do not revert in case of errors
|
|
98
96
|
-q, --quiet disable lint-staged’s own console output (default: false)
|
|
99
97
|
-r, --relative pass relative filepaths to tasks (default: false)
|
|
100
|
-
-x, --shell [path] skip parsing of tasks for better shell support (default:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
failed output is shown (default: false)
|
|
98
|
+
-x, --shell [path] skip parsing of tasks for better shell support (default: false)
|
|
99
|
+
-v, --verbose show task output even when tasks succeed; by default only failed output is shown
|
|
100
|
+
(default: false)
|
|
104
101
|
-h, --help display help for command
|
|
105
102
|
```
|
|
106
103
|
|
|
107
104
|
- **`--allow-empty`**: By default, when linter tasks undo all staged changes, lint-staged will exit with an error and abort the commit. Use this flag to allow creating empty git commits.
|
|
105
|
+
- **`--concurrent [number|boolean]`**: Controls the concurrency of tasks being run by lint-staged. **NOTE**: This does NOT affect the concurrency of subtasks (they will always be run sequentially). Possible values are:
|
|
106
|
+
- `false`: Run all tasks serially
|
|
107
|
+
- `true` (default) : _Infinite_ concurrency. Runs as many tasks in parallel as possible.
|
|
108
|
+
- `{number}`: Run the specified number of tasks in parallel, where `1` is equivalent to `false`.
|
|
108
109
|
- **`--config [path]`**: Manually specify a path to a config file or npm package name. Note: when used, lint-staged won't perform the config file search and will print an error if the specified file cannot be found. If '-' is provided as the filename then the config will be read from stdin, allowing piping in the config like `cat my-config.json | npx lint-staged --config -`.
|
|
110
|
+
- **`--cwd [path]`**: By default tasks run in the current working directory. Use the `--cwd some/directory` to override this. The path can be absolute or relative to the current working directory.
|
|
109
111
|
- **`--debug`**: Run in debug mode. When set, it does the following:
|
|
110
112
|
- uses [debug](https://github.com/visionmedia/debug) internally to log additional information about staged files, commands being executed, location of binaries, etc. Debug logs, which are automatically enabled by passing the flag, can also be enabled by setting the environment variable `$DEBUG` to `lint-staged*`.
|
|
111
113
|
- uses [`verbose` renderer](https://github.com/SamVerschueren/listr-verbose-renderer) for `listr`; this causes serial, uncoloured output to the terminal, instead of the default (beautified, dynamic) output.
|
|
112
|
-
- **`--concurrent [number | (true/false)]`**: Controls the concurrency of tasks being run by lint-staged. **NOTE**: This does NOT affect the concurrency of subtasks (they will always be run sequentially). Possible values are:
|
|
113
|
-
- `false`: Run all tasks serially
|
|
114
|
-
- `true` (default) : _Infinite_ concurrency. Runs as many tasks in parallel as possible.
|
|
115
|
-
- `{number}`: Run the specified number of tasks in parallel, where `1` is equivalent to `false`.
|
|
116
114
|
- **`--no-stash`**: By default a backup stash will be created before running the tasks, and all task modifications will be reverted in case of an error. This option will disable creating the stash, and instead leave all modifications in the index when aborting the commit.
|
|
117
115
|
- **`--quiet`**: Supress all CLI output, except from tasks.
|
|
118
116
|
- **`--relative`**: Pass filepaths relative to `process.cwd()` (where `lint-staged` runs) to tasks. Default is `false`.
|
package/bin/lint-staged.js
CHANGED
|
@@ -26,14 +26,15 @@ const version = packageJson.version
|
|
|
26
26
|
cmdline
|
|
27
27
|
.version(version)
|
|
28
28
|
.option('--allow-empty', 'allow empty commits when tasks revert all staged changes', false)
|
|
29
|
-
.option('-c, --config [path]', 'path to configuration file, or - to read from stdin')
|
|
30
|
-
.option('-d, --debug', 'print additional debug information', false)
|
|
31
|
-
.option('--no-stash', 'disable the backup stash, and do not revert in case of errors', false)
|
|
32
29
|
.option(
|
|
33
|
-
'-p, --concurrent <
|
|
34
|
-
'the number of tasks to run concurrently, or false
|
|
30
|
+
'-p, --concurrent <number|boolean>',
|
|
31
|
+
'the number of tasks to run concurrently, or false for serial',
|
|
35
32
|
true
|
|
36
33
|
)
|
|
34
|
+
.option('-c, --config [path]', 'path to configuration file, or - to read from stdin')
|
|
35
|
+
.option('--cwd [path]', 'run all tasks in specific directory, instead of the current')
|
|
36
|
+
.option('-d, --debug', 'print additional debug information', false)
|
|
37
|
+
.option('--no-stash', 'disable the backup stash, and do not revert in case of errors', false)
|
|
37
38
|
.option('-q, --quiet', 'disable lint-staged’s own console output', false)
|
|
38
39
|
.option('-r, --relative', 'pass relative filepaths to tasks', false)
|
|
39
40
|
.option('-x, --shell [path]', 'skip parsing of tasks for better shell support', false)
|
|
@@ -75,12 +76,13 @@ const options = {
|
|
|
75
76
|
allowEmpty: !!cmdlineOptions.allowEmpty,
|
|
76
77
|
concurrent: JSON.parse(cmdlineOptions.concurrent),
|
|
77
78
|
configPath: cmdlineOptions.config,
|
|
79
|
+
cwd: cmdlineOptions.cwd,
|
|
78
80
|
debug: !!cmdlineOptions.debug,
|
|
79
81
|
maxArgLength: getMaxArgLength() / 2,
|
|
80
|
-
stash: !!cmdlineOptions.stash, // commander inverts `no-<x>` flags to `!x`
|
|
81
82
|
quiet: !!cmdlineOptions.quiet,
|
|
82
83
|
relative: !!cmdlineOptions.relative,
|
|
83
84
|
shell: cmdlineOptions.shell /* Either a boolean or a string pointing to the shell */,
|
|
85
|
+
stash: !!cmdlineOptions.stash, // commander inverts `no-<x>` flags to `!x`
|
|
84
86
|
verbose: !!cmdlineOptions.verbose,
|
|
85
87
|
}
|
|
86
88
|
|
package/lib/getConfigGroups.js
CHANGED
|
@@ -2,10 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import path from 'path'
|
|
4
4
|
|
|
5
|
+
import debug from 'debug'
|
|
6
|
+
import objectInspect from 'object-inspect'
|
|
7
|
+
|
|
5
8
|
import { loadConfig } from './loadConfig.js'
|
|
6
9
|
import { ConfigNotFoundError } from './symbols.js'
|
|
7
10
|
import { validateConfig } from './validateConfig.js'
|
|
8
11
|
|
|
12
|
+
const debugLog = debug('lint-staged:getConfigGroups')
|
|
13
|
+
|
|
9
14
|
/**
|
|
10
15
|
* Return matched files grouped by their configuration.
|
|
11
16
|
*
|
|
@@ -13,17 +18,27 @@ import { validateConfig } from './validateConfig.js'
|
|
|
13
18
|
* @param {Object} [options.configObject] - Explicit config object from the js API
|
|
14
19
|
* @param {string} [options.configPath] - Explicit path to a config file
|
|
15
20
|
* @param {string} [options.cwd] - Current working directory
|
|
21
|
+
* @param {string} [options.files] - List of staged files
|
|
16
22
|
* @param {Logger} logger
|
|
17
23
|
*/
|
|
18
|
-
export const getConfigGroups = async (
|
|
24
|
+
export const getConfigGroups = async (
|
|
25
|
+
{ configObject, configPath, cwd, files },
|
|
26
|
+
logger = console
|
|
27
|
+
) => {
|
|
28
|
+
debugLog('Grouping configuration files...')
|
|
29
|
+
|
|
19
30
|
// Return explicit config object from js API
|
|
20
31
|
if (configObject) {
|
|
32
|
+
debugLog('Using single direct configuration object...')
|
|
33
|
+
|
|
21
34
|
const config = validateConfig(configObject, 'config object', logger)
|
|
22
35
|
return { '': { config, files } }
|
|
23
36
|
}
|
|
24
37
|
|
|
25
38
|
// Use only explicit config path instead of discovering multiple
|
|
26
39
|
if (configPath) {
|
|
40
|
+
debugLog('Using single configuration path...')
|
|
41
|
+
|
|
27
42
|
const { config, filepath } = await loadConfig({ configPath }, logger)
|
|
28
43
|
|
|
29
44
|
if (!config) {
|
|
@@ -35,6 +50,8 @@ export const getConfigGroups = async ({ configObject, configPath, files }, logge
|
|
|
35
50
|
return { [configPath]: { config: validatedConfig, files } }
|
|
36
51
|
}
|
|
37
52
|
|
|
53
|
+
debugLog('Grouping staged files by their directories...')
|
|
54
|
+
|
|
38
55
|
// Group files by their base directory
|
|
39
56
|
const filesByDir = files.reduce((acc, file) => {
|
|
40
57
|
const dir = path.normalize(path.dirname(file))
|
|
@@ -48,33 +65,48 @@ export const getConfigGroups = async ({ configObject, configPath, files }, logge
|
|
|
48
65
|
return acc
|
|
49
66
|
}, {})
|
|
50
67
|
|
|
68
|
+
debugLog('Grouped staged files into %d directories:', Object.keys(filesByDir).length)
|
|
69
|
+
debugLog(objectInspect(filesByDir, { indent: 2 }))
|
|
70
|
+
|
|
51
71
|
// Group files by their discovered config
|
|
52
72
|
// { '.lintstagedrc.json': { config: {...}, files: [...] } }
|
|
53
73
|
const configGroups = {}
|
|
54
74
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
75
|
+
debugLog('Searching config files...')
|
|
76
|
+
|
|
77
|
+
const searchConfig = async (cwd, files = []) => {
|
|
78
|
+
const { config, filepath } = await loadConfig({ cwd }, logger)
|
|
79
|
+
if (!config) {
|
|
80
|
+
debugLog('Found no config from "%s"!', cwd)
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (filepath in configGroups) {
|
|
85
|
+
debugLog('Found existing config "%s" from "%s"!', filepath, cwd)
|
|
86
|
+
// Re-use cached config and skip validation
|
|
87
|
+
configGroups[filepath].files.push(...files)
|
|
88
|
+
} else {
|
|
89
|
+
debugLog('Found new config "%s" from "%s"!', filepath, cwd)
|
|
60
90
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
91
|
+
const validatedConfig = validateConfig(config, filepath, logger)
|
|
92
|
+
configGroups[filepath] = { config: validatedConfig, files }
|
|
93
|
+
}
|
|
94
|
+
}
|
|
66
95
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
)
|
|
96
|
+
// Start by searching from cwd
|
|
97
|
+
await searchConfig(cwd)
|
|
98
|
+
|
|
99
|
+
// Discover configs from the base directory of each file
|
|
100
|
+
await Promise.all(Object.entries(filesByDir).map(([dir, files]) => searchConfig(dir, files)))
|
|
72
101
|
|
|
73
102
|
// Throw if no configurations were found
|
|
74
103
|
if (Object.keys(configGroups).length === 0) {
|
|
104
|
+
debugLog('Found no config groups!')
|
|
75
105
|
logger.error(`${ConfigNotFoundError.message}.`)
|
|
76
106
|
throw ConfigNotFoundError
|
|
77
107
|
}
|
|
78
108
|
|
|
109
|
+
debugLog('Grouped staged files into %d groups!', Object.keys(configGroups).length)
|
|
110
|
+
|
|
79
111
|
return configGroups
|
|
80
112
|
}
|
package/lib/index.js
CHANGED
|
@@ -37,7 +37,7 @@ const lintStaged = async (
|
|
|
37
37
|
concurrent = true,
|
|
38
38
|
config: configObject,
|
|
39
39
|
configPath,
|
|
40
|
-
cwd
|
|
40
|
+
cwd,
|
|
41
41
|
debug = false,
|
|
42
42
|
maxArgLength,
|
|
43
43
|
quiet = false,
|
|
@@ -48,7 +48,7 @@ const lintStaged = async (
|
|
|
48
48
|
} = {},
|
|
49
49
|
logger = console
|
|
50
50
|
) => {
|
|
51
|
-
await validateOptions({ shell }, logger)
|
|
51
|
+
await validateOptions({ cwd, shell }, logger)
|
|
52
52
|
|
|
53
53
|
// Unset GIT_LITERAL_PATHSPECS to not mess with path interpretation
|
|
54
54
|
debugLog('Unset GIT_LITERAL_PATHSPECS (was `%s`)', process.env.GIT_LITERAL_PATHSPECS)
|
package/lib/resolveGitRepo.js
CHANGED
|
@@ -14,7 +14,8 @@ const debugLog = debug('lint-staged:resolveGitRepo')
|
|
|
14
14
|
* submodules and worktrees
|
|
15
15
|
*/
|
|
16
16
|
const resolveGitConfigDir = async (gitDir) => {
|
|
17
|
-
|
|
17
|
+
// Get the real path in case it's a symlink
|
|
18
|
+
const defaultDir = normalize(await fs.realpath(path.join(gitDir, '.git')))
|
|
18
19
|
const stats = await fs.lstat(defaultDir)
|
|
19
20
|
// If .git is a directory, use it
|
|
20
21
|
if (stats.isDirectory()) return defaultDir
|
package/lib/runAll.js
CHANGED
|
@@ -66,7 +66,7 @@ export const runAll = async (
|
|
|
66
66
|
concurrent = true,
|
|
67
67
|
configObject,
|
|
68
68
|
configPath,
|
|
69
|
-
cwd
|
|
69
|
+
cwd,
|
|
70
70
|
debug = false,
|
|
71
71
|
maxArgLength,
|
|
72
72
|
quiet = false,
|
|
@@ -77,7 +77,11 @@ export const runAll = async (
|
|
|
77
77
|
},
|
|
78
78
|
logger = console
|
|
79
79
|
) => {
|
|
80
|
-
debugLog('Running all linter scripts')
|
|
80
|
+
debugLog('Running all linter scripts...')
|
|
81
|
+
|
|
82
|
+
// Resolve relative CWD option
|
|
83
|
+
cwd = cwd ? path.resolve(cwd) : process.cwd()
|
|
84
|
+
debugLog('Using working directory `%s`', cwd)
|
|
81
85
|
|
|
82
86
|
const ctx = getInitialState({ quiet })
|
|
83
87
|
|
|
@@ -114,7 +118,7 @@ export const runAll = async (
|
|
|
114
118
|
return ctx
|
|
115
119
|
}
|
|
116
120
|
|
|
117
|
-
const configGroups = await getConfigGroups({ configObject, configPath, files }, logger)
|
|
121
|
+
const configGroups = await getConfigGroups({ configObject, configPath, cwd, files }, logger)
|
|
118
122
|
|
|
119
123
|
// lint-staged 10 will automatically add modifications to index
|
|
120
124
|
// Warn user when their command includes `git add`
|
package/lib/validateOptions.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { constants, promises as fs } from 'fs'
|
|
2
|
+
import path from 'path'
|
|
2
3
|
|
|
3
4
|
import debug from 'debug'
|
|
4
5
|
|
|
@@ -10,6 +11,7 @@ const debugLog = debug('lint-staged:validateOptions')
|
|
|
10
11
|
/**
|
|
11
12
|
* Validate lint-staged options, either from the Node.js API or the command line flags.
|
|
12
13
|
* @param {*} options
|
|
14
|
+
* @param {boolean|string} [options.cwd] - Current working directory
|
|
13
15
|
* @param {boolean|string} [options.shell] - Skip parsing of tasks for better shell support
|
|
14
16
|
*
|
|
15
17
|
* @throws {InvalidOptionsError}
|
|
@@ -17,6 +19,17 @@ const debugLog = debug('lint-staged:validateOptions')
|
|
|
17
19
|
export const validateOptions = async (options = {}, logger) => {
|
|
18
20
|
debugLog('Validating options...')
|
|
19
21
|
|
|
22
|
+
/** Ensure the passed cwd option exists; it might also be relative */
|
|
23
|
+
if (typeof options.cwd === 'string') {
|
|
24
|
+
try {
|
|
25
|
+
const resolved = path.resolve(options.cwd)
|
|
26
|
+
await fs.access(resolved, constants.F_OK)
|
|
27
|
+
} catch (error) {
|
|
28
|
+
logger.error(invalidOption('cwd', options.cwd, error.message))
|
|
29
|
+
throw InvalidOptionsError
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
20
33
|
/** Ensure the passed shell option is executable */
|
|
21
34
|
if (typeof options.shell === 'string') {
|
|
22
35
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lint-staged",
|
|
3
|
-
"version": "12.2
|
|
3
|
+
"version": "12.3.2",
|
|
4
4
|
"description": "Lint files staged by git",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "https://github.com/okonet/lint-staged",
|
|
@@ -35,28 +35,28 @@
|
|
|
35
35
|
"debug": "^4.3.3",
|
|
36
36
|
"execa": "^5.1.1",
|
|
37
37
|
"lilconfig": "2.0.4",
|
|
38
|
-
"listr2": "^
|
|
38
|
+
"listr2": "^4.0.1",
|
|
39
39
|
"micromatch": "^4.0.4",
|
|
40
40
|
"normalize-path": "^3.0.0",
|
|
41
|
-
"object-inspect": "^1.
|
|
41
|
+
"object-inspect": "^1.12.0",
|
|
42
42
|
"string-argv": "^0.3.1",
|
|
43
43
|
"supports-color": "^9.2.1",
|
|
44
44
|
"yaml": "^1.10.2"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@babel/core": "^7.16.
|
|
47
|
+
"@babel/core": "^7.16.12",
|
|
48
48
|
"@babel/eslint-parser": "^7.16.5",
|
|
49
|
-
"@babel/preset-env": "^7.16.
|
|
50
|
-
"babel-jest": "^27.4.
|
|
49
|
+
"@babel/preset-env": "^7.16.11",
|
|
50
|
+
"babel-jest": "^27.4.6",
|
|
51
51
|
"consolemock": "^1.1.0",
|
|
52
|
-
"eslint": "^8.
|
|
52
|
+
"eslint": "^8.7.0",
|
|
53
53
|
"eslint-config-prettier": "^8.3.0",
|
|
54
|
-
"eslint-plugin-import": "^2.25.
|
|
54
|
+
"eslint-plugin-import": "^2.25.4",
|
|
55
55
|
"eslint-plugin-node": "^11.1.0",
|
|
56
56
|
"eslint-plugin-prettier": "^4.0.0",
|
|
57
57
|
"fs-extra": "^10.0.0",
|
|
58
58
|
"husky": "^7.0.4",
|
|
59
|
-
"jest": "^27.4.
|
|
59
|
+
"jest": "^27.4.7",
|
|
60
60
|
"jest-snapshot-serializer-ansi": "^1.0.0",
|
|
61
61
|
"prettier": "^2.5.1"
|
|
62
62
|
},
|