Skip to content

Commit 088ebf0

Browse files
authored
fix(get/set): Add support for global configuration. (#4074)
If we dont find the local one, we error now. If we get/set with --global, we properly do the right thing.
1 parent e91552f commit 088ebf0

File tree

9 files changed

+109
-31
lines changed

9 files changed

+109
-31
lines changed

packages/angular-cli/addon/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ module.exports = {
99

1010
config: function () {
1111
this.project.ngConfigObj = this.project.ngConfigObj || config.CliConfig.fromProject();
12-
this.project.ngConfig = this.project.ngConfig || this.project.ngConfigObj.config;
12+
this.project.ngConfig = this.project.ngConfig || (
13+
this.project.ngConfigObj && this.project.ngConfigObj.config);
1314
},
1415

1516
blueprintsPath: function () {

packages/angular-cli/commands/get.ts

+20-6
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,36 @@
1-
import * as chalk from 'chalk';
21
import {CliConfig} from '../models/config';
32

3+
const SilentError = require('silent-error');
44
const Command = require('../ember-cli/lib/models/command');
55

6+
7+
export interface GetOptions {
8+
global?: boolean;
9+
}
10+
11+
612
const GetCommand = Command.extend({
713
name: 'get',
814
description: 'Get a value from the configuration.',
915
works: 'everywhere',
1016

11-
availableOptions: [],
17+
availableOptions: [
18+
{ name: 'global', type: Boolean, 'default': false }
19+
],
1220

13-
run: function (commandOptions: any, rawArgs: string[]): Promise<void> {
21+
run: function (commandOptions: GetOptions, rawArgs: string[]): Promise<void> {
1422
return new Promise<void>(resolve => {
15-
const config = CliConfig.fromProject();
23+
const config = commandOptions.global ? CliConfig.fromGlobal() : CliConfig.fromProject();
24+
25+
if (config === null) {
26+
throw new SilentError('No config found. If you want to use global configuration, '
27+
+ 'you need the --global argument.');
28+
}
29+
1630
const value = config.get(rawArgs[0]);
1731

18-
if (value === null) {
19-
console.error(chalk.red('Value cannot be found.'));
32+
if (value === null || value === undefined) {
33+
throw new SilentError('Value cannot be found.');
2034
} else if (typeof value == 'object') {
2135
console.log(JSON.stringify(value));
2236
} else {

packages/angular-cli/commands/set.ts

+24-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1+
import {CliConfig} from '../models/config';
2+
13
const SilentError = require('silent-error');
24
const Command = require('../ember-cli/lib/models/command');
3-
import {CliConfig} from '../models/config';
5+
6+
7+
export interface SetOptions {
8+
global?: boolean;
9+
}
410

511

612
const SetCommand = Command.extend({
@@ -9,7 +15,7 @@ const SetCommand = Command.extend({
915
works: 'everywhere',
1016

1117
availableOptions: [
12-
{ name: 'global', type: Boolean, default: false, aliases: ['g'] },
18+
{ name: 'global', type: Boolean, 'default': false, aliases: ['g'] },
1319
],
1420

1521
asBoolean: function (raw: string): boolean {
@@ -28,13 +34,25 @@ const SetCommand = Command.extend({
2834
return +raw;
2935
},
3036

31-
run: function (commandOptions: any, rawArgs: string[]): Promise<void> {
37+
run: function (commandOptions: SetOptions, rawArgs: string[]): Promise<void> {
3238
return new Promise<void>(resolve => {
33-
const [jsonPath, rawValue] = rawArgs;
34-
const config = CliConfig.fromProject();
39+
const config = commandOptions.global ? CliConfig.fromGlobal() : CliConfig.fromProject();
40+
if (config === null) {
41+
throw new SilentError('No config found. If you want to use global configuration, '
42+
+ 'you need the --global argument.');
43+
}
44+
45+
let [jsonPath, rawValue] = rawArgs;
46+
47+
if (rawValue === undefined) {
48+
[jsonPath, rawValue] = jsonPath.split('=', 2);
49+
if (rawValue === undefined) {
50+
throw new SilentError('Must specify a value.');
51+
}
52+
}
53+
3554
const type = config.typeOf(jsonPath);
3655
let value: any = rawValue;
37-
3856
switch (type) {
3957
case 'boolean': value = this.asBoolean(rawValue); break;
4058
case 'number': value = this.asNumber(rawValue); break;

packages/angular-cli/ember-cli/lib/tasks.js

-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,4 @@ module.exports = {
77
InstallBlueprint: require('./tasks/install-blueprint'),
88
NpmInstall: require('./tasks/npm-install'),
99
NpmTask: require('./tasks/npm-task'),
10-
NpmUninstall: require('./tasks/npm-uninstall'),
1110
};

packages/angular-cli/ember-cli/lib/tasks/npm-uninstall.js

-11
This file was deleted.

packages/angular-cli/models/config.ts

+28-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ function _findUp(name: string, from: string) {
1616
return p;
1717
}
1818

19+
const nodeModuleP = path.join(currentDir, 'node_modules');
20+
if (fs.existsSync(nodeModuleP)) {
21+
return null;
22+
}
23+
1924
currentDir = path.dirname(currentDir);
2025
}
2126

@@ -24,7 +29,7 @@ function _findUp(name: string, from: string) {
2429

2530

2631
function getUserHome() {
27-
return process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'];
32+
return process.env[(process.platform.startsWith('win')) ? 'USERPROFILE' : 'HOME'];
2833
}
2934

3035

@@ -37,13 +42,34 @@ export class CliConfig extends CliConfigBase<ConfigInterface> {
3742
|| _findUp(CLI_CONFIG_FILE_NAME, __dirname);
3843
}
3944

45+
static fromGlobal(): CliConfig {
46+
const globalConfigPath = path.join(getUserHome(), CLI_CONFIG_FILE_NAME);
47+
48+
const cliConfig = CliConfigBase.fromConfigPath<ConfigInterface>(globalConfigPath);
49+
50+
const aliases = [
51+
cliConfig.alias('apps.0.root', 'defaults.sourceDir'),
52+
cliConfig.alias('apps.0.prefix', 'defaults.prefix')
53+
];
54+
55+
// If any of them returned true, output a deprecation warning.
56+
if (aliases.some(x => !!x)) {
57+
console.error(chalk.yellow(oneLine`
58+
The "defaults.prefix" and "defaults.sourceDir" properties of angular-cli.json
59+
are deprecated in favor of "apps[0].root" and "apps[0].prefix".\n
60+
Please update in order to avoid errors in future versions of angular-cli.
61+
`));
62+
}
63+
64+
return cliConfig;
65+
}
4066

4167
static fromProject(): CliConfig {
4268
const configPath = this.configFilePath();
4369
const globalConfigPath = path.join(getUserHome(), CLI_CONFIG_FILE_NAME);
4470

4571
if (!configPath) {
46-
return CliConfigBase.fromJson<ConfigInterface>({});
72+
return null;
4773
}
4874

4975
const cliConfig = CliConfigBase.fromConfigPath<ConfigInterface>(

packages/angular-cli/models/config/config.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ export class CliConfig<JsonType> {
6969
}
7070

7171
static fromConfigPath<T>(configPath: string, otherPath: string[] = []): CliConfig<T> {
72-
const configContent = fs.readFileSync(configPath, 'utf-8');
72+
const configContent = fs.existsSync(configPath)
73+
? fs.readFileSync(configPath, 'utf-8')
74+
: '{}';
7375
const schemaContent = fs.readFileSync(DEFAULT_CONFIG_SCHEMA_PATH, 'utf-8');
7476
const otherContents = otherPath
7577
.map(path => fs.existsSync(path) && fs.readFileSync(path, 'utf-8'))
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import {ng, silentNg} from '../../../utils/process';
2+
import {expectToFail} from '../../../utils/utils';
3+
4+
5+
export default function() {
6+
return Promise.resolve()
7+
.then(() => process.chdir('/'))
8+
.then(() => expectToFail(() => ng('get', 'defaults.inline.style')))
9+
.then(() => ng('get', '--global', 'defaults.inline.style'))
10+
.then(output => {
11+
if (!output.match(/false\n?/)) {
12+
throw new Error(`Expected "false", received "${JSON.stringify(output)}".`);
13+
}
14+
})
15+
.then(() => expectToFail(() => {
16+
return ng('set', '--global', 'defaults.inline.style', 'INVALID_BOOLEAN');
17+
}))
18+
.then(() => ng('set', '--global', 'defaults.inline.style', 'true'))
19+
.then(() => ng('get', '--global', 'defaults.inline.style'))
20+
.then(output => {
21+
if (!output.match(/true\n?/)) {
22+
throw new Error(`Expected "true", received "${JSON.stringify(output)}".`);
23+
}
24+
})
25+
.then(() => ng('set', '--global', 'defaults.inline.style', 'false'));
26+
}

tests/e2e_runner.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ testsToRun.reduce((previous, relativeName) => {
133133
.then(() => fn(() => clean = false))
134134
.then(() => ConsoleLoggerStack.pop(), (err: any) => { ConsoleLoggerStack.pop(); throw err; })
135135
.then(() => console.log('----'))
136-
.then(() => { ConsoleLoggerStack.push(NullLogger); })
137136
.then(() => {
138137
// If we're not in a setup, change the directory back to where it was before the test.
139138
// This allows tests to chdir without worrying about keeping the original directory.
@@ -145,10 +144,14 @@ testsToRun.reduce((previous, relativeName) => {
145144
// Only clean after a real test, not a setup step. Also skip cleaning if the test
146145
// requested an exception.
147146
if (allSetups.indexOf(relativeName) == -1 && clean) {
148-
return gitClean();
147+
ConsoleLoggerStack.push(NullLogger);
148+
return gitClean()
149+
.then(() => ConsoleLoggerStack.pop(), (err: any) => {
150+
ConsoleLoggerStack.pop();
151+
throw err;
152+
});
149153
}
150154
})
151-
.then(() => ConsoleLoggerStack.pop(), (err: any) => { ConsoleLoggerStack.pop(); throw err; })
152155
.then(() => printFooter(currentFileName, start),
153156
(err) => {
154157
printFooter(currentFileName, start);

0 commit comments

Comments
 (0)