Wrapped all modules into a promise chain

In order to ensure that submodules can perform asynchronous actions,
we've wrapped their invocation into a Q-based promise chain. Thus,
each can either return the original generator, or may return a
promise that eventually resolves with that same generator.
This commit is contained in:
Michael Krotscheck
2016-04-04 08:09:32 -07:00
parent c9fc7c4c7e
commit 1e679bc680
12 changed files with 216 additions and 71 deletions

View File

@@ -3,6 +3,7 @@
var yeoman = require('yeoman-generator');
var projectBuilder = require('./lib/project_builder');
var Q = require('q');
var gerrit = require('./lib/component/gerrit');
var editorconfig = require('./lib/component/editorconfig');
@@ -20,37 +21,55 @@
},
initializing: function() {
var done = this.async();
// Set our own defaults.
this.config.defaults({
projectName: this.appname
});
// Initialize components.
gerrit.init(this); // Gerrit
editorconfig.init(this); // Editorconfig
license.init(this); // Licensing
eslint.init(this); // Linting
gitignore.init(this); // Gitignore
Q(this)
.then(gerrit.init) // Gerrit
.then(editorconfig.init) // Editorconfig
.then(license.init) // Licensing
.then(eslint.init) // Linting
.then(gitignore.init) // Gitignore
.then(function() {
done();
});
},
prompting: function() {
if (!this.options['non-interactive']) {
var done = this.async();
// Prompt components.
gerrit.prompt(this); // Gerrit
editorconfig.prompt(this); // Editorconfig
license.prompt(this); // Licensing
eslint.prompt(this); // Linting
gitignore.prompt(this); // Gitignore
Q(this)
.then(gerrit.prompt) // Gerrit
.then(editorconfig.prompt) // Editorconfig
.then(license.prompt) // Licensing
.then(eslint.prompt) // Linting
.then(gitignore.prompt) // Gitignore
.then(function() {
done();
});
}
},
configuring: function() {
var done = this.async();
// Configure components.
gerrit.configure(this); // Gerrit
editorconfig.configure(this); // Editorconfig
license.configure(this); // Licensing
eslint.configure(this); // Linting
gitignore.configure(this); // Gitignore
Q(this)
.then(gerrit.configure) // Gerrit
.then(editorconfig.configure) // Editorconfig
.then(license.configure) // Licensing
.then(eslint.configure) // Linting
.then(gitignore.configure) // Gitignore
.then(function() {
done();
});
},
writing: function() {

View File

@@ -1,4 +1,4 @@
(function () {
(function() {
'use strict';
var projectBuilder = require('../project_builder');
@@ -6,19 +6,22 @@
/**
* No-op placeholder method, for handlers we don't need.
*
* @returns {void}
* @param {generator} generator The currently active generator.
* @returns {generator} The passed generator, for promise chaining.
*/
function noop () {
// Do nothing.
function noop (generator) {
return generator;
}
/**
* Configure the project by adding required files.
*
* @returns {void}
* @param {generator} generator The currently active generator.
* @returns {generator} The passed generator, for promise chaining.
*/
function configureEC () {
function configureEC (generator) {
projectBuilder.addFile('.editorconfig');
return generator;
}
module.exports = {

View File

@@ -12,18 +12,19 @@
/**
* No-op placeholder method, for handlers we don't need.
*
* @returns {void}
* @param {generator} generator The currently active generator.
* @returns {generator} The passed generator, for promise chaining.
*/
function noop () {
// Do nothing.
function noop (generator) {
return generator;
}
/**
* Read the existing .eslintrc and .eslintignore files, and populate our initial configuration
* with them.
*
* @param {*} generator The currently active yeoman generator.
* @returns {void}
* @param {generator} generator The currently active generator.
* @returns {generator} The passed generator, for promise chaining.
*/
function initializeEslint (generator) {
var fs = generator.fs;
@@ -42,20 +43,25 @@
if (fs.exists(rcFile)) {
eslintrc = yaml.safeLoad(fs.read(rcFile));
}
return generator;
}
/**
* Configure the project by adding required files.
*
* @returns {void}
* @param {generator} generator The currently active generator.
* @returns {generator} The passed generator, for promise chaining.
*/
function configureEslint () {
function configureEslint (generator) {
if (buildEslintIgnore().length === 0) {
projectBuilder.removeFile('.eslintignore');
} else {
projectBuilder.writeFile('.eslintignore', buildEslintIgnore);
}
projectBuilder.writeFile('.eslintrc', buildEslintRc);
return generator;
}
/**

View File

@@ -3,6 +3,7 @@
var projectBuilder = require('../project_builder');
var ini = require('ini');
var Q = require('q');
var gerritFile = '.gitreview';
var iniDefaults = {
@@ -28,8 +29,8 @@
* Initialize the gerrit component of this generator. In this case, we're
* only adding default configuration values.
*
* @param {Base} generator The generator to configure.
* @returns {void}
* @param {generator} generator The currently active generator.
* @returns {generator} The passed generator, for promise chaining.
*/
function initializeGerrit (generator) {
// Define our defaults
@@ -43,45 +44,46 @@
// Set the configuration defaults.
generator.config.defaults({enableGerrit: true});
return generator;
}
/**
* Initialize the gerrit component of this generator. In this case, we're
* only adding default configuration values.
*
* @param {Base} generator The generator to configure.
* @returns {void}
* @param {generator} generator The currently active generator.
* @returns {generator} The passed generator, for promise chaining.
*/
function promptUserOptions (generator) {
var done = generator.async();
var prompts = [{
type: 'confirm',
name: 'enableGerrit',
message: 'Will this project be managed by Gerrit?',
default: generator.config.get('enableGerrit')
}, {
when: gerritEnabled,
type: 'input',
name: 'gerritHost',
message: 'Gerrit URL:',
default: iniContent.gerrit.host
}, {
when: gerritEnabled,
type: 'input',
name: 'gerritPort',
message: 'Gerrit Port:',
default: iniContent.gerrit.port
}, {
when: gerritEnabled,
type: 'input',
name: 'gerritProject',
message: 'Gerrit Project:',
default: iniContent.gerrit.project
}];
var deferred = Q.defer();
// Go through the prompts.
generator.prompt(prompts,
generator.prompt(
[{
type: 'confirm',
name: 'enableGerrit',
message: 'Will this project be managed by Gerrit?',
default: generator.config.get('enableGerrit')
}, {
when: gerritEnabled,
type: 'input',
name: 'gerritHost',
message: 'Gerrit URL:',
default: iniContent.gerrit.host
}, {
when: gerritEnabled,
type: 'input',
name: 'gerritPort',
message: 'Gerrit Port:',
default: iniContent.gerrit.port
}, {
when: gerritEnabled,
type: 'input',
name: 'gerritProject',
message: 'Gerrit Project:',
default: iniContent.gerrit.project
}],
function(answers) {
generator.config.set({
enableGerrit: answers.enableGerrit
@@ -92,16 +94,27 @@
port: answers.gerritPort,
project: answers.gerritProject
};
done();
deferred.resolve(generator);
});
return deferred.promise;
}
/**
* Configure gerrit
*
* @param {generator} generator The currently active generator.
* @returns {generator} The passed generator, for promise chaining.
*/
function configureGerrit (generator) {
if (generator.config.get('enableGerrit')) {
projectBuilder.writeFile(gerritFile, buildGerritFile);
} else {
projectBuilder.removeFile(gerritFile);
}
return generator;
}
function buildGerritFile () {
@@ -113,4 +126,5 @@
prompt: promptUserOptions,
configure: configureGerrit
};
})();
})
();

View File

@@ -6,19 +6,23 @@
/**
* No-op placeholder method, for handlers we don't need.
*
* @returns {void}
* @param {generator} generator The currently active generator.
* @returns {generator} The passed generator, for promise chaining.
*/
function noop () {
// Do nothing.
function noop (generator) {
return generator;
}
/**
* Configure the project by adding required files.
*
* @returns {void}
* @param {generator} generator The currently active generator.
* @returns {generator} The passed generator, for promise chaining.
*/
function configureGitIgnore () {
function configureGitIgnore (generator) {
projectBuilder.addFile('.gitignore');
return generator;
}
module.exports = {

View File

@@ -6,19 +6,23 @@
/**
* No-op placeholder method, for handlers we don't need.
*
* @returns {void}
* @param {generator} generator The currently active generator.
* @returns {generator} The passed generator, for promise chaining.
*/
function noop () {
// Do nothing.
function noop (generator) {
return generator;
}
/**
* Configure the project by adding required files.
*
* @returns {void}
* @param {generator} generator The currently active generator.
* @returns {generator} The passed generator, for promise chaining.
*/
function configureLicense () {
function configureLicense (generator) {
projectBuilder.addFile('LICENSE');
return generator;
}
module.exports = {

View File

@@ -25,6 +25,7 @@
"dependencies": {
"ini": "^1.3.4",
"js-yaml": "^3.5.5",
"q": "^1.4.1",
"yeoman-generator": "^0.21.1"
},
"devDependencies": {
@@ -32,6 +33,8 @@
"eslint-config-openstack": "1.2.4",
"istanbul": "0.4.2",
"jasmine": "2.4.1",
"karma": "^0.13.22",
"karma-htmlfile-reporter": "^0.2.2",
"nsp": "2.2.1",
"yeoman-assert": "2.0.0",
"yeoman-test": "^1.1.0"

View File

@@ -22,6 +22,12 @@
});
describe('init()', function () {
it('should return a generator',
function () {
var outputGenerator = editorconfig.init(mockGenerator);
expect(outputGenerator).toEqual(mockGenerator);
});
it('should do nothing',
function () {
var spy = spyOn(mockGenerator.config, 'defaults');
@@ -31,6 +37,12 @@
});
describe('prompt()', function () {
it('should return a generator',
function () {
var outputGenerator = editorconfig.prompt(mockGenerator);
expect(outputGenerator).toEqual(mockGenerator);
});
it('should do nothing',
function () {
var spy = spyOn(mockGenerator, 'prompt');
@@ -40,6 +52,12 @@
});
describe('configure()', function () {
it('should return a generator',
function () {
var outputGenerator = editorconfig.configure(mockGenerator);
expect(outputGenerator).toEqual(mockGenerator);
});
it('should add editorconfig to the project files.',
function () {
editorconfig.configure(mockGenerator);

View File

@@ -25,6 +25,12 @@
});
describe('init()', function() {
it('should return a generator',
function () {
var outputGenerator = eslint.init(mockGenerator);
expect(outputGenerator).toEqual(mockGenerator);
});
it('should not interact with config',
function() {
var spy = spyOn(mockGenerator.config, 'defaults');
@@ -34,6 +40,12 @@
});
describe('prompt()', function() {
it('should return a generator',
function () {
var outputGenerator = eslint.prompt(mockGenerator);
expect(outputGenerator).toEqual(mockGenerator);
});
it('should do nothing',
function() {
var spy = spyOn(mockGenerator, 'prompt');
@@ -43,6 +55,12 @@
});
describe('configure()', function() {
it('should return a generator',
function () {
var outputGenerator = eslint.configure(mockGenerator);
expect(outputGenerator).toEqual(mockGenerator);
});
it('should add .eslintrc and .eslintignore to the project files.',
function() {
eslint.configure(mockGenerator);

View File

@@ -55,6 +55,13 @@
});
describe('init()', function() {
it('should return a generator',
function () {
var generator = mocks.buildGenerator();
var outputGenerator = gerrit.init(generator);
expect(outputGenerator).toEqual(generator);
});
it('should set defaults',
function() {
var generator = mocks.buildGenerator();
@@ -91,6 +98,12 @@
});
describe('prompt()', function() {
it('should return a generator',
function () {
var generator = mocks.buildGenerator();
var outputGenerator = gerrit.init(generator);
expect(outputGenerator).toEqual(generator);
});
it('should revert to config defaults if no answers provided',
function() {
@@ -144,6 +157,13 @@
});
describe('configure()', function() {
it('should return a generator',
function () {
var generator = mocks.buildGenerator();
var outputGenerator = gerrit.init(generator);
expect(outputGenerator).toEqual(generator);
});
it('should create a .gitreview file if enabled',
function() {
var mockConfig = {enableGerrit: true};

View File

@@ -22,6 +22,12 @@
});
describe('init()', function () {
it('should return a generator',
function () {
var outputGenerator = gitignore.init(mockGenerator);
expect(outputGenerator).toEqual(mockGenerator);
});
it('should do nothing',
function () {
var spy = spyOn(mockGenerator.config, 'defaults');
@@ -31,6 +37,12 @@
});
describe('prompt()', function () {
it('should return a generator',
function () {
var outputGenerator = gitignore.prompt(mockGenerator);
expect(outputGenerator).toEqual(mockGenerator);
});
it('should do nothing',
function () {
var spy = spyOn(mockGenerator, 'prompt');
@@ -40,6 +52,12 @@
});
describe('configure()', function () {
it('should return a generator',
function () {
var outputGenerator = gitignore.configure(mockGenerator);
expect(outputGenerator).toEqual(mockGenerator);
});
it('should add gitignore to the project files.',
function () {
gitignore.configure(mockGenerator);

View File

@@ -22,6 +22,12 @@
});
describe('init()', function () {
it('should return a generator',
function () {
var outputGenerator = license.init(mockGenerator);
expect(outputGenerator).toEqual(mockGenerator);
});
it('should do nothing',
function () {
var spy = spyOn(mockGenerator.config, 'defaults');
@@ -31,6 +37,12 @@
});
describe('prompt()', function () {
it('should return a generator',
function () {
var outputGenerator = license.prompt(mockGenerator);
expect(outputGenerator).toEqual(mockGenerator);
});
it('should do nothing',
function () {
var spy = spyOn(mockGenerator, 'prompt');
@@ -40,6 +52,12 @@
});
describe('configure()', function () {
it('should return a generator',
function () {
var outputGenerator = license.configure(mockGenerator);
expect(outputGenerator).toEqual(mockGenerator);
});
it('should add license to the project files.',
function () {
license.configure(mockGenerator);