lint-staged 5.0.0 → 6.1.1
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 +72 -4
- package/index.js +11 -1
- package/package.json +88 -1
- package/src/findBin.js +8 -2
- package/src/generateTasks.js +15 -5
- package/src/getConfig.js +21 -17
- package/src/index.js +16 -7
- package/src/runAll.js +10 -4
- package/src/runScript.js +11 -2
package/README.md
CHANGED
|
@@ -50,6 +50,32 @@ See [examples](#examples) and [configuration](#configuration) below.
|
|
|
50
50
|
>
|
|
51
51
|
> To mitigate this rename your `commit` npm script to something non git hook namespace like, for example `{ cz: git-cz }`
|
|
52
52
|
|
|
53
|
+
## Changelog
|
|
54
|
+
|
|
55
|
+
[releases](https://github.com/okonet/lint-staged/releases)
|
|
56
|
+
|
|
57
|
+
## Command line flags
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
$ ./node_modules/.bin/lint-staged --help
|
|
61
|
+
|
|
62
|
+
Usage: lint-staged [options]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
Options:
|
|
66
|
+
|
|
67
|
+
-V, --version output the version number
|
|
68
|
+
-c, --config [path] Path to configuration file
|
|
69
|
+
-d, --debug Enable debug mode
|
|
70
|
+
-h, --help output usage information
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
* **`--config [path]`**: This can be used to manually specify the `lint-staged` config file location. However, if the specified file cannot be found, it will error out instead of performing the usual search.
|
|
74
|
+
* **`--debug`**: Enabling the debug mode does the following:
|
|
75
|
+
- `lint-staged` uses the [debug](https://github.com/visionmedia/debug) module internally to log 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*`.
|
|
76
|
+
- Use the [`verbose` renderer](https://github.com/SamVerschueren/listr-verbose-renderer) for `listr`.
|
|
77
|
+
- Do not pass `--silent` to npm scripts.
|
|
78
|
+
|
|
53
79
|
## Configuration
|
|
54
80
|
|
|
55
81
|
Starting with v3.1 you can now use different ways of configuring it:
|
|
@@ -98,16 +124,19 @@ To set options and keep lint-staged extensible, advanced format can be used. Thi
|
|
|
98
124
|
|
|
99
125
|
## Options
|
|
100
126
|
|
|
101
|
-
* `linters` — `Object` — keys (`String`) are glob patterns, values (`Array<String> | String`) are commands to execute.
|
|
102
127
|
* `concurrent` — *true* — runs linters for each glob pattern simultaneously. If you don’t want this, you can set `concurrent: false`
|
|
103
128
|
* `chunkSize` — Max allowed chunk size based on number of files for glob pattern. This is important on windows based systems to avoid command length limitations. See [#147](https://github.com/okonet/lint-staged/issues/147)
|
|
129
|
+
* `globOptions` — `{ matchBase: true, dot: true }` — [minimatch options](https://github.com/isaacs/minimatch#options) to
|
|
130
|
+
customize how glob patterns match files.
|
|
131
|
+
* `ignore` - `['**/docs/**/*.js']` - array of glob patterns to entirely ignore from any task.
|
|
132
|
+
* `linters` — `Object` — keys (`String`) are glob patterns, values (`Array<String> | String`) are commands to execute.
|
|
104
133
|
* `subTaskConcurrency` — `1` — Controls concurrency for processing chunks generated for each linter. Execution is **not** concurrent by default(see [#225](https://github.com/okonet/lint-staged/issues/225))
|
|
105
|
-
* `verbose` — *false* — runs lint-staged in verbose mode. When `true` it will use https://github.com/SamVerschueren/listr-verbose-renderer.
|
|
106
|
-
* `globOptions` — `{ matchBase: true, dot: true }` — [minimatch options](https://github.com/isaacs/minimatch#options) to customize how glob patterns match files.
|
|
107
134
|
|
|
108
135
|
## Filtering files
|
|
109
136
|
|
|
110
|
-
It is possible to run linters for certain paths only by using [minimatch](https://github.com/isaacs/minimatch)
|
|
137
|
+
It is possible to run linters for certain paths only by using glob patterns. [minimatch](https://github.com/isaacs/minimatch) is used to filter the staged files according to these patterns. File patterns should be specified _relative to the `package.json` location_ (i.e. where `lint-staged` is installed).
|
|
138
|
+
|
|
139
|
+
**NOTE:** If you're using `lint-staged<5` globs have to be _relative to the git root_.
|
|
111
140
|
|
|
112
141
|
```js
|
|
113
142
|
{
|
|
@@ -122,6 +151,17 @@ It is possible to run linters for certain paths only by using [minimatch](https:
|
|
|
122
151
|
}
|
|
123
152
|
```
|
|
124
153
|
|
|
154
|
+
When matching, `lint-staged` will do the following
|
|
155
|
+
|
|
156
|
+
* Resolve the git root automatically, no configuration needed.
|
|
157
|
+
* Pick the staged files which are present inside the project directory.
|
|
158
|
+
* Filter them using the specified glob patterns.
|
|
159
|
+
* Pass absolute paths to the linters as arguments.
|
|
160
|
+
|
|
161
|
+
**NOTE:** `lint-staged` will pass _absolute_ paths to the linters to avoid any confusion in case they're executed in a different working directory (i.e. when your `.git` directory isn't the same as your `package.json` directory).
|
|
162
|
+
|
|
163
|
+
Also see [How to use `lint-staged` in a multi package monorepo?](#how-to-use-lint-staged-in-a-multi-package-monorepo)
|
|
164
|
+
|
|
125
165
|
## What commands are supported?
|
|
126
166
|
|
|
127
167
|
Supported are both local npm scripts (`npm run-script`), or any executables installed locally or globally via `npm` as well as any executable from your $PATH.
|
|
@@ -140,6 +180,15 @@ Pass arguments to your commands separated by space as you would do in the shell.
|
|
|
140
180
|
|
|
141
181
|
Starting from [v2.0.0](https://github.com/okonet/lint-staged/releases/tag/2.0.0) sequences of commands are supported. Pass an array of commands instead of a single one and they will run sequentially. This is useful for running autoformatting tools like `eslint --fix` or `stylefmt` but can be used for any arbitrary sequences.
|
|
142
182
|
|
|
183
|
+
## How to use `lint-staged` in a multi package monorepo?
|
|
184
|
+
|
|
185
|
+
Starting with v5.0, `lint-staged` automatically resolves the git root **without any** additional configuration. You configure `lint-staged` as you normally would if your project root and git root were the same directory.
|
|
186
|
+
|
|
187
|
+
If you wish to use `lint-staged` in a multi package monorepo, it is recommended to install [`husky`](https://github.com/typicode/husky) in the root package.json.
|
|
188
|
+
[`lerna`](https://github.com/lerna/lerna) can be used to execute the `precommit` script in all sub-packages.
|
|
189
|
+
|
|
190
|
+
Example repo: [sudo-suhas/lint-staged-multi-pkg](https://github.com/sudo-suhas/lint-staged-multi-pkg).
|
|
191
|
+
|
|
143
192
|
## Reformatting the code
|
|
144
193
|
|
|
145
194
|
Tools like ESLint/TSLint or stylefmt can reformat your code according to an appropriate config by running `eslint --fix`/`tslint --fix`. After the code is reformatted, we want it to be added to the same commit. This can be done using following config:
|
|
@@ -223,3 +272,22 @@ This will run `eslint --fix` and automatically add changes to the commit. Please
|
|
|
223
272
|
]
|
|
224
273
|
}
|
|
225
274
|
```
|
|
275
|
+
|
|
276
|
+
### Minify the images and add files to commit
|
|
277
|
+
|
|
278
|
+
```json
|
|
279
|
+
{
|
|
280
|
+
"*.{png,jpeg,jpg,gif,svg}": [
|
|
281
|
+
"imagemin-lint-staged",
|
|
282
|
+
"git add"
|
|
283
|
+
]
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
<details>
|
|
288
|
+
<summary>More about <code>imagemin-lint-staged</code></summary>
|
|
289
|
+
|
|
290
|
+
[imagemin-lint-staged](https://github.com/tomchentw/imagemin-lint-staged) is a CLI tool designed for lint-staged usage with sensible defaults.
|
|
291
|
+
|
|
292
|
+
See more on [this blog post](https://medium.com/@tomchentw/imagemin-lint-staged-in-place-minify-the-images-before-adding-to-the-git-repo-5acda0b4c57e) for benefits of this approach.
|
|
293
|
+
</details>
|
package/index.js
CHANGED
|
@@ -3,11 +3,21 @@
|
|
|
3
3
|
'use strict'
|
|
4
4
|
|
|
5
5
|
const cmdline = require('commander')
|
|
6
|
+
const debugLib = require('debug')
|
|
6
7
|
const pkg = require('./package.json')
|
|
7
8
|
|
|
9
|
+
const debug = debugLib('lint-staged:bin')
|
|
10
|
+
|
|
8
11
|
cmdline
|
|
9
12
|
.version(pkg.version)
|
|
10
13
|
.option('-c, --config [path]', 'Path to configuration file')
|
|
14
|
+
.option('-d, --debug', 'Enable debug mode')
|
|
11
15
|
.parse(process.argv)
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
if (cmdline.debug) {
|
|
18
|
+
debugLib.enable('lint-staged*')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
debug('Running `lint-staged@%s`', pkg.version)
|
|
22
|
+
|
|
23
|
+
require('./src')(console, cmdline.config, cmdline.debug)
|
package/package.json
CHANGED
|
@@ -1 +1,88 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"name": "lint-staged",
|
|
3
|
+
"version": "6.1.1",
|
|
4
|
+
"description": "Lint files staged by git",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": "https://github.com/okonet/lint-staged",
|
|
7
|
+
"author": "Andrey Okonetchnikov <andrey@okonet.ru>",
|
|
8
|
+
"maintainers": [
|
|
9
|
+
"Lufty Wiranda <lufty.wiranda@gmail.com>",
|
|
10
|
+
"Suhas Karanth <sudo.suhas@gmail.com>"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=4.2.0"
|
|
14
|
+
},
|
|
15
|
+
"bin": "index.js",
|
|
16
|
+
"files": [
|
|
17
|
+
"index.js",
|
|
18
|
+
"src"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"precommit": "node index.js",
|
|
22
|
+
"cz": "git-cz",
|
|
23
|
+
"lint": "eslint .",
|
|
24
|
+
"lint:fix": "yarn lint --fix",
|
|
25
|
+
"pretest": "yarn lint",
|
|
26
|
+
"test": "jest --coverage",
|
|
27
|
+
"test:watch": "jest --watch"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"app-root-path": "^2.0.0",
|
|
31
|
+
"chalk": "^2.1.0",
|
|
32
|
+
"commander": "^2.11.0",
|
|
33
|
+
"cosmiconfig": "^4.0.0",
|
|
34
|
+
"debug": "^3.1.0",
|
|
35
|
+
"dedent": "^0.7.0",
|
|
36
|
+
"execa": "^0.8.0",
|
|
37
|
+
"find-parent-dir": "^0.3.0",
|
|
38
|
+
"is-glob": "^4.0.0",
|
|
39
|
+
"jest-validate": "^21.1.0",
|
|
40
|
+
"listr": "^0.13.0",
|
|
41
|
+
"lodash": "^4.17.4",
|
|
42
|
+
"log-symbols": "^2.0.0",
|
|
43
|
+
"minimatch": "^3.0.0",
|
|
44
|
+
"npm-which": "^3.0.1",
|
|
45
|
+
"p-map": "^1.1.1",
|
|
46
|
+
"path-is-inside": "^1.0.2",
|
|
47
|
+
"pify": "^3.0.0",
|
|
48
|
+
"staged-git-files": "1.0.0",
|
|
49
|
+
"stringify-object": "^3.2.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"babel-preset-env": "^1.6.0",
|
|
53
|
+
"commitizen": "^2.9.6",
|
|
54
|
+
"consolemock": "^1.0.2",
|
|
55
|
+
"cz-conventional-changelog": "^2.0.0",
|
|
56
|
+
"eslint": "^4.5.0",
|
|
57
|
+
"eslint-config-okonet": "^5.0.1",
|
|
58
|
+
"eslint-plugin-node": "^5.1.1",
|
|
59
|
+
"husky": "^0.14.3",
|
|
60
|
+
"jest": "^22.0.4",
|
|
61
|
+
"jsonlint": "^1.6.2",
|
|
62
|
+
"prettier": "1.9.2"
|
|
63
|
+
},
|
|
64
|
+
"config": {
|
|
65
|
+
"commitizen": {
|
|
66
|
+
"path": "./node_modules/cz-conventional-changelog"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"jest": {
|
|
70
|
+
"testEnvironment": "node",
|
|
71
|
+
"setupFiles": [
|
|
72
|
+
"./testSetup.js"
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
"keywords": [
|
|
76
|
+
"lint",
|
|
77
|
+
"git",
|
|
78
|
+
"staged",
|
|
79
|
+
"eslint",
|
|
80
|
+
"prettier",
|
|
81
|
+
"stylelint",
|
|
82
|
+
"code",
|
|
83
|
+
"quality",
|
|
84
|
+
"check",
|
|
85
|
+
"format",
|
|
86
|
+
"validate"
|
|
87
|
+
]
|
|
88
|
+
}
|
package/src/findBin.js
CHANGED
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
const npmWhich = require('npm-which')(process.cwd())
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const debug = require('debug')('lint-staged:find-bin')
|
|
6
|
+
|
|
7
|
+
module.exports = function findBin(cmd, scripts, debugMode) {
|
|
8
|
+
debug('Resolving binary for command `%s`', cmd)
|
|
6
9
|
const npmArgs = (bin, args) =>
|
|
7
10
|
// We always add `--` even if args are not defined. This is required
|
|
8
11
|
// because we pass filenames later.
|
|
9
|
-
['run',
|
|
12
|
+
['run', debugMode ? undefined : '--silent', bin, '--']
|
|
10
13
|
// args could be undefined but we filter that out.
|
|
11
14
|
.concat(args)
|
|
12
15
|
.filter(arg => arg !== undefined)
|
|
@@ -39,6 +42,7 @@ module.exports = function findBin(cmd, scripts, options) {
|
|
|
39
42
|
*/
|
|
40
43
|
if (scripts[cmd] !== undefined) {
|
|
41
44
|
// Support for scripts from package.json
|
|
45
|
+
debug('`%s` resolved to npm script - `%s`', cmd, scripts[cmd])
|
|
42
46
|
return { bin: 'npm', args: npmArgs(cmd) }
|
|
43
47
|
}
|
|
44
48
|
|
|
@@ -47,6 +51,7 @@ module.exports = function findBin(cmd, scripts, options) {
|
|
|
47
51
|
const args = parts.splice(1)
|
|
48
52
|
|
|
49
53
|
if (scripts[bin] !== undefined) {
|
|
54
|
+
debug('`%s` resolved to npm script - `%s`', bin, scripts[bin])
|
|
50
55
|
return { bin: 'npm', args: npmArgs(bin, args) }
|
|
51
56
|
}
|
|
52
57
|
|
|
@@ -76,5 +81,6 @@ module.exports = function findBin(cmd, scripts, options) {
|
|
|
76
81
|
throw new Error(`${bin} could not be found. Try \`npm install ${bin}\`.`)
|
|
77
82
|
}
|
|
78
83
|
|
|
84
|
+
debug('Binary for `%s` resolved to `%s`', cmd, bin)
|
|
79
85
|
return { bin, args }
|
|
80
86
|
}
|
package/src/generateTasks.js
CHANGED
|
@@ -6,10 +6,20 @@ const pathIsInside = require('path-is-inside')
|
|
|
6
6
|
const getConfig = require('./getConfig').getConfig
|
|
7
7
|
const resolveGitDir = require('./resolveGitDir')
|
|
8
8
|
|
|
9
|
+
const debug = require('debug')('lint-staged:gen-tasks')
|
|
10
|
+
|
|
9
11
|
module.exports = function generateTasks(config, relFiles) {
|
|
12
|
+
debug('Generating linter tasks')
|
|
13
|
+
|
|
10
14
|
const normalizedConfig = getConfig(config) // Ensure we have a normalized config
|
|
11
15
|
const linters = normalizedConfig.linters
|
|
12
16
|
const globOptions = normalizedConfig.globOptions
|
|
17
|
+
const ignoreFilters = normalizedConfig.ignore.map(pattern => minimatch.filter(pattern))
|
|
18
|
+
// if there are filters, then return false if the input matches any
|
|
19
|
+
// if there are not, then return true for all input
|
|
20
|
+
const ignoreFilter = ignoreFilters.length
|
|
21
|
+
? input => !ignoreFilters.some(filter => filter(input))
|
|
22
|
+
: () => true
|
|
13
23
|
|
|
14
24
|
const gitDir = resolveGitDir()
|
|
15
25
|
const cwd = process.cwd()
|
|
@@ -26,13 +36,13 @@ module.exports = function generateTasks(config, relFiles) {
|
|
|
26
36
|
.map(file => path.relative(cwd, file))
|
|
27
37
|
// We want to filter before resolving paths
|
|
28
38
|
.filter(filter)
|
|
39
|
+
.filter(ignoreFilter)
|
|
29
40
|
// Return absolute path after the filter is run
|
|
30
41
|
.map(file => path.resolve(cwd, file))
|
|
31
42
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
43
|
+
const task = { pattern, commands, fileList }
|
|
44
|
+
debug('Generated task: \n%O', task)
|
|
45
|
+
|
|
46
|
+
return task
|
|
37
47
|
})
|
|
38
48
|
}
|
package/src/getConfig.js
CHANGED
|
@@ -12,10 +12,12 @@ const logValidationWarning = require('jest-validate').logValidationWarning
|
|
|
12
12
|
const unknownOptionWarning = require('jest-validate/build/warnings').unknownOptionWarning
|
|
13
13
|
const isGlob = require('is-glob')
|
|
14
14
|
|
|
15
|
+
const debug = require('debug')('lint-staged:cfg')
|
|
16
|
+
|
|
15
17
|
/**
|
|
16
18
|
* Default config object
|
|
17
19
|
*
|
|
18
|
-
* @type {{concurrent: boolean, chunkSize: number, globOptions: {matchBase: boolean, dot: boolean}, linters: {}, subTaskConcurrency: number, renderer: string
|
|
20
|
+
* @type {{concurrent: boolean, chunkSize: number, globOptions: {matchBase: boolean, dot: boolean}, linters: {}, subTaskConcurrency: number, renderer: string}}
|
|
19
21
|
*/
|
|
20
22
|
const defaultConfig = {
|
|
21
23
|
concurrent: true,
|
|
@@ -25,9 +27,9 @@ const defaultConfig = {
|
|
|
25
27
|
dot: true
|
|
26
28
|
},
|
|
27
29
|
linters: {},
|
|
30
|
+
ignore: [],
|
|
28
31
|
subTaskConcurrency: 1,
|
|
29
|
-
renderer: 'update'
|
|
30
|
-
verbose: false
|
|
32
|
+
renderer: 'update'
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
/**
|
|
@@ -72,7 +74,7 @@ function unknownValidationReporter(config, example, option, options) {
|
|
|
72
74
|
will fix it and remove this message.`
|
|
73
75
|
|
|
74
76
|
const comment = options.comment
|
|
75
|
-
const name =
|
|
77
|
+
const name = options.title.warning
|
|
76
78
|
return logValidationWarning(name, message, comment)
|
|
77
79
|
}
|
|
78
80
|
// If it is not glob pattern, use default jest-validate reporter
|
|
@@ -88,10 +90,11 @@ function unknownValidationReporter(config, example, option, options) {
|
|
|
88
90
|
*
|
|
89
91
|
* @param {Object} sourceConfig
|
|
90
92
|
* @returns {{
|
|
91
|
-
* concurrent: boolean, chunkSize: number, globOptions: {matchBase: boolean, dot: boolean}, linters: {}, subTaskConcurrency: number, renderer: string
|
|
93
|
+
* concurrent: boolean, chunkSize: number, globOptions: {matchBase: boolean, dot: boolean}, linters: {}, subTaskConcurrency: number, renderer: string
|
|
92
94
|
* }}
|
|
93
95
|
*/
|
|
94
|
-
function getConfig(sourceConfig) {
|
|
96
|
+
function getConfig(sourceConfig, debugMode) {
|
|
97
|
+
debug('Normalizing config')
|
|
95
98
|
const config = defaultsDeep(
|
|
96
99
|
{}, // Do not mutate sourceConfig!!!
|
|
97
100
|
isSimple(sourceConfig) ? { linters: sourceConfig } : sourceConfig,
|
|
@@ -100,18 +103,25 @@ function getConfig(sourceConfig) {
|
|
|
100
103
|
|
|
101
104
|
// Check if renderer is set in sourceConfig and if not, set accordingly to verbose
|
|
102
105
|
if (isObject(sourceConfig) && !sourceConfig.hasOwnProperty('renderer')) {
|
|
103
|
-
config.renderer =
|
|
106
|
+
config.renderer = debugMode ? 'verbose' : 'update'
|
|
104
107
|
}
|
|
105
108
|
|
|
106
109
|
return config
|
|
107
110
|
}
|
|
108
111
|
|
|
112
|
+
const optRmMsg = (opt, helpMsg) => ` Option ${chalk.bold(opt)} was removed.
|
|
113
|
+
|
|
114
|
+
${helpMsg}
|
|
115
|
+
|
|
116
|
+
Please remove ${chalk.bold(opt)} from your configuration.`
|
|
117
|
+
|
|
109
118
|
/**
|
|
110
119
|
* Runs config validation. Throws error if the config is not valid.
|
|
111
120
|
* @param config {Object}
|
|
112
121
|
* @returns config {Object}
|
|
113
122
|
*/
|
|
114
123
|
function validateConfig(config) {
|
|
124
|
+
debug('Validating config')
|
|
115
125
|
const exampleConfig = Object.assign({}, defaultConfig, {
|
|
116
126
|
linters: {
|
|
117
127
|
'*.js': ['eslint --fix', 'git add'],
|
|
@@ -120,14 +130,12 @@ function validateConfig(config) {
|
|
|
120
130
|
})
|
|
121
131
|
|
|
122
132
|
const deprecatedConfig = {
|
|
123
|
-
gitDir: () =>
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
Please remove ${chalk.bold('gitDir')} from your configuration.`
|
|
133
|
+
gitDir: () => optRmMsg('gitDir', "lint-staged now automatically resolves '.git' directory."),
|
|
134
|
+
verbose: () =>
|
|
135
|
+
optRmMsg('verbose', `Use the command line flag ${chalk.bold('--debug')} instead.`)
|
|
128
136
|
}
|
|
129
137
|
|
|
130
|
-
|
|
138
|
+
validate(config, {
|
|
131
139
|
exampleConfig,
|
|
132
140
|
deprecatedConfig,
|
|
133
141
|
unknown: unknownValidationReporter,
|
|
@@ -135,10 +143,6 @@ function validateConfig(config) {
|
|
|
135
143
|
'Please refer to https://github.com/okonet/lint-staged#configuration for more information...'
|
|
136
144
|
})
|
|
137
145
|
|
|
138
|
-
if (!validation.isValid) {
|
|
139
|
-
throw new Error('lint-staged config is invalid... Aborting.')
|
|
140
|
-
}
|
|
141
|
-
|
|
142
146
|
return config
|
|
143
147
|
}
|
|
144
148
|
|
package/src/index.js
CHANGED
|
@@ -11,8 +11,9 @@ const validateConfig = require('./getConfig').validateConfig
|
|
|
11
11
|
const printErrors = require('./printErrors')
|
|
12
12
|
const runAll = require('./runAll')
|
|
13
13
|
|
|
14
|
+
const debug = require('debug')('lint-staged')
|
|
15
|
+
|
|
14
16
|
// Find the right package.json at the root of the project
|
|
15
|
-
// TODO: Test if it should be aware of `gitDir`
|
|
16
17
|
const packageJson = require(appRoot.resolve('package.json'))
|
|
17
18
|
|
|
18
19
|
// Force colors for packages that depend on https://www.npmjs.com/package/supports-color
|
|
@@ -26,7 +27,8 @@ const errConfigNotFound = new Error('Config could not be found')
|
|
|
26
27
|
/**
|
|
27
28
|
* Root lint-staged function that is called from .bin
|
|
28
29
|
*/
|
|
29
|
-
module.exports = function lintStaged(injectedLogger, configPath) {
|
|
30
|
+
module.exports = function lintStaged(injectedLogger, configPath, debugMode) {
|
|
31
|
+
debug('Loading config using `cosmiconfig`')
|
|
30
32
|
const logger = injectedLogger || console
|
|
31
33
|
|
|
32
34
|
const explorer = cosmiconfig('lint-staged', {
|
|
@@ -36,23 +38,30 @@ module.exports = function lintStaged(injectedLogger, configPath) {
|
|
|
36
38
|
})
|
|
37
39
|
|
|
38
40
|
return explorer
|
|
39
|
-
.load(
|
|
41
|
+
.load()
|
|
40
42
|
.then(result => {
|
|
41
43
|
if (result == null) throw errConfigNotFound
|
|
42
44
|
|
|
45
|
+
debug('Successfully loaded config from `%s`:\n%O', result.filepath, result.config)
|
|
43
46
|
// result.config is the parsed configuration object
|
|
44
47
|
// result.filepath is the path to the config file that was found
|
|
45
|
-
const config = validateConfig(getConfig(result.config))
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
const config = validateConfig(getConfig(result.config, debugMode))
|
|
49
|
+
if (debugMode) {
|
|
50
|
+
// Log using logger to be able to test through `consolemock`.
|
|
48
51
|
logger.log('Running lint-staged with the following config:')
|
|
49
52
|
logger.log(stringifyObject(config, { indent: ' ' }))
|
|
53
|
+
} else {
|
|
54
|
+
// We might not be in debug mode but `DEBUG=lint-staged*` could have
|
|
55
|
+
// been set.
|
|
56
|
+
debug('Normalized config:\n%O', config)
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
const scripts = packageJson.scripts || {}
|
|
60
|
+
debug('Loaded scripts from package.json:\n%O', scripts)
|
|
53
61
|
|
|
54
|
-
runAll(scripts, config)
|
|
62
|
+
runAll(scripts, config, debugMode)
|
|
55
63
|
.then(() => {
|
|
64
|
+
debug('linters were executed successfully!')
|
|
56
65
|
// No errors, exiting with 0
|
|
57
66
|
process.exitCode = 0
|
|
58
67
|
})
|
package/src/runAll.js
CHANGED
|
@@ -8,30 +8,36 @@ const runScript = require('./runScript')
|
|
|
8
8
|
const generateTasks = require('./generateTasks')
|
|
9
9
|
const resolveGitDir = require('./resolveGitDir')
|
|
10
10
|
|
|
11
|
+
const debug = require('debug')('lint-staged:run')
|
|
12
|
+
|
|
11
13
|
/**
|
|
12
14
|
* Executes all tasks and either resolves or rejects the promise
|
|
13
15
|
* @param scripts
|
|
14
16
|
* @param config {Object}
|
|
15
17
|
* @returns {Promise}
|
|
16
18
|
*/
|
|
17
|
-
module.exports = function runAll(scripts, config) {
|
|
19
|
+
module.exports = function runAll(scripts, config, debugMode) {
|
|
20
|
+
debug('Running all linter scripts')
|
|
18
21
|
// Config validation
|
|
19
22
|
if (!config || !has(config, 'concurrent') || !has(config, 'renderer')) {
|
|
20
23
|
throw new Error('Invalid config provided to runAll! Use getConfig instead.')
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
const gitDir = config.gitDir
|
|
24
26
|
const concurrent = config.concurrent
|
|
25
27
|
const renderer = config.renderer
|
|
26
|
-
|
|
28
|
+
const gitDir = resolveGitDir()
|
|
29
|
+
debug('Resolved git directory to be `%s`', gitDir)
|
|
27
30
|
|
|
31
|
+
sgf.cwd = gitDir
|
|
28
32
|
return pify(sgf)('ACM').then(files => {
|
|
29
33
|
/* files is an Object{ filename: String, status: String } */
|
|
30
34
|
const filenames = files.map(file => file.filename)
|
|
35
|
+
debug('Loaded list of staged files in git:\n%O', filenames)
|
|
36
|
+
|
|
31
37
|
const tasks = generateTasks(config, filenames).map(task => ({
|
|
32
38
|
title: `Running tasks for ${task.pattern}`,
|
|
33
39
|
task: () =>
|
|
34
|
-
new Listr(runScript(task.commands, task.fileList, scripts, config), {
|
|
40
|
+
new Listr(runScript(task.commands, task.fileList, scripts, config, debugMode), {
|
|
35
41
|
// In sub-tasks we don't want to run concurrently
|
|
36
42
|
// and we want to abort on errors
|
|
37
43
|
dateFormat: false,
|
package/src/runScript.js
CHANGED
|
@@ -10,7 +10,11 @@ const calcChunkSize = require('./calcChunkSize')
|
|
|
10
10
|
const findBin = require('./findBin')
|
|
11
11
|
const resolveGitDir = require('./resolveGitDir')
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
const debug = require('debug')('lint-staged:run-script')
|
|
14
|
+
|
|
15
|
+
module.exports = function runScript(commands, pathsToLint, scripts, config, debugMode) {
|
|
16
|
+
debug('Running script with commands %o', commands)
|
|
17
|
+
|
|
14
18
|
const normalizedConfig = getConfig(config)
|
|
15
19
|
const chunkSize = normalizedConfig.chunkSize
|
|
16
20
|
const concurrency = normalizedConfig.subTaskConcurrency
|
|
@@ -24,7 +28,7 @@ module.exports = function runScript(commands, pathsToLint, scripts, config) {
|
|
|
24
28
|
title: linter,
|
|
25
29
|
task: () => {
|
|
26
30
|
try {
|
|
27
|
-
const res = findBin(linter, scripts,
|
|
31
|
+
const res = findBin(linter, scripts, debugMode)
|
|
28
32
|
|
|
29
33
|
// Only use gitDir as CWD if we are using the git binary
|
|
30
34
|
// e.g `npm` should run tasks in the actual CWD
|
|
@@ -35,6 +39,10 @@ module.exports = function runScript(commands, pathsToLint, scripts, config) {
|
|
|
35
39
|
const mapper = pathsChunk => {
|
|
36
40
|
const args = res.args.concat(pathsChunk)
|
|
37
41
|
|
|
42
|
+
debug('bin:', res.bin)
|
|
43
|
+
debug('args: %O', args)
|
|
44
|
+
debug('opts: %o', execaOptions)
|
|
45
|
+
|
|
38
46
|
return (
|
|
39
47
|
execa(res.bin, args, Object.assign({}, execaOptions))
|
|
40
48
|
/* If we don't catch, pMap will terminate on first rejection */
|
|
@@ -59,6 +67,7 @@ module.exports = function runScript(commands, pathsToLint, scripts, config) {
|
|
|
59
67
|
const errStdout = errors.map(err => err.stdout).join('')
|
|
60
68
|
const errStderr = errors.map(err => err.stderr).join('')
|
|
61
69
|
|
|
70
|
+
// prettier-ignore
|
|
62
71
|
throw new Error(dedent`
|
|
63
72
|
${logSymbols.error} ${linter} found some errors. Please fix them and try committing again.
|
|
64
73
|
${errStdout}
|