Skip to content

feat(@angular/cli): allow to create new projects in existing directory #4901

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
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
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'));
}