2
2
3
3
import { basename , join } from 'path'
4
4
5
+ import debug from 'debug'
5
6
import normalize from 'normalize-path'
6
7
7
8
import { execGit } from './execGit.js'
8
9
import { loadConfig , searchPlaces } from './loadConfig.js'
9
10
import { parseGitZOutput } from './parseGitZOutput.js'
10
11
import { validateConfig } from './validateConfig.js'
11
12
13
+ const debugLog = debug ( 'lint-staged:searchConfigs' )
14
+
12
15
const EXEC_GIT = [ 'ls-files' , '-z' , '--full-name' ]
13
16
14
17
const filterPossibleConfigFiles = ( file ) => searchPlaces . includes ( basename ( file ) )
@@ -17,14 +20,44 @@ const numberOfLevels = (file) => file.split('/').length
17
20
18
21
const sortDeepestParth = ( a , b ) => ( numberOfLevels ( a ) > numberOfLevels ( b ) ? - 1 : 1 )
19
22
23
+ const isInsideDirectory = ( dir ) => ( file ) => file . startsWith ( normalize ( dir ) )
24
+
25
+ export const ConfigObjectSymbol = Symbol ( )
26
+
20
27
/**
21
- * Search all config files from the git repository
28
+ * Search all config files from the git repository, preferring those inside `cwd`.
22
29
*
23
- * @param {string } gitDir
30
+ * @param {object } options
31
+ * @param {Object } [options.configObject] - Explicit config object from the js API
32
+ * @param {string } [options.configPath] - Explicit path to a config file
33
+ * @param {string } [options.cwd] - Current working directory
24
34
* @param {Logger } logger
25
- * @returns {Promise<{ [key: string]: * }> } found configs with filepath as key, and config as value
35
+ *
36
+ * @returns {Promise<{ [key: string]: { config: *, files: string[] } }> } found configs with filepath as key, and config as value
26
37
*/
27
- export const searchConfigs = async ( gitDir = process . cwd ( ) , logger ) => {
38
+ export const searchConfigs = async (
39
+ { configObject, configPath, cwd = process . cwd ( ) , gitDir = cwd } ,
40
+ logger
41
+ ) => {
42
+ debugLog ( 'Searching for configuration files...' )
43
+
44
+ // Return explicit config object from js API
45
+ if ( configObject ) {
46
+ debugLog ( 'Using single direct configuration object...' )
47
+
48
+ return { [ ConfigObjectSymbol ] : validateConfig ( configObject , 'config object' , logger ) }
49
+ }
50
+
51
+ // Use only explicit config path instead of discovering multiple
52
+ if ( configPath ) {
53
+ debugLog ( 'Using single configuration path...' )
54
+
55
+ const { config, filepath } = await loadConfig ( { configPath } , logger )
56
+
57
+ if ( ! config ) return { }
58
+ return { [ configPath ] : validateConfig ( config , filepath , logger ) }
59
+ }
60
+
28
61
/** Get all possible config files known to git */
29
62
const cachedFiles = parseGitZOutput ( await execGit ( EXEC_GIT , { cwd : gitDir } ) ) . filter (
30
63
filterPossibleConfigFiles
@@ -39,8 +72,11 @@ export const searchConfigs = async (gitDir = process.cwd(), logger) => {
39
72
const possibleConfigFiles = [ ...cachedFiles , ...otherFiles ]
40
73
. map ( ( file ) => join ( gitDir , file ) )
41
74
. map ( ( file ) => normalize ( file ) )
75
+ . filter ( isInsideDirectory ( cwd ) )
42
76
. sort ( sortDeepestParth )
43
77
78
+ debugLog ( 'Found possible config files:' , possibleConfigFiles )
79
+
44
80
/** Create object with key as config file, and value as null */
45
81
const configs = possibleConfigFiles . reduce (
46
82
( acc , configPath ) => Object . assign ( acc , { [ configPath ] : null } ) ,
@@ -65,5 +101,24 @@ export const searchConfigs = async (gitDir = process.cwd(), logger) => {
65
101
. filter ( ( [ , value ] ) => ! ! value )
66
102
. reduce ( ( acc , [ key , value ] ) => ( { ...acc , [ key ] : value } ) , { } )
67
103
104
+ /**
105
+ * Try to find a single config from parent directories
106
+ * to match old behavior before monorepo support
107
+ */
108
+ if ( ! Object . keys ( foundConfigs ) . length ) {
109
+ debugLog ( 'Could not find config files inside "%s"' , cwd )
110
+
111
+ const { config, filepath } = await loadConfig ( { cwd } , logger )
112
+ if ( config ) {
113
+ debugLog ( 'Found parent configuration file from "%s"' , filepath )
114
+
115
+ foundConfigs [ filepath ] = validateConfig ( config , filepath , logger )
116
+ } else {
117
+ debugLog ( 'Could not find parent configuration files from "%s"' , cwd )
118
+ }
119
+ }
120
+
121
+ debugLog ( 'Found %d config files' , Object . keys ( foundConfigs ) . length )
122
+
68
123
return foundConfigs
69
124
}
0 commit comments