Skip to content

Commit

Permalink
allow just using a string for a volofile command or an array of strin…
Browse files Browse the repository at this point in the history
…gs, and use shell-quote to expand that to an array usable by v.spawn. Also allow running a local node command via an n prefix on the command.
  • Loading branch information
jrburke committed Jun 6, 2012
1 parent 129cd19 commit d988c0d
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 11 deletions.
27 changes: 26 additions & 1 deletion lib/commands.js
Expand Up @@ -61,7 +61,7 @@

run: function (command, venv, namedArgs /*other args can be passed*/) {
var d = q.defer(),
args;
shellCommand, args;

if (!venv) {
venv = v(path.resolve('.')).env;
Expand All @@ -75,6 +75,31 @@
command = {
run: command
};
} else if (typeof command === 'string' ||
Array.isArray(command)) {
command = {
run: command
};
}

//Now convert run to a function if it is not.
//This allows a command to have depends and
//a run property that is just a shell string or array
//of shell strings
if (typeof command.run === 'string') {
shellCommand = command.run;
command.run = function (d, v, namedArgs) {
d.resolve(v.shell(shellCommand, {
useConsole: true
}));
};
} else if (Array.isArray(command.run)) {
shellCommand = command.run;
command.run = function (d, v, namedArgs) {
d.resolve(v.sequence(shellCommand, {
useConsole: true
}));
};
}

args = [].slice.call(arguments, 2);
Expand Down
50 changes: 46 additions & 4 deletions lib/v.js
Expand Up @@ -13,13 +13,15 @@ var path = require('path'),
q = require('q'),
spawn = require('child_process').spawn,
exec = require('child_process').exec,
shellQuote = require('shell-quote'),
file = require('./file'),
template = require('./template'),
qutil = require('./qutil'),
tty = require('tty'),
voloMainPath = path.join(__dirname, '..', 'volo'),
defaultEncoding = 'utf8',
lineRegExp = /(\r)?\n$/;
lineRegExp = /(\r)?\n$/,
nodeModulesBinPrefix = 'node_modules/.bin/';

function execToConsole(value) {
console.log(value.replace(lineRegExp, ''));
Expand Down Expand Up @@ -165,17 +167,54 @@ function v(dirName) {

return d.promise;
},

//Runs a command in the shell. Similar to spawn(),
//but does not require constructing string arrays,
//just type in the command with its args as a string.
shell: function (cmd, options) {
return instance.env.spawn.apply(instance.env, shellQuote.parse(cmd).concat(options));
},

//Spawns a command in the shell via child_process.spawn.
//If options.useConsole is true, then data sent to stdout,
//stderr will be sent to console as soon as it is received.
//Otherwise, it works similar to exec(), except spawn separates
//the command from the args passed to it.
spawn: function (cmd, args, options) {
var d = q.defer(),
spawned = spawn(cmd, args, options),
okResponse = '',
errResponse = '',
onData, onErrData;
spawned, onData, onErrData;

if (typeof args === 'string') {
//If args is a string, then this is a variadic call,
//with the last one possibly being an options arg.
args = [].slice.call(arguments, 0);
cmd = args.shift();
if (typeof args[args.length - 1] !== 'string') {
options = args.pop();
} else {
options = {};
}
}

//Is this a command that should test for
//a local node_modules bin file?
if (cmd.indexOf('n!') === 0) {
cmd = cmd.substring(2);

if (path.existsSync(nodeModulesBinPrefix + cmd)) {
cmd = nodeModulesBinPrefix + cmd;

//Add the command back to the args,
//and use 'node' as the command,
//so that it works on windows.
args.unshift(cmd);
cmd = 'node';
}
}

spawned = spawn(cmd, args, options);

options = options || {};

Expand Down Expand Up @@ -216,13 +255,16 @@ function v(dirName) {
//the second array value is a method name and the rest of the
//array values are arguments. Example:
//v.sequence([
// ['git', 'init'], //ends up with v.sequence('git', ['init'], options)
// ['git', 'init'], //ends up with v.spawn('git', ['init'], options)
// [v, 'rm', 'README.md'] //ends up calling v.rm.apply(v, ['README.md']);
//], options);
sequence: function (list, options) {
var result = q.resolve();
list.forEach(function (item) {
result = result.then(function () {
//Allow for string values that are just plain shell commands.
item = typeof item === 'string' ? shellQuote.parse(item) : item;

var start = item[0],
action = item[1],
useSpawn = typeof start === 'string',
Expand Down
14 changes: 9 additions & 5 deletions lib/volofile.js
Expand Up @@ -85,11 +85,15 @@ function volofile(basePath, callback, errback) {
contents = fs.readFileSync(volofilePath, 'utf8');

//Look for define, and the absence of amdefine use.
if (parse.usesAmdOrRequireJs(volofilePath, contents) &&
contents.indexOf('amdefine') === -1) {
d.resolve(legacy01Exec(volofilePath, contents));
} else {
d.resolve(require(volofilePath));
try {
if (parse.usesAmdOrRequireJs(volofilePath, contents) &&
contents.indexOf('amdefine') === -1) {
d.resolve(legacy01Exec(volofilePath, contents));
} else {
d.resolve(require(volofilePath));
}
} catch (e) {
d.reject('Malformed volofile: ' + volofilePath + ': ' + e);
}
} else {
d.resolve();
Expand Down
33 changes: 33 additions & 0 deletions node_modules/shell-quote/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 53 additions & 0 deletions node_modules/shell-quote/package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -27,7 +27,8 @@
"dependencies": {
"q": "0.8.5",
"zip": "0.0.6",
"uglify-js": "1.2.6"
"uglify-js": "1.2.6",
"shell-quote": "0.0.1"
},

"main": "volo"
Expand Down

0 comments on commit d988c0d

Please sign in to comment.