fix(compiler-cli): ensure ngcc can handle wildcard base-paths (#41033)
Ngcc uses the `paths` property to compute the potential base-paths for packages that are being processed. If the `paths` contain a wildcard `*` within a path segment, ngcc was not finding the base-path correctly. Now when a wildcard is found, there is an additional search to look for paths that might match the wildcard. Fixes #41014 PR Close #41033
This commit is contained in:
parent
e12d9dec64
commit
0b69fabcf5
|
@ -5,7 +5,7 @@
|
|||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {AbsoluteFsPath, getFileSystem, PathManipulation} from '../../../src/ngtsc/file_system';
|
||||
import {AbsoluteFsPath, getFileSystem, PathManipulation, ReadonlyFileSystem} from '../../../src/ngtsc/file_system';
|
||||
import {Logger} from '../../../src/ngtsc/logging';
|
||||
import {PathMappings} from '../path_mappings';
|
||||
|
||||
|
@ -41,21 +41,52 @@ export function getBasePaths(
|
|||
`This is likely to mess up how ngcc finds entry-points and is probably not correct.\n` +
|
||||
`Please check your path mappings configuration such as in the tsconfig.json file.`);
|
||||
}
|
||||
Object.values(pathMappings.paths).forEach(paths => paths.forEach(path => {
|
||||
// We only want base paths that exist and are not files
|
||||
let basePath = fs.resolve(baseUrl, extractPathPrefix(path));
|
||||
if (fs.exists(basePath) && fs.stat(basePath).isFile()) {
|
||||
basePath = fs.dirname(basePath);
|
||||
for (const paths of Object.values(pathMappings.paths)) {
|
||||
for (const path of paths) {
|
||||
let foundMatch = false;
|
||||
|
||||
// We only want base paths that exist and are not files
|
||||
const {prefix, hasWildcard} = extractPathPrefix(path);
|
||||
let basePath = fs.resolve(baseUrl, prefix);
|
||||
if (fs.exists(basePath) && fs.stat(basePath).isFile()) {
|
||||
basePath = fs.dirname(basePath);
|
||||
}
|
||||
|
||||
if (fs.exists(basePath)) {
|
||||
// The `basePath` is itself a directory
|
||||
basePaths.push(basePath);
|
||||
foundMatch = true;
|
||||
}
|
||||
|
||||
if (hasWildcard) {
|
||||
// The path contains a wildcard (`*`) so also try searching for directories that start
|
||||
// with the wildcard prefix path segment.
|
||||
const wildcardContainer = fs.dirname(basePath);
|
||||
const wildcardPrefix = fs.basename(basePath);
|
||||
if (isExistingDirectory(fs, wildcardContainer)) {
|
||||
const candidates = fs.readdir(wildcardContainer);
|
||||
for (const candidate of candidates) {
|
||||
if (candidate.startsWith(wildcardPrefix)) {
|
||||
const candidatePath = fs.resolve(wildcardContainer, candidate);
|
||||
if (isExistingDirectory(fs, candidatePath)) {
|
||||
foundMatch = true;
|
||||
basePaths.push(candidatePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundMatch) {
|
||||
// We neither found a direct match (i.e. `basePath` is an existing directory) nor a
|
||||
// directory that starts with a wildcard prefix.
|
||||
logger.debug(
|
||||
`The basePath "${basePath}" computed from baseUrl "${baseUrl}" and path mapping "${
|
||||
path}" does not exist in the file-system.\n` +
|
||||
`It will not be scanned for entry-points.`);
|
||||
}
|
||||
}
|
||||
if (fs.exists(basePath)) {
|
||||
basePaths.push(basePath);
|
||||
} else {
|
||||
logger.debug(
|
||||
`The basePath "${basePath}" computed from baseUrl "${baseUrl}" and path mapping "${
|
||||
path}" does not exist in the file-system.\n` +
|
||||
`It will not be scanned for entry-points.`);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
const dedupedBasePaths = dedupePaths(fs, basePaths);
|
||||
|
@ -70,13 +101,18 @@ export function getBasePaths(
|
|||
return dedupedBasePaths;
|
||||
}
|
||||
|
||||
function isExistingDirectory(fs: ReadonlyFileSystem, path: AbsoluteFsPath): boolean {
|
||||
return fs.exists(path) && fs.stat(path).isDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract everything in the `path` up to the first `*`.
|
||||
* @param path The path to parse.
|
||||
* @returns The extracted prefix.
|
||||
* @returns The extracted prefix and a flag to indicate whether there was a wildcard `*`.
|
||||
*/
|
||||
function extractPathPrefix(path: string) {
|
||||
return path.split('*', 1)[0];
|
||||
function extractPathPrefix(path: string): {prefix: string, hasWildcard: boolean} {
|
||||
const [prefix, rest] = path.split('*', 2);
|
||||
return {prefix, hasWildcard: rest !== undefined};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -48,6 +48,24 @@ runInEachFileSystem(() => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('should find base-paths that start with a wildcard prefix', () => {
|
||||
const projectDirectory = _('/path/to/project');
|
||||
const fs = getFileSystem();
|
||||
fs.ensureDir(fs.resolve(projectDirectory, 'dist'));
|
||||
fs.ensureDir(fs.resolve(projectDirectory, 'dist-a'));
|
||||
fs.ensureDir(fs.resolve(projectDirectory, 'dist-b'));
|
||||
|
||||
const sourceDirectory = _('/path/to/project/node_modules');
|
||||
const pathMappings = {baseUrl: projectDirectory, paths: {'@dist*': ['dist*']}};
|
||||
const basePaths = getBasePaths(logger, sourceDirectory, pathMappings);
|
||||
expect(basePaths).toEqual([
|
||||
sourceDirectory,
|
||||
fs.resolve(projectDirectory, 'dist'),
|
||||
fs.resolve(projectDirectory, 'dist-a'),
|
||||
fs.resolve(projectDirectory, 'dist-b'),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not be confused by folders that have the same starting string', () => {
|
||||
const projectDirectory = _('/path/to/project');
|
||||
const fs = getFileSystem();
|
||||
|
|
Loading…
Reference in New Issue