UNPKG

4.34 kBJavaScriptView Raw
1import debug from 'debug'
2
3import {
4 PREVENTED_EMPTY_COMMIT,
5 GIT_ERROR,
6 RESTORE_STASH_EXAMPLE,
7 NO_CONFIGURATION,
8} from './messages.js'
9import { printTaskOutput } from './printTaskOutput.js'
10import { runAll } from './runAll.js'
11import {
12 ApplyEmptyCommitError,
13 ConfigNotFoundError,
14 GetBackupStashError,
15 GitError,
16} from './symbols.js'
17import { validateOptions } from './validateOptions.js'
18
19const 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 */
28const 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 {string} [options.diff] - Override the default "--staged" flag of "git diff" to get list of files
53 * @param {string} [options.diffFilter] - Override the default "--diff-filter=ACMR" flag of "git diff" to get list of files
54 * @param {number} [options.maxArgLength] - Maximum argument string length
55 * @param {boolean} [options.quiet] - Disable lint-staged’s own console output
56 * @param {boolean} [options.relative] - Pass relative filepaths to tasks
57 * @param {boolean|string} [options.shell] - Skip parsing of tasks for better shell support
58 * @param {boolean} [options.stash] - Enable the backup stash, and revert in case of errors
59 * @param {boolean} [options.verbose] - Show task output even when tasks succeed; by default only failed output is shown
60 * @param {Logger} [logger]
61 *
62 * @returns {Promise<boolean>} Promise of whether the linting passed or failed
63 */
64const lintStaged = async (
65 {
66 allowEmpty = false,
67 concurrent = true,
68 config: configObject,
69 configPath,
70 cwd,
71 debug = false,
72 diff,
73 diffFilter,
74 maxArgLength = getMaxArgLength() / 2,
75 quiet = false,
76 relative = false,
77 shell = false,
78 stash = true,
79 verbose = false,
80 } = {},
81 logger = console
82) => {
83 await validateOptions({ cwd, shell }, logger)
84
85 // Unset GIT_LITERAL_PATHSPECS to not mess with path interpretation
86 debugLog('Unset GIT_LITERAL_PATHSPECS (was `%s`)', process.env.GIT_LITERAL_PATHSPECS)
87 delete process.env.GIT_LITERAL_PATHSPECS
88
89 const options = {
90 allowEmpty,
91 concurrent,
92 configObject,
93 configPath,
94 cwd,
95 debug,
96 diff,
97 diffFilter,
98 maxArgLength,
99 quiet,
100 relative,
101 shell,
102 stash,
103 verbose,
104 }
105
106 try {
107 const ctx = await runAll(options, logger)
108 debugLog('Tasks were executed successfully!')
109 printTaskOutput(ctx, logger)
110 return true
111 } catch (runAllError) {
112 if (runAllError?.ctx?.errors) {
113 const { ctx } = runAllError
114
115 if (ctx.errors.has(ConfigNotFoundError)) {
116 logger.error(NO_CONFIGURATION)
117 } else if (ctx.errors.has(ApplyEmptyCommitError)) {
118 logger.warn(PREVENTED_EMPTY_COMMIT)
119 } else if (ctx.errors.has(GitError) && !ctx.errors.has(GetBackupStashError)) {
120 logger.error(GIT_ERROR)
121 if (ctx.shouldBackup) {
122 // No sense to show this if the backup stash itself is missing.
123 logger.error(RESTORE_STASH_EXAMPLE)
124 }
125 }
126
127 printTaskOutput(ctx, logger)
128 return false
129 }
130
131 // Probably a compilation error in the config js file. Pass it up to the outer error handler for logging.
132 throw runAllError
133 }
134}
135
136export default lintStaged