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));
|
||||
}
|
||||
|
||||
/**
|
||||
* @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,
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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']);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue