Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat(@angular/cli): allow to create new projects in existing directory
Unless the directory is already under an Angular CLI project.
  • Loading branch information
hansl committed Feb 22, 2017
commit 4ac4c32050596ca625f730ec10717355bd72f6ab
52 changes: 41 additions & 11 deletions packages/@angular/cli/commands/new.ts
Original file line number Diff line number Diff line change
@@ -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',
Expand All @@ -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();

Expand All @@ -44,24 +56,42 @@ 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,
tasks: this.tasks,
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));
}
});
Expand Down
1 change: 0 additions & 1 deletion packages/@angular/cli/ember-cli/lib/tasks.js
Original file line number Diff line number Diff line change
@@ -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'),
Expand Down

This file was deleted.

21 changes: 12 additions & 9 deletions packages/@angular/cli/models/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ export class CliConfig extends CliConfigBase<ConfigInterface> {
|| 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<ConfigInterface>(globalConfigPath);

const aliases = [
Expand All @@ -55,7 +59,7 @@ export class CliConfig extends CliConfigBase<ConfigInterface> {
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
Expand All @@ -66,9 +70,9 @@ export class CliConfig extends CliConfigBase<ConfigInterface> {
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;
}

Expand All @@ -78,8 +82,7 @@ export class CliConfig extends CliConfigBase<ConfigInterface> {
globalConfigPath = altGlobalConfigPath;
}

const cliConfig = CliConfigBase.fromConfigPath<ConfigInterface>(
CliConfig.configFilePath(), [globalConfigPath]);
const cliConfig = CliConfigBase.fromConfigPath<ConfigInterface>(configPath, [globalConfigPath]);

const aliases = [
cliConfig.alias('apps.0.root', 'defaults.sourceDir'),
Expand All @@ -98,7 +101,7 @@ export class CliConfig extends CliConfigBase<ConfigInterface> {
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
Expand Down
4 changes: 3 additions & 1 deletion packages/@angular/cli/utilities/find-up.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
15 changes: 15 additions & 0 deletions tests/e2e/tests/commands/new/existing-directory.ts
Original file line number Diff line number Diff line change
@@ -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'));
}