Skip to content

Commit

Permalink
Implementation for issue gulpjs#92
Browse files Browse the repository at this point in the history
  • Loading branch information
sttk committed Sep 4, 2016
1 parent 9b053ed commit 5385b87
Show file tree
Hide file tree
Showing 30 changed files with 1,332 additions and 71 deletions.
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ install:
test_script:
- node --version
- npm --version
- for %%f in (test\*.js) do node_modules\.bin\lab %%f -v -m 5000 -I Reflect & if errorlevel 1 exit /b 1
- for %%f in (test\lib\*.js test\*.js) do node_modules\.bin\lab %%f -v -m 5000 -I Reflect & if errorlevel 1 exit /b 1

build: off

Expand Down
59 changes: 50 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ var verifyDeps = require('./lib/shared/verifyDependencies');
var cliVersion = require('./package.json').version;
var getBlacklist = require('./lib/shared/getBlacklist');
var toConsole = require('./lib/shared/log/toConsole');
var customization = require('./lib/shared/customization');

// Logging functions
var logVerify = require('./lib/shared/log/verify');
Expand Down Expand Up @@ -50,6 +51,8 @@ var cli = new Liftoff({
},
});

var specifiedFlags = customization.getSpecifiedFlags(yargs.argv, cliOptions);

var usage =
'\n' + chalk.bold('Usage:') +
' gulp ' + chalk.blue('[options]') + ' tasks';
Expand Down Expand Up @@ -96,14 +99,8 @@ module.exports = run;

