Skip to content

Commit e794ff9

Browse files
committed
Add some more options to isGitIgnored functions
1 parent fcb07c3 commit e794ff9

File tree

5 files changed

+549
-41
lines changed

5 files changed

+549
-41
lines changed

ignore.js

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -109,49 +109,55 @@ const getIsIgnoredPredicate = (files, cwd) => {
109109
};
110110
};
111111

112-
const normalizeOptions = (options = {}) => ({
113-
cwd: toPath(options.cwd) ?? process.cwd(),
114-
suppressErrors: Boolean(options.suppressErrors),
115-
deep: typeof options.deep === 'number' ? options.deep : Number.POSITIVE_INFINITY,
116-
ignore: [...options.ignore ?? [], ...defaultIgnoredDirectories],
117-
});
112+
const normalizeOptions = (options = {}) => {
113+
const ignoreOption = options.ignore
114+
? (Array.isArray(options.ignore) ? options.ignore : [options.ignore])
115+
: [];
116+
117+
const cwd = toPath(options.cwd) ?? process.cwd();
118+
119+
// Only pass through specific fast-glob options that make sense for finding ignore files
120+
return {
121+
cwd,
122+
suppressErrors: options.suppressErrors ?? false,
123+
deep: typeof options.deep === 'number' ? options.deep : Number.POSITIVE_INFINITY,
124+
ignore: [...ignoreOption, ...defaultIgnoredDirectories],
125+
followSymbolicLinks: options.followSymbolicLinks ?? true,
126+
concurrency: options.concurrency,
127+
throwErrorOnBrokenSymbolicLink: options.throwErrorOnBrokenSymbolicLink ?? false,
128+
};
129+
};
118130

119131
export const isIgnoredByIgnoreFiles = async (patterns, options) => {
120-
const {cwd, suppressErrors, deep, ignore} = normalizeOptions(options);
132+
const normalizedOptions = normalizeOptions(options);
121133

122134
const paths = await fastGlob(patterns, {
123-
cwd,
124-
suppressErrors,
125-
deep,
126-
ignore,
127-
...ignoreFilesGlobOptions,
135+
...normalizedOptions,
136+
...ignoreFilesGlobOptions, // Must be last to ensure absolute and dot are always set
128137
});
129138

130139
const files = await Promise.all(paths.map(async filePath => ({
131140
filePath,
132141
content: await fsPromises.readFile(filePath, 'utf8'),
133142
})));
134143

135-
return getIsIgnoredPredicate(files, cwd);
144+
return getIsIgnoredPredicate(files, normalizedOptions.cwd);
136145
};
137146

138147
export const isIgnoredByIgnoreFilesSync = (patterns, options) => {
139-
const {cwd, suppressErrors, deep, ignore} = normalizeOptions(options);
148+
const normalizedOptions = normalizeOptions(options);
140149

141150
const paths = fastGlob.sync(patterns, {
142-
cwd,
143-
suppressErrors,
144-
deep,
145-
ignore,
146-
...ignoreFilesGlobOptions,
151+
...normalizedOptions,
152+
...ignoreFilesGlobOptions, // Must be last to ensure absolute and dot are always set
147153
});
148154

149155
const files = paths.map(filePath => ({
150156
filePath,
151157
content: fs.readFileSync(filePath, 'utf8'),
152158
}));
153159

154-
return getIsIgnoredPredicate(files, cwd);
160+
return getIsIgnoredPredicate(files, normalizedOptions.cwd);
155161
};
156162

