Skip to content

Commit 227f30e

Browse files
committed
fix(@angular/cli): remove version command node module assumptions
This change removes all direct usage of the `node_modules` directory from the version command. This provides improved support for yarn PnP as well as prevents a crash when a workspace does not have a `node_modules` directory. Fixes #10474 (cherry picked from commit b6ea1ab)
1 parent b17dc80 commit 227f30e

File tree

1 file changed

+41
-66
lines changed

1 file changed

+41
-66
lines changed

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

Lines changed: 41 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,28 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88
import { JsonParseMode, isJsonObject, parseJson } from '@angular-devkit/core';
9-
import * as child_process from 'child_process';
109
import * as fs from 'fs';
1110
import * as path from 'path';
1211
import { Command } from '../models/command';
1312
import { colors } from '../utilities/color';
14-
import { findUp } from '../utilities/find-up';
1513
import { Schema as VersionCommandSchema } from './version';
1614

15+
interface PartialPackageInfo {
16+
name: string;
17+
version: string;
18+
dependencies?: Record<string, string>;
19+
devDependencies?: Record<string, string>;
20+
}
21+
1722
export class VersionCommand extends Command<VersionCommandSchema> {
1823
public static aliases = ['v'];
1924

2025
async run() {
21-
const pkg = require(path.resolve(__dirname, '..', 'package.json'));
22-
let projPkg;
26+
const cliPackage: PartialPackageInfo = require('../package.json');
27+
let workspacePackage: PartialPackageInfo | undefined;
2328
try {
24-
projPkg = require(path.resolve(this.workspace.root, 'package.json'));
25-
} catch {
26-
projPkg = undefined;
27-
}
29+
workspacePackage = require(path.resolve(this.workspace.root, 'package.json'));
30+
} catch {}
2831

2932
const patterns = [
3033
/^@angular\/.*/,
@@ -39,33 +42,13 @@ export class VersionCommand extends Command<VersionCommandSchema> {
3942
/^webpack$/,
4043
];
4144

42-
const maybeNodeModules = findUp('node_modules', __dirname);
43-
const packageRoot = projPkg
44-
? path.resolve(this.workspace.root, 'node_modules')
45-
: maybeNodeModules;
46-
4745
const packageNames = [
48-
...Object.keys((pkg && pkg['dependencies']) || {}),
49-
...Object.keys((pkg && pkg['devDependencies']) || {}),
50-
...Object.keys((projPkg && projPkg['dependencies']) || {}),
51-
...Object.keys((projPkg && projPkg['devDependencies']) || {}),
46+
...Object.keys(cliPackage.dependencies || {}),
47+
...Object.keys(cliPackage.devDependencies || {}),
48+
...Object.keys(workspacePackage?.dependencies || {}),
49+
...Object.keys(workspacePackage?.devDependencies || {}),
5250
];
5351

54-
if (packageRoot != null) {
55-
// Add all node_modules and node_modules/@*/*
56-
const nodePackageNames = fs.readdirSync(packageRoot).reduce<string[]>((acc, name) => {
57-
if (name.startsWith('@')) {
58-
return acc.concat(
59-
fs.readdirSync(path.resolve(packageRoot, name)).map(subName => name + '/' + subName),
60-
);
61-
} else {
62-
return acc.concat(name);
63-
}
64-
}, []);
65-
66-
packageNames.push(...nodePackageNames);
67-
}
68-
6952
const versions = packageNames
7053
.filter(x => patterns.some(p => p.test(x)))
7154
.reduce(
@@ -74,31 +57,18 @@ export class VersionCommand extends Command<VersionCommandSchema> {
7457
return acc;
7558
}
7659

77-
acc[name] = this.getVersion(name, packageRoot, maybeNodeModules);
60+
acc[name] = this.getVersion(name);
7861

7962
return acc;
8063
},
8164
{} as { [module: string]: string },
8265
);
8366

84-
let ngCliVersion = pkg.version;
85-
if (!__dirname.match(/node_modules/)) {
86-
let gitBranch = '??';
87-
try {
88-
const gitRefName = child_process.execSync('git rev-parse --abbrev-ref HEAD', {
89-
cwd: __dirname,
90-
encoding: 'utf8',
91-
stdio: 'pipe',
92-
});
93-
gitBranch = gitRefName.replace('\n', '');
94-
} catch {}
95-
96-
ngCliVersion = `local (v${pkg.version}, branch: ${gitBranch})`;
97-
}
67+
const ngCliVersion = cliPackage.version;
9868
let angularCoreVersion = '';
9969
const angularSameAsCore: string[] = [];
10070

101-
if (projPkg) {
71+
if (workspacePackage) {
10272
// Filter all angular versions that are the same as core.
10373
angularCoreVersion = versions['@angular/core'];
10474
if (angularCoreVersion) {
@@ -156,7 +126,7 @@ export class VersionCommand extends Command<VersionCommandSchema> {
156126
return acc;
157127
}, [])
158128
.join('\n... ')}
159-
Ivy Workspace: ${projPkg ? this.getIvyWorkspace() : ''}
129+
Ivy Workspace: ${workspacePackage ? this.getIvyWorkspace() : ''}
160130
161131
Package${namePad.slice(7)}Version
162132
-------${namePad.replace(/ /g, '-')}------------------
@@ -168,28 +138,33 @@ export class VersionCommand extends Command<VersionCommandSchema> {
168138
);
169139
}
170140

171-
private getVersion(
172-
moduleName: string,
173-
projectNodeModules: string | null,
174-
cliNodeModules: string | null,
175-
): string {
176-
try {
177-
if (projectNodeModules) {
178-
const modulePkg = require(path.resolve(projectNodeModules, moduleName, 'package.json'));
141+
private getVersion(moduleName: string): string {
142+
let packagePath;
143+
let cliOnly = false;
179144

180-
return modulePkg.version;
181-
}
145+
// Try to find the package in the workspace
146+
try {
147+
packagePath = require.resolve(`${moduleName}/package.json`, { paths: [ this.workspace.root ]});
182148
} catch {}
183149

184-
try {
185-
if (cliNodeModules) {
186-
const modulePkg = require(path.resolve(cliNodeModules, moduleName, 'package.json'));
150+
// If not found, try to find within the CLI
151+
if (!packagePath) {
152+
try {
153+
packagePath = require.resolve(`${moduleName}/package.json`);
154+
cliOnly = true;
155+
} catch {}
156+
}
187157

188-
return modulePkg.version + ' (cli-only)';
189-
}
190-
} catch {}
158+
let version: string | undefined;
159+
160+
// If found, attempt to get the version
161+
if (packagePath) {
162+
try {
163+
version = require(packagePath).version + (cliOnly ? ' (cli-only)' : '');
164+
} catch {}
165+
}
191166

192-
return '<error>';
167+
return version || '<error>';
193168
}
194169

195170
private getIvyWorkspace(): string {

0 commit comments

Comments
 (0)