Skip to content

Commit 3c3ff53

Browse files
author
sttk
committed
Restrict config properties
1 parent dd7ff9f commit 3c3ff53

24 files changed

+837
-44
lines changed

index.js

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@
33
var fs = require('fs');
44
var path = require('path');
55
var log = require('gulplog');
6+
var fancyLog = require('fancy-log');
67
var chalk = require('chalk');
78
var yargs = require('yargs');
89
var Liftoff = require('liftoff');
910
var tildify = require('tildify');
1011
var interpret = require('interpret');
1112
var v8flags = require('v8flags');
12-
var merge = require('lodash.merge');
13-
var isString = require('lodash.isstring');
1413
var findRange = require('semver-greatest-satisfied-range');
1514
var exit = require('./lib/shared/exit');
1615
var cliOptions = require('./lib/shared/cliOptions');
@@ -20,6 +19,10 @@ var cliVersion = require('./package.json').version;
2019
var getBlacklist = require('./lib/shared/getBlacklist');
2120
var toConsole = require('./lib/shared/log/toConsole');
2221

22+
var loadConfigFiles = require('./lib/shared/config/loadfiles');
23+
var mergeToCliFlags = require('./lib/shared/config/cli-flags');
24+
var mergeToEnvFlags = require('./lib/shared/config/env-flags');
25+
2326
// Logging functions
2427
var logVerify = require('./lib/shared/log/verify');
2528
var logBlacklistError = require('./lib/shared/log/blacklistError');
@@ -65,15 +68,13 @@ if (opts.continue) {
6568
process.env.UNDERTAKER_SETTLE = 'true';
6669
}
6770

68-
// Set up event listeners for logging.
69-
toConsole(log, opts);
70-
7171
cli.on('require', function(name) {
72-
log.info('Requiring external module', chalk.magenta(name));
72+
fancyLog('Requiring external module', chalk.magenta(name));
7373
});
7474

7575
cli.on('requireFail', function(name) {
76-
log.error(chalk.red('Failed to load external module'), chalk.magenta(name));
76+
fancyLog.error(
77+
chalk.red('Failed to load external module'), chalk.magenta(name));
7778
});
7879

