Skip to content

Commit

Permalink
Git based app blueprints
Browse files Browse the repository at this point in the history
Extends `ember new'`s --blueprint option to accept git remotes in
either git@someservice.com:app-blueprint-test.git or
https://someservice.com/trek/app-blueprint-test.git style git remote
urls.
  • Loading branch information
trek committed Sep 28, 2014
1 parent ee901ce commit 37564dd
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 14 deletions.
5 changes: 2 additions & 3 deletions lib/commands/new.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
'use strict';

var chalk = require('chalk');
var path = require('path');
var Command = require('../models/command');
var Promise = require('../ext/promise');
var path = require('path');
var NULL_PROJECT = require('../models/project').NULL_PROJECT;

var SilentError = require('../errors/silent');
var validProjectName = require('../utilities/valid-project-name');

Expand All @@ -17,7 +16,7 @@ module.exports = Command.extend({
availableOptions: [
{ name: 'dry-run', type: Boolean, default: false },
{ name: 'verbose', type: Boolean, default: false },
{ name: 'blueprint', type: path, default: 'app' },
{ name: 'blueprint', type: ['gitUrl', path], default: 'app' },
{ name: 'skip-npm', type: Boolean, default: false },
{ name: 'skip-bower', type: Boolean, default: false },
{ name: 'skip-git', type: Boolean, default: false },
Expand Down
14 changes: 14 additions & 0 deletions lib/models/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var chalk = require('chalk');
var path = require('path');
var camelize = require('../utilities/string').camelize;
var getCallerFile = require('../utilities/get-caller-file');
var isGitRepo = require('../utilities/git-repo');
var Promise = require('../ext/promise');
var defaults = require('lodash-node/modern/objects/defaults');
var EOL = require('os').EOL;
Expand All @@ -16,6 +17,19 @@ var allowedWorkOptions = {
everywhere: true
};

// extend nopt to recognize 'gitUrl' as a type
nopt.typeDefs.gitUrl = {
type: 'gitUrl',
validate: function(data, k, val){
if(isGitRepo(val)) {
data[k] = val;
return true;
} else {
return false;
}
}
};

module.exports = Command;

function Command() {
Expand Down
45 changes: 34 additions & 11 deletions lib/tasks/install-blueprint.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
'use strict';

var Blueprint = require('../models/blueprint');
var Task = require('../models/task');
var Blueprint = require('../models/blueprint');
var Task = require('../models/task');
var isGitRepo = require('../utilities/git-repo');
var RSVP = require('rsvp');
var temp = require('temp');
var childProcess = require('child_process');
var path = require('path');

// Automatically track and cleanup temp files at exit
temp.track();

var mkdir = RSVP.denodeify(temp.mkdir);
var exec = RSVP.denodeify(childProcess.exec);

module.exports = Task.extend({
run: function(options) {
var cwd = process.cwd();
var name = options.rawName;
var blueprintName = options.blueprint || 'app';
var path = require('path');
var cwd = process.cwd();
var name = options.rawName;
var blueprintOption = options.blueprint;
// If we're in a dry run, pretend we changed directories.
// Pretending we cd'd avoids prompts in the actual current directory.
var fakeCwd = path.join(process.cwd(), name);
var target = options.dryRun ? fakeCwd : cwd;

var blueprint = Blueprint.lookup(blueprintName);
var fakeCwd = path.join(process.cwd(), name);
var target = options.dryRun ? fakeCwd : cwd;

var installOptions = {
target: target,
Expand All @@ -25,6 +33,21 @@ module.exports = Task.extend({
dryRun: options.dryRun
};

return blueprint.install(installOptions);
if (isGitRepo(blueprintOption)) {
return mkdir('ember-cli').then(function(pathName){
var execArgs = ['git', 'clone', blueprintOption, pathName].join(' ');
return exec(execArgs).then(function(){
return exec('npm install', {cwd: pathName}).then(function(){
var blueprint = Blueprint.load(pathName);
return blueprint.install(installOptions);
});
});
});
} else {
var blueprintName = blueprintOption || 'app';
var blueprint = Blueprint.lookup(blueprintName);

return blueprint.install(installOptions);
}
}
});
8 changes: 8 additions & 0 deletions lib/utilities/git-repo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict';

// Detect if the string refers to a remote git repo.
// Proably a bit janky, but borrowed from Bower,
// so it's at least a Known Trick.
module.exports = function(str){
return (/^git(\+(ssh|https?))?:\/\//i).test(str) || (/\.git\/?$/i).test(str) || (/^git@/i).test(str);
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
"rimraf": "^2.2.8",
"rsvp": "^3.0.13",
"semver": "^3.0.1",
"temp": "0.8.1",
"testem": "0.6.19",
"through": "^2.3.4",
"tiny-lr": "0.1.4",
Expand Down
14 changes: 14 additions & 0 deletions tests/acceptance/blueprint-test-slow.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var fs = require('fs');
var ncp = Promise.denodeify(require('ncp'));
var assert = require('assert');

var ember = require('../helpers/ember');
var buildApp = require('../helpers/build-app');
var runCommand = require('../helpers/run-command');

Expand Down Expand Up @@ -64,6 +65,19 @@ describe('Acceptance: blueprint smoke tests', function() {
return tmp.teardown('./tmp');
});

it('ember new with git blueprint uses checks out the blueprint and uses it', function(){
return ember([
'new',
'foo',
'--skip-npm',
'--skip-bower',
'--skip-git',
'--blueprint=https://github.com/trek/app-blueprint-test.git'
]).then(function() {
assert(fs.existsSync('.ember-cli'));
});
});

it('generating an http-proxy installs packages to package.json', function() {
console.log(' running the slow end-to-end it will take some time');

Expand Down
16 changes: 16 additions & 0 deletions tests/acceptance/new-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,22 @@ describe('Acceptance: ember new', function() {
.then(confirmBlueprintedForDir('tmp/my_blueprint'));
});


it('ember new with git blueprint uses checks out the blueprint and uses it', function(){
this.timeout(10000);

return ember([
'new',
'foo',
'--skip-npm',
'--skip-bower',
'--skip-git',
'--blueprint=https://github.com/trek/app-blueprint-test.git'
]).then(function() {
assert(fs.existsSync('.ember-cli'));
});
});

it('ember new without skip-git flag creates .git dir', function(){
return ember([
'new',
Expand Down
13 changes: 13 additions & 0 deletions tests/unit/utilities/git-repo-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';

var isGitRepo = require('../../../lib/utilities/git-repo');
var assert = require('assert');

describe('cleanBaseURL()', function() {
it('recognizes git-style urls in various formats', function() {
assert.ok(isGitRepo('https://github.com/trek/app-blueprint-test.git'));
assert.ok(isGitRepo('git@github.com:trek/app-blueprint-test.git'));
assert.ok(isGitRepo('git+ssh://user@server/project.git'));
assert.ok(isGitRepo('git+https://user@server/project.git'));
});
});

0 comments on commit 37564dd

Please sign in to comment.