diff --git a/packages/angular-cli/addon/index.js b/packages/angular-cli/addon/index.js index 8b294f9a2718..cf283cc72a50 100644 --- a/packages/angular-cli/addon/index.js +++ b/packages/angular-cli/addon/index.js @@ -9,7 +9,8 @@ module.exports = { config: function () { this.project.ngConfigObj = this.project.ngConfigObj || config.CliConfig.fromProject(); - this.project.ngConfig = this.project.ngConfig || this.project.ngConfigObj.config; + this.project.ngConfig = this.project.ngConfig || ( + this.project.ngConfigObj && this.project.ngConfigObj.config); }, blueprintsPath: function () { diff --git a/packages/angular-cli/commands/get.ts b/packages/angular-cli/commands/get.ts index 87220310d4fb..04e9af4df4d2 100644 --- a/packages/angular-cli/commands/get.ts +++ b/packages/angular-cli/commands/get.ts @@ -1,22 +1,36 @@ -import * as chalk from 'chalk'; import {CliConfig} from '../models/config'; +const SilentError = require('silent-error'); const Command = require('../ember-cli/lib/models/command'); + +export interface GetOptions { + global?: boolean; +} + + const GetCommand = Command.extend({ name: 'get', description: 'Get a value from the configuration.', works: 'everywhere', - availableOptions: [], + availableOptions: [ + { name: 'global', type: Boolean, 'default': false } + ], - run: function (commandOptions: any, rawArgs: string[]): Promise { + run: function (commandOptions: GetOptions, rawArgs: string[]): Promise { return new Promise(resolve => { - const config = CliConfig.fromProject(); + const config = commandOptions.global ? CliConfig.fromGlobal() : CliConfig.fromProject(); + + if (config === null) { + throw new SilentError('No config found. If you want to use global configuration, ' + + 'you need the --global argument.'); + } + const value = config.get(rawArgs[0]); - if (value === null) { - console.error(chalk.red('Value cannot be found.')); + if (value === null || value === undefined) { + throw new SilentError('Value cannot be found.'); } else if (typeof value == 'object') { console.log(JSON.stringify(value)); } else { diff --git a/packages/angular-cli/commands/set.ts b/packages/angular-cli/commands/set.ts index a89184980e1d..52a38f0c3637 100644 --- a/packages/angular-cli/commands/set.ts +++ b/packages/angular-cli/commands/set.ts @@ -1,6 +1,12 @@ +import {CliConfig} from '../models/config'; + const SilentError = require('silent-error'); const Command = require('../ember-cli/lib/models/command'); -import {CliConfig} from '../models/config'; + + +export interface SetOptions { + global?: boolean; +} const SetCommand = Command.extend({ @@ -9,7 +15,7 @@ const SetCommand = Command.extend({ works: 'everywhere', availableOptions: [ - { name: 'global', type: Boolean, default: false, aliases: ['g'] }, + { name: 'global', type: Boolean, 'default': false, aliases: ['g'] }, ], asBoolean: function (raw: string): boolean { @@ -28,13 +34,25 @@ const SetCommand = Command.extend({ return +raw; }, - run: function (commandOptions: any, rawArgs: string[]): Promise { + run: function (commandOptions: SetOptions, rawArgs: string[]): Promise { return new Promise(resolve => { - const [jsonPath, rawValue] = rawArgs; - const config = CliConfig.fromProject(); + const config = commandOptions.global ? CliConfig.fromGlobal() : CliConfig.fromProject(); + if (config === null) { + throw new SilentError('No config found. If you want to use global configuration, ' + + 'you need the --global argument.'); + } + + let [jsonPath, rawValue] = rawArgs; + + if (rawValue === undefined) { + [jsonPath, rawValue] = jsonPath.split('=', 2); + if (rawValue === undefined) { + throw new SilentError('Must specify a value.'); + } + } + const type = config.typeOf(jsonPath); let value: any = rawValue; - switch (type) { case 'boolean': value = this.asBoolean(rawValue); break; case 'number': value = this.asNumber(rawValue); break; diff --git a/packages/angular-cli/ember-cli/lib/tasks.js b/packages/angular-cli/ember-cli/lib/tasks.js index efb5b22acbaf..3fc3b2a34b22 100644 --- a/packages/angular-cli/ember-cli/lib/tasks.js +++ b/packages/angular-cli/ember-cli/lib/tasks.js @@ -7,5 +7,4 @@ module.exports = { InstallBlueprint: require('./tasks/install-blueprint'), NpmInstall: require('./tasks/npm-install'), NpmTask: require('./tasks/npm-task'), - NpmUninstall: require('./tasks/npm-uninstall'), }; diff --git a/packages/angular-cli/ember-cli/lib/tasks/npm-uninstall.js b/packages/angular-cli/ember-cli/lib/tasks/npm-uninstall.js deleted file mode 100644 index 79db8f8a0ace..000000000000 --- a/packages/angular-cli/ember-cli/lib/tasks/npm-uninstall.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -// Runs `npm uninstall` in cwd - -var NpmTask = require('./npm-task'); - -module.exports = NpmTask.extend({ - command: 'uninstall', - startProgressMessage: 'Uninstalling packages for tooling via npm', - completionMessage: 'Uninstalled packages for tooling via npm.' -}); diff --git a/packages/angular-cli/models/config.ts b/packages/angular-cli/models/config.ts index f98e113f070a..cd7d136cd2a8 100644 --- a/packages/angular-cli/models/config.ts +++ b/packages/angular-cli/models/config.ts @@ -16,6 +16,11 @@ function _findUp(name: string, from: string) { return p; } + const nodeModuleP = path.join(currentDir, 'node_modules'); + if (fs.existsSync(nodeModuleP)) { + return null; + } + currentDir = path.dirname(currentDir); } @@ -24,7 +29,7 @@ function _findUp(name: string, from: string) { function getUserHome() { - return process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME']; + return process.env[(process.platform.startsWith('win')) ? 'USERPROFILE' : 'HOME']; } @@ -37,13 +42,34 @@ export class CliConfig extends CliConfigBase { || _findUp(CLI_CONFIG_FILE_NAME, __dirname); } + static fromGlobal(): CliConfig { + const globalConfigPath = path.join(getUserHome(), CLI_CONFIG_FILE_NAME); + + const cliConfig = CliConfigBase.fromConfigPath(globalConfigPath); + + const aliases = [ + cliConfig.alias('apps.0.root', 'defaults.sourceDir'), + cliConfig.alias('apps.0.prefix', 'defaults.prefix') + ]; + + // If any of them returned true, output a deprecation warning. + if (aliases.some(x => !!x)) { + console.error(chalk.yellow(oneLine` + The "defaults.prefix" and "defaults.sourceDir" properties of angular-cli.json + are deprecated in favor of "apps[0].root" and "apps[0].prefix".\n + Please update in order to avoid errors in future versions of angular-cli. + `)); + } + + return cliConfig; + } static fromProject(): CliConfig { const configPath = this.configFilePath(); const globalConfigPath = path.join(getUserHome(), CLI_CONFIG_FILE_NAME); if (!configPath) { - return CliConfigBase.fromJson({}); + return null; } const cliConfig = CliConfigBase.fromConfigPath( diff --git a/packages/angular-cli/models/config/config.ts b/packages/angular-cli/models/config/config.ts index ba98d5398e2d..37290ed3808d 100644 --- a/packages/angular-cli/models/config/config.ts +++ b/packages/angular-cli/models/config/config.ts @@ -69,7 +69,9 @@ export class CliConfig { } static fromConfigPath(configPath: string, otherPath: string[] = []): CliConfig { - const configContent = fs.readFileSync(configPath, 'utf-8'); + const configContent = fs.existsSync(configPath) + ? fs.readFileSync(configPath, 'utf-8') + : '{}'; const schemaContent = fs.readFileSync(DEFAULT_CONFIG_SCHEMA_PATH, 'utf-8'); const otherContents = otherPath .map(path => fs.existsSync(path) && fs.readFileSync(path, 'utf-8')) diff --git a/tests/e2e/tests/commands/config/get.ts b/tests/e2e/tests/commands/config/get.ts new file mode 100644 index 000000000000..ef454b44a7db --- /dev/null +++ b/tests/e2e/tests/commands/config/get.ts @@ -0,0 +1,26 @@ +import {ng, silentNg} from '../../../utils/process'; +import {expectToFail} from '../../../utils/utils'; + + +export default function() { + return Promise.resolve() + .then(() => process.chdir('/')) + .then(() => expectToFail(() => ng('get', 'defaults.inline.style'))) + .then(() => ng('get', '--global', 'defaults.inline.style')) + .then(output => { + if (!output.match(/false\n?/)) { + throw new Error(`Expected "false", received "${JSON.stringify(output)}".`); + } + }) + .then(() => expectToFail(() => { + return ng('set', '--global', 'defaults.inline.style', 'INVALID_BOOLEAN'); + })) + .then(() => ng('set', '--global', 'defaults.inline.style', 'true')) + .then(() => ng('get', '--global', 'defaults.inline.style')) + .then(output => { + if (!output.match(/true\n?/)) { + throw new Error(`Expected "true", received "${JSON.stringify(output)}".`); + } + }) + .then(() => ng('set', '--global', 'defaults.inline.style', 'false')); +} diff --git a/tests/e2e_runner.ts b/tests/e2e_runner.ts index 4f97a80cc955..6dded9b0cd44 100644 --- a/tests/e2e_runner.ts +++ b/tests/e2e_runner.ts @@ -133,7 +133,6 @@ testsToRun.reduce((previous, relativeName) => { .then(() => fn(() => clean = false)) .then(() => ConsoleLoggerStack.pop(), (err: any) => { ConsoleLoggerStack.pop(); throw err; }) .then(() => console.log('----')) - .then(() => { ConsoleLoggerStack.push(NullLogger); }) .then(() => { // If we're not in a setup, change the directory back to where it was before the test. // This allows tests to chdir without worrying about keeping the original directory. @@ -145,10 +144,14 @@ testsToRun.reduce((previous, relativeName) => { // Only clean after a real test, not a setup step. Also skip cleaning if the test // requested an exception. if (allSetups.indexOf(relativeName) == -1 && clean) { - return gitClean(); + ConsoleLoggerStack.push(NullLogger); + return gitClean() + .then(() => ConsoleLoggerStack.pop(), (err: any) => { + ConsoleLoggerStack.pop(); + throw err; + }); } }) - .then(() => ConsoleLoggerStack.pop(), (err: any) => { ConsoleLoggerStack.pop(); throw err; }) .then(() => printFooter(currentFileName, start), (err) => { printFooter(currentFileName, start);