7980
cli.on('respawn', function(flags, child) {
@@ -84,26 +85,35 @@ cli.on('respawn', function(flags, child) {
8485
});
8586

8687
function run() {
87-
cli.launch({
88+
var envOpts = {
8889
cwd: opts.cwd,
8990
configPath: opts.gulpfile,
9091
require: opts.require,
9192
completion: opts.completion,
92-
}, handleArguments);
93+
};
94+
95+
cli.launch(envOpts, function(env) {
96+
var config;
97+
try {
98+
config = loadConfigFiles(env.configFiles['.gulp'], ['home', 'cwd']);
99+
} catch (e) {
100+
log.error(chalk.red(e.message));
101+
exit(1);
102+
}
103+
104+
mergeToCliFlags(opts, config, cliOptions);
105+
mergeToEnvFlags(env, config, envOpts);
106+
107+
handleArguments(env, opts, config);
108+
});
93109
}
94110

95111
module.exports = run;
96112

97113
// The actual logic
98-
function handleArguments(env) {
99-
100-
// Map an array of keys to preserve order
101-
var configFilePaths = ['home', 'cwd'].map(function(key) {
102-
return env.configFiles['.gulp'][key];
103-
});
104-
configFilePaths.filter(isString).forEach(function(filePath) {
105-
merge(opts, require(filePath));
106-
});
114+
function handleArguments(env, opts, cfg) {
115+
// Set up event listeners for logging.
116+
toConsole(log, opts);
107117

108118
if (opts.help) {
109119
console.log(parser.help());
@@ -169,5 +179,5 @@ function handleArguments(env) {
169179
}
170180

171181
// Load and execute the CLI version
172-
require(path.join(__dirname, '/lib/versioned/', range, '/'))(opts, env);
182+
require(path.join(__dirname, '/lib/versioned/', range, '/'))(opts, env, cfg);
173183
}

lib/shared/config/cfg-specs.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'use strict';
2+
3+
var path = require('path');
4+
5+
module.exports = {
6+
7+
description: {
8+
validate: function(value) {
9+
if (typeof value !== 'string') {
10+
throw new TypeError('config.description must be a string: ' + value);
11+
}
12+
if (!value) {
13+
throw new Error('config.description requires a value.');
14+
}
15+
return value;
16+
},
17+
},
18+
19+
'flags.silent': {
20+
validate: function(value) {
21+
if (typeof value !== 'boolean') {
22+
throw new TypeError('config.flags.silent must be a boolean: ' + value);
23+
}
24+
return value;
25+
},
26+
},
27+
28+
'flags.gulpfile': {
29+
validate: function(value, configFile) {
30+
if (typeof value !== 'string') {
31+
throw new TypeError(
32+
'config.flags.gulpfile must be a string: ' + value);
33+
}
34+
if (!value) {
35+
throw new Error('config.flags.gulpfile requires a value.');
36+
}
37+
return path.resolve(path.dirname(configFile), value);
38+
},
39+
},
40+
};

lib/shared/config/cli-flags.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
3+
var yargs = require('yargs');
4+
var camelCase = require('lodash.camelcase');
5+
6+
function mergeToCliFlags(cliFlags, config, cliOptions) {
7+
var argv = yargs(process.argv.slice(2)).argv;
8+
var cfgFlags = config.flags || {};
9+
10+
var optNames = ['silent'];
11+
optNames.filter(excludeArgsByUser).map(camelCase).forEach(copyConfig);
12+
13+
function excludeArgsByUser(name) {
14+
return !(argv[name] != null || argv[cliOptions[name].alias] != null);
15+
}
16+
17+
function copyConfig(name) {
18+
if (cfgFlags[name] !== undefined) {
19+
cliFlags[name] = cfgFlags[name];
20+
}
21+
}
22+
}
23+
24+
module.exports = mergeToCliFlags;

lib/shared/config/env-flags.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
'use strict';
2+
3+
var path = require('path');
4+
5+
function mergeToEnvFlags(envFlags, config, envOpts) {
6+
var cfgFlags = config.flags || {};
7+
8+
if (!envOpts.configPath && cfgFlags.gulpfile) {
9+
envFlags.configPath = cfgFlags.gulpfile;
10+
envFlags.configBase = path.dirname(cfgFlags.gulpfile);
11+
}
12+
}
13+
14+
module.exports = mergeToEnvFlags;

lib/shared/config/loadfiles.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
3+
var get = require('lodash.get');
4+
var set = require('lodash.set');
5+
var isString = require('lodash.isstring');
6+
var configSpecs = require('./cfg-specs');
7+
8+
function loadConfigFiles(configFilesBase, keysInOrder) {
9+
var config = {};
10+
11+
var configFilePaths = keysInOrder.map(function(key) {
12+
return configFilesBase[key];
13+
}).filter(isString);
14+
15+
configFilePaths.forEach(function(filePath) {
16+
var loadedCfg = require(filePath);
17+
18+
Object.keys(configSpecs).forEach(function(keyPath) {
19+
var spec = configSpecs[keyPath];
20+
21+
var value = get(loadedCfg, keyPath);
22+
if (value === undefined) {
23+
return;
24+
}
25+
26+
set(config, keyPath, spec.validate(value, filePath));
27+
});
28+
});
29+
30+
return config;
31+
}
32+
33+
module.exports = loadConfigFiles;

lib/versioned/^3.7.0/index.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@ var chalk = require('chalk');
44
var log = require('gulplog');
55
var stdout = require('mute-stdout');
66
var tildify = require('tildify');
7-
var isString = require('lodash.isstring');
87

98
var taskTree = require('./taskTree');
109
var logTasks = require('../../shared/log/tasks');
1110
var logEvents = require('./log/events');
1211
var logTasksSimple = require('./log/tasksSimple');
1312
var registerExports = require('../../shared/registerExports');
1413

15-
function execute(opts, env) {
14+
function execute(opts, env, config) {
1615
var tasks = opts._;
1716
var toRun = tasks.length ? tasks : ['default'];
1817

@@ -39,8 +38,8 @@ function execute(opts, env) {
3938
}
4039
if (opts.tasks) {
4140
var tree = taskTree(gulpInst.tasks);
42-
if (opts.description && isString(opts.description)) {
43-
tree.label = opts.description;
41+
if (config.description) {
42+
tree.label = config.description;
4443
} else {
4544
tree.label = 'Tasks for ' + chalk.magenta(tildify(env.configPath));
4645
}

lib/versioned/^4.0.0-alpha.1/index.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ var log = require('gulplog');
66
var chalk = require('chalk');
77
var stdout = require('mute-stdout');
88
var tildify = require('tildify');
9-
var isString = require('lodash.isstring');
109

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

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

19-
function execute(opts, env) {
18+
function execute(opts, env, config) {
2019

2120
var tasks = opts._;
2221
var toRun = tasks.length ? tasks : ['default'];
@@ -44,8 +43,8 @@ function execute(opts, env) {
4443
}
4544
if (opts.tasks) {
4645
var tree = {};
47-
if (opts.description && isString(opts.description)) {
48-
tree.label = opts.description;
46+
if (config.description) {
47+
tree.label = config.description;
4948
} else {
5049
tree.label = 'Tasks for ' + chalk.magenta(tildify(env.configPath));
5150
}

lib/versioned/^4.0.0-alpha.2/index.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ var log = require('gulplog');
66
var chalk = require('chalk');
77
var stdout = require('mute-stdout');
88
var tildify = require('tildify');
9-
var isString = require('lodash.isstring');
109

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

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

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

21-
function execute(opts, env) {
20+
function execute(opts, env, config) {
2221

2322
var tasks = opts._;
2423
var toRun = tasks.length ? tasks : ['default'];
@@ -49,8 +48,8 @@ function execute(opts, env) {
4948
}
5049
if (opts.tasks) {
5150
tree = gulpInst.tree({ deep: true });
52-
if (opts.description && isString(opts.description)) {
53-
tree.label = opts.description;
51+
if (config.description) {
52+
tree.label = config.description;
5453
} else {
5554
tree.label = 'Tasks for ' + chalk.magenta(tildify(env.configPath));
5655
}
@@ -59,8 +58,8 @@ function execute(opts, env) {
5958
}
6059
if (opts.tasksJson) {
6160
tree = gulpInst.tree({ deep: true });
62-
if (opts.description && isString(opts.description)) {
63-
tree.label = opts.description;
61+
if (config.description) {
62+
tree.label = config.description;
6463
} else {
6564
tree.label = 'Tasks for ' + tildify(env.configPath);
6665
}

lib/versioned/^4.0.0/index.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ var log = require('gulplog');
66
var chalk = require('chalk');
77
var stdout = require('mute-stdout');
88
var tildify = require('tildify');
9-
var isString = require('lodash.isstring');
109

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

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

1918
var getTask = require('./log/getTask');
2019

21-
function execute(opts, env) {
20+
function execute(opts, env, config) {
2221

2322
var tasks = opts._;
2423
var toRun = tasks.length ? tasks : ['default'];
@@ -49,8 +48,8 @@ function execute(opts, env) {
4948
}
5049
if (opts.tasks) {
5150
tree = gulpInst.tree({ deep: true });
52-
if (opts.description && isString(opts.description)) {
53-
tree.label = opts.description;
51+
if (config.description) {
52+
tree.label = config.description;
5453
} else {
5554
tree.label = 'Tasks for ' + chalk.magenta(tildify(env.configPath));
5655
}
@@ -59,8 +58,8 @@ function execute(opts, env) {
5958
}
6059
if (opts.tasksJson) {
6160
tree = gulpInst.tree({ deep: true });
62-
if (opts.description && isString(opts.description)) {
63-
tree.label = opts.description;
61+
if (config.description) {
62+
tree.label = config.description;
6463
} else {
6564
tree.label = 'Tasks for ' + tildify(env.configPath);
6665
}

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"lint": "eslint . && jscs index.js bin/ lib/ test/",
2727
"prepublish": "marked-man --name gulp docs/CLI.md > gulp.1",
2828
"pretest": "npm run lint",
29-
"test": "mocha --async-only --timeout 3000",
29+
"test": "mocha --async-only --timeout 3000 test/lib test",
3030
"cover": "nyc --reporter=lcov --reporter=text-summary npm test",
3131
"coveralls": "nyc --reporter=text-lcov npm test | coveralls",
3232
"changelog": "github-changes -o gulpjs -r gulp-cli -b master -f ./CHANGELOG.md --order-semver --use-commit-body"
@@ -38,10 +38,12 @@
3838
"gulplog": "^1.0.0",
3939
"interpret": "^1.0.0",
4040
"liftoff": "^2.3.0",
41+
"lodash.camelcase": "^4.3.0",
42+
"lodash.get": "^4.4.2",
4143
"lodash.isfunction": "^3.0.8",
4244
"lodash.isplainobject": "^4.0.4",
4345
"lodash.isstring": "^4.0.1",
44-
"lodash.merge": "^4.5.1",
46+
"lodash.set": "^4.3.2",
4547
"lodash.sortby": "^4.5.0",
4648
"matchdep": "^1.0.0",
4749
"mute-stdout": "^1.0.0",
@@ -62,8 +64,7 @@
6264
"fs-extra": "^0.26.1",
6365
"github-changes": "^1.0.1",
6466
"gulp": "gulpjs/gulp#4.0",
65-
"gulp-test-tools": "^0.6.0",
66-
"istanbul": "^0.4.5",
67+
"gulp-test-tools": "^0.6.1",
6768
"jscs": "^2.3.5",
6869
"jscs-preset-gulp": "^1.0.0",
6970
"marked-man": "^0.1.3",

0 commit comments

Comments
 (0)