Skip to content

Commit c34db58

Browse files
clydinhansl
authored andcommitted
fix(@angular/cli): honor global config command option
1 parent 2955462 commit c34db58

File tree

4 files changed

+172
-31
lines changed

4 files changed

+172
-31
lines changed

packages/@angular/cli/commands/config.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,17 +120,18 @@ export default class ConfigCommand extends Command {
120120
public readonly description = 'Get/set configuration values.';
121121
public readonly arguments = ['jsonPath', 'value'];
122122
public readonly options: Option[] = [
123-
// {
124-
// name: 'global',
125-
// type: Boolean,
126-
// 'default': false,
127-
// aliases: ['g'],
128-
// description: 'Get/set the value in the global configuration (in your home directory).'
129-
// }
123+
{
124+
name: 'global',
125+
type: Boolean,
126+
'default': false,
127+
aliases: ['g'],
128+
description: 'Get/set the value in the global configuration (in your home directory).'
129+
}
130130
];
131131

132132
public run(options: ConfigOptions) {
133-
const config = (getWorkspace() as {} as { _workspace: WorkspaceJson});
133+
const level = options.global ? 'global' : 'local';
134+
const config = (getWorkspace(level) as {} as { _workspace: WorkspaceJson});
134135

135136
if (!config) {
136137
throw new SilentError('No config found.');
@@ -156,7 +157,7 @@ export default class ConfigCommand extends Command {
156157
}
157158

158159
private set(options: ConfigOptions) {
159-
const [config, configPath] = getWorkspaceRaw();
160+
const [config, configPath] = getWorkspaceRaw(options.global ? 'global' : 'local');
160161

161162
// TODO: Modify & save without destroying comments
162163
const configValue = config.value;

packages/@angular/cli/utilities/config.ts

Lines changed: 131 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { existsSync, writeFileSync } from 'fs';
2+
import * as os from 'os';
13
import * as path from 'path';
24
import {
35
JsonAstObject,
@@ -19,44 +21,88 @@ function getSchemaLocation(): string {
1921

2022
export const workspaceSchemaPath = getSchemaLocation();
2123

22-
function configFilePath(projectPath?: string): string | null {
23-
const configNames = [ 'angular.json', '.angular.json' ];
24+
const configNames = [ 'angular.json', '.angular.json' ];
25+
26+
function projectFilePath(projectPath?: string): string | null {
2427
// Find the configuration, either where specified, in the Angular CLI project
2528
// (if it's in node_modules) or from the current process.
2629
return (projectPath && findUp(configNames, projectPath))
2730
|| findUp(configNames, process.cwd())
2831
|| findUp(configNames, __dirname);
2932
}
3033

31-
let cachedWorkspace: experimental.workspace.Workspace | null | undefined = undefined;
32-
export function getWorkspace(): experimental.workspace.Workspace | null {
33-
if (cachedWorkspace != undefined) {
34-
return cachedWorkspace;
34+
function globalFilePath(): string | null {
35+
const home = os.homedir();
36+
if (!home) {
37+
return null;
38+
}
39+
40+
for (const name of configNames) {
41+
const p = path.join(home, name);
42+
if (existsSync(p)) {
43+
return p;
44+
}
45+
}
46+
47+
return null;
48+
}
49+
50+
const cachedWorkspaces = new Map<string, experimental.workspace.Workspace | null>();
51+
52+
export function getWorkspace(
53+
level: 'local' | 'global' = 'local',
54+
): experimental.workspace.Workspace | null {
55+
const cached = cachedWorkspaces.get(level);
56+
if (cached != undefined) {
57+
return cached;
3558
}
3659

37-
const configPath = configFilePath();
60+
let configPath = level === 'local' ? projectFilePath() : globalFilePath();
3861

3962
if (!configPath) {
40-
cachedWorkspace = null;
41-
return null;
63+
if (level === 'global') {
64+
configPath = createGlobalSettings();
65+
} else {
66+
cachedWorkspaces.set(level, null);
67+
return null;
68+
}
4269
}
4370

44-
const root = path.dirname(configPath);
71+
const root = normalize(path.dirname(configPath));
72+
const file = normalize(path.basename(configPath));
4573
const workspace = new experimental.workspace.Workspace(
46-
normalize(root),
74+
root,
4775
new NodeJsSyncHost(),
4876
);
4977

50-
workspace.loadWorkspaceFromHost(normalize(path.basename(configPath))).subscribe();
51-
cachedWorkspace = workspace;
78+
workspace.loadWorkspaceFromHost(file).subscribe();
79+
cachedWorkspaces.set(level, workspace);
5280
return workspace;
5381
}
5482

55-
export function getWorkspaceRaw(): [JsonAstObject | null, string] {
56-
const configPath = configFilePath();
83+
function createGlobalSettings(): string {
84+
const home = os.homedir();
85+
if (!home) {
86+
throw new Error('No home directory found.');
87+
}
88+
89+
const globalPath = path.join(home, configNames[1]);
90+
writeFileSync(globalPath, JSON.stringify({ version: 1 }));
91+
92+
return globalPath;
93+
}
94+
95+
export function getWorkspaceRaw(
96+
level: 'local' | 'global' = 'local',
97+
): [JsonAstObject | null, string | null] {
98+
let configPath = level === 'local' ? projectFilePath() : globalFilePath();
5799

58100
if (!configPath) {
59-
return null;
101+
if (level === 'global') {
102+
configPath = createGlobalSettings();
103+
} else {
104+
return [null, null];
105+
}
60106
}
61107

62108
let content;
@@ -89,19 +135,60 @@ export function validateWorkspace(json: JsonValue) {
89135
return true;
90136
}
91137

138+
export function getProjectByCwd(_workspace: experimental.workspace.Workspace): string | null {
139+
// const cwd = process.cwd();
140+
// TOOD: Implement project location logic
141+
return null;
142+
}
143+
92144
export function getPackageManager(): string {
93-
const workspace = getWorkspace();
145+
let workspace = getWorkspace();
146+
147+
if (workspace) {
148+
const project = getProjectByCwd(workspace);
149+
if (project && workspace.getProject(project).cli) {
150+
const value = workspace.getProject(project).cli['packageManager'];
151+
if (typeof value == 'string') {
152+
return value;
153+
}
154+
} else if (workspace.getCli()) {
155+
const value = workspace.getCli()['packageManager'];
156+
if (typeof value == 'string') {
157+
return value;
158+
}
159+
}
160+
}
161+
162+
workspace = getWorkspace('global');
94163
if (workspace && workspace.getCli()) {
95164
const value = workspace.getCli()['packageManager'];
96165
if (typeof value == 'string') {
97166
return value;
98167
}
99168
}
169+
100170
return 'npm';
101171
}
102172

103173
export function getDefaultSchematicCollection(): string {
104-
const workspace = getWorkspace();
174+
let workspace = getWorkspace('local');
175+
176+
if (workspace) {
177+
const project = getProjectByCwd(workspace);
178+
if (project && workspace.getProject(project).schematics) {
179+
const value = workspace.getProject(project).schematics['defaultCollection'];
180+
if (typeof value == 'string') {
181+
return value;
182+
}
183+
} else if (workspace.getSchematics()) {
184+
const value = workspace.getSchematics()['defaultCollection'];
185+
if (typeof value == 'string') {
186+
return value;
187+
}
188+
}
189+
}
190+
191+
workspace = getWorkspace('global');
105192
if (workspace && workspace.getSchematics()) {
106193
const value = workspace.getSchematics()['defaultCollection'];
107194
if (typeof value == 'string') {
@@ -113,13 +200,36 @@ export function getDefaultSchematicCollection(): string {
113200
}
114201

115202
export function isWarningEnabled(warning: string): boolean {
116-
const workspace = getWorkspace();
203+
let workspace = getWorkspace('local');
204+
205+
if (workspace) {
206+
const project = getProjectByCwd(workspace);
207+
if (project && workspace.getProject(project).cli) {
208+
const warnings = workspace.getProject(project).cli['warnings'];
209+
if (typeof warnings == 'object' && !Array.isArray(warnings)) {
210+
const value = warnings[warning];
211+
if (typeof value == 'boolean') {
212+
return value;
213+
}
214+
}
215+
} else if (workspace.getCli()) {
216+
const warnings = workspace.getCli()['warnings'];
217+
if (typeof warnings == 'object' && !Array.isArray(warnings)) {
218+
const value = warnings[warning];
219+
if (typeof value == 'boolean') {
220+
return value;
221+
}
222+
}
223+
}
224+
}
225+
226+
workspace = getWorkspace('global');
117227
if (workspace && workspace.getCli()) {
118228
const warnings = workspace.getCli()['warnings'];
119229
if (typeof warnings == 'object' && !Array.isArray(warnings)) {
120230
const value = warnings[warning];
121-
if (value === false) {
122-
return false;
231+
if (typeof value == 'boolean') {
232+
return value;
123233
}
124234
}
125235
}

tests/e2e/tests/commands/config/config-get.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {expectToFail} from '../../../utils/utils';
44

55
export default function() {
66
return Promise.resolve()
7-
.then(() => expectToFail(() => ng('config', 'schematics.@schematics/angular.component.inlineStyle'))
7+
.then(() => expectToFail(() => ng('config', 'schematics.@schematics/angular.component.inlineStyle')))
88
.then(() => ng('config', 'schematics.@schematics/angular.component.inlineStyle', 'false'))
99
.then(() => ng('config', 'schematics.@schematics/angular.component.inlineStyle'))
1010
.then(({ stdout }) => {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import {ng} from '../../../utils/process';
2+
import {expectToFail} from '../../../utils/utils';
3+
import { expectFileToExist } from '../../../utils/fs';
4+
import * as path from 'path';
5+
import { homedir } from 'os';
6+
7+
8+
export default function() {
9+
return Promise.resolve()
10+
.then(() => expectToFail(() => ng('config', '--global', 'schematics.@schematics/angular.component.inlineStyle')))
11+
.then(() => ng('config', '--global', 'schematics.@schematics/angular.component.inlineStyle', 'false'))
12+
.then(() => ng('config', '--global', 'schematics.@schematics/angular.component.inlineStyle'))
13+
.then(({ stdout }) => {
14+
if (!stdout.match(/false\n?/)) {
15+
throw new Error(`Expected "false", received "${JSON.stringify(stdout)}".`);
16+
}
17+
})
18+
.then(() => expectToFail(() => {
19+
return ng('config', '--global', 'schematics.@schematics/angular.component.inlineStyle', 'INVALID_BOOLEAN');
20+
}))
21+
.then(() => ng('config', '--global', 'schematics.@schematics/angular.component.inlineStyle', 'true'))
22+
.then(() => ng('config', '--global', 'schematics.@schematics/angular.component.inlineStyle'))
23+
.then(({ stdout }) => {
24+
if (!stdout.match(/true\n?/)) {
25+
throw new Error(`Expected "true", received "${JSON.stringify(stdout)}".`);
26+
}
27+
})
28+
.then(() => ng('config', '--global', 'schematics.@schematics/angular.component.inlineStyle', 'false'))
29+
.then(() => expectFileToExist(path.join(homedir(), '.angular.json')));
30+
}

0 commit comments

Comments
 (0)