Skip to content
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

Pr 4049 #4168

Merged
merged 5 commits into from
May 27, 2015
Merged

Pr 4049 #4168

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion lib/cli/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ var emberCLIVersion = versionUtils.emberCLIVersion;
var InstallationChecker = require('../models/installation-checker');

function CLI(options) {
this.name = options.name;
this.ui = options.ui;
this.analytics = options.analytics;
this.testing = options.testing;
this.root = options.root;
this.npmPackage = options.npmPackage;

debug('testing %o', !!this.testing);
}
Expand All @@ -41,7 +44,8 @@ CLI.prototype.run = function(environment) {
tasks: environment.tasks,
project: environment.project,
settings: environment.settings,
testing: this.testing
testing: this.testing,
cli: this
});

getOptionArgs('--verbose', commandArgs).forEach(function(arg){
Expand Down
31 changes: 18 additions & 13 deletions lib/cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,12 @@ var CLI = require('./cli');
var packageConfig = require('../../package.json');
var debug = require('debug')('ember-cli:cli/index');
var merge = require('lodash/object/merge');
var path = require('path');

var version = packageConfig.version;
var name = packageConfig.name;
var trackingCode = packageConfig.trackingCode;

// Options: Array cliArgs, Stream inputStream, Stream outputStream
module.exports = cli;

function clientId() {
var ConfigStore = require('configstore');
var configStore = new ConfigStore('ember-cli');
Expand All @@ -33,7 +31,8 @@ function clientId() {
}
}

function cli(options) {
// Options: Array cliArgs, Stream inputStream, Stream outputStream
module.exports = function(options) {
var UI = options.UI || require('../ui');
var Leek = options.Leek || require('leek');
var Yam = options.Yam || require('yam');
Expand All @@ -46,10 +45,8 @@ function cli(options) {
writeLevel: ~process.argv.indexOf('--silent') ? 'ERROR' : undefined
});

var project = Project.projectOrNullProject(ui);

var config = new Yam('ember-cli', {
primary: project.root
primary: Project.getProjectRoot()
});

var leekOptions;
Expand Down Expand Up @@ -81,6 +78,18 @@ function cli(options) {
debug('leek: %o', leekOptions);

var leek = new Leek(leekOptions);

var cli = new CLI({
ui: ui,
analytics: leek,
testing: options.testing,
name: options.cli ? options.cli.name : 'ember',
root: options.cli ? options.cli.root : path.resolve(__dirname, '..', '..'),
npmPackage: options.cli ? options.cli.npmPackage : 'ember-cli'
});

var project = Project.projectOrnullProject(ui, cli);

var environment = {
tasks: tasks,
cliArgs: options.cliArgs,
Expand All @@ -89,9 +98,5 @@ function cli(options) {
settings: merge(defaultUpdateCheckerOptions, config.getAll())
};

return new CLI({
ui: ui,
analytics: leek,
testing: options.testing
}).run(environment);
}
return cli.run(environment);
};
4 changes: 2 additions & 2 deletions lib/commands/new.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
var chalk = require('chalk');
var Command = require('../models/command');
var Promise = require('../ext/promise');
var NULL_PROJECT = require('../models/project').NULL_PROJECT;
var Project = require('../models/project');
var SilentError = require('../errors/silent');
var validProjectName = require('../utilities/valid-project-name');
var normalizeBlueprint = require('../utilities/normalize-blueprint-option');
Expand Down Expand Up @@ -77,7 +77,7 @@ module.exports = Command.extend({
ui: this.ui,
analytics: this.analytics,
tasks: this.tasks,
project: NULL_PROJECT
project: Project.nullProject(this.ui, this.cli)
});

return createAndStepIntoDirectory
Expand Down
10 changes: 9 additions & 1 deletion lib/models/addon-discovery.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ AddonDiscovery.prototype.constructor = AddonDiscovery;
AddonDiscovery.prototype.discoverProjectAddons = function(project) {
var projectAsAddon = this.discoverFromProjectItself(project);
var internalAddons = this.discoverFromInternalProjectAddons(project);
var cliAddons = this.discoverFromCli(project.cli);
var dependencyAddons = this.discoverFromDependencies(project.root, project.nodeModulesPath, project.pkg, false);
var inRepoAddons = this.discoverInRepoAddons(project.root, project.pkg);
var addons = projectAsAddon.concat(internalAddons, dependencyAddons, inRepoAddons);
var addons = projectAsAddon.concat(cliAddons, internalAddons, dependencyAddons, inRepoAddons);

return addons;
};
Expand Down Expand Up @@ -170,6 +171,13 @@ AddonDiscovery.prototype.discoverFromInternalProjectAddons = function(project) {
}).filter(Boolean);
};

AddonDiscovery.prototype.discoverFromCli = function (cli) {
if (!cli) { return []; }

var cliPkg = require(path.resolve(cli.root, 'package.json'));
return this.discoverInRepoAddons(cli.root, cliPkg);
};

/**
Given a particular path, return undefined if the path is not an addon, or if it is,
a node with the info about the addon.
Expand Down
1 change: 1 addition & 0 deletions lib/models/addon.js
Original file line number Diff line number Diff line change
Expand Up @@ -767,4 +767,5 @@ Addon.lookup = function(addon) {
@method buildError
@param {Error} error The error that was caught during the processes listed above
*/

module.exports = Addon;
95 changes: 68 additions & 27 deletions lib/models/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ var emberCLIVersion = versionUtils.emberCLIVersion;
@param {String} root Root directory for the project
@param {Object} pkg Contents of package.json
*/
function Project(root, pkg, ui) {
function Project(root, pkg, ui, cli) {
debug('init root: %s', root);
this.root = root;
this.pkg = pkg;
this.ui = ui;
this.cli = cli;
this.addonPackages = {};
this.addons = [];
this.liveReloadFilterPatterns = [];
Expand Down Expand Up @@ -82,21 +83,31 @@ Project.prototype.setupNodeModulesPath = function(){
debug('nodeModulesPath: %s', this.nodeModulesPath);
};

var NULL_PROJECT = new Project(process.cwd(), {});
var processCwd = process.cwd();
// ensure NULL_PROJECT is a singleton
var NULL_PROJECT;

NULL_PROJECT.isEmberCLIProject = function() {
return false;
};
Project.nullProject = function (ui, cli) {
if (NULL_PROJECT) { return NULL_PROJECT; }

NULL_PROJECT.isEmberCLIAddon = function() {
return false;
};
NULL_PROJECT = new Project(processCwd, {}, ui, cli);

NULL_PROJECT.name = function() {
return path.basename(process.cwd());
};
NULL_PROJECT.isEmberCLIProject = function() {
return false;
};

NULL_PROJECT.isEmberCLIAddon = function() {
return false;
};

Project.NULL_PROJECT = NULL_PROJECT;
NULL_PROJECT.name = function() {
return path.basename(process.cwd());
};

NULL_PROJECT.initializeAddons();

return NULL_PROJECT;
};

/**
Returns the name from package.json.
Expand All @@ -118,7 +129,7 @@ Project.prototype.name = function() {
@return {Boolean} Whether this is an Ember CLI project
*/
Project.prototype.isEmberCLIProject = function() {
return 'ember-cli' in this.dependencies();
return (this.cli ? this.cli.npmPackage : 'ember-cli') in this.dependencies();
};

/**
Expand Down Expand Up @@ -407,7 +418,7 @@ Project.prototype.blueprintLookupPaths = function() {

return lookupPaths.concat(addonLookupPaths);
} else {
return [];
return this.addonBlueprintLookupPaths();
}
};

Expand Down Expand Up @@ -490,17 +501,16 @@ Project.prototype.findAddonByName = function(name) {
@param {String} pathName Path to your project
@return {Promise} Promise which resolves to a {Project}
*/
Project.closest = function(pathName, _ui) {
Project.closest = function(pathName, _ui, _cli) {
var ui = ensureUI(_ui);

return closestPackageJSON(pathName)
.then(function(result) {
debug('closest %s -> %s', pathName, result);
if (result.pkg && result.pkg.name === 'ember-cli') {
return NULL_PROJECT;
return Project.nullProject(_ui, _cli);
}

return new Project(result.directory, result.pkg, ui);
return new Project(result.directory, result.pkg, ui, _cli);
})
.catch(function(reason) {
handleFindupError(pathName, reason);
Expand All @@ -518,19 +528,19 @@ Project.closest = function(pathName, _ui) {
@param {UI} ui The UI instance to provide to the created Project.
@return {Project} Project instance
*/
Project.closestSync = function(pathName, _ui) {
Project.closestSync = function(pathName, _ui, _cli) {
var ui = ensureUI(_ui);

try {
var directory = findup.sync(pathName, 'package.json');
var pkg = require(path.join(directory, 'package.json'));

if (pkg && pkg.name === 'ember-cli') {
return NULL_PROJECT;
return Project.nullProject(_ui, _cli);
}

debug('closestSync %s -> %s', pathName, directory);
return new Project(directory, pkg, ui);
return new Project(directory, pkg, ui, _cli);
} catch(reason) {
handleFindupError(pathName, reason);
}
Expand All @@ -544,23 +554,50 @@ Project.closestSync = function(pathName, _ui) {

@private
@static
@method projectOrNullProject
@method projectOrnullProject
@param {String} pathName Path to your project
@param {UI} ui The UI instance to provide to the created Project.
@return {Project} Project instance
*/
Project.projectOrNullProject = function(_ui) {
Project.projectOrnullProject = function(_ui, _cli) {
try {
return Project.closestSync(process.cwd(), _ui);
return Project.closestSync(process.cwd(), _ui, _cli);
} catch(reason) {
if (reason instanceof Project.NotFoundError) {
return Project.NULL_PROJECT;
return Project.nullProject(_ui, _cli);
} else {
throw reason;
}
}
};

/**
Returns the project root based on the first package.json that is found

@return {String} The project root directory
*/
Project.getProjectRoot = function () {
try {
var directory = findup.sync(process.cwd(), 'package.json');
var pkg = require(path.join(directory, 'package.json'));

if (pkg && pkg.name === 'ember-cli') {
debug('getProjectRoot: named \'ember-cli\'. Will use cwd: %s', process.cwd());
return process.cwd();
}

debug('getProjectRoot %s -> %s', process.cwd(), directory);
return directory;
} catch(reason) {
if (isFindupError(reason)) {
debug('getProjectRoot: not found. Will use cwd: %s', process.cwd());
return process.cwd();
} else{
throw reason;
}
}
};

function NotFoundError(message) {
this.name = 'NotFoundError';
this.message = message;
Expand Down Expand Up @@ -598,9 +635,13 @@ function closestPackageJSON(pathName) {
});
}

function handleFindupError(pathName, reason) {
function isFindupError(reason) {
// Would be nice if findup threw error subclasses
if (reason && /not found/i.test(reason.message)) {
return reason && /not found/i.test(reason.message);
}

function handleFindupError(pathName, reason) {
if (isFindupError(reason)) {
throw new NotFoundError('No project found at or up from: `' + pathName + '`');
} else {
throw reason;
Expand Down
4 changes: 3 additions & 1 deletion lib/tasks/install-blueprint.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ module.exports = Task.extend({
});
} else {
var blueprintName = blueprintOption || 'app';
var blueprint = Blueprint.lookup(blueprintName);
var blueprint = Blueprint.lookup(blueprintName, {
paths: this.project.blueprintLookupPaths()
});

return blueprint.install(installOptions);
}
Expand Down
8 changes: 4 additions & 4 deletions lib/utilities/markdown-color.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var backgroundColors = ['bgRed', 'bgGreen', 'bgBlue', 'bgCyan', 'bgMagenta', 'bg
module.exports = MarkdownColor;

/*
Parses markdown and applies coloring to output by matching defined tokens and
Parses markdown and applies coloring to output by matching defined tokens and
applying styling. Default outputs chalk.js coloring for terminal output.
Options:
tokens: pass additional tokens in the following format:
Expand All @@ -25,10 +25,10 @@ module.exports = MarkdownColor;
render: function(string) { return string + '!'} // function that takes and returns a string
}
}

markdownOptions: object containing options to pass (or override) to markdown-it-terminal upon
instantiation. See https://github.com/trabus/markdown-it-terminal/blob/master/index.js#L8

renderStyles: pass an object to render color styles, default is chalk.js

@class MarkdownColor
Expand All @@ -40,7 +40,7 @@ function MarkdownColor(options) {
var renderStyles = options && options.renderStyles || chalk;
var tokens = this.generateTokens(renderStyles);
var markdownOptions = options && options.markdownOptions || {};

this.options = options || {};
this.markdown = markdown().use(terminal, markdownOptions);
this.tokens = merge(tokens, optionTokens);
Expand Down
10 changes: 8 additions & 2 deletions tests/unit/models/project-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,12 +267,12 @@ describe('models/project.js', function() {
expect(project.blueprintLookupPaths()).to.deep.equal(expected);
});

it('returns an empty list of blueprint paths if outside a project', function() {
it('does not include blueprint path relative to root if outside a project', function() {
project.isEmberCLIProject = function() {
return false;
};

expect(project.blueprintLookupPaths()).to.deep.equal([]);
expect(project.blueprintLookupPaths()).to.deep.equal(project.addonBlueprintLookupPaths());
});

it('returns an instance of an addon with an object export', function() {
Expand Down Expand Up @@ -521,4 +521,10 @@ describe('models/project.js', function() {
expect(project.nodeModulesPath).to.equal(path.join(projectPath, 'node_modules'));
});
});

describe('.nullProject', function (){
it('is a singleton', function() {
expect(Project.nullProject()).to.equal(Project.nullProject());
});
});
});