Skip to content

Commit e67db8c

Browse files
hanslMRHarrison
authored andcommitted
fix(new): Make sure the project name is valid. (angular#3478)
1 parent 7d09422 commit e67db8c

File tree

2 files changed

+58
-25
lines changed

2 files changed

+58
-25
lines changed

packages/angular-cli/commands/new.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as chalk from 'chalk';
22
import InitCommand from './init';
3+
import {oneLine} from 'common-tags';
34

45
const Command = require('../ember-cli/lib/models/command');
56
const Project = require('../ember-cli/lib/models/project');
@@ -37,6 +38,12 @@ const NewCommand = Command.extend({
3738
`The "ng ${this.name}" command requires a name argument to be specified. ` +
3839
`For more details, use "ng help".`));
3940
}
41+
if (!packageName.match(/^[a-zA-Z][.0-9a-zA-Z]*(-[a-zA-Z][.0-9a-zA-Z]*)*$/)) {
42+
return Promise.reject(new SilentError(oneLine`
43+
Project name "${packageName}" is not valid. New project names must
44+
start with a letter, and must contain only alphanumeric characters or dashes.
45+
`));
46+
}
4047

4148
commandOptions.name = packageName;
4249
if (commandOptions.dryRun) {

tests/acceptance/new.spec.js renamed to tests/acceptance/new.spec.ts

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
'use strict';
2-
3-
var fs = require('fs-extra');
4-
var ng = require('../helpers/ng');
5-
var existsSync = require('exists-sync');
6-
var expect = require('chai').expect;
7-
var forEach = require('lodash/forEach');
8-
var walkSync = require('walk-sync');
9-
var Blueprint = require('angular-cli/ember-cli/lib/models/blueprint');
10-
var path = require('path');
11-
var tmp = require('../helpers/tmp');
12-
var root = process.cwd();
13-
var util = require('util');
14-
var EOL = require('os').EOL;
15-
var SilentError = require('silent-error');
1+
const fs = require('fs-extra');
2+
const ng = require('../helpers/ng');
3+
const existsSync = require('exists-sync');
4+
const expect = require('chai').expect;
5+
const forEach = require('lodash/forEach');
6+
const walkSync = require('walk-sync');
7+
const Blueprint = require('angular-cli/ember-cli/lib/models/blueprint');
8+
const path = require('path');
9+
const tmp = require('../helpers/tmp');
10+
const root = process.cwd();
11+
const util = require('util');
12+
const EOL = require('os').EOL;
13+
const SilentError = require('silent-error');
14+
1615

1716
describe('Acceptance: ng new', function () {
1817
beforeEach(function () {
@@ -29,10 +28,10 @@ describe('Acceptance: ng new', function () {
2928

3029
function confirmBlueprintedForDir(dir) {
3130
return function () {
32-
var blueprintPath = path.join(root, dir, 'files');
33-
var expected = walkSync(blueprintPath);
34-
var actual = walkSync('.').sort();
35-
var directory = path.basename(process.cwd());
31+
let blueprintPath = path.join(root, dir, 'files');
32+
let expected = walkSync(blueprintPath);
33+
let actual = walkSync('.').sort();
34+
let directory = path.basename(process.cwd());
3635

3736
forEach(Blueprint.renamedFiles, function (destFile, srcFile) {
3837
expected[expected.indexOf(srcFile)] = destFile;
@@ -56,6 +55,33 @@ describe('Acceptance: ng new', function () {
5655
return confirmBlueprintedForDir('blueprints/ng2');
5756
}
5857

58+
it('requires a valid name (!)', () => {
59+
return ng(['new', '!', '--skip-npm', '--skip-git', '--inline-template'])
60+
.then(() => { throw new Error(); }, () => {});
61+
});
62+
it('requires a valid name (abc-.)', () => {
63+
return ng(['new', 'abc-.', '--skip-npm', '--skip-git', '--inline-template'])
64+
.then(() => { throw new Error(); }, () => {});
65+
});
66+
it('requires a valid name (abc-)', () => {
67+
return ng(['new', 'abc-', '--skip-npm', '--skip-git', '--inline-template'])
68+
.then(() => { throw new Error(); }, () => {});
69+
});
70+
it('requires a valid name (abc-def-)', () => {
71+
return ng(['new', 'abc-def-', '--skip-npm', '--skip-git', '--inline-template'])
72+
.then(() => { throw new Error(); }, () => {});
73+
});
74+
it('requires a valid name (abc-123)', () => {
75+
return ng(['new', 'abc-123', '--skip-npm', '--skip-git', '--inline-template'])
76+
.then(() => { throw new Error(); }, () => {});
77+
});
78+
it('requires a valid name (abc)', () => {
79+
return ng(['new', 'abc', '--skip-npm', '--skip-git', '--inline-template']);
80+
});
81+
it('requires a valid name (abc-def)', () => {
82+
return ng(['new', 'abc-def', '--skip-npm', '--skip-git', '--inline-template']);
83+
});
84+
5985
it('ng new foo, where foo does not yet exist, works', function () {
6086
return ng(['new', 'foo', '--skip-npm', '--skip-bower']).then(confirmBlueprinted);
6187
});
@@ -72,7 +98,7 @@ describe('Acceptance: ng new', function () {
7298
return ng(['new', 'FooApp', '--skip-npm', '--skip-bower', '--skip-git']).then(function () {
7399
expect(!existsSync('FooApp'));
74100

75-
var pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
101+
const pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
76102
expect(pkgJson.name).to.equal('foo-app');
77103
});
78104
});
@@ -81,7 +107,7 @@ describe('Acceptance: ng new', function () {
81107
return ng(['new', 'FooApp', '--skip-npm', '--skip-bower', '--skip-git']).then(function () {
82108
expect(!existsSync('FooApp'));
83109

84-
var editorConfig = fs.readFileSync('.editorconfig', 'utf8');
110+
const editorConfig = fs.readFileSync('.editorconfig', 'utf8');
85111
expect(editorConfig).to.exist;
86112
});
87113
});
@@ -93,7 +119,7 @@ describe('Acceptance: ng new', function () {
93119
throw new SilentError('Cannot run ng new, inside of ember-cli project should fail.');
94120
}, () => {
95121
expect(!existsSync('foo'));
96-
})
122+
});
97123
})
98124
.then(confirmBlueprinted);
99125
});
@@ -106,7 +132,7 @@ describe('Acceptance: ng new', function () {
106132

107133
it('ng new with --dry-run does not create new directory', function () {
108134
return ng(['new', 'foo', '--dry-run']).then(function () {
109-
var cwd = process.cwd();
135+
const cwd = process.cwd();
110136
expect(cwd).to.not.match(/foo/, 'does not change cwd to foo in a dry run');
111137
expect(!existsSync(path.join(cwd, 'foo')), 'does not create new directory');
112138
expect(!existsSync(path.join(cwd, '.git')), 'does not create git in current directory');
@@ -116,14 +142,14 @@ describe('Acceptance: ng new', function () {
116142
it('ng new with --directory uses given directory name and has correct package name', function () {
117143
return ng(['new', 'foo', '--skip-npm', '--skip-bower', '--skip-git', '--directory=bar'])
118144
.then(function () {
119-
var cwd = process.cwd();
145+
const cwd = process.cwd();
120146
expect(cwd).to.not.match(/foo/, 'does not use app name for directory name');
121147
expect(!existsSync(path.join(cwd, 'foo')), 'does not create new directory with app name');
122148

123149
expect(cwd).to.match(/bar/, 'uses given directory name');
124150
expect(existsSync(path.join(cwd, 'bar')), 'creates new directory with specified name');
125151

126-
var pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
152+
const pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
127153
expect(pkgJson.name).to.equal('foo', 'uses app name for package name');
128154
});
129155
});

0 commit comments

Comments
 (0)