// The actual logic
function handleArguments(env) {

// Map an array of keys to preserve order
var configFilePaths = ['home', 'cwd'].map(function(key) {
return env.configFiles['.gulp'][key];
});
configFilePaths.filter(isString).forEach(function(filePath) {
merge(opts, require(filePath));
});
var disp = {}; // Display settings.
customize(opts, env, disp);

if (opts.help) {
console.log(parser.help());
Expand Down Expand Up @@ -169,5 +166,49 @@ function handleArguments(env) {
}

// Load and execute the CLI version
require(path.join(__dirname, '/lib/versioned/', range, '/'))(opts, env);
require(path.join(__dirname, '/lib/versioned/', range, '/'))(opts, env, disp);
}

function customize(opts, env, disp) {
var specifiedOpts = customization.getSpecifiedOpts(opts, specifiedFlags);
var specifiedEnv = customization.getSpecifiedEnv(env, specifiedFlags);

// Map an array of keys to preserve order
var configFilePaths = ['home', 'cwd'].map(function(key) {
return env.configFiles['.gulp'][key];
});

configFilePaths.filter(isString).forEach(function(filePath) {
var config = require(filePath);
customizeByEachConfig(config, opts, env, disp, filePath);
});

merge(opts, specifiedOpts);
merge(env, specifiedEnv);
}

function customizeByEachConfig(config, opts, env, disp, filePath) {
try {
var config = require(filePath);

var customizationOpts = {
basedir: path.dirname(filePath),
};

customization.copyProps(config, opts, customization.configSpecs, {
'flags.help': 'help',
}, customizationOpts);

customization.copyProps(config, env, customization.configSpecs, {
'flags.gulpfile': 'configPath',
}, customizationOpts);

customization.copyProps(config, disp, customization.configSpecs, {
description: 'description',
}, customizationOpts);

} catch (e) {
log.error(chalk.red('Invalid config: ' + e.message + ' in ' + filePath));
exit(1);
}
}
61 changes: 61 additions & 0 deletions lib/shared/customization/cli-flags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
'use strict';

var camelCase = require('camelcase');
var pick = require('lodash.pick');

var cliFlags = {};

cliFlags.getNamesInArgv = function(argv, cliOptions) {
return Object.keys(cliOptions).filter(isInArgv).map(toCamelCase);

/* $lab:coverage:off$ */
function isInArgv(flag) {
/* $lab:coverage:on$ */
if (argv[flag] !== undefined) {
return true;
}
if (argv[cliOptions[flag].alias] !== undefined) {
return true;
}
return false;
}
};

// `camelCase` can receive multiple arguments.
// So an error occurs when using with Array.map
function toCamelCase(str) {
return camelCase(str);
}

cliFlags.getOptsByNames = function(opts, optnames) {
return pick(opts, optnames);
};

cliFlags.getEnvByOptNames = function(env, optnames) {
var result = {};

for (var i = 0, n = optnames.length; i < n; i++) {
switch (optnames[i]) {

case 'cwd':
case 'gulpfile': {
result.cwd = env.cwd;

if (env.configPath) {
result.configPath = env.configPath;
}
break;
}

case 'require': {
result.require = env.require;
break;
}

}
}

return result;
};

module.exports = cliFlags;
19 changes: 19 additions & 0 deletions lib/shared/customization/convert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';

var path = require('path');

module.exports = function(value, spec, opts) {
switch (spec.type) {

case 'string': {
if (spec.semtype === 'path') {
return path.resolve(opts.basedir, value);
}
return value;
}

default: {
return value;
}
}
};
33 changes: 33 additions & 0 deletions lib/shared/customization/copy-props.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use strict';

var validate = require('./validate');
var convert = require('./convert');
var getProp = require('lodash.get');
var setProp = require('lodash.set');

module.exports = function(src, dst, specs, propsFromTo, opts) {
var keys = Object.keys(propsFromTo);
for (var i = 0, n = keys.length; i < n; i++) {
var srcKey = keys[i];
var dstKey = propsFromTo[srcKey];

var srcVal = getProp(src, srcKey);
if (srcVal === undefined) {
continue;
}

var spec = getProp(specs, srcKey);
if (!spec) {
continue;
}

if (!validate(srcVal, spec)) {
throw new Error(srcKey);
}

srcVal = convert(srcVal, spec, opts);

setProp(dst, dstKey, srcVal);
}
};

17 changes: 17 additions & 0 deletions lib/shared/customization/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

var cliFlags = require('./cli-flags');


module.exports = {

getSpecifiedFlags: cliFlags.getNamesInArgv,

getSpecifiedOpts: cliFlags.getOptsByNames,

getSpecifiedEnv: cliFlags.getEnvByOptNames,

copyProps: require('./copy-props'),

configSpecs: require('./specs'),
};
21 changes: 21 additions & 0 deletions lib/shared/customization/specs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict';

module.exports = {

description: {
type: 'string',
requiresArg: true,
},

flags: {
help: {
type: 'boolean',
},

gulpfile: {
type: 'string',
requiresArg: true,
semtype: 'path',
},
},
};
24 changes: 24 additions & 0 deletions lib/shared/customization/validate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use strict';

var isString = require('lodash.isstring');

module.exports = function(val, spec) {
switch (spec.type) {

case 'string': {
if (!isString(val)) {
return false;
}

if (spec.requiresArg && !val) {
return false;
}

return true;
}

default: {
return (typeof val === spec.type);
}
}
};
7 changes: 3 additions & 4 deletions lib/versioned/^3.7.0/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ var chalk = require('chalk');
var log = require('gulplog');
var stdout = require('mute-stdout');
var tildify = require('tildify');
var isString = require('lodash.isstring');

var taskTree = require('./taskTree');
var logTasks = require('../../shared/log/tasks');
var logEvents = require('./log/events');
var logTasksSimple = require('./log/tasksSimple');
var registerExports = require('../../shared/registerExports');

function execute(opts, env) {
function execute(opts, env, disp) {
var tasks = opts._;
var toRun = tasks.length ? tasks : ['default'];

Expand All @@ -39,8 +38,8 @@ function execute(opts, env) {
}
if (opts.tasks) {
var tree = taskTree(gulpInst.tasks);
if (opts.description && isString(opts.description)) {
tree.label = opts.description;
if (disp.description) {
tree.label = disp.description;
} else {
tree.label = 'Tasks for ' + chalk.magenta(tildify(env.configPath));
}
Expand Down
7 changes: 3 additions & 4 deletions lib/versioned/^4.0.0-alpha.1/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ var log = require('gulplog');
var chalk = require('chalk');
var stdout = require('mute-stdout');
var tildify = require('tildify');
var isString = require('lodash.isstring');

var exit = require('../../shared/exit');

Expand All @@ -16,7 +15,7 @@ var logSyncTask = require('../^4.0.0/log/syncTask');
var logTasksSimple = require('../^4.0.0/log/tasksSimple');
var registerExports = require('../../shared/registerExports');

function execute(opts, env) {
function execute(opts, env, disp) {

var tasks = opts._;
var toRun = tasks.length ? tasks : ['default'];
Expand Down Expand Up @@ -44,8 +43,8 @@ function execute(opts, env) {
}
if (opts.tasks) {
var tree = {};
if (opts.description && isString(opts.description)) {
tree.label = opts.description;
if (disp.description) {
tree.label = disp.description;
} else {
tree.label = 'Tasks for ' + chalk.magenta(tildify(env.configPath));
}
Expand Down
11 changes: 5 additions & 6 deletions lib/versioned/^4.0.0-alpha.2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ var log = require('gulplog');
var chalk = require('chalk');
var stdout = require('mute-stdout');
var tildify = require('tildify');
var isString = require('lodash.isstring');

var exit = require('../../shared/exit');

Expand All @@ -18,7 +17,7 @@ var registerExports = require('../../shared/registerExports');

var getTask = require('../^4.0.0/log/getTask');

function execute(opts, env) {
function execute(opts, env, disp) {

var tasks = opts._;
var toRun = tasks.length ? tasks : ['default'];
Expand Down Expand Up @@ -49,8 +48,8 @@ function execute(opts, env) {
}
if (opts.tasks) {
tree = gulpInst.tree({ deep: true });
if (opts.description && isString(opts.description)) {
tree.label = opts.description;
if (disp.description) {
tree.label = disp.description;
} else {
tree.label = 'Tasks for ' + chalk.magenta(tildify(env.configPath));
}
Expand All @@ -59,8 +58,8 @@ function execute(opts, env) {
}
if (opts.tasksJson) {
tree = gulpInst.tree({ deep: true });
if (opts.description && isString(opts.description)) {
tree.label = opts.description;
if (disp.description) {
tree.label = disp.description;
} else {
tree.label = 'Tasks for ' + tildify(env.configPath);
}
Expand Down
Loading

0 comments on commit 5385b87

Please sign in to comment.