feat(providence): support fullPath notation in optimisedGlob

This commit is contained in:
Thijs Louisse 2024-10-21 18:46:40 +02:00 committed by Thijs Louisse
parent 2f3f4276fb
commit 6ec74dc58b
3 changed files with 67 additions and 16 deletions

View file

@ -0,0 +1,5 @@
---
'providence-analytics': patch
---
support fullPath notation in optimisedGlob

View file

@ -130,6 +130,14 @@ function toUniqueArray(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 {{cwd:string}} cfg
@ -162,7 +170,10 @@ function postprocessOptions(matchedEntries, options) {
}
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') {
const driveChar = path.win32.resolve(options.cwd).slice(0, 1).toUpperCase();
filteredPaths = filteredPaths.map(f => `${driveChar}:${f}`);
@ -183,19 +194,17 @@ function postprocessOptions(matchedEntries, options) {
const getStartPath = memoize(
/**
* @param {string} glob
* @returns {string}
*/
glob => {
const reservedChars = ['?', '[', ']', '{', '}', ',', '.', '*'];
let hasFoundReservedChar = false;
return glob
.split('/')
.map(part => {
if (hasFoundReservedChar) return undefined;
hasFoundReservedChar = reservedChars.some(reservedChar => part.includes(reservedChar));
return hasFoundReservedChar ? undefined : part;
})
.filter(Boolean)
.join('/');
const startPathParts = [];
for (const part of glob.split('/')) {
const hasReservedChar = reservedChars.some(reservedChar => part.includes(reservedChar));
if (hasReservedChar) break;
startPathParts.push(part);
}
return startPathParts.join('/');
},
);
@ -315,9 +324,12 @@ export async function optimisedGlob(globOrGlobs, providedOptions = {}) {
const ignoreGlobs = options.ignore.map((/** @type {string} */ g) =>
g.startsWith('!') ? g : `!${g}`,
);
const globs = toUniqueArray([...regularGlobs, ...ignoreGlobs]);
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) {
const negativeGlobs = [...ignoreGlobs, ...regularGlobs.filter(r => r.startsWith('!'))].map(r =>
r.slice(1),
@ -350,8 +362,6 @@ export async function optimisedGlob(globOrGlobs, providedOptions = {}) {
);
}
const globs = toUniqueArray([...regularGlobs, ...ignoreGlobs]);
/** @type {RegExp[]} */
const matchRegexesNegative = [];
/** @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
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 {
const allDirEntsRelativeToCwd = await getAllDirentsRelativeToCwd(fullStartPath, {
cwd: options.cwd,
cwd,
fs: options.fs,
});

View file

@ -40,6 +40,8 @@ async function runOptimisedGlobAndCheckGlobbyParity(patterns, options) {
);
}
console.debug({ optimisedGlobResult, globbyResult });
expect(optimisedGlobResult).to.deep.equal(globbyResult);
return optimisedGlobResult;
@ -302,6 +304,38 @@ function runSuiteForOptimisedGlob() {
).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']);
});
});
});
}