lint-staged 11.2.6 → 12.0.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 +1 -1
- package/bin/lint-staged.js +17 -23
- package/lib/chunkFiles.js +10 -9
- package/lib/execGit.js +7 -9
- package/lib/figures.js +6 -8
- package/lib/file.js +14 -24
- package/lib/generateTasks.js +8 -10
- package/lib/getRenderer.js +1 -5
- package/lib/getStagedFiles.js +2 -4
- package/lib/gitWorkflow.js +33 -34
- package/lib/index.js +15 -15
- package/lib/makeCmdTasks.js +7 -9
- package/lib/messages.js +19 -39
- package/lib/printTaskOutput.js +1 -5
- package/lib/resolveGitRepo.js +11 -17
- package/lib/resolveTaskFn.js +13 -13
- package/lib/runAll.js +18 -20
- package/lib/state.js +11 -24
- package/lib/symbols.js +23 -29
- package/lib/validateBraces.js +3 -7
- package/lib/validateConfig.js +9 -11
- package/lib/validateOptions.js +9 -9
- package/package.json +22 -33
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# 🚫💩 lint-staged  [ [](https://badge.fury.io/js/lint-staged) [](https://codecov.io/gh/okonet/lint-staged)
|
|
2
2
|
|
|
3
3
|
Run linters against staged git files and don't let :poop: slip into your code base!
|
|
4
4
|
|
package/bin/lint-staged.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import { fileURLToPath } from 'url'
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
import cmdline from 'commander'
|
|
8
|
+
import debug from 'debug'
|
|
9
|
+
import supportsColor from 'supports-color'
|
|
10
|
+
|
|
11
|
+
import lintStaged from '../lib/index.js'
|
|
12
|
+
import { CONFIG_STDIN_ERROR } from '../lib/messages.js'
|
|
6
13
|
|
|
7
14
|
// Force colors for packages that depend on https://www.npmjs.com/package/supports-color
|
|
8
|
-
const supportsColor = require('supports-color')
|
|
9
15
|
if (supportsColor.stdout) {
|
|
10
16
|
process.env.FORCE_COLOR = supportsColor.stdout.level.toString()
|
|
11
17
|
}
|
|
@@ -13,24 +19,12 @@ if (supportsColor.stdout) {
|
|
|
13
19
|
// Do not terminate main Listr process on SIGINT
|
|
14
20
|
process.on('SIGINT', () => {})
|
|
15
21
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
engines: {
|
|
20
|
-
node: '>=12.13.0', // First LTS release of 'Erbium'
|
|
21
|
-
},
|
|
22
|
-
})
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
const cmdline = require('commander')
|
|
26
|
-
const debugLib = require('debug')
|
|
27
|
-
const lintStaged = require('../lib')
|
|
28
|
-
const { CONFIG_STDIN_ERROR } = require('../lib/messages')
|
|
29
|
-
|
|
30
|
-
const debug = debugLib('lint-staged:bin')
|
|
22
|
+
const packageJsonPath = path.join(fileURLToPath(import.meta.url), '../../package.json')
|
|
23
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath))
|
|
24
|
+
const version = packageJson.version
|
|
31
25
|
|
|
32
26
|
cmdline
|
|
33
|
-
.version(
|
|
27
|
+
.version(version)
|
|
34
28
|
.option('--allow-empty', 'allow empty commits when tasks revert all staged changes', false)
|
|
35
29
|
.option('-c, --config [path]', 'path to configuration file, or - to read from stdin')
|
|
36
30
|
.option('-d, --debug', 'print additional debug information', false)
|
|
@@ -50,11 +44,11 @@ cmdline
|
|
|
50
44
|
)
|
|
51
45
|
.parse(process.argv)
|
|
52
46
|
|
|
47
|
+
const debugLog = debug('lint-staged:bin')
|
|
53
48
|
if (cmdline.debug) {
|
|
54
|
-
|
|
49
|
+
debug.enable('lint-staged*')
|
|
55
50
|
}
|
|
56
|
-
|
|
57
|
-
debug('Running `lint-staged@%s`', pkg.version)
|
|
51
|
+
debugLog('Running `lint-staged@%s`', version)
|
|
58
52
|
|
|
59
53
|
/**
|
|
60
54
|
* Get the maximum length of a command-line argument string based on current platform
|
|
@@ -89,7 +83,7 @@ const options = {
|
|
|
89
83
|
verbose: !!cmdlineOptions.verbose,
|
|
90
84
|
}
|
|
91
85
|
|
|
92
|
-
|
|
86
|
+
debugLog('Options parsed from command-line:', options)
|
|
93
87
|
|
|
94
88
|
if (options.configPath === '-') {
|
|
95
89
|
delete options.configPath
|
package/lib/chunkFiles.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import path from 'path'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import debug from 'debug'
|
|
4
|
+
import normalize from 'normalize-path'
|
|
5
|
+
|
|
6
|
+
const debugLog = debug('lint-staged:chunkFiles')
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Chunk array into sub-arrays
|
|
@@ -10,7 +11,7 @@ const path = require('path')
|
|
|
10
11
|
* @param {Number} chunkCount
|
|
11
12
|
* @retuns {Array<Array>}
|
|
12
13
|
*/
|
|
13
|
-
|
|
14
|
+
const chunkArray = (arr, chunkCount) => {
|
|
14
15
|
if (chunkCount === 1) return [arr]
|
|
15
16
|
const chunked = []
|
|
16
17
|
let position = 0
|
|
@@ -32,21 +33,21 @@ function chunkArray(arr, chunkCount) {
|
|
|
32
33
|
* @param {Boolean} [opts.relative] whether files are relative to `gitDir` or should be resolved as absolute
|
|
33
34
|
* @returns {Array<Array<String>>}
|
|
34
35
|
*/
|
|
35
|
-
|
|
36
|
+
export const chunkFiles = ({ files, baseDir, maxArgLength = null, relative = false }) => {
|
|
36
37
|
const normalizedFiles = files.map((file) =>
|
|
37
38
|
normalize(relative || !baseDir ? file : path.resolve(baseDir, file))
|
|
38
39
|
)
|
|
39
40
|
|
|
40
41
|
if (!maxArgLength) {
|
|
41
|
-
|
|
42
|
+
debugLog('Skip chunking files because of undefined maxArgLength')
|
|
42
43
|
return [normalizedFiles] // wrap in an array to return a single chunk
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
const fileListLength = normalizedFiles.join(' ').length
|
|
46
|
-
|
|
47
|
+
debugLog(
|
|
47
48
|
`Resolved an argument string length of ${fileListLength} characters from ${normalizedFiles.length} files`
|
|
48
49
|
)
|
|
49
50
|
const chunkCount = Math.min(Math.ceil(fileListLength / maxArgLength), normalizedFiles.length)
|
|
50
|
-
|
|
51
|
+
debugLog(`Creating ${chunkCount} chunks for maxArgLength of ${maxArgLength}`)
|
|
51
52
|
return chunkArray(normalizedFiles, chunkCount)
|
|
52
53
|
}
|
package/lib/execGit.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import debug from 'debug'
|
|
2
|
+
import execa from 'execa'
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
-
const execa = require('execa')
|
|
4
|
+
const debugLog = debug('lint-staged:execGit')
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Explicitly never recurse commands into submodules, overriding local/global configuration.
|
|
@@ -9,10 +9,11 @@ const execa = require('execa')
|
|
|
9
9
|
*/
|
|
10
10
|
const NO_SUBMODULE_RECURSE = ['-c', 'submodule.recurse=false']
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
// exported for tests
|
|
13
|
+
export const GIT_GLOBAL_OPTIONS = [...NO_SUBMODULE_RECURSE]
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
export const execGit = async (cmd, options = {}) => {
|
|
16
|
+
debugLog('Running git command', cmd)
|
|
16
17
|
try {
|
|
17
18
|
const { stdout } = await execa('git', GIT_GLOBAL_OPTIONS.concat(cmd), {
|
|
18
19
|
...options,
|
|
@@ -24,6 +25,3 @@ module.exports = async function execGit(cmd, options = {}) {
|
|
|
24
25
|
throw new Error(all)
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
-
// exported for tests
|
|
29
|
-
module.exports.GIT_GLOBAL_OPTIONS = GIT_GLOBAL_OPTIONS
|
package/lib/figures.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { blue, redBright, yellow } from 'colorette'
|
|
2
|
+
import { figures } from 'listr2'
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
export const info = blue(figures.arrowRight)
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
warning: yellow(warning),
|
|
10
|
-
}
|
|
6
|
+
export const error = redBright(figures.cross)
|
|
7
|
+
|
|
8
|
+
export const warning = yellow(figures.warning)
|
package/lib/file.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { promises as fs } from 'fs'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const fs = require('fs')
|
|
5
|
-
const { promisify } = require('util')
|
|
3
|
+
import debug from 'debug'
|
|
6
4
|
|
|
7
|
-
const
|
|
8
|
-
const fsUnlink = promisify(fs.unlink)
|
|
9
|
-
const fsWriteFile = promisify(fs.writeFile)
|
|
5
|
+
const debugLog = debug('lint-staged:file')
|
|
10
6
|
|
|
11
7
|
/**
|
|
12
8
|
* Read contents of a file to buffer
|
|
@@ -14,13 +10,13 @@ const fsWriteFile = promisify(fs.writeFile)
|
|
|
14
10
|
* @param {Boolean} [ignoreENOENT=true] — Whether to throw if the file doesn't exist
|
|
15
11
|
* @returns {Promise<Buffer>}
|
|
16
12
|
*/
|
|
17
|
-
const readFile = async (filename, ignoreENOENT = true) => {
|
|
18
|
-
|
|
13
|
+
export const readFile = async (filename, ignoreENOENT = true) => {
|
|
14
|
+
debugLog('Reading file `%s`', filename)
|
|
19
15
|
try {
|
|
20
|
-
return await
|
|
16
|
+
return await fs.readFile(filename)
|
|
21
17
|
} catch (error) {
|
|
22
18
|
if (ignoreENOENT && error.code === 'ENOENT') {
|
|
23
|
-
|
|
19
|
+
debugLog("File `%s` doesn't exist, ignoring...", filename)
|
|
24
20
|
return null // no-op file doesn't exist
|
|
25
21
|
} else {
|
|
26
22
|
throw error
|
|
@@ -33,13 +29,13 @@ const readFile = async (filename, ignoreENOENT = true) => {
|
|
|
33
29
|
* @param {String} filename
|
|
34
30
|
* @param {Boolean} [ignoreENOENT=true] — Whether to throw if the file doesn't exist
|
|
35
31
|
*/
|
|
36
|
-
const unlink = async (filename, ignoreENOENT = true) => {
|
|
37
|
-
|
|
32
|
+
export const unlink = async (filename, ignoreENOENT = true) => {
|
|
33
|
+
debugLog('Removing file `%s`', filename)
|
|
38
34
|
try {
|
|
39
|
-
await
|
|
35
|
+
await fs.unlink(filename)
|
|
40
36
|
} catch (error) {
|
|
41
37
|
if (ignoreENOENT && error.code === 'ENOENT') {
|
|
42
|
-
|
|
38
|
+
debugLog("File `%s` doesn't exist, ignoring...", filename)
|
|
43
39
|
} else {
|
|
44
40
|
throw error
|
|
45
41
|
}
|
|
@@ -51,13 +47,7 @@ const unlink = async (filename, ignoreENOENT = true) => {
|
|
|
51
47
|
* @param {String} filename
|
|
52
48
|
* @param {Buffer} buffer
|
|
53
49
|
*/
|
|
54
|
-
const writeFile = async (filename, buffer) => {
|
|
55
|
-
|
|
56
|
-
await
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
module.exports = {
|
|
60
|
-
readFile,
|
|
61
|
-
unlink,
|
|
62
|
-
writeFile,
|
|
50
|
+
export const writeFile = async (filename, buffer) => {
|
|
51
|
+
debugLog('Writing file `%s`', filename)
|
|
52
|
+
await fs.writeFile(filename, buffer)
|
|
63
53
|
}
|
package/lib/generateTasks.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import path from 'path'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import debug from 'debug'
|
|
4
|
+
import micromatch from 'micromatch'
|
|
5
|
+
import normalize from 'normalize-path'
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const debugLog = debug('lint-staged:generateTasks')
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Generates all task commands, and filelist
|
|
@@ -16,8 +16,8 @@ const debug = require('debug')('lint-staged:gen-tasks')
|
|
|
16
16
|
* @param {boolean} [options.files] - Staged filepaths
|
|
17
17
|
* @param {boolean} [options.relative] - Whether filepaths to should be relative to gitDir
|
|
18
18
|
*/
|
|
19
|
-
const generateTasks = ({ config, cwd = process.cwd(), gitDir, files, relative = false }) => {
|
|
20
|
-
|
|
19
|
+
export const generateTasks = ({ config, cwd = process.cwd(), gitDir, files, relative = false }) => {
|
|
20
|
+
debugLog('Generating linter tasks')
|
|
21
21
|
|
|
22
22
|
const absoluteFiles = files.map((file) => normalize(path.resolve(gitDir, file)))
|
|
23
23
|
const relativeFiles = absoluteFiles.map((file) => normalize(path.relative(cwd, file)))
|
|
@@ -47,10 +47,8 @@ const generateTasks = ({ config, cwd = process.cwd(), gitDir, files, relative =
|
|
|
47
47
|
const fileList = matches.map((file) => normalize(relative ? file : path.resolve(cwd, file)))
|
|
48
48
|
|
|
49
49
|
const task = { pattern, commands, fileList }
|
|
50
|
-
|
|
50
|
+
debugLog('Generated task: \n%O', task)
|
|
51
51
|
|
|
52
52
|
return task
|
|
53
53
|
})
|
|
54
54
|
}
|
|
55
|
-
|
|
56
|
-
module.exports = generateTasks
|
package/lib/getRenderer.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const getRenderer = ({ debug, quiet }, env = process.env) => {
|
|
1
|
+
export const getRenderer = ({ debug, quiet }, env = process.env) => {
|
|
4
2
|
if (quiet) return { renderer: 'silent' }
|
|
5
3
|
// Better support for dumb terminals: https://en.wikipedia.org/wiki/Computer_terminal#Dumb_terminals
|
|
6
4
|
const isDumbTerminal = env.TERM === 'dumb'
|
|
7
5
|
if (debug || isDumbTerminal || env.NODE_ENV === 'test') return { renderer: 'verbose' }
|
|
8
6
|
return { renderer: 'update', rendererOptions: { dateFormat: false } }
|
|
9
7
|
}
|
|
10
|
-
|
|
11
|
-
module.exports = getRenderer
|
package/lib/getStagedFiles.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { execGit } from './execGit.js'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
module.exports = async function getStagedFiles(options) {
|
|
3
|
+
export const getStagedFiles = async (options) => {
|
|
6
4
|
try {
|
|
7
5
|
// Docs for --diff-filter option: https://git-scm.com/docs/git-diff#Documentation/git-diff.txt---diff-filterACDMRTUXB82308203
|
|
8
6
|
// Docs for -z option: https://git-scm.com/docs/git-diff#Documentation/git-diff.txt--z
|
package/lib/gitWorkflow.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import path from 'path'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const path = require('path')
|
|
3
|
+
import debug from 'debug'
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
import { execGit } from './execGit.js'
|
|
6
|
+
import { readFile, unlink, writeFile } from './file.js'
|
|
7
|
+
import {
|
|
9
8
|
GitError,
|
|
10
9
|
RestoreOriginalStateError,
|
|
11
10
|
ApplyEmptyCommitError,
|
|
@@ -13,7 +12,9 @@ const {
|
|
|
13
12
|
HideUnstagedChangesError,
|
|
14
13
|
RestoreMergeStatusError,
|
|
15
14
|
RestoreUnstagedChangesError,
|
|
16
|
-
}
|
|
15
|
+
} from './symbols.js'
|
|
16
|
+
|
|
17
|
+
const debugLog = debug('lint-staged:GitWorkflow')
|
|
17
18
|
|
|
18
19
|
const MERGE_HEAD = 'MERGE_HEAD'
|
|
19
20
|
const MERGE_MODE = 'MERGE_MODE'
|
|
@@ -63,7 +64,7 @@ const handleError = (error, ctx, symbol) => {
|
|
|
63
64
|
throw error
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
class GitWorkflow {
|
|
67
|
+
export class GitWorkflow {
|
|
67
68
|
constructor({ allowEmpty, gitConfigDir, gitDir, matchedFileChunks }) {
|
|
68
69
|
this.execGit = (args, options = {}) => execGit(args, { ...options, cwd: gitDir })
|
|
69
70
|
this.deletedFiles = []
|
|
@@ -107,13 +108,13 @@ class GitWorkflow {
|
|
|
107
108
|
* Get a list of unstaged deleted files
|
|
108
109
|
*/
|
|
109
110
|
async getDeletedFiles() {
|
|
110
|
-
|
|
111
|
+
debugLog('Getting deleted files...')
|
|
111
112
|
const lsFiles = await this.execGit(['ls-files', '--deleted'])
|
|
112
113
|
const deletedFiles = lsFiles
|
|
113
114
|
.split('\n')
|
|
114
115
|
.filter(Boolean)
|
|
115
116
|
.map((file) => path.resolve(this.gitDir, file))
|
|
116
|
-
|
|
117
|
+
debugLog('Found deleted files:', deletedFiles)
|
|
117
118
|
return deletedFiles
|
|
118
119
|
}
|
|
119
120
|
|
|
@@ -121,30 +122,30 @@ class GitWorkflow {
|
|
|
121
122
|
* Save meta information about ongoing git merge
|
|
122
123
|
*/
|
|
123
124
|
async backupMergeStatus() {
|
|
124
|
-
|
|
125
|
+
debugLog('Backing up merge state...')
|
|
125
126
|
await Promise.all([
|
|
126
127
|
readFile(this.mergeHeadFilename).then((buffer) => (this.mergeHeadBuffer = buffer)),
|
|
127
128
|
readFile(this.mergeModeFilename).then((buffer) => (this.mergeModeBuffer = buffer)),
|
|
128
129
|
readFile(this.mergeMsgFilename).then((buffer) => (this.mergeMsgBuffer = buffer)),
|
|
129
130
|
])
|
|
130
|
-
|
|
131
|
+
debugLog('Done backing up merge state!')
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
/**
|
|
134
135
|
* Restore meta information about ongoing git merge
|
|
135
136
|
*/
|
|
136
137
|
async restoreMergeStatus(ctx) {
|
|
137
|
-
|
|
138
|
+
debugLog('Restoring merge state...')
|
|
138
139
|
try {
|
|
139
140
|
await Promise.all([
|
|
140
141
|
this.mergeHeadBuffer && writeFile(this.mergeHeadFilename, this.mergeHeadBuffer),
|
|
141
142
|
this.mergeModeBuffer && writeFile(this.mergeModeFilename, this.mergeModeBuffer),
|
|
142
143
|
this.mergeMsgBuffer && writeFile(this.mergeMsgFilename, this.mergeMsgBuffer),
|
|
143
144
|
])
|
|
144
|
-
|
|
145
|
+
debugLog('Done restoring merge state!')
|
|
145
146
|
} catch (error) {
|
|
146
|
-
|
|
147
|
-
|
|
147
|
+
debugLog('Failed restoring merge state with error:')
|
|
148
|
+
debugLog(error)
|
|
148
149
|
handleError(
|
|
149
150
|
new Error('Merge state could not be restored due to an error!'),
|
|
150
151
|
ctx,
|
|
@@ -159,7 +160,7 @@ class GitWorkflow {
|
|
|
159
160
|
* both the "from" and "to" filenames, where "from" is no longer on disk.
|
|
160
161
|
*/
|
|
161
162
|
async getPartiallyStagedFiles() {
|
|
162
|
-
|
|
163
|
+
debugLog('Getting partially staged files...')
|
|
163
164
|
const status = await this.execGit(['status', '-z'])
|
|
164
165
|
/**
|
|
165
166
|
* See https://git-scm.com/docs/git-status#_short_format
|
|
@@ -179,7 +180,7 @@ class GitWorkflow {
|
|
|
179
180
|
})
|
|
180
181
|
.map((line) => line.substr(3)) // Remove first three letters (index, workingTree, and a whitespace)
|
|
181
182
|
.filter(Boolean) // Filter empty string
|
|
182
|
-
|
|
183
|
+
debugLog('Found partially staged files:', partiallyStaged)
|
|
183
184
|
return partiallyStaged.length ? partiallyStaged : null
|
|
184
185
|
}
|
|
185
186
|
|
|
@@ -188,7 +189,7 @@ class GitWorkflow {
|
|
|
188
189
|
*/
|
|
189
190
|
async prepare(ctx) {
|
|
190
191
|
try {
|
|
191
|
-
|
|
192
|
+
debugLog('Backing up original state...')
|
|
192
193
|
|
|
193
194
|
// Get a list of files with bot staged and unstaged changes.
|
|
194
195
|
// Unstaged changes to these files should be hidden before the tasks run.
|
|
@@ -222,7 +223,7 @@ class GitWorkflow {
|
|
|
222
223
|
const hash = await this.execGit(['stash', 'create'])
|
|
223
224
|
await this.execGit(['stash', 'store', '--quiet', '--message', STASH, hash])
|
|
224
225
|
|
|
225
|
-
|
|
226
|
+
debugLog('Done backing up original state!')
|
|
226
227
|
} catch (error) {
|
|
227
228
|
handleError(error, ctx)
|
|
228
229
|
}
|
|
@@ -249,7 +250,7 @@ class GitWorkflow {
|
|
|
249
250
|
* In case of a merge-conflict retry with 3-way merge.
|
|
250
251
|
*/
|
|
251
252
|
async applyModifications(ctx) {
|
|
252
|
-
|
|
253
|
+
debugLog('Adding task modifications to index...')
|
|
253
254
|
|
|
254
255
|
// `matchedFileChunks` includes staged files that lint-staged originally detected and matched against a task.
|
|
255
256
|
// Add only these files so any 3rd-party edits to other files won't be included in the commit.
|
|
@@ -259,7 +260,7 @@ class GitWorkflow {
|
|
|
259
260
|
await this.execGit(['add', '--', ...files])
|
|
260
261
|
}
|
|
261
262
|
|
|
262
|
-
|
|
263
|
+
debugLog('Done adding task modifications to index!')
|
|
263
264
|
|
|
264
265
|
const stagedFilesAfterAdd = await this.execGit(['diff', '--name-only', '--cached'])
|
|
265
266
|
if (!stagedFilesAfterAdd && !this.allowEmpty) {
|
|
@@ -275,20 +276,20 @@ class GitWorkflow {
|
|
|
275
276
|
* 3-way merge usually fixes this, and in case it doesn't we should just give up and throw.
|
|
276
277
|
*/
|
|
277
278
|
async restoreUnstagedChanges(ctx) {
|
|
278
|
-
|
|
279
|
+
debugLog('Restoring unstaged changes...')
|
|
279
280
|
const unstagedPatch = this.getHiddenFilepath(PATCH_UNSTAGED)
|
|
280
281
|
try {
|
|
281
282
|
await this.execGit(['apply', ...GIT_APPLY_ARGS, unstagedPatch])
|
|
282
283
|
} catch (applyError) {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
284
|
+
debugLog('Error while restoring changes:')
|
|
285
|
+
debugLog(applyError)
|
|
286
|
+
debugLog('Retrying with 3-way merge')
|
|
286
287
|
try {
|
|
287
288
|
// Retry with a 3-way merge if normal apply fails
|
|
288
289
|
await this.execGit(['apply', ...GIT_APPLY_ARGS, '--3way', unstagedPatch])
|
|
289
290
|
} catch (threeWayApplyError) {
|
|
290
|
-
|
|
291
|
-
|
|
291
|
+
debugLog('Error while restoring unstaged changes using 3-way merge:')
|
|
292
|
+
debugLog(threeWayApplyError)
|
|
292
293
|
handleError(
|
|
293
294
|
new Error('Unstaged changes could not be restored due to a merge conflict!'),
|
|
294
295
|
ctx,
|
|
@@ -303,7 +304,7 @@ class GitWorkflow {
|
|
|
303
304
|
*/
|
|
304
305
|
async restoreOriginalState(ctx) {
|
|
305
306
|
try {
|
|
306
|
-
|
|
307
|
+
debugLog('Restoring original state...')
|
|
307
308
|
await this.execGit(['reset', '--hard', 'HEAD'])
|
|
308
309
|
await this.execGit(['stash', 'apply', '--quiet', '--index', await this.getBackupStash(ctx)])
|
|
309
310
|
|
|
@@ -316,7 +317,7 @@ class GitWorkflow {
|
|
|
316
317
|
// Clean out patch
|
|
317
318
|
await unlink(this.getHiddenFilepath(PATCH_UNSTAGED))
|
|
318
319
|
|
|
319
|
-
|
|
320
|
+
debugLog('Done restoring original state!')
|
|
320
321
|
} catch (error) {
|
|
321
322
|
handleError(error, ctx, RestoreOriginalStateError)
|
|
322
323
|
}
|
|
@@ -327,13 +328,11 @@ class GitWorkflow {
|
|
|
327
328
|
*/
|
|
328
329
|
async cleanup(ctx) {
|
|
329
330
|
try {
|
|
330
|
-
|
|
331
|
+
debugLog('Dropping backup stash...')
|
|
331
332
|
await this.execGit(['stash', 'drop', '--quiet', await this.getBackupStash(ctx)])
|
|
332
|
-
|
|
333
|
+
debugLog('Done dropping backup stash!')
|
|
333
334
|
} catch (error) {
|
|
334
335
|
handleError(error, ctx)
|
|
335
336
|
}
|
|
336
337
|
}
|
|
337
338
|
}
|
|
338
|
-
|
|
339
|
-
module.exports = GitWorkflow
|
package/lib/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const runAll = require('./runAll')
|
|
10
|
-
const {
|
|
1
|
+
import { cosmiconfig } from 'cosmiconfig'
|
|
2
|
+
import debug from 'debug'
|
|
3
|
+
import inspect from 'object-inspect'
|
|
4
|
+
|
|
5
|
+
import { PREVENTED_EMPTY_COMMIT, GIT_ERROR, RESTORE_STASH_EXAMPLE } from './messages.js'
|
|
6
|
+
import { printTaskOutput } from './printTaskOutput.js'
|
|
7
|
+
import { runAll } from './runAll.js'
|
|
8
|
+
import {
|
|
11
9
|
ApplyEmptyCommitError,
|
|
12
10
|
ConfigNotFoundError,
|
|
13
11
|
GetBackupStashError,
|
|
14
12
|
GitError,
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
} from './symbols.js'
|
|
14
|
+
import { validateConfig } from './validateConfig.js'
|
|
15
|
+
import { validateOptions } from './validateOptions.js'
|
|
16
|
+
|
|
17
|
+
const debugLog = debug('lint-staged')
|
|
18
18
|
|
|
19
19
|
const resolveConfig = (configPath) => {
|
|
20
20
|
try {
|
|
@@ -104,7 +104,7 @@ const lintStaged = async (
|
|
|
104
104
|
if (debug) {
|
|
105
105
|
// Log using logger to be able to test through `consolemock`.
|
|
106
106
|
logger.log('Running lint-staged with the following config:')
|
|
107
|
-
logger.log(
|
|
107
|
+
logger.log(inspect(config, { indent: 2 }))
|
|
108
108
|
} else {
|
|
109
109
|
// We might not be in debug mode but `DEBUG=lint-staged*` could have
|
|
110
110
|
// been set.
|
|
@@ -157,4 +157,4 @@ const lintStaged = async (
|
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
export default lintStaged
|
package/lib/makeCmdTasks.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import cliTruncate from 'cli-truncate'
|
|
2
|
+
import debug from 'debug'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
import { configurationError } from './messages.js'
|
|
5
|
+
import { resolveTaskFn } from './resolveTaskFn.js'
|
|
5
6
|
|
|
6
|
-
const
|
|
7
|
-
const resolveTaskFn = require('./resolveTaskFn')
|
|
7
|
+
const debugLog = debug('lint-staged:makeCmdTasks')
|
|
8
8
|
|
|
9
9
|
const STDOUT_COLUMNS_DEFAULT = 80
|
|
10
10
|
|
|
@@ -34,8 +34,8 @@ const getTitleLength = (renderer, columns = process.stdout.columns) => {
|
|
|
34
34
|
* @param {Boolean} shell
|
|
35
35
|
* @param {Boolean} verbose
|
|
36
36
|
*/
|
|
37
|
-
const makeCmdTasks = async ({ commands, files, gitDir, renderer, shell, verbose }) => {
|
|
38
|
-
|
|
37
|
+
export const makeCmdTasks = async ({ commands, files, gitDir, renderer, shell, verbose }) => {
|
|
38
|
+
debugLog('Creating listr tasks for commands %o', commands)
|
|
39
39
|
const commandArray = Array.isArray(commands) ? commands : [commands]
|
|
40
40
|
const cmdTasks = []
|
|
41
41
|
|
|
@@ -68,5 +68,3 @@ const makeCmdTasks = async ({ commands, files, gitDir, renderer, shell, verbose
|
|
|
68
68
|
|
|
69
69
|
return cmdTasks
|
|
70
70
|
}
|
|
71
|
-
|
|
72
|
-
module.exports = makeCmdTasks
|
package/lib/messages.js
CHANGED
|
@@ -1,50 +1,48 @@
|
|
|
1
|
-
|
|
1
|
+
import { redBright, bold, yellow } from 'colorette'
|
|
2
|
+
import inspect from 'object-inspect'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const format = require('stringify-object')
|
|
4
|
+
import { error, info, warning } from './figures.js'
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
const configurationError = (opt, helpMsg, value) =>
|
|
6
|
+
export const configurationError = (opt, helpMsg, value) =>
|
|
9
7
|
`${redBright(`${error} Validation Error:`)}
|
|
10
8
|
|
|
11
9
|
Invalid value for '${bold(opt)}': ${bold(
|
|
12
|
-
|
|
10
|
+
inspect(value, { inlineCharacterLimit: Number.POSITIVE_INFINITY })
|
|
13
11
|
)}
|
|
14
12
|
|
|
15
13
|
${helpMsg}`
|
|
16
14
|
|
|
17
|
-
const NOT_GIT_REPO = redBright(`${error} Current directory is not a git directory!`)
|
|
15
|
+
export const NOT_GIT_REPO = redBright(`${error} Current directory is not a git directory!`)
|
|
18
16
|
|
|
19
|
-
const FAILED_GET_STAGED_FILES = redBright(`${error} Failed to get staged files!`)
|
|
17
|
+
export const FAILED_GET_STAGED_FILES = redBright(`${error} Failed to get staged files!`)
|
|
20
18
|
|
|
21
|
-
const incorrectBraces = (before, after) =>
|
|
19
|
+
export const incorrectBraces = (before, after) =>
|
|
22
20
|
yellow(
|
|
23
21
|
`${warning} Detected incorrect braces with only single value: \`${before}\`. Reformatted as: \`${after}\`
|
|
24
22
|
`
|
|
25
23
|
)
|
|
26
24
|
|
|
27
|
-
const NO_STAGED_FILES = `${info} No staged files found.`
|
|
25
|
+
export const NO_STAGED_FILES = `${info} No staged files found.`
|
|
28
26
|
|
|
29
|
-
const NO_TASKS = `${info} No staged files match any configured task.`
|
|
27
|
+
export const NO_TASKS = `${info} No staged files match any configured task.`
|
|
30
28
|
|
|
31
|
-
const skippingBackup = (hasInitialCommit) => {
|
|
29
|
+
export const skippingBackup = (hasInitialCommit) => {
|
|
32
30
|
const reason = hasInitialCommit ? '`--no-stash` was used' : 'there’s no initial commit yet'
|
|
33
31
|
return yellow(`${warning} Skipping backup because ${reason}.\n`)
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
const DEPRECATED_GIT_ADD = yellow(
|
|
34
|
+
export const DEPRECATED_GIT_ADD = yellow(
|
|
37
35
|
`${warning} Some of your tasks use \`git add\` command. Please remove it from the config since all modifications made by tasks will be automatically added to the git commit index.
|
|
38
36
|
`
|
|
39
37
|
)
|
|
40
38
|
|
|
41
|
-
const TASK_ERROR = 'Skipped because of errors from tasks.'
|
|
39
|
+
export const TASK_ERROR = 'Skipped because of errors from tasks.'
|
|
42
40
|
|
|
43
|
-
const SKIPPED_GIT_ERROR = 'Skipped because of previous git error.'
|
|
41
|
+
export const SKIPPED_GIT_ERROR = 'Skipped because of previous git error.'
|
|
44
42
|
|
|
45
|
-
const GIT_ERROR = `\n ${redBright(`${error} lint-staged failed due to a git error.`)}`
|
|
43
|
+
export const GIT_ERROR = `\n ${redBright(`${error} lint-staged failed due to a git error.`)}`
|
|
46
44
|
|
|
47
|
-
const invalidOption = (name, value, message) => `${redBright(`${error} Validation Error:`)}
|
|
45
|
+
export const invalidOption = (name, value, message) => `${redBright(`${error} Validation Error:`)}
|
|
48
46
|
|
|
49
47
|
Invalid value for option '${bold(name)}': ${bold(value)}
|
|
50
48
|
|
|
@@ -52,34 +50,16 @@ const invalidOption = (name, value, message) => `${redBright(`${error} Validatio
|
|
|
52
50
|
|
|
53
51
|
See https://github.com/okonet/lint-staged#command-line-flags`
|
|
54
52
|
|
|
55
|
-
const PREVENTED_EMPTY_COMMIT = `
|
|
53
|
+
export const PREVENTED_EMPTY_COMMIT = `
|
|
56
54
|
${yellow(`${warning} lint-staged prevented an empty git commit.
|
|
57
55
|
Use the --allow-empty option to continue, or check your task configuration`)}
|
|
58
56
|
`
|
|
59
57
|
|
|
60
|
-
const RESTORE_STASH_EXAMPLE = ` Any lost modifications can be restored from a git stash:
|
|
58
|
+
export const RESTORE_STASH_EXAMPLE = ` Any lost modifications can be restored from a git stash:
|
|
61
59
|
|
|
62
60
|
> git stash list
|
|
63
61
|
stash@{0}: automatic lint-staged backup
|
|
64
62
|
> git stash apply --index stash@{0}
|
|
65
63
|
`
|
|
66
64
|
|
|
67
|
-
const CONFIG_STDIN_ERROR = 'Error: Could not read config from stdin.'
|
|
68
|
-
|
|
69
|
-
module.exports = {
|
|
70
|
-
CONFIG_STDIN_ERROR,
|
|
71
|
-
configurationError,
|
|
72
|
-
DEPRECATED_GIT_ADD,
|
|
73
|
-
FAILED_GET_STAGED_FILES,
|
|
74
|
-
GIT_ERROR,
|
|
75
|
-
incorrectBraces,
|
|
76
|
-
invalidOption,
|
|
77
|
-
NO_STAGED_FILES,
|
|
78
|
-
NO_TASKS,
|
|
79
|
-
NOT_GIT_REPO,
|
|
80
|
-
PREVENTED_EMPTY_COMMIT,
|
|
81
|
-
RESTORE_STASH_EXAMPLE,
|
|
82
|
-
SKIPPED_GIT_ERROR,
|
|
83
|
-
skippingBackup,
|
|
84
|
-
TASK_ERROR,
|
|
85
|
-
}
|
|
65
|
+
export const CONFIG_STDIN_ERROR = 'Error: Could not read config from stdin.'
|
package/lib/printTaskOutput.js
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Handle logging of listr `ctx.output` to the specified `logger`
|
|
5
3
|
* @param {Object} ctx - The listr initial state
|
|
6
4
|
* @param {Object} logger - The logger
|
|
7
5
|
*/
|
|
8
|
-
const printTaskOutput = (ctx = {}, logger) => {
|
|
6
|
+
export const printTaskOutput = (ctx = {}, logger) => {
|
|
9
7
|
if (!Array.isArray(ctx.output)) return
|
|
10
8
|
const log = ctx.errors && ctx.errors.size > 0 ? logger.error : logger.log
|
|
11
9
|
for (const line of ctx.output) {
|
|
12
10
|
log(line)
|
|
13
11
|
}
|
|
14
12
|
}
|
|
15
|
-
|
|
16
|
-
module.exports = printTaskOutput
|
package/lib/resolveGitRepo.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
import { promises as fs } from 'fs'
|
|
2
|
+
import path from 'path'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const fs = require('fs')
|
|
6
|
-
const path = require('path')
|
|
7
|
-
const { promisify } = require('util')
|
|
4
|
+
import debug from 'debug'
|
|
5
|
+
import normalize from 'normalize-path'
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
import { execGit } from './execGit.js'
|
|
8
|
+
import { readFile } from './file.js'
|
|
11
9
|
|
|
12
|
-
const
|
|
10
|
+
const debugLog = debug('lint-staged:resolveGitRepo')
|
|
13
11
|
|
|
14
12
|
/**
|
|
15
13
|
* Resolve path to the .git directory, with special handling for
|
|
@@ -17,7 +15,7 @@ const fsLstat = promisify(fs.lstat)
|
|
|
17
15
|
*/
|
|
18
16
|
const resolveGitConfigDir = async (gitDir) => {
|
|
19
17
|
const defaultDir = normalize(path.join(gitDir, '.git'))
|
|
20
|
-
const stats = await
|
|
18
|
+
const stats = await fs.lstat(defaultDir)
|
|
21
19
|
// If .git is a directory, use it
|
|
22
20
|
if (stats.isDirectory()) return defaultDir
|
|
23
21
|
// Otherwise .git is a file containing path to real location
|
|
@@ -25,7 +23,8 @@ const resolveGitConfigDir = async (gitDir) => {
|
|
|
25
23
|
return path.resolve(gitDir, file.replace(/^gitdir: /, '')).trim()
|
|
26
24
|
}
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
// exported for test
|
|
27
|
+
export const determineGitDir = (cwd, relativeDir) => {
|
|
29
28
|
// if relative dir and cwd have different endings normalize it
|
|
30
29
|
// this happens under windows, where normalize is unable to normalize git's output
|
|
31
30
|
if (relativeDir && relativeDir.endsWith(path.sep)) {
|
|
@@ -43,7 +42,7 @@ const determineGitDir = (cwd, relativeDir) => {
|
|
|
43
42
|
/**
|
|
44
43
|
* Resolve git directory and possible submodule paths
|
|
45
44
|
*/
|
|
46
|
-
const resolveGitRepo = async (cwd = process.cwd()) => {
|
|
45
|
+
export const resolveGitRepo = async (cwd = process.cwd()) => {
|
|
47
46
|
try {
|
|
48
47
|
debugLog('Resolving git repo from `%s`', cwd)
|
|
49
48
|
|
|
@@ -68,8 +67,3 @@ const resolveGitRepo = async (cwd = process.cwd()) => {
|
|
|
68
67
|
return { error, gitDir: null, gitConfigDir: null }
|
|
69
68
|
}
|
|
70
69
|
}
|
|
71
|
-
|
|
72
|
-
module.exports = resolveGitRepo
|
|
73
|
-
|
|
74
|
-
// exported for test
|
|
75
|
-
module.exports.determineGitDir = determineGitDir
|
package/lib/resolveTaskFn.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
import { redBright, dim } from 'colorette'
|
|
2
|
+
import execa from 'execa'
|
|
3
|
+
import debug from 'debug'
|
|
4
|
+
import { parseArgsStringToArgv } from 'string-argv'
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const { parseArgsStringToArgv } = require('string-argv')
|
|
6
|
+
import { error, info } from './figures.js'
|
|
7
|
+
import { getInitialState } from './state.js'
|
|
8
|
+
import { TaskError } from './symbols.js'
|
|
7
9
|
|
|
8
|
-
const
|
|
9
|
-
const { getInitialState } = require('./state')
|
|
10
|
-
const { TaskError } = require('./symbols')
|
|
10
|
+
const debugLog = debug('lint-staged:resolveTaskFn')
|
|
11
11
|
|
|
12
12
|
const getTag = ({ code, killed, signal }) => signal || (killed && 'KILLED') || code || 'FAILED'
|
|
13
13
|
|
|
@@ -76,7 +76,7 @@ const makeErr = (command, result, ctx) => {
|
|
|
76
76
|
* @param {Boolean} [options.verbose] — Always show task verbose
|
|
77
77
|
* @returns {function(): Promise<Array<string>>}
|
|
78
78
|
*/
|
|
79
|
-
|
|
79
|
+
export const resolveTaskFn = ({
|
|
80
80
|
command,
|
|
81
81
|
files,
|
|
82
82
|
gitDir,
|
|
@@ -84,10 +84,10 @@ module.exports = function resolveTaskFn({
|
|
|
84
84
|
relative,
|
|
85
85
|
shell = false,
|
|
86
86
|
verbose = false,
|
|
87
|
-
}) {
|
|
87
|
+
}) => {
|
|
88
88
|
const [cmd, ...args] = parseArgsStringToArgv(command)
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
debugLog('cmd:', cmd)
|
|
90
|
+
debugLog('args:', args)
|
|
91
91
|
|
|
92
92
|
const execaOptions = { preferLocal: true, reject: false, shell }
|
|
93
93
|
if (relative) {
|
|
@@ -97,7 +97,7 @@ module.exports = function resolveTaskFn({
|
|
|
97
97
|
// e.g `npm` should run tasks in the actual CWD
|
|
98
98
|
execaOptions.cwd = gitDir
|
|
99
99
|
}
|
|
100
|
-
|
|
100
|
+
debugLog('execaOptions:', execaOptions)
|
|
101
101
|
|
|
102
102
|
return async (ctx = getInitialState()) => {
|
|
103
103
|
const result = await (shell
|
package/lib/runAll.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
/** @typedef {import('./index').Logger} Logger */
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
import debug from 'debug'
|
|
4
|
+
import { Listr } from 'listr2'
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const {
|
|
6
|
+
import { chunkFiles } from './chunkFiles.js'
|
|
7
|
+
import { execGit } from './execGit.js'
|
|
8
|
+
import { generateTasks } from './generateTasks.js'
|
|
9
|
+
import { getRenderer } from './getRenderer.js'
|
|
10
|
+
import { getStagedFiles } from './getStagedFiles.js'
|
|
11
|
+
import { GitWorkflow } from './gitWorkflow.js'
|
|
12
|
+
import { makeCmdTasks } from './makeCmdTasks.js'
|
|
13
|
+
import {
|
|
16
14
|
DEPRECATED_GIT_ADD,
|
|
17
15
|
FAILED_GET_STAGED_FILES,
|
|
18
16
|
NOT_GIT_REPO,
|
|
@@ -20,9 +18,9 @@ const {
|
|
|
20
18
|
NO_TASKS,
|
|
21
19
|
SKIPPED_GIT_ERROR,
|
|
22
20
|
skippingBackup,
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
} from './messages.js'
|
|
22
|
+
import { resolveGitRepo } from './resolveGitRepo.js'
|
|
23
|
+
import {
|
|
26
24
|
applyModificationsSkipped,
|
|
27
25
|
cleanupEnabled,
|
|
28
26
|
cleanupSkipped,
|
|
@@ -31,8 +29,10 @@ const {
|
|
|
31
29
|
restoreOriginalStateEnabled,
|
|
32
30
|
restoreOriginalStateSkipped,
|
|
33
31
|
restoreUnstagedChangesSkipped,
|
|
34
|
-
}
|
|
35
|
-
|
|
32
|
+
} from './state.js'
|
|
33
|
+
import { GitRepoError, GetStagedFilesError, GitError } from './symbols.js'
|
|
34
|
+
|
|
35
|
+
const debugLog = debug('lint-staged:runAll')
|
|
36
36
|
|
|
37
37
|
const createError = (ctx) => Object.assign(new Error('lint-staged failed'), { ctx })
|
|
38
38
|
|
|
@@ -54,7 +54,7 @@ const createError = (ctx) => Object.assign(new Error('lint-staged failed'), { ct
|
|
|
54
54
|
* @param {Logger} logger
|
|
55
55
|
* @returns {Promise}
|
|
56
56
|
*/
|
|
57
|
-
const runAll = async (
|
|
57
|
+
export const runAll = async (
|
|
58
58
|
{
|
|
59
59
|
allowEmpty = false,
|
|
60
60
|
concurrent = true,
|
|
@@ -254,5 +254,3 @@ const runAll = async (
|
|
|
254
254
|
|
|
255
255
|
return ctx
|
|
256
256
|
}
|
|
257
|
-
|
|
258
|
-
module.exports = runAll
|
package/lib/state.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { GIT_ERROR, TASK_ERROR } = require('./messages')
|
|
4
|
-
const {
|
|
1
|
+
import { GIT_ERROR, TASK_ERROR } from './messages.js'
|
|
2
|
+
import {
|
|
5
3
|
ApplyEmptyCommitError,
|
|
6
4
|
TaskError,
|
|
7
5
|
RestoreOriginalStateError,
|
|
8
6
|
GitError,
|
|
9
7
|
RestoreUnstagedChangesError,
|
|
10
|
-
}
|
|
8
|
+
} from './symbols.js'
|
|
11
9
|
|
|
12
|
-
const getInitialState = ({ quiet = false } = {}) => ({
|
|
10
|
+
export const getInitialState = ({ quiet = false } = {}) => ({
|
|
13
11
|
hasPartiallyStagedFiles: null,
|
|
14
12
|
shouldBackup: null,
|
|
15
13
|
errors: new Set([]),
|
|
@@ -17,9 +15,9 @@ const getInitialState = ({ quiet = false } = {}) => ({
|
|
|
17
15
|
quiet,
|
|
18
16
|
})
|
|
19
17
|
|
|
20
|
-
const hasPartiallyStagedFiles = (ctx) => ctx.hasPartiallyStagedFiles
|
|
18
|
+
export const hasPartiallyStagedFiles = (ctx) => ctx.hasPartiallyStagedFiles
|
|
21
19
|
|
|
22
|
-
const applyModificationsSkipped = (ctx) => {
|
|
20
|
+
export const applyModificationsSkipped = (ctx) => {
|
|
23
21
|
// Always apply back unstaged modifications when skipping backup
|
|
24
22
|
if (!ctx.shouldBackup) return false
|
|
25
23
|
// Should be skipped in case of git errors
|
|
@@ -32,7 +30,7 @@ const applyModificationsSkipped = (ctx) => {
|
|
|
32
30
|
}
|
|
33
31
|
}
|
|
34
32
|
|
|
35
|
-
const restoreUnstagedChangesSkipped = (ctx) => {
|
|
33
|
+
export const restoreUnstagedChangesSkipped = (ctx) => {
|
|
36
34
|
// Should be skipped in case of git errors
|
|
37
35
|
if (ctx.errors.has(GitError)) {
|
|
38
36
|
return GIT_ERROR
|
|
@@ -43,13 +41,13 @@ const restoreUnstagedChangesSkipped = (ctx) => {
|
|
|
43
41
|
}
|
|
44
42
|
}
|
|
45
43
|
|
|
46
|
-
const restoreOriginalStateEnabled = (ctx) =>
|
|
44
|
+
export const restoreOriginalStateEnabled = (ctx) =>
|
|
47
45
|
ctx.shouldBackup &&
|
|
48
46
|
(ctx.errors.has(TaskError) ||
|
|
49
47
|
ctx.errors.has(ApplyEmptyCommitError) ||
|
|
50
48
|
ctx.errors.has(RestoreUnstagedChangesError))
|
|
51
49
|
|
|
52
|
-
const restoreOriginalStateSkipped = (ctx) => {
|
|
50
|
+
export const restoreOriginalStateSkipped = (ctx) => {
|
|
53
51
|
// Should be skipped in case of unknown git errors
|
|
54
52
|
if (
|
|
55
53
|
ctx.errors.has(GitError) &&
|
|
@@ -60,9 +58,9 @@ const restoreOriginalStateSkipped = (ctx) => {
|
|
|
60
58
|
}
|
|
61
59
|
}
|
|
62
60
|
|
|
63
|
-
const cleanupEnabled = (ctx) => ctx.shouldBackup
|
|
61
|
+
export const cleanupEnabled = (ctx) => ctx.shouldBackup
|
|
64
62
|
|
|
65
|
-
const cleanupSkipped = (ctx) => {
|
|
63
|
+
export const cleanupSkipped = (ctx) => {
|
|
66
64
|
// Should be skipped in case of unknown git errors
|
|
67
65
|
if (
|
|
68
66
|
ctx.errors.has(GitError) &&
|
|
@@ -76,14 +74,3 @@ const cleanupSkipped = (ctx) => {
|
|
|
76
74
|
return GIT_ERROR
|
|
77
75
|
}
|
|
78
76
|
}
|
|
79
|
-
|
|
80
|
-
module.exports = {
|
|
81
|
-
getInitialState,
|
|
82
|
-
hasPartiallyStagedFiles,
|
|
83
|
-
applyModificationsSkipped,
|
|
84
|
-
restoreUnstagedChangesSkipped,
|
|
85
|
-
restoreOriginalStateEnabled,
|
|
86
|
-
restoreOriginalStateSkipped,
|
|
87
|
-
cleanupEnabled,
|
|
88
|
-
cleanupSkipped,
|
|
89
|
-
}
|
package/lib/symbols.js
CHANGED
|
@@ -1,29 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const GetBackupStashError = Symbol('GetBackupStashError')
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
HideUnstagedChangesError,
|
|
25
|
-
RestoreMergeStatusError,
|
|
26
|
-
RestoreOriginalStateError,
|
|
27
|
-
RestoreUnstagedChangesError,
|
|
28
|
-
TaskError,
|
|
29
|
-
}
|
|
1
|
+
export const ApplyEmptyCommitError = Symbol('ApplyEmptyCommitError')
|
|
2
|
+
|
|
3
|
+
export const ConfigNotFoundError = new Error('Config could not be found')
|
|
4
|
+
|
|
5
|
+
export const GetBackupStashError = Symbol('GetBackupStashError')
|
|
6
|
+
|
|
7
|
+
export const GetStagedFilesError = Symbol('GetStagedFilesError')
|
|
8
|
+
|
|
9
|
+
export const GitError = Symbol('GitError')
|
|
10
|
+
|
|
11
|
+
export const GitRepoError = Symbol('GitRepoError')
|
|
12
|
+
|
|
13
|
+
export const HideUnstagedChangesError = Symbol('HideUnstagedChangesError')
|
|
14
|
+
|
|
15
|
+
export const InvalidOptionsError = new Error('Invalid Options')
|
|
16
|
+
|
|
17
|
+
export const RestoreMergeStatusError = Symbol('RestoreMergeStatusError')
|
|
18
|
+
|
|
19
|
+
export const RestoreOriginalStateError = Symbol('RestoreOriginalStateError')
|
|
20
|
+
|
|
21
|
+
export const RestoreUnstagedChangesError = Symbol('RestoreUnstagedChangesError')
|
|
22
|
+
|
|
23
|
+
export const TaskError = Symbol('TaskError')
|
package/lib/validateBraces.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { incorrectBraces } from './messages.js'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* A correctly-formed brace expansion must contain unquoted opening and closing braces,
|
|
@@ -28,7 +28,7 @@ const { incorrectBraces } = require('./messages')
|
|
|
28
28
|
* - *.${js} // dollar-sign inhibits expansion, so treated literally
|
|
29
29
|
* - *.{js\,ts} // the comma is escaped, so treated literally
|
|
30
30
|
*/
|
|
31
|
-
const BRACES_REGEXP = /(?<![\\$])({)(?:(?!(?<!\\),|\.\.|\{|\}).)*?(?<!\\)(})/g
|
|
31
|
+
export const BRACES_REGEXP = /(?<![\\$])({)(?:(?!(?<!\\),|\.\.|\{|\}).)*?(?<!\\)(})/g
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* @param {string} pattern
|
|
@@ -56,7 +56,7 @@ const withoutIncorrectBraces = (pattern) => {
|
|
|
56
56
|
* @param {*} logger
|
|
57
57
|
* @returns {string}
|
|
58
58
|
*/
|
|
59
|
-
const validateBraces = (pattern, logger) => {
|
|
59
|
+
export const validateBraces = (pattern, logger) => {
|
|
60
60
|
const fixedPattern = withoutIncorrectBraces(pattern)
|
|
61
61
|
|
|
62
62
|
if (fixedPattern !== pattern) {
|
|
@@ -65,7 +65,3 @@ const validateBraces = (pattern, logger) => {
|
|
|
65
65
|
|
|
66
66
|
return fixedPattern
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
module.exports = validateBraces
|
|
70
|
-
|
|
71
|
-
module.exports.BRACES_REGEXP = BRACES_REGEXP
|
package/lib/validateConfig.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import debug from 'debug'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { configurationError } from './messages.js'
|
|
4
|
+
import { validateBraces } from './validateBraces.js'
|
|
4
5
|
|
|
5
|
-
const
|
|
6
|
+
const debugLog = debug('lint-staged:validateConfig')
|
|
6
7
|
|
|
7
|
-
const
|
|
8
|
-
const validateBraces = require('./validateBraces')
|
|
8
|
+
const isObject = (test) => test && typeof test === 'object' && !Array.isArray(test)
|
|
9
9
|
|
|
10
10
|
const TEST_DEPRECATED_KEYS = new Map([
|
|
11
11
|
['concurrent', (key) => typeof key === 'boolean'],
|
|
12
12
|
['chunkSize', (key) => typeof key === 'number'],
|
|
13
|
-
['globOptions',
|
|
14
|
-
['linters',
|
|
13
|
+
['globOptions', isObject],
|
|
14
|
+
['linters', isObject],
|
|
15
15
|
['ignore', (key) => Array.isArray(key)],
|
|
16
16
|
['subTaskConcurrency', (key) => typeof key === 'number'],
|
|
17
17
|
['renderer', (key) => typeof key === 'string'],
|
|
@@ -23,8 +23,8 @@ const TEST_DEPRECATED_KEYS = new Map([
|
|
|
23
23
|
* @param config {Object}
|
|
24
24
|
* @returns config {Object}
|
|
25
25
|
*/
|
|
26
|
-
const validateConfig = (config, logger) => {
|
|
27
|
-
|
|
26
|
+
export const validateConfig = (config, logger) => {
|
|
27
|
+
debugLog('Validating config')
|
|
28
28
|
|
|
29
29
|
if (!config || (typeof config !== 'object' && typeof config !== 'function')) {
|
|
30
30
|
throw new Error('Configuration should be an object or a function!')
|
|
@@ -104,5 +104,3 @@ See https://github.com/okonet/lint-staged#configuration.`)
|
|
|
104
104
|
|
|
105
105
|
return validatedConfig
|
|
106
106
|
}
|
|
107
|
-
|
|
108
|
-
module.exports = validateConfig
|
package/lib/validateOptions.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import { constants, promises as fs } from 'fs'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const { InvalidOptionsError } = require('./symbols')
|
|
3
|
+
import debug from 'debug'
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
import { invalidOption } from './messages.js'
|
|
6
|
+
import { InvalidOptionsError } from './symbols.js'
|
|
7
|
+
|
|
8
|
+
const debugLog = debug('lint-staged:validateOptions')
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Validate lint-staged options, either from the Node.js API or the command line flags.
|
|
@@ -12,8 +14,8 @@ const debug = require('debug')('lint-staged:options')
|
|
|
12
14
|
*
|
|
13
15
|
* @throws {InvalidOptionsError}
|
|
14
16
|
*/
|
|
15
|
-
const validateOptions = async (options = {}, logger) => {
|
|
16
|
-
|
|
17
|
+
export const validateOptions = async (options = {}, logger) => {
|
|
18
|
+
debugLog('Validating options...')
|
|
17
19
|
|
|
18
20
|
/** Ensure the passed shell option is executable */
|
|
19
21
|
if (typeof options.shell === 'string') {
|
|
@@ -25,7 +27,5 @@ const validateOptions = async (options = {}, logger) => {
|
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
debugLog('Validated options!')
|
|
29
31
|
}
|
|
30
|
-
|
|
31
|
-
module.exports = validateOptions
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lint-staged",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.0.1",
|
|
4
4
|
"description": "Lint files staged by git",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "https://github.com/okonet/lint-staged",
|
|
@@ -13,8 +13,13 @@
|
|
|
13
13
|
"funding": {
|
|
14
14
|
"url": "https://opencollective.com/lint-staged"
|
|
15
15
|
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": "^12.20.0 || ^14.13.1 || >=16.0.0",
|
|
18
|
+
"npm": ">=8.1.3"
|
|
19
|
+
},
|
|
20
|
+
"type": "module",
|
|
16
21
|
"bin": "./bin/lint-staged.js",
|
|
17
|
-
"
|
|
22
|
+
"exports": "./lib/index.js",
|
|
18
23
|
"files": [
|
|
19
24
|
"bin",
|
|
20
25
|
"lib"
|
|
@@ -22,41 +27,38 @@
|
|
|
22
27
|
"scripts": {
|
|
23
28
|
"cz": "git-cz",
|
|
24
29
|
"lint": "eslint .",
|
|
25
|
-
"pretest": "npm run lint",
|
|
26
30
|
"test": "jest --coverage",
|
|
27
31
|
"test:watch": "jest --watch"
|
|
28
32
|
},
|
|
29
33
|
"dependencies": {
|
|
30
|
-
"cli-truncate": "
|
|
31
|
-
"colorette": "^
|
|
32
|
-
"commander": "^8.
|
|
34
|
+
"cli-truncate": "3.1.0",
|
|
35
|
+
"colorette": "^2.0.16",
|
|
36
|
+
"commander": "^8.3.0",
|
|
33
37
|
"cosmiconfig": "^7.0.1",
|
|
34
38
|
"debug": "^4.3.2",
|
|
35
|
-
"enquirer": "^2.3.6",
|
|
36
39
|
"execa": "^5.1.1",
|
|
37
|
-
"listr2": "^3.
|
|
40
|
+
"listr2": "^3.13.3",
|
|
38
41
|
"micromatch": "^4.0.4",
|
|
39
42
|
"normalize-path": "^3.0.0",
|
|
40
|
-
"
|
|
43
|
+
"object-inspect": "1.11.0",
|
|
41
44
|
"string-argv": "0.3.1",
|
|
42
|
-
"
|
|
43
|
-
"supports-color": "8.1.1"
|
|
45
|
+
"supports-color": "9.0.2"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|
|
46
|
-
"@babel/core": "^7.
|
|
47
|
-
"@babel/eslint-parser": "
|
|
48
|
-
"@babel/
|
|
49
|
-
"
|
|
50
|
-
"babel-jest": "^27.2.4",
|
|
48
|
+
"@babel/core": "^7.16.0",
|
|
49
|
+
"@babel/eslint-parser": "7.16.3",
|
|
50
|
+
"@babel/preset-env": "^7.16.0",
|
|
51
|
+
"babel-jest": "27.3.1",
|
|
51
52
|
"consolemock": "^1.1.0",
|
|
52
|
-
"eslint": "^
|
|
53
|
+
"eslint": "^8.2.0",
|
|
53
54
|
"eslint-config-prettier": "^8.3.0",
|
|
54
|
-
"eslint-plugin-import": "^2.
|
|
55
|
+
"eslint-plugin-import": "^2.25.3",
|
|
55
56
|
"eslint-plugin-node": "^11.1.0",
|
|
56
57
|
"eslint-plugin-prettier": "^4.0.0",
|
|
57
58
|
"fs-extra": "^10.0.0",
|
|
58
|
-
"husky": "^7.0.
|
|
59
|
-
"jest": "^27.
|
|
59
|
+
"husky": "^7.0.4",
|
|
60
|
+
"jest": "^27.3.1",
|
|
61
|
+
"jest-mock-console": "1.2.3",
|
|
60
62
|
"jest-snapshot-serializer-ansi": "^1.0.0",
|
|
61
63
|
"prettier": "^2.4.1"
|
|
62
64
|
},
|
|
@@ -65,19 +67,6 @@
|
|
|
65
67
|
"path": "./node_modules/cz-conventional-changelog"
|
|
66
68
|
}
|
|
67
69
|
},
|
|
68
|
-
"jest": {
|
|
69
|
-
"collectCoverage": true,
|
|
70
|
-
"collectCoverageFrom": [
|
|
71
|
-
"lib/**/*.js"
|
|
72
|
-
],
|
|
73
|
-
"setupFiles": [
|
|
74
|
-
"./testSetup.js"
|
|
75
|
-
],
|
|
76
|
-
"snapshotSerializers": [
|
|
77
|
-
"jest-snapshot-serializer-ansi"
|
|
78
|
-
],
|
|
79
|
-
"testEnvironment": "node"
|
|
80
|
-
},
|
|
81
70
|
"keywords": [
|
|
82
71
|
"lint",
|
|
83
72
|
"git",
|