feat(providence): support fullPath notation in optimisedGlob
This commit is contained in:
parent
2f3f4276fb
commit
6ec74dc58b
3 changed files with 67 additions and 16 deletions
5
.changeset/tall-ligers-rhyme.md
Normal file
5
.changeset/tall-ligers-rhyme.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'providence-analytics': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
support fullPath notation in optimisedGlob
|
||||||
|
|
@ -130,6 +130,14 @@ function toUniqueArray(arr) {
|
||||||
return Array.from(new Set(arr));
|
return Array.from(new Set(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} glob
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
function isRootGlob(glob) {
|
||||||
|
return glob.startsWith('/') || glob.startsWith('!/') || Boolean(glob.match(/^([A-Z]:\\|\\\\)/));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {DirentWithPath} dirent
|
* @param {DirentWithPath} dirent
|
||||||
* @param {{cwd:string}} cfg
|
* @param {{cwd:string}} cfg
|
||||||
|
|
@ -162,7 +170,10 @@ function postprocessOptions(matchedEntries, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.absolute) {
|
if (options.absolute) {
|
||||||
filteredPaths = filteredPaths.map(f => toPosixPath(path.join(options.cwd, f)));
|
filteredPaths = filteredPaths.map(f => {
|
||||||
|
const isRootPath = isRootGlob(f);
|
||||||
|
return isRootPath ? toPosixPath(f) : toPosixPath(path.join(options.cwd, f));
|
||||||
|
});
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
const driveChar = path.win32.resolve(options.cwd).slice(0, 1).toUpperCase();
|
const driveChar = path.win32.resolve(options.cwd).slice(0, 1).toUpperCase();
|
||||||
filteredPaths = filteredPaths.map(f => `${driveChar}:${f}`);
|
filteredPaths = filteredPaths.map(f => `${driveChar}:${f}`);
|
||||||
|
|
@ -183,19 +194,17 @@ function postprocessOptions(matchedEntries, options) {
|
||||||
const getStartPath = memoize(
|
const getStartPath = memoize(
|
||||||
/**
|
/**
|
||||||
* @param {string} glob
|
* @param {string} glob
|
||||||
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
glob => {
|
glob => {
|
||||||
const reservedChars = ['?', '[', ']', '{', '}', ',', '.', '*'];
|
const reservedChars = ['?', '[', ']', '{', '}', ',', '.', '*'];
|
||||||
let hasFoundReservedChar = false;
|
const startPathParts = [];
|
||||||
return glob
|
for (const part of glob.split('/')) {
|
||||||
.split('/')
|
const hasReservedChar = reservedChars.some(reservedChar => part.includes(reservedChar));
|
||||||
.map(part => {
|
if (hasReservedChar) break;
|
||||||
if (hasFoundReservedChar) return undefined;
|
startPathParts.push(part);
|
||||||
hasFoundReservedChar = reservedChars.some(reservedChar => part.includes(reservedChar));
|
}
|
||||||
return hasFoundReservedChar ? undefined : part;
|
return startPathParts.join('/');
|
||||||
})
|
|
||||||
.filter(Boolean)
|
|
||||||
.join('/');
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -315,9 +324,12 @@ export async function optimisedGlob(globOrGlobs, providedOptions = {}) {
|
||||||
const ignoreGlobs = options.ignore.map((/** @type {string} */ g) =>
|
const ignoreGlobs = options.ignore.map((/** @type {string} */ g) =>
|
||||||
g.startsWith('!') ? g : `!${g}`,
|
g.startsWith('!') ? g : `!${g}`,
|
||||||
);
|
);
|
||||||
|
const globs = toUniqueArray([...regularGlobs, ...ignoreGlobs]);
|
||||||
|
|
||||||
const optionsNotSupportedByNativeGlob = ['onlyDirectories', 'dot'];
|
const optionsNotSupportedByNativeGlob = ['onlyDirectories', 'dot'];
|
||||||
const doesConfigAllowNative = !optionsNotSupportedByNativeGlob.some(opt => options[opt]);
|
const hasGlobWithFullPath = globs.some(isRootGlob);
|
||||||
|
const doesConfigAllowNative =
|
||||||
|
!optionsNotSupportedByNativeGlob.some(opt => options[opt]) && !hasGlobWithFullPath;
|
||||||
if (isExperimentalFsGlobEnabled && options.fs.promises.glob && doesConfigAllowNative) {
|
if (isExperimentalFsGlobEnabled && options.fs.promises.glob && doesConfigAllowNative) {
|
||||||
const negativeGlobs = [...ignoreGlobs, ...regularGlobs.filter(r => r.startsWith('!'))].map(r =>
|
const negativeGlobs = [...ignoreGlobs, ...regularGlobs.filter(r => r.startsWith('!'))].map(r =>
|
||||||
r.slice(1),
|
r.slice(1),
|
||||||
|
|
@ -350,8 +362,6 @@ export async function optimisedGlob(globOrGlobs, providedOptions = {}) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const globs = toUniqueArray([...regularGlobs, ...ignoreGlobs]);
|
|
||||||
|
|
||||||
/** @type {RegExp[]} */
|
/** @type {RegExp[]} */
|
||||||
const matchRegexesNegative = [];
|
const matchRegexesNegative = [];
|
||||||
/** @type {RegExp[]} */
|
/** @type {RegExp[]} */
|
||||||
|
|
@ -377,11 +387,13 @@ export async function optimisedGlob(globOrGlobs, providedOptions = {}) {
|
||||||
|
|
||||||
// Search for the "deepest" starting point in the filesystem that we can use to search the fs
|
// Search for the "deepest" starting point in the filesystem that we can use to search the fs
|
||||||
const startPath = getStartPath(globNormalized);
|
const startPath = getStartPath(globNormalized);
|
||||||
const fullStartPath = path.join(options.cwd, startPath);
|
const isRootPath = isRootGlob(startPath);
|
||||||
|
const cwd = isRootPath ? '/' : options.cwd;
|
||||||
|
const fullStartPath = path.join(cwd, startPath);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const allDirEntsRelativeToCwd = await getAllDirentsRelativeToCwd(fullStartPath, {
|
const allDirEntsRelativeToCwd = await getAllDirentsRelativeToCwd(fullStartPath, {
|
||||||
cwd: options.cwd,
|
cwd,
|
||||||
fs: options.fs,
|
fs: options.fs,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@ async function runOptimisedGlobAndCheckGlobbyParity(patterns, options) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.debug({ optimisedGlobResult, globbyResult });
|
||||||
|
|
||||||
expect(optimisedGlobResult).to.deep.equal(globbyResult);
|
expect(optimisedGlobResult).to.deep.equal(globbyResult);
|
||||||
|
|
||||||
return optimisedGlobResult;
|
return optimisedGlobResult;
|
||||||
|
|
@ -302,6 +304,38 @@ function runSuiteForOptimisedGlob() {
|
||||||
).to.throw();
|
).to.throw();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Edge cases', () => {
|
||||||
|
it('allows prefixing a system path (regardless of cwd)', async () => {
|
||||||
|
const files = await runOptimisedGlobAndCheckGlobbyParity(
|
||||||
|
'/fakeFs/my/folder/*/some/file.{js,d.ts}',
|
||||||
|
testCfg,
|
||||||
|
);
|
||||||
|
expect(files).to.deep.equal([
|
||||||
|
'/fakeFs/my/folder/lvl1/some/file.d.ts',
|
||||||
|
'/fakeFs/my/folder/lvl1/some/file.js',
|
||||||
|
]);
|
||||||
|
// With non-existing cwd
|
||||||
|
const files2 = await runOptimisedGlobAndCheckGlobbyParity(
|
||||||
|
'/fakeFs/my/folder/*/some/file.{js,d.ts}',
|
||||||
|
{
|
||||||
|
...testCfg,
|
||||||
|
cwd: '/nonExisting/path', // this will not exist
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect(files2).to.deep.equal([
|
||||||
|
'/fakeFs/my/folder/lvl1/some/file.d.ts',
|
||||||
|
'/fakeFs/my/folder/lvl1/some/file.js',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// // With negative globs: this is not supported by globby
|
||||||
|
// const files3 = await runOptimisedGlobAndCheckGlobbyParity(
|
||||||
|
// ['!/fakeFs/my/**/*.d.ts', '/fakeFs/my/folder/*/some/file.{js,d.ts}'],
|
||||||
|
// testCfg,
|
||||||
|
// );
|
||||||
|
// expect(files3).to.deep.equal(['/fakeFs/my/folder/lvl1/some/file.js']);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue