diff --git a/lib/program.js b/lib/program.js index 121632fb..9f185168 100644 --- a/lib/program.js +++ b/lib/program.js @@ -267,6 +267,25 @@ Program.prototype = new (function () { } } + // if task sets option greedy, then add all remaining CLI params + // are consumed by the task and passed as arguments + try { + taskNames = taskNames.reduceRight((accum, taskName) => { + let task = jake.rootNamespace.resolveTask(taskName); + if (task && task.greedy && accum.length) { + accum[0]=[`${taskName}[${accum[0].join(",")}]`]; + accum.unshift([]); + } else { + accum[0].unshift(taskName); + } + return accum; + }, [[]]).flat(); + } catch (err) { + // Might be possible for resolveTask to throw an exception. + // If this happens, fall back to standard argument handling, + // leaving taskNames unchanged. + } + rootTask = task(Task.ROOT_TASK_NAME, taskNames, function () {}); rootTask._internal = true; diff --git a/lib/task/task.js b/lib/task/task.js index 9e8886fa..ec7c32a8 100644 --- a/lib/task/task.js +++ b/lib/task/task.js @@ -68,6 +68,7 @@ class Task extends EventEmitter { this.endTime = null; this.directory = null; this.namespace = null; + this.greedy = false; // Support legacy async-flag -- if not explicitly passed or falsy, will // be set to empty-object @@ -81,6 +82,9 @@ class Task extends EventEmitter { if (opts.concurrency) { this.concurrency = opts.concurrency; } + if (opts.greedy) { + this.greedy = true; + } } //Do a test on self dependencies for this task diff --git a/test/integration/jakefile.js b/test/integration/jakefile.js index f3b7d1a4..6ec573fe 100644 --- a/test/integration/jakefile.js +++ b/test/integration/jakefile.js @@ -334,4 +334,10 @@ namespace("large", function () { task("different", different, { concurrency: 2 } , function () { console.log("large:different") }) + }); + +desc("Task that greedily consumes all remaining CLI params"); +task("oink", { greedy: true } , function (...args) { + console.log("greedy task consumed", args.length, "remaining arguments: ", args); +}) diff --git a/test/integration/task_base.js b/test/integration/task_base.js index 242d8396..1e64b9b1 100644 --- a/test/integration/task_base.js +++ b/test/integration/task_base.js @@ -161,4 +161,9 @@ suite('taskBase', function () { assert.equal('one:one\none:two', out); }); + test('greedy task consumes all remaining CLI params as arguments', function () { + let out = exec('./node_modules/.bin/jake -q oink one two three').toString().trim(); + assert.equal("greedy task consumed 3 remaining arguments: [ \'one\', \'two\', \'three\' ]", out); + }); + }); diff --git a/test/unit/jakefile.js b/test/unit/jakefile.js index 89ff5233..02e6d223 100644 --- a/test/unit/jakefile.js +++ b/test/unit/jakefile.js @@ -25,6 +25,10 @@ namespace('zooby', function () { }); task('asdf', function () {}); + + task('zumm', { greedy: true }, function (args) { + console.log('ran zooby:frang:zumm'); + }); }); }); diff --git a/test/unit/namespace.js b/test/unit/namespace.js index c6b3ff56..603f1ec8 100644 --- a/test/unit/namespace.js +++ b/test/unit/namespace.js @@ -66,6 +66,7 @@ suite('namespace', function () { let curr = Namespace.ROOT_NAMESPACE.resolveNamespace('hurr:durr'); let task = curr.resolveTask('zooby:frang:w00t:bar'); assert.ok(task.action.toString().indexOf('zooby:frang:w00t:bar') > -1); + assert.ok(!task.greedy); }); test('resolution miss with throw error', function () { @@ -74,4 +75,10 @@ suite('namespace', function () { assert.ok(!task); }); + test('resolution task with greedy option set', function () { + let curr = Namespace.ROOT_NAMESPACE; + let task = curr.resolveTask('zooby:frang:zumm'); + assert.ok(task.action.toString().indexOf('zooby:frang:zumm') > -1); + assert.ok(task.greedy); + }); });