diff --git a/lib/rule.js b/lib/rule.js index ae43dedb..ee430a65 100644 --- a/lib/rule.js +++ b/lib/rule.js @@ -236,7 +236,6 @@ Rule.prototype = new (function () { , source , action , opts - , prereqs , parts , valid , src @@ -244,26 +243,70 @@ Rule.prototype = new (function () { , createdTask , name = Task.getBaseTaskName(fullName) , nsPath = Task.getBaseNamespacePath(fullName) - , ns = this.ns.resolveNamespace(nsPath); + , ns = this.ns.resolveNamespace(nsPath) + , prereqs = this.prereqs.slice(); // Get a copy to work with pattern = this.pattern; source = this.source; - if (typeof source == 'string') { - src = Matcher.getSource(name, pattern, source); + // TODO: Write a utility function that appends a + // taskname to a namespace path + var completeNamespace = function(s){ + return nsPath.split(':').filter(function (item) { + return !!item; + }).concat(s).join(':'); + }; + + // Deal with the various things the source argument can be: + // 1: A function + if (typeof source == 'function') { + source = source(name); + + if (source instanceof Array) { + // It's a function that returns an array of sources (strings) + src = []; + source.forEach(function(srcName){ + src.push(completeNamespace( srcName) ); + }); + prereqs = prereqs.concat(src); + } + + else if (typeof source == 'string') { + // It's a function that returns a single source (string) + src = completeNamespace(source); + prereqs.unshift(src); + } + + else { + // It's a function that returns a headache. + debugger; + throw new Error("Can't parse rule source."); + } } - else { - src = source(name); + + // 2: An array of sources + else if (source instanceof Array) { + // Find them all: + src = []; + source.forEach(function(srcName){ + src.push(completeNamespace( Matcher.getSource(name, pattern, srcName) )); + }); + prereqs = prereqs.concat(src); + } + + // 3: A single source + else if (typeof source == 'string') { + src = completeNamespace( Matcher.getSource(name, pattern, source) ); + prereqs.unshift(src); } - // TODO: Write a utility function that appends a - // taskname to a namespace path - src = nsPath.split(':').filter(function (item) { - return !!item; - }).concat(src).join(':'); + // 4: There is no #4 + else { + throw new Error("Can't parse rule source."); + } // Generate the prerequisite for the matching task. - // It is the original prerequisites plus the prerequisite + // It is the original prerequisites plus the definied prerequisite/prerequisites // representing source file, i.e., // // rule( '%.o', '%.c', ['some.h'] ... @@ -271,8 +314,6 @@ Rule.prototype = new (function () { // If the objective is main.o, then new task should be // // file( 'main.o', ['main.c', 'some.h' ] ... - prereqs = this.prereqs.slice(); // Get a copy to work with - prereqs.unshift(src); // Prereq should be: // 1. an existing task @@ -307,7 +348,14 @@ Rule.prototype = new (function () { tNs = jake.currentNamespace; jake.currentNamespace = ns; createdTask = jake.createTask('file', name, prereqs, action, opts); - createdTask.source = src.split(':').pop(); + if (src instanceof Array) { + createdTask.source = []; + src.forEach(function(s){ + createdTask.source.push(s.split(':').pop()); + }); + } else { + createdTask.source = src.split(':').pop(); + } jake.currentNamespace = tNs; return createdTask; diff --git a/test/Jakefile.rule b/test/Jakefile.rule index 6ac84a27..d8a6904d 100644 --- a/test/Jakefile.rule +++ b/test/Jakefile.rule @@ -9,6 +9,7 @@ task('default', ['tmp']); directory('tmpsrc'); directory('tmpbin'); + //////////////////////////////////////////////////////////// // Simple Suffix Rule file('tmp', ['tmp_init', 'tmp_dep1.o', 'tmp_dep2.o'], function (params) { @@ -112,6 +113,54 @@ task('tmp_src_init', ['tmpsrc'], function () { }, {async: true}); //////////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +// Rule having multiple sources + +//////////////////////////////////////////////////////////// +// Multiple Source Rule tests +task('tmp_ms', [ + 'tmpbin', + 'tmpbin/bar123.glom', + 'sourceFunction:tmpbin/foo123.glom' + ], function () { + console.log('multiple source rules task'); + var data1 = fs.readFileSync('tmpbin/foo123.glom'); + var data2 = fs.readFileSync('tmpbin/bar123.glom'); + fs.writeFileSync('tmp_ms', data1 + data2 + ' multiple source rules'); +}); + ++function(){ + var srcFuncMulti = function (taskName) { + var list = []; + + list.push(taskName.replace('tmpbin', 'tmpsrc').replace(/\.[^.]+$/, '.1') ); + list.push(taskName.replace('tmpbin', 'tmpsrc').replace(/\.[^.]+$/, '.2') ); + list.push(taskName.replace('tmpbin', 'tmpsrc').replace(/\.[^.]+$/, '.3') ); + + return list; + }; + + rule(/.*\.glom$/, srcFuncMulti, function () { + var data = fs.readFileSync(this.source[0]); + data += fs.readFileSync(this.source[1]); + data += fs.readFileSync(this.source[2]); + fs.writeFileSync(this.name, data.toString()); + console.log('created .glom'); + }); +}(); + +[1, 2, 3].forEach(function (key) { + var name = 'tmpsrc/bar123.' + key; + file(name, ['tmpsrc'], function () { + fs.writeFile(name, name+ "\n", function (err) { + if (err) { + throw err; + } + console.log(name + ' task'); + complete(); + }); + }, {async: true}); +}); //////////////////////////////////////////////////////////// // Namespace Test. This is a Mixed Test. @@ -227,6 +276,7 @@ namespace('regexPattern', function () { namespace('sourceFunction', function () { var srcFunc = function (taskName) { + /* console.log(taskName.replace(/\.[^.]+$/, '.txt')); */ return taskName.replace(/\.[^.]+$/, '.txt'); }; @@ -239,8 +289,41 @@ namespace('sourceFunction', function () { var data = fs.readFileSync(this.source); fs.writeFileSync(this.name, data.toString()); }); + + var srcFuncMulti = function (taskName) { + var list = []; + + list.push(taskName.replace('tmpbin', 'tmpsrc').replace(/\.[^.]+$/, '.1') ); + list.push(taskName.replace('tmpbin', 'tmpsrc').replace(/\.[^.]+$/, '.2') ); + list.push(taskName.replace('tmpbin', 'tmpsrc').replace(/\.[^.]+$/, '.3') ); + + return list; + }; + + // Testing multiple rule sources returned by a function: + + rule(/.*\.glom$/, srcFuncMulti, function () { + var data = fs.readFileSync(this.source[0]); + data += fs.readFileSync(this.source[1]); + data += fs.readFileSync(this.source[2]); + fs.writeFileSync(this.name, data.toString()); + console.log('created .glom'); + }); + + [1, 2, 3].forEach(function (key) { + var name = 'tmpsrc/foo123.' + key; + file(name, ['tmpsrc'], function () { + fs.writeFile(name, name+ "\n", function (err) { + if (err) { + throw err; + } + console.log(name + ' task'); + complete(); + }); + }, {async: true}); }); +}); //////////////////////////////////////////////////////////// task('clean', function () { utils.file.rmRf('./foo'); diff --git a/test/rule.js b/test/rule.js index 16ba70bd..907a8aa9 100644 --- a/test/rule.js +++ b/test/rule.js @@ -11,6 +11,7 @@ var cleanUpAndNext = function (callback) { var tmpFiles = [ 'tmp' , 'tmp_ns' + , 'tmp_ms' , 'tmp_cr' , 'tmp_p' , 'tmp_pf' @@ -141,6 +142,34 @@ var tests = { }); } +, 'test rule w multiple source': function (next) { + h.exec( '../bin/cli.js -f Jakefile.rule tmp_ms', function (out) { + debugger; + var output = [ + "tmpsrc/bar123.1 task" + , "tmpsrc/bar123.2 task" + , "tmpsrc/bar123.3 task" + , "created .glom" + , "tmpsrc/foo123.1 task" + , "tmpsrc/foo123.2 task" + , "tmpsrc/foo123.3 task" + , "created .glom" + , "multiple source rules task" ]; + var data; + assert.equal( output.join('\n') , out); + data = fs.readFileSync(process.cwd() + '/tmp_ms'); + assert.equal([ + 'tmpsrc/foo123.1', + 'tmpsrc/foo123.2', + 'tmpsrc/foo123.3', + 'tmpsrc/bar123.1', + 'tmpsrc/bar123.2', + 'tmpsrc/bar123.3', + ' multiple source rules'].join("\n"), data.toString()); + cleanUpAndNext(next); + }); + } + }; ['precedence', 'regexPattern', 'sourceFunction'].forEach(function (key) {