Skip to content

Commit 2565077

Browse files
clydinKeen Yee Liau
authored and
Keen Yee Liau
committed
fix(@angular/cli): correctly account for linked packages in update
Fixes #15511 Fixes #15294
1 parent 1824fc0 commit 2565077

File tree

3 files changed

+53
-56
lines changed

3 files changed

+53
-56
lines changed

packages/angular/cli/commands/update-impl.ts

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,10 @@ import { getPackageManager } from '../utilities/package-manager';
2020
import {
2121
PackageIdentifier,
2222
PackageManifest,
23+
PackageMetadata,
2324
fetchPackageMetadata,
2425
} from '../utilities/package-metadata';
25-
import {
26-
PackageTreeActual,
27-
findNodeDependencies,
28-
readPackageTree,
29-
} from '../utilities/package-tree';
26+
import { PackageTreeNode, findNodeDependencies, readPackageTree } from '../utilities/package-tree';
3027
import { Schema as UpdateCommandSchema } from './update';
3128

3229
const npa = require('npm-package-arg');
@@ -311,26 +308,26 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
311308
}
312309

313310
const packageName = packages[0].name;
314-
let packageNode = rootDependencies[packageName];
315-
if (typeof packageNode === 'string') {
311+
const packageDependency = rootDependencies[packageName];
312+
let packageNode = packageDependency && packageDependency.node;
313+
if (packageDependency && !packageNode) {
316314
this.logger.error('Package found in package.json but is not installed.');
317315

318316
return 1;
319-
} else if (!packageNode) {
317+
} else if (!packageDependency) {
320318
// Allow running migrations on transitively installed dependencies
321319
// There can technically be nested multiple versions
322320
// TODO: If multiple, this should find all versions and ask which one to use
323321
const child = packageTree.children.find(c => c.name === packageName);
324322
if (child) {
325-
// A link represents a symlinked package so use the actual in this case
326-
packageNode = child.isLink ? child.target : child;
323+
packageNode = child;
327324
}
325+
}
328326

329-
if (!packageNode) {
330-
this.logger.error('Package is not installed.');
327+
if (!packageNode) {
328+
this.logger.error('Package is not installed.');
331329

332-
return 1;
333-
}
330+
return 1;
334331
}
335332

336333
const updateMetadata = packageNode.package['ng-update'];
@@ -399,12 +396,12 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
399396

400397
const requests: {
401398
identifier: PackageIdentifier;
402-
node: PackageTreeActual | string;
399+
node: PackageTreeNode | string;
403400
}[] = [];
404401

405402
// Validate packages actually are part of the workspace
406403
for (const pkg of packages) {
407-
const node = rootDependencies[pkg.name];
404+
const node = rootDependencies[pkg.name] && rootDependencies[pkg.name].node;
408405
if (!node) {
409406
this.logger.error(`Package '${pkg.name}' is not a dependency.`);
410407

packages/angular/cli/utilities/package-metadata.ts

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,10 @@ export interface PackageManifest {
4040
peerDependencies: PackageDependencies;
4141
optionalDependencies: PackageDependencies;
4242

43-
'ng-add'?: {
44-
45-
};
43+
'ng-add'?: {};
4644
'ng-update'?: {
47-
migrations: string,
48-
packageGroup: { [name: string]: string },
45+
migrations: string;
46+
packageGroup: { [name: string]: string };
4947
};
5048
}
5149

@@ -61,12 +59,12 @@ function ensureNpmrc(logger: logging.LoggerApi, usingYarn: boolean, verbose: boo
6159
if (!npmrc) {
6260
try {
6361
npmrc = readOptions(logger, false, verbose);
64-
} catch { }
62+
} catch {}
6563

6664
if (usingYarn) {
6765
try {
6866
npmrc = { ...npmrc, ...readOptions(logger, true, verbose) };
69-
} catch { }
67+
} catch {}
7068
}
7169
}
7270
}
@@ -95,9 +93,7 @@ function readOptions(
9593
(!yarn && process.env.NPM_CONFIG_USERCONFIG) || path.join(homedir(), dotFilename),
9694
];
9795

98-
const projectConfigLocations: string[] = [
99-
path.join(cwd, dotFilename),
100-
];
96+
const projectConfigLocations: string[] = [path.join(cwd, dotFilename)];
10197
const root = path.parse(cwd).root;
10298
for (let curDir = path.dirname(cwd); curDir && curDir !== root; curDir = path.dirname(curDir)) {
10399
projectConfigLocations.unshift(path.join(curDir, dotFilename));
@@ -125,7 +121,7 @@ function readOptions(
125121
delete options.cafile;
126122
try {
127123
options.ca = readFileSync(cafile, 'utf8').replace(/\r?\n/, '\\n');
128-
} catch { }
124+
} catch {}
129125
}
130126
} else if (showPotentials) {
131127
logger.info(`Trying '${location}'...not found.`);
@@ -151,7 +147,7 @@ function normalizeManifest(rawManifest: {}): PackageManifest {
151147
peerDependencies: {},
152148
optionalDependencies: {},
153149
// tslint:disable-next-line:no-any
154-
...rawManifest as any,
150+
...(rawManifest as any),
155151
};
156152
}
157153