157163
const getPatternsFromIgnoreFiles = (files, cwd) => files.flatMap(file => parseIgnoreFile(file, cwd));
@@ -163,14 +169,11 @@ This avoids reading the same files twice (once for patterns, once for filtering)
163169
@returns {Promise<{patterns: string[], predicate: Function}>}
164170
*/
165171
export const getIgnorePatternsAndPredicate = async (patterns, options) => {
166-
const {cwd, suppressErrors, deep, ignore} = normalizeOptions(options);
172+
const normalizedOptions = normalizeOptions(options);
167173

168174
const paths = await fastGlob(patterns, {
169-
cwd,
170-
suppressErrors,
171-
deep,
172-
ignore,
173-
...ignoreFilesGlobOptions,
175+
...normalizedOptions,
176+
...ignoreFilesGlobOptions, // Must be last to ensure absolute and dot are always set
174177
});
175178

176179
const files = await Promise.all(paths.map(async filePath => ({
@@ -179,8 +182,8 @@ export const getIgnorePatternsAndPredicate = async (patterns, options) => {
179182
})));
180183

181184
return {
182-
patterns: getPatternsFromIgnoreFiles(files, cwd),
183-
predicate: getIsIgnoredPredicate(files, cwd),
185+
patterns: getPatternsFromIgnoreFiles(files, normalizedOptions.cwd),
186+
predicate: getIsIgnoredPredicate(files, normalizedOptions.cwd),
184187
};
185188
};
186189

@@ -190,14 +193,11 @@ Read ignore files and return both patterns and predicate (sync version).
190193
@returns {{patterns: string[], predicate: Function}}
191194
*/
192195
export const getIgnorePatternsAndPredicateSync = (patterns, options) => {
193-
const {cwd, suppressErrors, deep, ignore} = normalizeOptions(options);
196+
const normalizedOptions = normalizeOptions(options);
194197

195198
const paths = fastGlob.sync(patterns, {
196-
cwd,
197-
suppressErrors,
198-
deep,
199-
ignore,
200-
...ignoreFilesGlobOptions,
199+
...normalizedOptions,
200+
...ignoreFilesGlobOptions, // Must be last to ensure absolute and dot are always set
201201
});
202202

203203
const files = paths.map(filePath => ({
@@ -206,8 +206,8 @@ export const getIgnorePatternsAndPredicateSync = (patterns, options) => {
206206
}));
207207

208208
return {
209-
patterns: getPatternsFromIgnoreFiles(files, cwd),
210-
predicate: getIsIgnoredPredicate(files, cwd),
209+
patterns: getPatternsFromIgnoreFiles(files, normalizedOptions.cwd),
210+
predicate: getIsIgnoredPredicate(files, normalizedOptions.cwd),
211211
};
212212
};
213213

index.d.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,56 @@ export type Options = {
6868
} & FastGlobOptionsWithoutCwd;
6969

7070
export type GitignoreOptions = {
71+
/**
72+
The current working directory in which to search.
73+
74+
@default process.cwd()
75+
*/
7176
readonly cwd?: URL | string;
77+
78+
/**
79+
Suppress errors when encountering directories or files without read permissions.
80+
81+
By default, fast-glob only suppresses `ENOENT` errors. Set to `true` to suppress any error.
82+
83+
@default false
84+
*/
85+
readonly suppressErrors?: boolean;
86+
87+
/**
88+
Specifies the maximum depth of ignore file search relative to the start directory.
89+
90+
@default Infinity
91+
*/
92+
readonly deep?: number;
93+
94+
/**
95+
Glob patterns to exclude from ignore file search.
96+
97+
@default []
98+
*/
99+
readonly ignore?: string | readonly string[];
100+
101+
/**
102+
Indicates whether to traverse descendants of symbolic link directories.
103+
104+
@default true
105+
*/
106+
readonly followSymbolicLinks?: boolean;
107+
108+
/**
109+
Specifies the maximum number of concurrent requests from a reader to read directories.
110+
111+
@default os.cpus().length
112+
*/
113+
readonly concurrency?: number;
114+
115+
/**
116+
Throw an error when symbolic link is broken if `true` or safely return `lstat` call if `false`.
117+
118+
@default false
119+
*/
120+
readonly throwErrorOnBrokenSymbolicLink?: boolean;
72121
};
73122

74123
export type GlobbyFilterFunction = (path: URL | string) => boolean;

index.test-d.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,47 @@ expectType<Promise<GlobbyFilterFunction>>(isGitIgnored({
134134
cwd: new URL('file:///path/to/cwd'),
135135
}));
136136

137+
// Supported option: suppressErrors
138+
expectType<Promise<GlobbyFilterFunction>>(isGitIgnored({
139+
suppressErrors: true,
140+
}));
141+
142+
// Supported option: deep
143+
expectType<Promise<GlobbyFilterFunction>>(isGitIgnored({
144+
deep: 2,
145+
}));
146+
147+
// Supported option: ignore
148+
expectType<Promise<GlobbyFilterFunction>>(isGitIgnored({
149+
ignore: ['**/node_modules'],
150+
}));
151+
152+
// Supported option: followSymbolicLinks
153+
expectType<Promise<GlobbyFilterFunction>>(isGitIgnored({
154+
followSymbolicLinks: false,
155+
}));
156+
157+
// Supported option: concurrency
158+
expectType<Promise<GlobbyFilterFunction>>(isGitIgnored({
159+
concurrency: 4,
160+
}));
161+
162+
// Supported option: throwErrorOnBrokenSymbolicLink
163+
expectType<Promise<GlobbyFilterFunction>>(isGitIgnored({
164+
throwErrorOnBrokenSymbolicLink: false,
165+
}));
166+
167+
// Multiple supported options combined
168+
expectType<Promise<GlobbyFilterFunction>>(isGitIgnored({
169+
cwd: __dirname,
170+
suppressErrors: true,
171+
deep: 1,
172+
ignore: ['**/node_modules', '**/dist'],
173+
followSymbolicLinks: false,
174+
concurrency: 8,
175+
throwErrorOnBrokenSymbolicLink: false,
176+
}));
177+
137178
// IsGitIgnoredSync
138179
expectType<GlobbyFilterFunction>(isGitIgnoredSync());
139180
expectType<GlobbyFilterFunction>(isGitIgnoredSync({
@@ -142,3 +183,44 @@ expectType<GlobbyFilterFunction>(isGitIgnoredSync({
142183
expectType<GlobbyFilterFunction>(isGitIgnoredSync({
143184
cwd: new URL('file:///path/to/cwd'),
144185
}));
186+
187+
// Supported option: suppressErrors (sync)
188+
expectType<GlobbyFilterFunction>(isGitIgnoredSync({
189+
suppressErrors: true,
190+
}));
191+
192+
// Supported option: deep (sync)
193+
expectType<GlobbyFilterFunction>(isGitIgnoredSync({
194+
deep: 2,
195+
}));
196+
197+
// Supported option: ignore (sync)
198+
expectType<GlobbyFilterFunction>(isGitIgnoredSync({
199+
ignore: ['**/node_modules'],
200+
}));
201+
202+
// Supported option: followSymbolicLinks (sync)
203+
expectType<GlobbyFilterFunction>(isGitIgnoredSync({
204+
followSymbolicLinks: false,
205+
}));
206+
207+
// Supported option: concurrency (sync)
208+
expectType<GlobbyFilterFunction>(isGitIgnoredSync({
209+
concurrency: 4,
210+
}));
211+
212+
// Supported option: throwErrorOnBrokenSymbolicLink (sync)
213+
expectType<GlobbyFilterFunction>(isGitIgnoredSync({
214+
throwErrorOnBrokenSymbolicLink: true,
215+
}));
216+
217+
// Multiple supported options combined (sync)
218+
expectType<GlobbyFilterFunction>(isGitIgnoredSync({
219+
cwd: __dirname,
220+
suppressErrors: true,
221+
deep: 1,
222+
ignore: ['**/node_modules', '**/dist'],
223+
followSymbolicLinks: false,
224+
concurrency: 4,
225+
throwErrorOnBrokenSymbolicLink: false,
226+
}));

0 commit comments

Comments
 (0)