1 | import debug from 'debug'
|
2 |
|
3 | import {
|
4 | PREVENTED_EMPTY_COMMIT,
|
5 | GIT_ERROR,
|
6 | RESTORE_STASH_EXAMPLE,
|
7 | NO_CONFIGURATION,
|
8 | } from './messages.js'
|
9 | import { printTaskOutput } from './printTaskOutput.js'
|
10 | import { runAll } from './runAll.js'
|
11 | import {
|
12 | ApplyEmptyCommitError,
|
13 | ConfigNotFoundError,
|
14 | GetBackupStashError,
|
15 | GitError,
|
16 | } from './symbols.js'
|
17 | import { validateOptions } from './validateOptions.js'
|
18 |
|
19 | const debugLog = debug('lint-staged')
|
20 |
|
21 | /**
|
22 | * Get the maximum length of a command-line argument string based on current platform
|
23 | *
|
24 | * https://serverfault.com/questions/69430/what-is-the-maximum-length-of-a-command-line-in-mac-os-x
|
25 | * https://support.microsoft.com/en-us/help/830473/command-prompt-cmd-exe-command-line-string-limitation
|
26 | * https://unix.stackexchange.com/a/120652
|
27 | */
|
28 | const getMaxArgLength = () => {
|
29 | switch (process.platform) {
|
30 | case 'darwin':
|
31 | return 262144
|
32 | case 'win32':
|
33 | return 8191
|
34 | default:
|
35 | return 131072
|
36 | }
|
37 | }
|
38 |
|
39 | /**
|
40 | * @typedef {(...any) => void} LogFunction
|
41 | * @typedef {{ error: LogFunction, log: LogFunction, warn: LogFunction }} Logger
|
42 | *
|
43 | * Root lint-staged function that is called from `bin/lint-staged`.
|
44 | *
|
45 | * @param {object} options
|
46 | * @param {Object} [options.allowEmpty] - Allow empty commits when tasks revert all staged changes
|
47 | * @param {boolean | number} [options.concurrent] - The number of tasks to run concurrently, or false to run tasks serially
|
48 | * @param {object} [options.config] - Object with configuration for programmatic API
|
49 | * @param {string} [options.configPath] - Path to configuration file
|
50 | * @param {Object} [options.cwd] - Current working directory
|
51 | * @param {boolean} [options.debug] - Enable debug mode
|
52 | * @param {number} [options.maxArgLength] - Maximum argument string length
|
53 | * @param {boolean} [options.quiet] - Disable lint-staged’s own console output
|
54 | * @param {boolean} [options.relative] - Pass relative filepaths to tasks
|
55 | * @param {boolean|string} [options.shell] - Skip parsing of tasks for better shell support
|
56 | * @param {boolean} [options.stash] - Enable the backup stash, and revert in case of errors
|
57 | * @param {boolean} [options.verbose] - Show task output even when tasks succeed; by default only failed output is shown
|
58 | * @param {Logger} [logger]
|
59 | *
|
60 | * @returns {Promise<boolean>} Promise of whether the linting passed or failed
|
61 | */
|
62 | const lintStaged = async (
|
63 | {
|
64 | allowEmpty = false,
|
65 | concurrent = true,
|
66 | config: configObject,
|
67 | configPath,
|
68 | cwd,
|
69 | debug = false,
|
70 | maxArgLength = getMaxArgLength() / 2,
|
71 | quiet = false,
|
72 | relative = false,
|
73 | shell = false,
|
74 | stash = true,
|
75 | verbose = false,
|
76 | } = {},
|
77 | logger = console
|
78 | ) => {
|
79 | await validateOptions({ cwd, shell }, logger)
|
80 |
|
81 | // Unset GIT_LITERAL_PATHSPECS to not mess with path interpretation
|
82 | debugLog('Unset GIT_LITERAL_PATHSPECS (was `%s`)', process.env.GIT_LITERAL_PATHSPECS)
|
83 | delete process.env.GIT_LITERAL_PATHSPECS
|
84 |
|
85 | try {
|
86 | const ctx = await runAll(
|
87 | {
|
88 | allowEmpty,
|
89 | concurrent,
|
90 | configObject,
|
91 | configPath,
|
92 | cwd,
|
93 | debug,
|
94 | maxArgLength,
|
95 | quiet,
|
96 | relative,
|
97 | shell,
|
98 | stash,
|
99 | verbose,
|
100 | },
|
101 | logger
|
102 | )
|
103 | debugLog('Tasks were executed successfully!')
|
104 | printTaskOutput(ctx, logger)
|
105 | return true
|
106 | } catch (runAllError) {
|
107 | if (runAllError && runAllError.ctx && runAllError.ctx.errors) {
|
108 | const { ctx } = runAllError
|
109 |
|
110 | if (ctx.errors.has(ConfigNotFoundError)) {
|
111 | logger.error(NO_CONFIGURATION)
|
112 | } else if (ctx.errors.has(ApplyEmptyCommitError)) {
|
113 | logger.warn(PREVENTED_EMPTY_COMMIT)
|
114 | } else if (ctx.errors.has(GitError) && !ctx.errors.has(GetBackupStashError)) {
|
115 | logger.error(GIT_ERROR)
|
116 | if (ctx.shouldBackup) {
|
117 | // No sense to show this if the backup stash itself is missing.
|
118 | logger.error(RESTORE_STASH_EXAMPLE)
|
119 | }
|
120 | }
|
121 |
|
122 | printTaskOutput(ctx, logger)
|
123 | return false
|
124 | }
|
125 |
|
126 | // Probably a compilation error in the config js file. Pass it up to the outer error handler for logging.
|
127 | throw runAllError
|
128 | }
|
129 | }
|
130 |
|
131 | export default lintStaged
|