Skip to content

Commit 5e354d1

Browse files
clydinvikerman
authored andcommitted
feat(@angular/cli): autodetect default package manager (#12753)
1 parent df4ee8c commit 5e354d1

File tree

5 files changed

+64
-59
lines changed

5 files changed

+64
-59
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { NodePackageDoesNotSupportSchematics } from '@angular-devkit/schematics/
1212
import { Arguments } from '../models/interface';
1313
import { SchematicCommand } from '../models/schematic-command';
1414
import { NpmInstall } from '../tasks/npm-install';
15-
import { getPackageManager } from '../utilities/config';
15+
import { getPackageManager } from '../utilities/package-manager';
1616
import { Schema as AddCommandSchema } from './add';
1717

1818
export class AddCommand extends SchematicCommand<AddCommandSchema> {
@@ -28,7 +28,7 @@ export class AddCommand extends SchematicCommand<AddCommandSchema> {
2828
return 1;
2929
}
3030

31-
const packageManager = getPackageManager();
31+
const packageManager = getPackageManager(this.workspace.root);
3232

3333
const npmInstall: NpmInstall = require('../tasks/npm-install').default;
3434

packages/angular/cli/models/schematic-command.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ import * as inquirer from 'inquirer';
3838
import * as systemPath from 'path';
3939
import { WorkspaceLoader } from '../models/workspace-loader';
4040
import {
41-
getPackageManager,
4241
getProjectByCwd,
4342
getSchematicDefaults,
4443
getWorkspace,
4544
getWorkspaceRaw,
4645
} from '../utilities/config';
4746
import { parseJsonSchemaToOptions } from '../utilities/json-schema';
47+
import { getPackageManager } from '../utilities/package-manager';
4848
import { BaseCommandOptions, Command } from './command';
4949
import { Arguments, CommandContext, CommandDescription, Option } from './interface';
5050
import { parseArguments, parseFreeFormArguments } from './parser';
@@ -255,7 +255,7 @@ export abstract class SchematicCommand<
255255
{
256256
force,
257257
dryRun,
258-
packageManager: getPackageManager(),
258+
packageManager: getPackageManager(this.workspace.root),
259259
root: normalize(this.workspace.root),
260260
},
261261
);

packages/angular/cli/utilities/check-package-manager.ts

Lines changed: 0 additions & 53 deletions
This file was deleted.

packages/angular/cli/utilities/config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ export function getProjectByCwd(workspace: experimental.workspace.Workspace): st
151151
}
152152
}
153153

154-
export function getPackageManager(): string {
154+
export function getConfiguredPackageManager(): string | null {
155155
let workspace = getWorkspace('local');
156156

157157
if (workspace) {
@@ -186,7 +186,7 @@ export function getPackageManager(): string {
186186
}
187187
}
188188

189-
return 'npm';
189+
return null;
190190
}
191191

192192
export function migrateLegacyGlobalConfig(): boolean {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
import { execSync } from 'child_process';
9+
import { existsSync } from 'fs';
10+
import { join } from 'path';
11+
import { getConfiguredPackageManager } from './config';
12+
13+
14+
export function supportsYarn(): boolean {
15+
try {
16+
execSync('yarn --version');
17+
18+
return true;
19+
} catch {
20+
return false;
21+
}
22+
}
23+
24+
export function supportsNpm(): boolean {
25+
try {
26+
execSync('npm --version');
27+
28+
return true;
29+
} catch {
30+
return false;
31+
}
32+
}
33+
34+
export function getPackageManager(root: string): string {
35+
let packageManager = getConfiguredPackageManager();
36+
if (packageManager) {
37+
return packageManager;
38+
}
39+
40+
const hasYarn = supportsYarn();
41+
const hasYarnLock = existsSync(join(root, 'yarn.lock'));
42+
const hasNpm = supportsNpm();
43+
const hasNpmLock = existsSync(join(root, 'package-lock.json'));
44+
45+
if (hasYarn && hasYarnLock && !hasNpmLock) {
46+
packageManager = 'yarn';
47+
} else if (hasNpm && hasNpmLock && !hasYarnLock) {
48+
packageManager = 'npm';
49+
} else if (hasYarn && !hasNpm) {
50+
packageManager = 'yarn';
51+
} else if (hasNpm && !hasYarn) {
52+
packageManager = 'npm';
53+
}
54+
55+
// TODO: This should eventually inform the user of ambiguous package manager usage.
56+
// Potentially with a prompt to choose and optionally set as the default.
57+
return packageManager || 'npm';
58+
}

0 commit comments

Comments
 (0)