refactor(ivy): ngcc - mark target entry-point as processed even if ngcc was a noop (#29092)

If `targetEntryPointPath` is provided to `mainNgcc` then we will now mark all
the `propertiesToConsider` for that entry-point if we determine that
it does not contain code that was compiled by Angular (for instance it has
no `...metadata.json` file).

The commit also renames `__modified_by_ngcc__` to `__processed_by_ivy_ngcc__`, since
there may be entry-points that are marked despite ngcc not actually compiling anything.

PR Close #29092
This commit is contained in:
Pete Bacon Darwin
2019-03-20 13:47:59 +00:00
committed by Matias Niemelä
parent 083fb99033
commit a827bc2e3a
7 changed files with 131 additions and 119 deletions

View File

@ -7,10 +7,11 @@
*/
import {resolve} from 'canonical-path';
import {readFileSync} from 'fs';
import {AbsoluteFsPath, PathSegment} from '../../src/ngtsc/path';
import {AbsoluteFsPath} from '../../src/ngtsc/path';
import {checkMarker, writeMarker} from './packages/build_marker';
import {hasBeenProcessed, markAsProcessed} from './packages/build_marker';
import {DependencyHost} from './packages/dependency_host';
import {DependencyResolver} from './packages/dependency_resolver';
import {EntryPointFormat, EntryPointJsonProperty, SUPPORTED_FORMAT_PROPERTIES, getEntryPointFormat} from './packages/entry_point';
@ -67,22 +68,41 @@ export function mainNgcc({basePath, targetEntryPointPath,
undefined;
const {entryPoints} =
finder.findEntryPoints(AbsoluteFsPath.from(basePath), absoluteTargetEntryPointPath);
entryPoints.forEach(entryPoint => {
if (absoluteTargetEntryPointPath && entryPoints.every(entryPoint => {
return entryPoint.path !== absoluteTargetEntryPointPath;
})) {
// If we get here, then the requested entry-point did not contain anything compiled by
// the old Angular compiler. Therefore there is nothing for ngcc to do.
// So mark all formats in this entry-point as processed so that clients of ngcc can avoid
// triggering ngcc for this entry-point in the future.
const packageJsonPath =
AbsoluteFsPath.from(resolve(absoluteTargetEntryPointPath, 'package.json'));
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
propertiesToConsider.forEach(formatProperty => {
if (packageJson[formatProperty])
markAsProcessed(packageJson, packageJsonPath, formatProperty as EntryPointJsonProperty);
});
return;
}
entryPoints.forEach(entryPoint => {
// Are we compiling the Angular core?
const isCore = entryPoint.name === '@angular/core';
const compiledFormats = new Set<string>();
const entryPointPackageJson = entryPoint.packageJson;
const entryPointPackageJsonPath = AbsoluteFsPath.from(resolve(entryPoint.path, 'package.json'));
for (let i = 0; i < propertiesToConsider.length; i++) {
const property = propertiesToConsider[i] as EntryPointJsonProperty;
const formatPath = entryPoint.packageJson[property];
const formatPath = entryPointPackageJson[property];
const format = getEntryPointFormat(property);
// No format then this property is not supposed to be compiled.
if (!formatPath || !format || SUPPORTED_FORMATS.indexOf(format) === -1) continue;
if (checkMarker(entryPoint, property)) {
if (hasBeenProcessed(entryPointPackageJson, property)) {
compiledFormats.add(formatPath);
console.warn(`Skipping ${entryPoint.name} : ${property} (already compiled).`);
continue;
@ -109,7 +129,7 @@ export function mainNgcc({basePath, targetEntryPointPath,
// Either this format was just compiled or its underlying format was compiled because of a
// previous property.
if (compiledFormats.has(formatPath)) {
writeMarker(entryPoint, property);
markAsProcessed(entryPointPackageJson, entryPointPackageJsonPath, property);
}
}

View File

@ -6,10 +6,11 @@
* found in the LICENSE file at https://angular.io/license
*/
import {resolve} from 'canonical-path';
import {writeFileSync} from 'fs';
import {EntryPoint, EntryPointJsonProperty} from './entry_point';
import {AbsoluteFsPath} from '../../../src/ngtsc/path';
import {EntryPointJsonProperty, EntryPointPackageJson} from './entry_point';
export const NGCC_VERSION = '0.0.0-PLACEHOLDER';
@ -25,36 +26,19 @@ export const NGCC_VERSION = '0.0.0-PLACEHOLDER';
* @throws Error if the `packageJson` property is not an object.
* @throws Error if the entry-point has already been processed with a different ngcc version.
*/
export function hasBeenProcessed(packageJson: any, format: string): boolean {
if (typeof packageJson !== 'object') {
throw new Error('`packageJson` parameter is invalid. It parameter must be an object.');
}
if (!packageJson.__modified_by_ngcc__) {
export function hasBeenProcessed(
packageJson: EntryPointPackageJson, format: EntryPointJsonProperty): boolean {
if (!packageJson.__processed_by_ivy_ngcc__) {
return false;
}
if (Object.keys(packageJson.__modified_by_ngcc__)
.some(property => packageJson.__modified_by_ngcc__[property] !== NGCC_VERSION)) {
if (Object.keys(packageJson.__processed_by_ivy_ngcc__)
.some(property => packageJson.__processed_by_ivy_ngcc__ ![property] !== NGCC_VERSION)) {
throw new Error(
'The ngcc compiler has changed since the last ngcc build.\n' +
'Please completely remove `node_modules` and try again.');
}
return packageJson.__modified_by_ngcc__[format] === NGCC_VERSION;
}
/**
* Check whether there is a marker for the given entry-point and format property, indicating that
* the given bundle has already been processed.
* @param entryPoint the entry-point to check for a marker.
* @param format the property in the package.json of the format for which we are checking for a
* marker.
* @returns true if the entry-point and format have already been processed with this ngcc version.
* @throws Error if the entry-point and format have already been processed with a different ngcc
* version.
*/
export function checkMarker(entryPoint: EntryPoint, format: EntryPointJsonProperty): boolean {
const pkg = entryPoint.packageJson;
return hasBeenProcessed(pkg, format);
return packageJson.__processed_by_ivy_ngcc__[format] === NGCC_VERSION;
}
/**
@ -64,9 +48,10 @@ export function checkMarker(entryPoint: EntryPoint, format: EntryPointJsonProper
* @param entryPoint the entry-point to write a marker.
* @param format the property in the package.json of the format for which we are writing the marker.
*/
export function writeMarker(entryPoint: EntryPoint, format: EntryPointJsonProperty) {
const pkg = entryPoint.packageJson;
if (!pkg.__modified_by_ngcc__) pkg.__modified_by_ngcc__ = {};
pkg.__modified_by_ngcc__[format] = NGCC_VERSION;
writeFileSync(resolve(entryPoint.path, 'package.json'), JSON.stringify(pkg), 'utf8');
export function markAsProcessed(
packageJson: EntryPointPackageJson, packageJsonPath: AbsoluteFsPath,
format: EntryPointJsonProperty) {
if (!packageJson.__processed_by_ivy_ngcc__) packageJson.__processed_by_ivy_ngcc__ = {};
packageJson.__processed_by_ivy_ngcc__[format] = NGCC_VERSION;
writeFileSync(packageJsonPath, JSON.stringify(packageJson), 'utf8');
}

View File

@ -51,7 +51,7 @@ interface PackageJsonFormatProperties {
*/
export interface EntryPointPackageJson extends PackageJsonFormatProperties {
name: string;
__modified_by_ngcc__?: {[key: string]: string};
__processed_by_ivy_ngcc__?: {[key: string]: string};
}
export type EntryPointJsonProperty = keyof(PackageJsonFormatProperties);