Skip to content

Commit

Permalink
Switch to execSync
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanpenner committed Oct 2, 2016
1 parent ab70f42 commit d5c24bd
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 200 deletions.
71 changes: 36 additions & 35 deletions lib/models/command.js
Expand Up @@ -15,7 +15,7 @@ var CoreObject = require('core-object');
var logger = require('heimdalljs-logger')('ember-cli:command');
var WatchDetector = require('../models/watch-detector');
var SilentError = require('silent-error');
var exec = Promise.denodeify(require('child_process').exec)
var execSync = require('child_process').execSync;
var fs = require('fs')

var cache = {};
Expand Down Expand Up @@ -192,50 +192,51 @@ var Command = CoreObject.extend({
@return {Promise}
*/
validateAndRun: function(args) {
var commandOptions = this.parseArgs(args);
// if the help option was passed, resolve with 'callHelp' to call help command
if (commandOptions && (commandOptions.options.help || commandOptions.options.h)) {
logger.info(this.name + ' called with help option');
return Promise.resolve('callHelp');
}
return new Promise(function(resolve) {
var commandOptions = this.parseArgs(args);
// if the help option was passed, resolve with 'callHelp' to call help command
if (commandOptions && (commandOptions.options.help || commandOptions.options.h)) {
logger.info(this.name + ' called with help option');
return resolve('callHelp');
}

this.analytics.track({
name: 'ember ',
message: this.name
});
this.analytics.track({
name: 'ember ',
message: this.name
});

if (commandOptions === null) {
return Promise.resolve();
}
if (commandOptions === null) {
return resolve();
}

if (this.works === 'outsideProject' && this.isWithinProject) {
return Promise.reject(new SilentError(
'You cannot use the ' + chalk.green(this.name) + ' command inside an ember-cli project.'
));
}
if (this.works === 'outsideProject' && this.isWithinProject) {
throw new SilentError(
'You cannot use the ' + chalk.green(this.name) + ' command inside an ember-cli project.'
);
}

if (this.works === 'insideProject') {
if (!this.project.hasDependencies()) {
throw new SilentError('node_modules appears empty, you may need to run `npm install`');
if (this.works === 'insideProject') {
if (!this.project.hasDependencies()) {
throw new SilentError('node_modules appears empty, you may need to run `npm install`');
}
}
}

var detector = new WatchDetector({
ui: this.ui,
childProcess: { exec: exec },
fs: fs,
watchmanSupportsPlatform: /^win/.test(process.platform),
cache: cache,
root: this.project.root
});
var detector = new WatchDetector({
ui: this.ui,
childProcess: { execSync: execSync },
fs: fs,
watchmanSupportsPlatform: /^win/.test(process.platform),
cache: cache,
root: this.project.root
});

var options = commandOptions.options;
var options = commandOptions.options;

// do stuff to try and provide a good experience when it comes to file watching
return detector.findBestWatcherOption(options).then(function(watchPreference) {
// do stuff to try and provide a good experience when it comes to file watching
var watchPreference = detector.findBestWatcherOption(options);
this.project._watchmanInfo = watchPreference.watchmanInfo;
options.watcher = watchPreference.watcher;
return this.run(options, commandOptions.args);
resolve(this.run(options, commandOptions.args));
}.bind(this));
},

Expand Down
121 changes: 58 additions & 63 deletions lib/models/watch-detector.js
Expand Up @@ -18,7 +18,6 @@ var POSSIBLE_WATCHERS = [
];

var debug = require('heimdalljs-logger')('ember-cli:watcher');
debugger;

function WatchPreference(watcher) {
this.watcher = watcher || null;
Expand Down Expand Up @@ -96,44 +95,40 @@ WatchDetector.prototype.extractPreferenceFromOptions = function(options) {
*/
WatchDetector.prototype.testIfNodeWatcherAppearsToWork = function() {
var root = this.root;
return new Promise(function(resolve) {
if (root in this._doesNodeWorkCache) {
resolve(this._doesNodeWorkCache[root]);
return;
}
if (root in this._doesNodeWorkCache) {
return this._doesNodeWorkCache[root];
}

this._doesNodeWorkCache[root] = false;
this._doesNodeWorkCache[root] = false;
try {
// builds a tmp directory at process.cwd() + '/tmp/' + 'something-unique';
var tmpDir = quickTemp.makeOrRemake(this, 'tmp');

var watcher = this.fs.watch(tmpDir, { persistent: false, recursive: false });
watcher.close();
} catch (e) {
debug.info('testing if node watcher failed with: %o', e)
return false;
} finally {
try {
// builds a tmp directory at process.cwd() + '/tmp/' + 'something-unique';
var tmpDir = quickTemp.makeOrRemake(this, 'tmp');

var watcher = this.fs.watch(tmpDir, { persistent: false, recursive: false });
watcher.close();
quickTemp.remove(this, 'tmp');
// cleanup dir
} catch (e) {
debug.info('testing if node watcher failed with: %o', e)
resolve(false);
return;
} finally {
try {
quickTemp.remove(this, 'tmp');
// cleanup dir
} catch (e) {
// not much we can do, lets debug log.
debug.info('cleaning up dir failed with: %o', e)
}
// not much we can do, lets debug log.
debug.info('cleaning up dir failed with: %o', e)
}
}

// it seems we where able to at least watch and unwatch, this should catch
// systems that have a very broken NodeWatcher.
//
// NOTE: we could also add a more advance chance, that triggers a change
// and expects to be informed of the change. This can be added in a future
// iteration.
//
// it seems we where able to at least watch and unwatch, this should catch
// systems that have a very broken NodeWatcher.
//
// NOTE: we could also add a more advance chance, that triggers a change
// and expects to be informed of the change. This can be added in a future
// iteration.
//

this._doesNodeWorkCache[root] = true;
resolve(true);
}.bind(this));
this._doesNodeWorkCache[root] = true;
return true;
};

/*
Expand All @@ -160,32 +155,31 @@ WatchDetector.prototype.findBestWatcherOption = function(options) {
preference = this.checkWatchman();
}

return Promise.resolve(preference).then(function(bestOption) {
if (bestOption.watcher === NODE) {
// although up to this point, we may believe Node is the best watcher
// this may not be true because:
// * not all platforms that run node, support node.watch
// * not all file systems support node watch
//
return this.testIfNodeWatcherAppearsToWork().then(function(appearsToWork) {
return new WatchPreference(appearsToWork ? NODE : POLLING);
});
} else {
return bestOption;
}
}.bind(this)).then(function(actual) {
debug.info('foundBestWatcherOption, preference was: %o, actual: %o', options, actual);
if (actual /* if no preference was initial set, don't bother informing the user */ &&
original /* if no original was set, the fallback is expected */ &&
actual.watcher !== original &&

// events represents either watcherman or node, but no preference
!(original === EVENTS && (actual.watcher === WATCHMAN || actual.watcher === NODE))) {
// if there was an initial preference, but we had to fall back inform the user.
this.ui.writeLine('was unable to use: "' + original + '", fell back to: "' + actual.watcher + '"')
}
return actual;
}.bind(this));
var bestOption = preference;
var actual;

if (bestOption.watcher === NODE) {
// although up to this point, we may believe Node is the best watcher
// this may not be true because:
// * not all platforms that run node, support node.watch
// * not all file systems support node watch
//
var appearsToWork = this.testIfNodeWatcherAppearsToWork();
actual = new WatchPreference(appearsToWork ? NODE : POLLING);
} else {
actual = bestOption;
}
debug.info('foundBestWatcherOption, preference was: %o, actual: %o', options, actual);
if (actual /* if no preference was initial set, don't bother informing the user */ &&
original /* if no original was set, the fallback is expected */ &&
actual.watcher !== original &&

// events represents either watcherman or node, but no preference
!(original === EVENTS && (actual.watcher === WATCHMAN || actual.watcher === NODE))) {
// if there was an initial preference, but we had to fall back inform the user.
this.ui.writeLine('was unable to use: "' + original + '", fell back to: "' + actual.watcher + '"');
}
return actual;
};

/*
Expand All @@ -204,8 +198,9 @@ WatchDetector.prototype.findBestWatcherOption = function(options) {
WatchDetector.prototype.checkWatchman = function() {
var result = new WatchPreference(null);

debug.info('exev("watchman version")');
return this.childProcess.exec('watchman version').then(function(output) {
debug.info('execSync("watchman version")');
try {
var output = this.childProcess.execSync('watchman version', { stdio: [] });
debug.info('watchman version STDOUT: %s', output);
var version;
try {
Expand Down Expand Up @@ -239,7 +234,7 @@ WatchDetector.prototype.checkWatchman = function() {
}

return result;
}.bind(this), function(reason) {
} catch (reason) {
debug.info('detecting watchman failed %o', reason);

if (this.watchmanSupportsPlatform) {
Expand All @@ -252,5 +247,5 @@ WatchDetector.prototype.checkWatchman = function() {

result.watcher = NODE;
return result;
}.bind(this));
}
};
8 changes: 5 additions & 3 deletions tests/unit/commands/generate-test.js
Expand Up @@ -49,9 +49,11 @@ describe('generate command', function() {
it('runs GenerateFromBlueprint but with null nodeModulesPath', function() {
command.project.hasDependencies = function() { return false; };

expect(function() {
command.validateAndRun(['controller', 'foo']);
}).to.throw(SilentError, 'node_modules appears empty, you may need to run `npm install`');
return command.validateAndRun(['controller', 'foo']).then(function() {
expect(true).to.be.false;
}).catch(function(reason) {
expect(reason.message).to.eql('node_modules appears empty, you may need to run `npm install`');
})
});

it('runs GenerateFromBlueprint with expected options', function() {
Expand Down

0 comments on commit d5c24bd

Please sign in to comment.