diff --git a/packages/@angular/cli/commands/new.ts b/packages/@angular/cli/commands/new.ts index 47af03940b3e..c4696011162b 100644 --- a/packages/@angular/cli/commands/new.ts +++ b/packages/@angular/cli/commands/new.ts @@ -1,9 +1,17 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import denodeify = require('denodeify'); + import InitCommand from './init'; +import { CliConfig } from '../models/config'; import { validateProjectName } from '../utilities/validate-project-name'; +import { oneLine } from 'common-tags'; const Command = require('../ember-cli/lib/models/command'); const Project = require('../ember-cli/lib/models/project'); const SilentError = require('silent-error'); +const mkdir = denodeify(fs.mkdir); + const NewCommand = Command.extend({ name: 'new', @@ -28,6 +36,10 @@ const NewCommand = Command.extend({ { name: 'inline-template', type: Boolean, default: false, aliases: ['it'] } ], + isProject: function (projectPath: string) { + return CliConfig.fromProject(projectPath) !== null; + }, + run: function (commandOptions: any, rawArgs: string[]) { const packageName = rawArgs.shift(); @@ -44,12 +56,8 @@ const NewCommand = Command.extend({ commandOptions.skipGit = true; } - if (!commandOptions.directory) { - commandOptions.directory = packageName; - } - - const createAndStepIntoDirectory = - new this.tasks.CreateAndStepIntoDirectory({ ui: this.ui }); + const directoryName = path.join(process.cwd(), + commandOptions.directory ? commandOptions.directory : packageName); const initCommand = new InitCommand({ ui: this.ui, @@ -57,11 +65,33 @@ const NewCommand = Command.extend({ project: Project.nullProject(this.ui, this.cli) }); - return createAndStepIntoDirectory - .run({ - directoryName: commandOptions.directory, - dryRun: commandOptions.dryRun - }) + let createDirectory; + if (commandOptions.dryRun) { + createDirectory = Promise.resolve() + .then(() => { + if (fs.existsSync(directoryName) && this.isProject(directoryName)) { + throw new SilentError(oneLine` + Directory ${directoryName} exists and is already an Angular CLI project. + `); + } + }); + } else { + createDirectory = mkdir(directoryName) + .catch(err => { + if (err.code === 'EEXIST') { + if (this.isProject(directoryName)) { + throw new SilentError(oneLine` + Directory ${directoryName} exists and is already an Angular CLI project. + `); + } + } else { + throw err; + } + }) + .then(() => process.chdir(directoryName)); + } + + return createDirectory .then(initCommand.run.bind(initCommand, commandOptions, rawArgs)); } }); diff --git a/packages/@angular/cli/ember-cli/lib/tasks.js b/packages/@angular/cli/ember-cli/lib/tasks.js index 3fc3b2a34b22..17b1ff5a576e 100644 --- a/packages/@angular/cli/ember-cli/lib/tasks.js +++ b/packages/@angular/cli/ember-cli/lib/tasks.js @@ -1,6 +1,5 @@ module.exports = { - CreateAndStepIntoDirectory: require('./tasks/create-and-step-into-directory'), DestroyFromBlueprint: require('./tasks/destroy-from-blueprint'), GenerateFromBlueprint: require('./tasks/generate-from-blueprint'), GitInit: require('./tasks/git-init'), diff --git a/packages/@angular/cli/ember-cli/lib/tasks/create-and-step-into-directory.js b/packages/@angular/cli/ember-cli/lib/tasks/create-and-step-into-directory.js deleted file mode 100644 index c853649301ec..000000000000 --- a/packages/@angular/cli/ember-cli/lib/tasks/create-and-step-into-directory.js +++ /dev/null @@ -1,55 +0,0 @@ -'use strict'; - -// Creates a directory with the name directoryName in cwd and then sets cwd to -// this directory. - -var Promise = require('../ext/promise'); -var fs = require('fs'); -var mkdir = Promise.denodeify(fs.mkdir); -var Task = require('../models/task'); -var SilentError = require('silent-error'); - -function existsSync(path) { - try { - fs.accessSync(path); - return true; - } - catch (e) { - return false; - } -} - -module.exports = Task.extend({ - // Options: String directoryName, Boolean: dryRun - - warnDirectoryAlreadyExists: function warnDirectoryAlreadyExists() { - var message = 'Directory \'' + this.directoryName + '\' already exists.'; - return new SilentError(message); - }, - - run: function(options) { - var directoryName = this.directoryName = options.directoryName; - if (options.dryRun) { - return new Promise(function(resolve, reject) { - if (existsSync(directoryName)) { - return reject(this.warnDirectoryAlreadyExists()); - } - resolve(); - }.bind(this)); - } - - return mkdir(directoryName) - .catch(function(err) { - if (err.code === 'EEXIST') { - throw this.warnDirectoryAlreadyExists(); - } else { - throw err; - } - }.bind(this)) - .then(function() { - var cwd = process.cwd(); - process.chdir(directoryName); - return { initialDirectory: cwd }; - }); - } -}); diff --git a/packages/@angular/cli/models/config.ts b/packages/@angular/cli/models/config.ts index e856e3336ae7..7f2dd328ebf5 100644 --- a/packages/@angular/cli/models/config.ts +++ b/packages/@angular/cli/models/config.ts @@ -29,13 +29,17 @@ export class CliConfig extends CliConfigBase { || findUp(CLI_CONFIG_FILE_NAME_ALT, __dirname); } - static fromGlobal(): CliConfig { + static globalConfigFilePath(): string { let globalConfigPath = path.join(getUserHome(), CLI_CONFIG_FILE_NAME); const altGlobalConfigPath = path.join(getUserHome(), CLI_CONFIG_FILE_NAME_ALT); if (!fs.existsSync(globalConfigPath) && fs.existsSync(altGlobalConfigPath)) { - globalConfigPath = altGlobalConfigPath; + return altGlobalConfigPath; } + return globalConfigPath; + } + static fromGlobal(): CliConfig { + const globalConfigPath = this.globalConfigFilePath(); const cliConfig = CliConfigBase.fromConfigPath(globalConfigPath); const aliases = [ @@ -55,7 +59,7 @@ export class CliConfig extends CliConfigBase { cliConfig.alias('defaults.component.service', 'defaults.spec.service'); // If any of them returned true, output a deprecation warning. - if (aliases.some(x => !!x)) { + 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 @@ -66,9 +70,9 @@ export class CliConfig extends CliConfigBase { return cliConfig; } - static fromProject(): CliConfig { - const configPath = this.configFilePath(); - if (!configPath) { + static fromProject(projectPath?: string): CliConfig { + const configPath = this.configFilePath(projectPath); + if (!configPath || configPath === this.globalConfigFilePath()) { return null; } @@ -78,8 +82,7 @@ export class CliConfig extends CliConfigBase { globalConfigPath = altGlobalConfigPath; } - const cliConfig = CliConfigBase.fromConfigPath( - CliConfig.configFilePath(), [globalConfigPath]); + const cliConfig = CliConfigBase.fromConfigPath(configPath, [globalConfigPath]); const aliases = [ cliConfig.alias('apps.0.root', 'defaults.sourceDir'), @@ -98,7 +101,7 @@ export class CliConfig extends CliConfigBase { cliConfig.alias('defaults.component.service', 'defaults.spec.service'); // If any of them returned true, output a deprecation warning. - if (aliases.some(x => !!x)) { + 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 diff --git a/packages/@angular/cli/utilities/find-up.ts b/packages/@angular/cli/utilities/find-up.ts index 0d54428a3659..8b4446fa4fd7 100644 --- a/packages/@angular/cli/utilities/find-up.ts +++ b/packages/@angular/cli/utilities/find-up.ts @@ -2,8 +2,10 @@ import * as path from 'path'; import { existsSync } from 'fs'; export function findUp(name: string, from: string, stopOnNodeModules = false) { + const root = path.parse(from).root; + let currentDir = from; - while (currentDir && currentDir !== path.parse(currentDir).root) { + while (currentDir && currentDir !== root) { const p = path.join(currentDir, name); if (existsSync(p)) { return p; diff --git a/tests/e2e/tests/commands/new/existing-directory.ts b/tests/e2e/tests/commands/new/existing-directory.ts new file mode 100644 index 000000000000..8563040822c8 --- /dev/null +++ b/tests/e2e/tests/commands/new/existing-directory.ts @@ -0,0 +1,15 @@ +import * as fs from 'fs'; +import denodeify = require('denodeify'); + +import {ng} from '../../../utils/process'; +import {getGlobalVariable} from '../../../utils/env'; + +const mkdir = denodeify(fs.mkdir); + + +export default function() { + return Promise.resolve() + .then(() => process.chdir(getGlobalVariable('tmp-root'))) + .then(() => mkdir('empty-directory')) + .then(() => ng('new', 'foo', '--dir=empty-directory', '--skip-install', '--skip-git')); +}