@@ -173,14 +169,11 @@ export async function fetchPackageMetadata(
173169

174170
ensureNpmrc(logger, usingYarn, verbose);
175171

176-
const response = await pacote.packument(
177-
name,
178-
{
179-
'full-metadata': true,
180-
...npmrc,
181-
...(registry ? { registry } : {}),
182-
},
183-
);
172+
const response = await pacote.packument(name, {
173+
'full-metadata': true,
174+
...npmrc,
175+
...(registry ? { registry } : {}),
176+
});
184177

185178
// Normalize the response
186179
const metadata: PackageMetadata = {
@@ -227,14 +220,11 @@ export async function fetchPackageManifest(
227220

228221
ensureNpmrc(logger, usingYarn, verbose);
229222

230-
const response = await pacote.manifest(
231-
name,
232-
{
233-
'full-metadata': true,
234-
...npmrc,
235-
...(registry ? { registry } : {}),
236-
},
237-
);
223+
const response = await pacote.manifest(name, {
224+
'full-metadata': true,
225+
...npmrc,
226+
...(registry ? { registry } : {}),
227+
});
238228

239229
return normalizeManifest(response);
240230
}

packages/angular/cli/utilities/package-tree.ts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,21 @@ export interface PackageTreeNodeBase {
1818
dependencies?: Record<string, string>;
1919
devDependencies?: Record<string, string>;
2020
peerDependencies?: Record<string, string>;
21+
optionalDependencies?: Record<string, string>;
2122
'ng-update'?: {
2223
migrations?: string;
2324
};
2425
};
26+
parent?: PackageTreeNode;
2527
children: PackageTreeNode[];
2628
}
2729

2830
export interface PackageTreeActual extends PackageTreeNodeBase {
2931
isLink: false;
30-
parent?: PackageTreeActual;
3132
}
3233

3334
export interface PackageTreeLink extends PackageTreeNodeBase {
3435
isLink: true;
35-
parent: null;
3636
target: PackageTreeActual;
3737
}
3838

@@ -52,25 +52,35 @@ export function readPackageTree(path: string): Promise<PackageTreeNode> {
5252
});
5353
}
5454

55-
export function findNodeDependencies(root: PackageTreeNode, node = root) {
56-
const actual = node.isLink ? node.target : node;
55+
export interface NodeDependency {
56+
version: string;
57+
node?: PackageTreeNode;
58+
}
5759

60+
export function findNodeDependencies(node: PackageTreeNode) {
5861
const rawDeps: Record<string, string> = {
59-
...actual.package.dependencies,
60-
...actual.package.devDependencies,
61-
...actual.package.peerDependencies,
62+
...node.package.dependencies,
63+
...node.package.devDependencies,
64+
...node.package.peerDependencies,
65+
...node.package.optionalDependencies,
6266
};
6367

6468
return Object.entries(rawDeps).reduce(
6569
(deps, [name, version]) => {
66-
const depNode = root.children.find(child => {
67-
return child.name === name && !child.isLink && child.parent === node;
68-
}) as PackageTreeActual | undefined;
70+
let dependencyNode;
71+
let parent: PackageTreeNode | undefined | null = node;
72+
while (!dependencyNode && parent) {
73+
dependencyNode = parent.children.find(child => child.name === name);
74+
parent = parent.parent;
75+
}
6976

70-
deps[name] = depNode || version;
77+
deps[name] = {
78+
node: dependencyNode,
79+
version,
80+
};
7181

7282
return deps;
7383
},
74-
{} as Record<string, string | PackageTreeActual | undefined>,
84+
Object.create(null) as Record<string, NodeDependency>,
7585
);
7686
}

0 commit comments

Comments
 (0)