From 022e9673e8cf768cc9816acfe85f160ae0a5356c Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Mon, 17 Dec 2018 18:02:28 -0500 Subject: [PATCH 01/22] De-duplicate the initial log state --- lib/run/log.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/run/log.js b/lib/run/log.js index b015338..798801d 100644 --- a/lib/run/log.js +++ b/lib/run/log.js @@ -1,7 +1,7 @@ var _ = require('lodash') -var isSilent = false -var output = '' +var isSilent +var output module.exports = function () { if (!isSilent) { @@ -27,3 +27,5 @@ module.exports.reset = function () { isSilent = false output = '' } + +module.exports.reset() From 6618d3192da6e277e02608c4bef2e639806c9de9 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Mon, 17 Dec 2018 18:04:07 -0500 Subject: [PATCH 02/22] Leverage util.format for pretty-printing log messages --- lib/run/log.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/run/log.js b/lib/run/log.js index 798801d..a989978 100644 --- a/lib/run/log.js +++ b/lib/run/log.js @@ -1,4 +1,5 @@ var _ = require('lodash') +var util = require('util') var isSilent var output @@ -11,7 +12,7 @@ module.exports = function () { console.log.apply(this, arguments) } } else { - output += _.toArray(arguments).join(' ') + '\n' + output += util.format.apply(util, arguments) + '\n' } } From 1e7d82f4be7084886b165afd23683eec1270e79a Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Mon, 17 Dec 2018 18:07:52 -0500 Subject: [PATCH 03/22] All scripty output goes to STDERR --- lib/run/log.js | 7 +------ lib/run/log.test.js | 14 ++++---------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/lib/run/log.js b/lib/run/log.js index a989978..4a91646 100644 --- a/lib/run/log.js +++ b/lib/run/log.js @@ -1,4 +1,3 @@ -var _ = require('lodash') var util = require('util') var isSilent @@ -6,11 +5,7 @@ var output module.exports = function () { if (!isSilent) { - if (_.startsWith(arguments[0], 'Error:')) { - console.error.apply(this, arguments) - } else { - console.log.apply(this, arguments) - } + console.error.apply(this, arguments) } else { output += util.format.apply(util, arguments) + '\n' } diff --git a/lib/run/log.test.js b/lib/run/log.test.js index 3158324..362b46a 100644 --- a/lib/run/log.test.js +++ b/lib/run/log.test.js @@ -2,19 +2,13 @@ var subject = require('./log') module.exports = { beforeEach: function () { - td.replace(console, 'log') td.replace(console, 'error') subject.reset() }, - normallyJustLogs: function () { + writesToStderr: function () { subject('foo') - td.verify(console.log('foo')) - }, - consoleErrorsWhenStartingWithError: function () { - subject('Error: foo') - - td.verify(console.error('Error: foo')) + td.verify(console.error('foo')) }, modeSwitchCapturesLogs: function () { subject.shush() @@ -22,7 +16,7 @@ module.exports = { subject('bar') subject('baz', 'noz') - td.verify(console.log(), { ignoreExtraArgs: true, times: 0 }) + td.verify(console.error(), { ignoreExtraArgs: true, times: 0 }) assert.equal(subject.read(), 'bar\nbaz noz\n') }, resetResetsMode: function () { @@ -31,7 +25,7 @@ module.exports = { subject.reset() subject('biz') - td.verify(console.log('biz')) + td.verify(console.error('biz')) }, resetResetsLog: function () { subject.shush() From ae9d110dc483c82477f1f9cf8cb34d9e2bdf1cb5 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Mon, 17 Dec 2018 18:19:53 -0500 Subject: [PATCH 04/22] Output goes through the logger --- lib/resolve-script/find-executables.js | 3 ++- lib/resolve-script/find-executables.test.js | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/resolve-script/find-executables.js b/lib/resolve-script/find-executables.js index cd933d7..ce02c5e 100644 --- a/lib/resolve-script/find-executables.js +++ b/lib/resolve-script/find-executables.js @@ -1,5 +1,6 @@ var _ = require('lodash') var globFirst = require('./glob-first') +var log = require('../run/log') var path = require('path') var async = require('async') @@ -13,7 +14,7 @@ module.exports = function (patterns, cb) { if (itIsExecutable) { cb(er, path.resolve(result)) } else { - console.warn( + log( 'Warning: scripty - ignoring script "' + result + '" because it' + ' was not executable. Run `chmod +x "' + result + '" if you want' + ' scripty to run it.' diff --git a/lib/resolve-script/find-executables.test.js b/lib/resolve-script/find-executables.test.js index cdf8f2f..79f2af4 100644 --- a/lib/resolve-script/find-executables.test.js +++ b/lib/resolve-script/find-executables.test.js @@ -1,5 +1,6 @@ var _ = require('lodash') var path = require('path') +var log = require('../run/log') var base = function (glob) { return path.resolve('test/fixtures/unit/find-executables', glob) @@ -8,7 +9,7 @@ var subject = require('./find-executables') module.exports = { beforeEach: function () { - td.replace(console, 'warn') + log.shush() }, noFilesFound: function (done) { subject([base('does-not-exist*')], function (er, result) { @@ -26,11 +27,11 @@ module.exports = { if (process.platform === 'win32') return done() subject([base('file.*')], function (er, result) { assert.deepEqual(result, [base('file.executable')]) - td.verify(console.warn( + assert.includes(log.read(), 'Warning: scripty - ignoring script "' + base('file.not.executable') + '" because it was not executable. Run `chmod +x "' + base('file.not.executable') + '" if you want scripty to run it.' - )) + ) done(er) }) }, From 283d7b238b0a778971a9b77d929acf697b4bd501 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Mon, 17 Dec 2018 18:26:56 -0500 Subject: [PATCH 05/22] Leverage util.format for printf-style logging --- lib/resolve-script/find-executables.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/resolve-script/find-executables.js b/lib/resolve-script/find-executables.js index ce02c5e..529e9af 100644 --- a/lib/resolve-script/find-executables.js +++ b/lib/resolve-script/find-executables.js @@ -15,10 +15,9 @@ module.exports = function (patterns, cb) { cb(er, path.resolve(result)) } else { log( - 'Warning: scripty - ignoring script "' + result + '" because it' + - ' was not executable. Run `chmod +x "' + result + '" if you want' + - ' scripty to run it.' - ) + 'Warning: scripty - ignoring script "%s" because it' + + ' was not executable. Run `chmod +x "%s" if you want' + + ' scripty to run it.', result, result) cb(er, undefined) } }) From 721e90bcfffcbd8b0f1f2b8de8e42e87004b80bd Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Mon, 17 Dec 2018 19:39:32 -0500 Subject: [PATCH 06/22] Derive the log level from various rules --- lib/load-log-level.js | 24 ++++++++++++++++++ lib/load-log-level.test.js | 52 ++++++++++++++++++++++++++++++++++++++ lib/run/log.js | 8 ++++++ 3 files changed, 84 insertions(+) create mode 100644 lib/load-log-level.js create mode 100644 lib/load-log-level.test.js diff --git a/lib/load-log-level.js b/lib/load-log-level.js new file mode 100644 index 0000000..c5e81a8 --- /dev/null +++ b/lib/load-log-level.js @@ -0,0 +1,24 @@ +var loadOption = require('./load-option') +var level = require('./run/log').levels + +module.exports = function () { + var logLevel = String(loadOption('logLevel')).toUpperCase() + + if (level[logLevel]) { + return level[logLevel] + } + + if (loadOption('verbose')) { + return level.VERBOSE + } + + if (loadOption('dryRun')) { + return level.INFO + } + + if (loadOption('silent') || loadOption('quiet')) { + return level.SILENT + } + + return level.INFO +} diff --git a/lib/load-log-level.test.js b/lib/load-log-level.test.js new file mode 100644 index 0000000..fee97b8 --- /dev/null +++ b/lib/load-log-level.test.js @@ -0,0 +1,52 @@ +var subject = require('./load-log-level') +var level = require('./run/log').levels + +module.exports = { + beforeEach: function () { + delete process.env.SCRIPTY_QUIET + delete process.env.SCRIPTY_SILENT + delete process.env.SCRIPTY_DRY_RUN + delete process.env.SCRIPTY_VERBOSE + delete process.env.SCRIPTY_LOG_LEVEL + }, + + 'defaults to INFO': function () { + assert.equal(subject(), level.INFO) + }, + + 'explicit logLevel takes precedence': function () { + process.env.SCRIPTY_SILENT = true + process.env.SCRIPTY_DRY_RUN = true + process.env.SCRIPTY_VERBOSE = true + process.env.SCRIPTY_LOG_LEVEL = 'warn' + assert.equal(subject(), level.WARN) + }, + + 'ignores unrecognized values': function () { + process.env.SCRIPTY_LOG_LEVEL = 'worn' + assert.equal(subject(), level.INFO) + }, + + 'verbose preempts dry-run and silent': function () { + process.env.SCRIPTY_SILENT = true + process.env.SCRIPTY_DRY_RUN = true + process.env.SCRIPTY_VERBOSE = true + assert.equal(subject(), level.VERBOSE) + }, + + 'dry-run preempts silent': function () { + process.env.SCRIPTY_SILENT = true + process.env.SCRIPTY_DRY_RUN = true + assert.equal(subject(), level.INFO) + }, + + 'silent is read last': function () { + process.env.SCRIPTY_SILENT = true + assert.equal(subject(), level.SILENT) + }, + + 'quiet is alias for silent': function () { + process.env.SCRIPTY_QUIET = true + assert.equal(subject(), level.SILENT) + } +} diff --git a/lib/run/log.js b/lib/run/log.js index 4a91646..d957fa2 100644 --- a/lib/run/log.js +++ b/lib/run/log.js @@ -24,4 +24,12 @@ module.exports.reset = function () { output = '' } +module.exports.levels = { + VERBOSE: 1, + INFO: 2, + WARN: 3, + ERROR: 4, + SILENT: 5 +} + module.exports.reset() From 6c11456f324416cb1db7c357e17a2fe743157d1e Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Mon, 17 Dec 2018 22:57:35 -0500 Subject: [PATCH 07/22] Adds methods to logger that respect the level --- lib/run/log.js | 29 +++++++++++++++++++++++------ lib/run/log.test.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/lib/run/log.js b/lib/run/log.js index d957fa2..4a4e961 100644 --- a/lib/run/log.js +++ b/lib/run/log.js @@ -2,6 +2,13 @@ var util = require('util') var isSilent var output +var LEVELS = { + VERBOSE: 1, + INFO: 2, + WARN: 3, + ERROR: 4, + SILENT: 5 +} module.exports = function () { if (!isSilent) { @@ -11,6 +18,8 @@ module.exports = function () { } } +module.exports.levels = LEVELS + module.exports.shush = function () { isSilent = true } @@ -22,14 +31,22 @@ module.exports.read = function () { module.exports.reset = function () { isSilent = false output = '' + module.exports.level(LEVELS.INFO) } -module.exports.levels = { - VERBOSE: 1, - INFO: 2, - WARN: 3, - ERROR: 4, - SILENT: 5 +module.exports.level = function (level) { + for (var l in LEVELS) { + var methodName = l.toLowerCase() + if (level <= LEVELS[l]) { + module.exports[methodName] = console.error + } else { + module.exports[methodName] = silentLogger + } + } +} + +function silentLogger () { + output += util.format.apply(util, arguments) + '\n' } module.exports.reset() diff --git a/lib/run/log.test.js b/lib/run/log.test.js index 362b46a..c904dc3 100644 --- a/lib/run/log.test.js +++ b/lib/run/log.test.js @@ -10,6 +10,39 @@ module.exports = { td.verify(console.error('foo')) }, + setTheLogLevel: { + verbose: function () { + subject.level(subject.levels.VERBOSE) + subject.verbose('ity') + td.verify(console.error('ity')) + }, + info: function () { + subject.level(subject.levels.INFO) + td.when(console.error('ity')).thenThrow(new Error('Should not log verbose calls at INFO level')) + subject.verbose('ity') + subject.info('mation') + td.verify(console.error('mation')) + }, + warn: function () { + subject.level(subject.levels.WARN) + td.when(console.error('mation')).thenThrow(new Error('Should not log info calls at WARN level')) + subject.info('mation') + subject.warn('ing') + td.verify(console.error('ing')) + }, + error: function () { + subject.level(subject.levels.ERROR) + td.when(console.error('ing')).thenThrow(new Error('Should not log warn calls at ERROR level')) + subject.warn('ing') + subject.error('fail') + td.verify(console.error('fail')) + }, + silent: function () { + subject.level(subject.levels.SILENT) + td.when(console.error('fail')).thenThrow(new Error('Should not log error calls at SILENT level')) + subject.error('fail') + } + }, modeSwitchCapturesLogs: function () { subject.shush() From c54fe668fada3e920fd98b7eb40bc2f4a7757eaa Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Mon, 17 Dec 2018 23:23:49 -0500 Subject: [PATCH 08/22] Log with explicit level-specific methods --- lib/resolve-script/find-executables.js | 2 +- lib/run/dry-run.js | 2 +- lib/run/log.js | 12 ++---------- lib/run/log.test.js | 12 ++++++------ lib/run/print-script.js | 6 +++--- 5 files changed, 13 insertions(+), 21 deletions(-) diff --git a/lib/resolve-script/find-executables.js b/lib/resolve-script/find-executables.js index 529e9af..feced6d 100644 --- a/lib/resolve-script/find-executables.js +++ b/lib/resolve-script/find-executables.js @@ -14,7 +14,7 @@ module.exports = function (patterns, cb) { if (itIsExecutable) { cb(er, path.resolve(result)) } else { - log( + log.warn( 'Warning: scripty - ignoring script "%s" because it' + ' was not executable. Run `chmod +x "%s" if you want' + ' scripty to run it.', result, result) diff --git a/lib/run/dry-run.js b/lib/run/dry-run.js index cad38f6..861eec7 100644 --- a/lib/run/dry-run.js +++ b/lib/run/dry-run.js @@ -4,7 +4,7 @@ var printScript = require('./print-script') var log = require('./log') module.exports = function (scriptFiles, cb) { - log('This is a dry run. Executed scripts would be:\n') + log.info('This is a dry run. Executed scripts would be:\n') _.map(scriptFiles, printScript) cb(null, 0) } diff --git a/lib/run/log.js b/lib/run/log.js index 4a4e961..276c8f9 100644 --- a/lib/run/log.js +++ b/lib/run/log.js @@ -1,6 +1,5 @@ var util = require('util') -var isSilent var output var LEVELS = { VERBOSE: 1, @@ -10,18 +9,12 @@ var LEVELS = { SILENT: 5 } -module.exports = function () { - if (!isSilent) { - console.error.apply(this, arguments) - } else { - output += util.format.apply(util, arguments) + '\n' - } -} +module.exports = {} module.exports.levels = LEVELS module.exports.shush = function () { - isSilent = true + module.exports.level(LEVELS.SILENT) } module.exports.read = function () { @@ -29,7 +22,6 @@ module.exports.read = function () { } module.exports.reset = function () { - isSilent = false output = '' module.exports.level(LEVELS.INFO) } diff --git a/lib/run/log.test.js b/lib/run/log.test.js index c904dc3..6914a5c 100644 --- a/lib/run/log.test.js +++ b/lib/run/log.test.js @@ -6,7 +6,7 @@ module.exports = { subject.reset() }, writesToStderr: function () { - subject('foo') + subject.info('foo') td.verify(console.error('foo')) }, @@ -38,7 +38,7 @@ module.exports = { td.verify(console.error('fail')) }, silent: function () { - subject.level(subject.levels.SILENT) + subject.shush() td.when(console.error('fail')).thenThrow(new Error('Should not log error calls at SILENT level')) subject.error('fail') } @@ -46,8 +46,8 @@ module.exports = { modeSwitchCapturesLogs: function () { subject.shush() - subject('bar') - subject('baz', 'noz') + subject.info('bar') + subject.info('baz', 'noz') td.verify(console.error(), { ignoreExtraArgs: true, times: 0 }) assert.equal(subject.read(), 'bar\nbaz noz\n') @@ -57,12 +57,12 @@ module.exports = { subject.reset() - subject('biz') + subject.info('biz') td.verify(console.error('biz')) }, resetResetsLog: function () { subject.shush() - subject('lalalal') + subject.info('lalalal') subject.reset() diff --git a/lib/run/print-script.js b/lib/run/print-script.js index bc9b719..04a5dfa 100644 --- a/lib/run/print-script.js +++ b/lib/run/print-script.js @@ -4,10 +4,10 @@ var _ = require('lodash') var log = require('./log') module.exports = function (scriptFile) { - log('Executing "' + scriptFile + '":\n') + log.info('Executing "' + scriptFile + '":\n') var script = read(scriptFile) if (script) { - log(_.map(script.split('\n'), function (line) { + log.verbose(_.map(script.split('\n'), function (line) { return '> ' + line }).join('\n') + '\n\n') } @@ -17,7 +17,7 @@ function read (scriptFile) { try { return fs.readFileSync(scriptFile).toString() } catch (e) { - log( + log.error( 'Error: scripty - failed trying to read "' + scriptFile + '":\n\n' + e.message ) From 5198abfe8f80840cad8761184d832ed7c681e0fe Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Mon, 17 Dec 2018 23:24:44 -0500 Subject: [PATCH 09/22] Derive log level at CLI start; Set log level when running --- cli.js | 2 ++ lib/run/index.js | 3 +++ 2 files changed, 5 insertions(+) diff --git a/cli.js b/cli.js index b15a3c4..dffc4a4 100755 --- a/cli.js +++ b/cli.js @@ -21,12 +21,14 @@ if (!lifecycleEvent) { } else { var scripty = require('./lib/scripty') var loadOption = require('./lib/load-option') + var loadLogLevel = require('./lib/load-log-level') scripty(lifecycleEvent, { userArgs: process.argv.slice(2), parallel: loadOption('parallel'), dryRun: loadOption('dryRun'), silent: loadOption('silent'), + logLevel: loadLogLevel(), spawn: { stdio: 'inherit' }, diff --git a/lib/run/index.js b/lib/run/index.js index 4839ff3..e5beae3 100644 --- a/lib/run/index.js +++ b/lib/run/index.js @@ -4,8 +4,11 @@ var dryRun = require('./dry-run') var commandify = require('./commandify') var spawnScript = require('./spawn-script') var all = require('./all') +var log = require('./log') module.exports = function (scriptFiles, options, cb) { + log.level(options.logLevel) + if (options.dryRun) return dryRun(scriptFiles, cb) var commands = commandify(spawnScript, scriptFiles, options) From b930b547c7ff48f33b922ceac90843ad0e0aa003 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Tue, 18 Dec 2018 11:27:21 -0500 Subject: [PATCH 10/22] Removes usage of old `silent` option --- cli.js | 1 - lib/run/spawn-script.js | 2 +- lib/scripty.js | 3 ++- test/run-scripty.js | 2 ++ test/safe-helper.js | 3 --- test/safe/silent-test.js | 7 +++++-- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/cli.js b/cli.js index dffc4a4..df3b0e9 100755 --- a/cli.js +++ b/cli.js @@ -27,7 +27,6 @@ if (!lifecycleEvent) { userArgs: process.argv.slice(2), parallel: loadOption('parallel'), dryRun: loadOption('dryRun'), - silent: loadOption('silent'), logLevel: loadLogLevel(), spawn: { stdio: 'inherit' diff --git a/lib/run/spawn-script.js b/lib/run/spawn-script.js index 0f0d926..e8ab093 100644 --- a/lib/run/spawn-script.js +++ b/lib/run/spawn-script.js @@ -3,7 +3,7 @@ var printScript = require('./print-script') var spawn = require('child_process').spawn module.exports = function (scriptFile, options, cb) { - if (!options.silent) printScript(scriptFile) + printScript(scriptFile) var userArgs = options.userArgs var child = spawn(scriptFile, userArgs, options.spawn) child.on('close', function (code) { diff --git a/lib/scripty.js b/lib/scripty.js index c8cd0a7..4c72dab 100644 --- a/lib/scripty.js +++ b/lib/scripty.js @@ -1,6 +1,7 @@ var optionify = require('./optionify') var resolveScript = require('./resolve-script') var run = require('./run') +var log = require('./run/log') module.exports = optionify(function scripty (npmLifecycle, options, cb) { resolveScript(npmLifecycle, options.resolve, function (er, scriptFiles) { @@ -11,7 +12,7 @@ module.exports = optionify(function scripty (npmLifecycle, options, cb) { userArgs: [], parallel: false, dryRun: false, - silent: false, + logLevel: log.levels.INFO, spawn: {}, resolve: {} }) diff --git a/test/run-scripty.js b/test/run-scripty.js index 5ae977b..adbf4c1 100644 --- a/test/run-scripty.js +++ b/test/run-scripty.js @@ -3,11 +3,13 @@ var path = require('path') var scripty = require('../lib/scripty') var grabStdio = require('./grab-stdio') +var logLevel = require('../lib/run/log').levels module.exports = function (name, opts, cb) { var stdio = {} scripty(name, _.defaultsDeep({}, opts, { + logLevel: logLevel.SILENT, resolve: { builtIn: path.resolve('test/fixtures/built-in-scripts'), builtInWin: path.resolve('test/fixtures/built-in-scripts-win'), diff --git a/test/safe-helper.js b/test/safe-helper.js index 13788dc..af3cb30 100644 --- a/test/safe-helper.js +++ b/test/safe-helper.js @@ -4,9 +4,6 @@ global.assert = decorateAssertions(require('assert')) var log = require('../lib/run/log') module.exports = { - beforeEach: function () { - log.shush() - }, afterEach: function () { log.reset() } diff --git a/test/safe/silent-test.js b/test/safe/silent-test.js index 31d3078..813a380 100644 --- a/test/safe/silent-test.js +++ b/test/safe/silent-test.js @@ -2,8 +2,11 @@ var runScripty = require('../run-scripty') var log = require('../../lib/run/log') module.exports = function doesNotEchoScriptContentInSilentMode (done) { - runScripty('hello:world', { silent: true }, function (er, code, stdio) { - assert.equal(log.read(), '') + var oldConsole = global.console + global.console = {} // blow up if a console method is invoked + + runScripty('hello:world', { logLevel: log.levels.SILENT }, function (er, code, stdio) { + global.console = oldConsole done(er) }) } From 1359fd84024c63611841b76def13e7d90391fd60 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Tue, 18 Dec 2018 11:50:11 -0500 Subject: [PATCH 11/22] Push the derivation of logLevel down a level Originally, the log level derivation (respecting verbose/silent/dryrun/quiet flags) happened at the CLI level. This was a level too high because it meant that direct invocations of scripty would not resolve the same log level (based on the other flags). Now we do the log level resolution at the same point where all the options are defaulted: within the optionify wrapper of scripty itself. This way we still have access to distinguish the user-provided values vs the defaults, and can apply the aliases and various supported flags. Downside is that now the CLI needs to read in all the various flags to pass them down, but that's an acceptable tradeoff. --- cli.js | 6 +++-- lib/derive-log-level.js | 13 +++++++++ lib/derive-log-level.test.js | 36 +++++++++++++++++++++++++ lib/load-log-level.js | 24 ----------------- lib/load-log-level.test.js | 52 ------------------------------------ lib/optionify.js | 5 ++++ 6 files changed, 58 insertions(+), 78 deletions(-) create mode 100644 lib/derive-log-level.js create mode 100644 lib/derive-log-level.test.js delete mode 100644 lib/load-log-level.js delete mode 100644 lib/load-log-level.test.js diff --git a/cli.js b/cli.js index df3b0e9..5fb0b3f 100755 --- a/cli.js +++ b/cli.js @@ -21,13 +21,15 @@ if (!lifecycleEvent) { } else { var scripty = require('./lib/scripty') var loadOption = require('./lib/load-option') - var loadLogLevel = require('./lib/load-log-level') scripty(lifecycleEvent, { userArgs: process.argv.slice(2), parallel: loadOption('parallel'), dryRun: loadOption('dryRun'), - logLevel: loadLogLevel(), + logLevel: loadOption('logLevel'), + quiet: loadOption('quiet'), + silent: loadOption('silent'), + verbose: loadOption('verbose'), spawn: { stdio: 'inherit' }, diff --git a/lib/derive-log-level.js b/lib/derive-log-level.js new file mode 100644 index 0000000..30cc329 --- /dev/null +++ b/lib/derive-log-level.js @@ -0,0 +1,13 @@ +var level = require('./run/log').levels + +module.exports = function deriveLogLevel (userOptions) { + if (!userOptions) return + + if (userOptions.logLevel) return userOptions.logLevel + + if (userOptions.verbose) return level.VERBOSE + + if (userOptions.dryRun) return level.INFO + + if (userOptions.silent || userOptions.quiet) return level.SILENT +} diff --git a/lib/derive-log-level.test.js b/lib/derive-log-level.test.js new file mode 100644 index 0000000..3bbaf99 --- /dev/null +++ b/lib/derive-log-level.test.js @@ -0,0 +1,36 @@ +var subject = require('./derive-log-level') +var level = require('./run/log').levels + +module.exports = { + 'does not default': function () { + assert.equal(subject(), undefined) + }, + + 'explicit logLevel takes precedence': function () { + assert.equal(subject({ + silent: true, + dryRun: true, + verbose: true, + logLevel: 'warn' }), 'warn') + }, + + 'passes through unrecognized values': function () { + assert.equal(subject({ logLevel: 'worn' }), 'worn') + }, + + 'verbose preempts dry-run and silent': function () { + assert.equal(subject({ silent: true, dryRun: true, verbose: true }), level.VERBOSE) + }, + + 'dry-run preempts silent': function () { + assert.equal(subject({ silent: true, dryRun: true }), level.INFO) + }, + + 'silent is read last': function () { + assert.equal(subject({ silent: true }), level.SILENT) + }, + + 'quiet is alias for silent': function () { + assert.equal(subject({ quiet: true }), level.SILENT) + } +} diff --git a/lib/load-log-level.js b/lib/load-log-level.js deleted file mode 100644 index c5e81a8..0000000 --- a/lib/load-log-level.js +++ /dev/null @@ -1,24 +0,0 @@ -var loadOption = require('./load-option') -var level = require('./run/log').levels - -module.exports = function () { - var logLevel = String(loadOption('logLevel')).toUpperCase() - - if (level[logLevel]) { - return level[logLevel] - } - - if (loadOption('verbose')) { - return level.VERBOSE - } - - if (loadOption('dryRun')) { - return level.INFO - } - - if (loadOption('silent') || loadOption('quiet')) { - return level.SILENT - } - - return level.INFO -} diff --git a/lib/load-log-level.test.js b/lib/load-log-level.test.js deleted file mode 100644 index fee97b8..0000000 --- a/lib/load-log-level.test.js +++ /dev/null @@ -1,52 +0,0 @@ -var subject = require('./load-log-level') -var level = require('./run/log').levels - -module.exports = { - beforeEach: function () { - delete process.env.SCRIPTY_QUIET - delete process.env.SCRIPTY_SILENT - delete process.env.SCRIPTY_DRY_RUN - delete process.env.SCRIPTY_VERBOSE - delete process.env.SCRIPTY_LOG_LEVEL - }, - - 'defaults to INFO': function () { - assert.equal(subject(), level.INFO) - }, - - 'explicit logLevel takes precedence': function () { - process.env.SCRIPTY_SILENT = true - process.env.SCRIPTY_DRY_RUN = true - process.env.SCRIPTY_VERBOSE = true - process.env.SCRIPTY_LOG_LEVEL = 'warn' - assert.equal(subject(), level.WARN) - }, - - 'ignores unrecognized values': function () { - process.env.SCRIPTY_LOG_LEVEL = 'worn' - assert.equal(subject(), level.INFO) - }, - - 'verbose preempts dry-run and silent': function () { - process.env.SCRIPTY_SILENT = true - process.env.SCRIPTY_DRY_RUN = true - process.env.SCRIPTY_VERBOSE = true - assert.equal(subject(), level.VERBOSE) - }, - - 'dry-run preempts silent': function () { - process.env.SCRIPTY_SILENT = true - process.env.SCRIPTY_DRY_RUN = true - assert.equal(subject(), level.INFO) - }, - - 'silent is read last': function () { - process.env.SCRIPTY_SILENT = true - assert.equal(subject(), level.SILENT) - }, - - 'quiet is alias for silent': function () { - process.env.SCRIPTY_QUIET = true - assert.equal(subject(), level.SILENT) - } -} diff --git a/lib/optionify.js b/lib/optionify.js index efe9664..f4a3a91 100644 --- a/lib/optionify.js +++ b/lib/optionify.js @@ -1,4 +1,5 @@ var _ = require('lodash') +var deriveLogLevel = require('./derive-log-level') var NULL_CB = function () {} module.exports = function (rawFunc, defaultOptions) { @@ -9,6 +10,10 @@ module.exports = function (rawFunc, defaultOptions) { if (!cb) { cb = NULL_CB } + + var logLevel = deriveLogLevel(userOptions) + if (logLevel) userOptions.logLevel = logLevel + var fullOptions = _.defaultsDeep({}, userOptions, defaultOptions) return rawFunc(mainArg, fullOptions, cb) } From 8f41ccaf527146c0aeeb3f31a9f45fc972c77eac Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Tue, 18 Dec 2018 12:13:37 -0500 Subject: [PATCH 12/22] Normalize the log level when setting the level --- lib/run/log.js | 13 ++++++++++++- lib/run/log.test.js | 9 +++++---- lib/scripty.js | 3 +-- test/run-scripty.js | 3 +-- test/safe/silent-test.js | 3 +-- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/lib/run/log.js b/lib/run/log.js index 276c8f9..44a4393 100644 --- a/lib/run/log.js +++ b/lib/run/log.js @@ -29,7 +29,7 @@ module.exports.reset = function () { module.exports.level = function (level) { for (var l in LEVELS) { var methodName = l.toLowerCase() - if (level <= LEVELS[l]) { + if (normalize(level) <= LEVELS[l]) { module.exports[methodName] = console.error } else { module.exports[methodName] = silentLogger @@ -41,4 +41,15 @@ function silentLogger () { output += util.format.apply(util, arguments) + '\n' } +function normalize (level) { + for (var l in LEVELS) { + if (level === LEVELS[l] || + l === String(level).toUpperCase()) { + return LEVELS[l] + } + } + + return LEVELS.INFO +} + module.exports.reset() diff --git a/lib/run/log.test.js b/lib/run/log.test.js index 6914a5c..0e0ebae 100644 --- a/lib/run/log.test.js +++ b/lib/run/log.test.js @@ -1,4 +1,5 @@ var subject = require('./log') +var LEVEL = subject.levels module.exports = { beforeEach: function () { @@ -12,26 +13,26 @@ module.exports = { }, setTheLogLevel: { verbose: function () { - subject.level(subject.levels.VERBOSE) + subject.level(LEVEL.VERBOSE) subject.verbose('ity') td.verify(console.error('ity')) }, info: function () { - subject.level(subject.levels.INFO) + subject.level(LEVEL.INFO) td.when(console.error('ity')).thenThrow(new Error('Should not log verbose calls at INFO level')) subject.verbose('ity') subject.info('mation') td.verify(console.error('mation')) }, warn: function () { - subject.level(subject.levels.WARN) + subject.level(LEVEL.WARN) td.when(console.error('mation')).thenThrow(new Error('Should not log info calls at WARN level')) subject.info('mation') subject.warn('ing') td.verify(console.error('ing')) }, error: function () { - subject.level(subject.levels.ERROR) + subject.level(LEVEL.ERROR) td.when(console.error('ing')).thenThrow(new Error('Should not log warn calls at ERROR level')) subject.warn('ing') subject.error('fail') diff --git a/lib/scripty.js b/lib/scripty.js index 4c72dab..325b88b 100644 --- a/lib/scripty.js +++ b/lib/scripty.js @@ -1,7 +1,6 @@ var optionify = require('./optionify') var resolveScript = require('./resolve-script') var run = require('./run') -var log = require('./run/log') module.exports = optionify(function scripty (npmLifecycle, options, cb) { resolveScript(npmLifecycle, options.resolve, function (er, scriptFiles) { @@ -12,7 +11,7 @@ module.exports = optionify(function scripty (npmLifecycle, options, cb) { userArgs: [], parallel: false, dryRun: false, - logLevel: log.levels.INFO, + logLevel: 'info', spawn: {}, resolve: {} }) diff --git a/test/run-scripty.js b/test/run-scripty.js index adbf4c1..172c97a 100644 --- a/test/run-scripty.js +++ b/test/run-scripty.js @@ -3,13 +3,12 @@ var path = require('path') var scripty = require('../lib/scripty') var grabStdio = require('./grab-stdio') -var logLevel = require('../lib/run/log').levels module.exports = function (name, opts, cb) { var stdio = {} scripty(name, _.defaultsDeep({}, opts, { - logLevel: logLevel.SILENT, + logLevel: 'silent', resolve: { builtIn: path.resolve('test/fixtures/built-in-scripts'), builtInWin: path.resolve('test/fixtures/built-in-scripts-win'), diff --git a/test/safe/silent-test.js b/test/safe/silent-test.js index 813a380..dd3b8ce 100644 --- a/test/safe/silent-test.js +++ b/test/safe/silent-test.js @@ -1,11 +1,10 @@ var runScripty = require('../run-scripty') -var log = require('../../lib/run/log') module.exports = function doesNotEchoScriptContentInSilentMode (done) { var oldConsole = global.console global.console = {} // blow up if a console method is invoked - runScripty('hello:world', { logLevel: log.levels.SILENT }, function (er, code, stdio) { + runScripty('hello:world', { logLevel: 'silent' }, function (er, code, stdio) { global.console = oldConsole done(er) }) From ab092d7dc9073f83c6179a6466c0343582fcbc7b Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Tue, 18 Dec 2018 12:17:07 -0500 Subject: [PATCH 13/22] Git rid of log.shush helper --- lib/resolve-script/find-executables.test.js | 2 +- lib/run/log.js | 4 ---- lib/run/log.test.js | 8 ++++---- lib/run/print-script.test.js | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/resolve-script/find-executables.test.js b/lib/resolve-script/find-executables.test.js index 79f2af4..b5b9d73 100644 --- a/lib/resolve-script/find-executables.test.js +++ b/lib/resolve-script/find-executables.test.js @@ -9,7 +9,7 @@ var subject = require('./find-executables') module.exports = { beforeEach: function () { - log.shush() + log.level('silent') }, noFilesFound: function (done) { subject([base('does-not-exist*')], function (er, result) { diff --git a/lib/run/log.js b/lib/run/log.js index 44a4393..0c531e0 100644 --- a/lib/run/log.js +++ b/lib/run/log.js @@ -13,10 +13,6 @@ module.exports = {} module.exports.levels = LEVELS -module.exports.shush = function () { - module.exports.level(LEVELS.SILENT) -} - module.exports.read = function () { return output } diff --git a/lib/run/log.test.js b/lib/run/log.test.js index 0e0ebae..3d38c6b 100644 --- a/lib/run/log.test.js +++ b/lib/run/log.test.js @@ -39,13 +39,13 @@ module.exports = { td.verify(console.error('fail')) }, silent: function () { - subject.shush() + subject.level(LEVEL.SILENT) td.when(console.error('fail')).thenThrow(new Error('Should not log error calls at SILENT level')) subject.error('fail') } }, modeSwitchCapturesLogs: function () { - subject.shush() + subject.level(LEVEL.SILENT) subject.info('bar') subject.info('baz', 'noz') @@ -54,7 +54,7 @@ module.exports = { assert.equal(subject.read(), 'bar\nbaz noz\n') }, resetResetsMode: function () { - subject.shush() + subject.level(LEVEL.SILENT) subject.reset() @@ -62,7 +62,7 @@ module.exports = { td.verify(console.error('biz')) }, resetResetsLog: function () { - subject.shush() + subject.level(LEVEL.SILENT) subject.info('lalalal') subject.reset() diff --git a/lib/run/print-script.test.js b/lib/run/print-script.test.js index b5539db..4e81b65 100644 --- a/lib/run/print-script.test.js +++ b/lib/run/print-script.test.js @@ -4,7 +4,7 @@ var log = require('./log') module.exports = { beforeEach: function () { - log.shush() + log.level('silent') this.subject = require('./print-script') }, happyPath: function () { From 3e53a14720cf44e48208686474e85c8916d1b25b Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Tue, 18 Dec 2018 12:21:16 -0500 Subject: [PATCH 14/22] cleanup exports --- lib/run/log.js | 50 ++++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/lib/run/log.js b/lib/run/log.js index 0c531e0..b73e304 100644 --- a/lib/run/log.js +++ b/lib/run/log.js @@ -9,33 +9,33 @@ var LEVELS = { SILENT: 5 } -module.exports = {} - -module.exports.levels = LEVELS - -module.exports.read = function () { - return output -} - -module.exports.reset = function () { - output = '' - module.exports.level(LEVELS.INFO) -} - -module.exports.level = function (level) { - for (var l in LEVELS) { - var methodName = l.toLowerCase() - if (normalize(level) <= LEVELS[l]) { - module.exports[methodName] = console.error - } else { - module.exports[methodName] = silentLogger +module.exports = { + levels: LEVELS, + + read: function () { + return output + }, + + reset: function () { + output = '' + module.exports.level(LEVELS.INFO) + }, + + level: function (level) { + for (var l in LEVELS) { + var methodName = l.toLowerCase() + if (normalize(level) <= LEVELS[l]) { + module.exports[methodName] = console.error + } else { + module.exports[methodName] = silentLogger + } } } } -function silentLogger () { - output += util.format.apply(util, arguments) + '\n' -} +module.exports.reset() + +// private function normalize (level) { for (var l in LEVELS) { @@ -48,4 +48,6 @@ function normalize (level) { return LEVELS.INFO } -module.exports.reset() +function silentLogger () { + output += util.format.apply(util, arguments) + '\n' +} From 6b6444e3d031aaa6c375e9d1969d9da2549ca392 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Wed, 19 Dec 2018 10:05:00 -0500 Subject: [PATCH 15/22] Log level must be set before running This way logs can be written during the script resolution process. --- lib/run/index.js | 3 --- lib/scripty.js | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/run/index.js b/lib/run/index.js index e5beae3..4839ff3 100644 --- a/lib/run/index.js +++ b/lib/run/index.js @@ -4,11 +4,8 @@ var dryRun = require('./dry-run') var commandify = require('./commandify') var spawnScript = require('./spawn-script') var all = require('./all') -var log = require('./log') module.exports = function (scriptFiles, options, cb) { - log.level(options.logLevel) - if (options.dryRun) return dryRun(scriptFiles, cb) var commands = commandify(spawnScript, scriptFiles, options) diff --git a/lib/scripty.js b/lib/scripty.js index 325b88b..76594ae 100644 --- a/lib/scripty.js +++ b/lib/scripty.js @@ -1,8 +1,11 @@ var optionify = require('./optionify') var resolveScript = require('./resolve-script') var run = require('./run') +var log = require('./run/log') module.exports = optionify(function scripty (npmLifecycle, options, cb) { + log.level(options.logLevel) + resolveScript(npmLifecycle, options.resolve, function (er, scriptFiles) { if (er) return cb(er) run(scriptFiles, options, cb) From a88be5eb3911dccf40698422600bffb71e558304 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Wed, 19 Dec 2018 10:09:22 -0500 Subject: [PATCH 16/22] Moves log from lib/run/ to lib/ The logger is needed before the run process begins so it's no longer a local dep of just the run process. (For instance, to write errors/warnings during the loading process.) --- lib/derive-log-level.js | 2 +- lib/derive-log-level.test.js | 2 +- lib/{run => }/log.js | 0 lib/{run => }/log.test.js | 0 lib/resolve-script/find-executables.js | 2 +- lib/resolve-script/find-executables.test.js | 2 +- lib/run/dry-run.js | 2 +- lib/run/print-script.js | 2 +- lib/run/print-script.test.js | 2 +- lib/scripty.js | 2 +- test/safe-helper.js | 2 +- test/safe/basic-test.js | 2 +- test/safe/dry-run-test.js | 2 +- test/unit-helper.js | 2 +- 14 files changed, 12 insertions(+), 12 deletions(-) rename lib/{run => }/log.js (100%) rename lib/{run => }/log.test.js (100%) diff --git a/lib/derive-log-level.js b/lib/derive-log-level.js index 30cc329..d5d9721 100644 --- a/lib/derive-log-level.js +++ b/lib/derive-log-level.js @@ -1,4 +1,4 @@ -var level = require('./run/log').levels +var level = require('./log').levels module.exports = function deriveLogLevel (userOptions) { if (!userOptions) return diff --git a/lib/derive-log-level.test.js b/lib/derive-log-level.test.js index 3bbaf99..7843428 100644 --- a/lib/derive-log-level.test.js +++ b/lib/derive-log-level.test.js @@ -1,5 +1,5 @@ var subject = require('./derive-log-level') -var level = require('./run/log').levels +var level = require('./log').levels module.exports = { 'does not default': function () { diff --git a/lib/run/log.js b/lib/log.js similarity index 100% rename from lib/run/log.js rename to lib/log.js diff --git a/lib/run/log.test.js b/lib/log.test.js similarity index 100% rename from lib/run/log.test.js rename to lib/log.test.js diff --git a/lib/resolve-script/find-executables.js b/lib/resolve-script/find-executables.js index feced6d..150a00c 100644 --- a/lib/resolve-script/find-executables.js +++ b/lib/resolve-script/find-executables.js @@ -1,6 +1,6 @@ var _ = require('lodash') var globFirst = require('./glob-first') -var log = require('../run/log') +var log = require('../log') var path = require('path') var async = require('async') diff --git a/lib/resolve-script/find-executables.test.js b/lib/resolve-script/find-executables.test.js index b5b9d73..96e719e 100644 --- a/lib/resolve-script/find-executables.test.js +++ b/lib/resolve-script/find-executables.test.js @@ -1,6 +1,6 @@ var _ = require('lodash') var path = require('path') -var log = require('../run/log') +var log = require('../log') var base = function (glob) { return path.resolve('test/fixtures/unit/find-executables', glob) diff --git a/lib/run/dry-run.js b/lib/run/dry-run.js index 861eec7..569db1d 100644 --- a/lib/run/dry-run.js +++ b/lib/run/dry-run.js @@ -1,7 +1,7 @@ var _ = require('lodash') var printScript = require('./print-script') -var log = require('./log') +var log = require('../log') module.exports = function (scriptFiles, cb) { log.info('This is a dry run. Executed scripts would be:\n') diff --git a/lib/run/print-script.js b/lib/run/print-script.js index 04a5dfa..ba2c5ba 100644 --- a/lib/run/print-script.js +++ b/lib/run/print-script.js @@ -1,7 +1,7 @@ var fs = require('fs') var _ = require('lodash') -var log = require('./log') +var log = require('../log') module.exports = function (scriptFile) { log.info('Executing "' + scriptFile + '":\n') diff --git a/lib/run/print-script.test.js b/lib/run/print-script.test.js index 4e81b65..2e41383 100644 --- a/lib/run/print-script.test.js +++ b/lib/run/print-script.test.js @@ -1,6 +1,6 @@ var path = require('path') -var log = require('./log') +var log = require('../log') module.exports = { beforeEach: function () { diff --git a/lib/scripty.js b/lib/scripty.js index 76594ae..c52a3b4 100644 --- a/lib/scripty.js +++ b/lib/scripty.js @@ -1,7 +1,7 @@ var optionify = require('./optionify') var resolveScript = require('./resolve-script') var run = require('./run') -var log = require('./run/log') +var log = require('./log') module.exports = optionify(function scripty (npmLifecycle, options, cb) { log.level(options.logLevel) diff --git a/test/safe-helper.js b/test/safe-helper.js index af3cb30..0b05e90 100644 --- a/test/safe-helper.js +++ b/test/safe-helper.js @@ -1,7 +1,7 @@ var decorateAssertions = require('./decorate-assertions') global.assert = decorateAssertions(require('assert')) -var log = require('../lib/run/log') +var log = require('../lib/log') module.exports = { afterEach: function () { diff --git a/test/safe/basic-test.js b/test/safe/basic-test.js index 5265416..d43c5e0 100644 --- a/test/safe/basic-test.js +++ b/test/safe/basic-test.js @@ -1,5 +1,5 @@ var runScripty = require('../run-scripty') -var log = require('../../lib/run/log') +var log = require('../../lib/log') module.exports = { outputAndRunScript: function (done) { diff --git a/test/safe/dry-run-test.js b/test/safe/dry-run-test.js index 78fcd50..d8de07a 100644 --- a/test/safe/dry-run-test.js +++ b/test/safe/dry-run-test.js @@ -1,5 +1,5 @@ var runScripty = require('../run-scripty') -var log = require('../../lib/run/log') +var log = require('../../lib/log') module.exports = function doesNotRunButPrintResolvedScripts (done) { runScripty('hello:world', { dryRun: true }, function (er, code, stdio) { diff --git a/test/unit-helper.js b/test/unit-helper.js index 47bc35b..c695b96 100644 --- a/test/unit-helper.js +++ b/test/unit-helper.js @@ -3,7 +3,7 @@ global.td = require('testdouble') var decorateAssertions = require('./decorate-assertions') global.assert = decorateAssertions(require('assert')) -var log = require('../lib/run/log') +var log = require('../lib/log') global.UNSUPPORTED_TDD = require('./is-old-node') if (UNSUPPORTED_TDD) { From f8ff1055156294c0098a75828481a058b0d5b8e3 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Wed, 19 Dec 2018 14:09:55 -0500 Subject: [PATCH 17/22] Write caught errors using our logger which respects logLevel --- cli.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cli.js b/cli.js index 5fb0b3f..3fe6156 100755 --- a/cli.js +++ b/cli.js @@ -21,6 +21,7 @@ if (!lifecycleEvent) { } else { var scripty = require('./lib/scripty') var loadOption = require('./lib/load-option') + var log = require('./lib/log') scripty(lifecycleEvent, { userArgs: process.argv.slice(2), @@ -40,7 +41,7 @@ if (!lifecycleEvent) { } }, function (er, code) { if (er) { - console.error(er) + log.error(er) code = code || er.code || 1 } process.exitCode = code From c58c48d0e0302fb4d336cfe949df94f77d4c0cbf Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Wed, 19 Dec 2018 16:01:09 -0500 Subject: [PATCH 18/22] Strip the stacktrace from printed errors --- lib/log.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/log.js b/lib/log.js index b73e304..4d8c01c 100644 --- a/lib/log.js +++ b/lib/log.js @@ -25,7 +25,7 @@ module.exports = { for (var l in LEVELS) { var methodName = l.toLowerCase() if (normalize(level) <= LEVELS[l]) { - module.exports[methodName] = console.error + module.exports[methodName] = formatError(console.error) } else { module.exports[methodName] = silentLogger } @@ -48,6 +48,14 @@ function normalize (level) { return LEVELS.INFO } +function formatError (f) { + return function () { + f.apply(null, Array.from(arguments, function (arg) { + return arg instanceof Error ? arg.message : arg + })) + } +} + function silentLogger () { output += util.format.apply(util, arguments) + '\n' } From 40a936398c46bcbbae0c471151a99de0db155fe3 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Wed, 19 Dec 2018 14:10:21 -0500 Subject: [PATCH 19/22] Refactor and reformat logging messages --- cli.js | 6 +- lib/derive-log-level.js | 8 +- lib/derive-log-level.test.js | 10 +-- lib/log.js | 87 +++++++++------------ lib/log.test.js | 33 ++++---- lib/resolve-script/find-executables.js | 6 +- lib/resolve-script/find-executables.test.js | 7 +- lib/resolve-script/index.js | 9 +-- lib/resolve-script/index.test.js | 7 +- lib/run/commandify.js | 9 --- lib/run/index.js | 3 +- lib/run/print-script.js | 16 +--- lib/run/print-script.test.js | 12 +-- lib/run/spawn-script.js | 20 ++--- lib/scripty.js | 2 +- test/safe/basic-test.js | 8 +- 16 files changed, 101 insertions(+), 142 deletions(-) delete mode 100644 lib/run/commandify.js diff --git a/cli.js b/cli.js index 3fe6156..088d48f 100755 --- a/cli.js +++ b/cli.js @@ -4,10 +4,8 @@ var lifecycleEvent = process.env.npm_lifecycle_event if (!lifecycleEvent) { console.error( - 'Error: scripty - it seems you may be running scripty from the ' + - 'command-line directly.\n' + - 'At this time, scripty can only be run within an ' + - 'npm script specified in your package.json.\n\n' + + 'scripty ERR! It seems you may be running scripty from the command-line directly.\n' + + 'At this time, scripty can only be run within an npm script specified in your package.json.\n\n' + 'Example package.json entry:\n\n' + ' "scripts": {\n' + ' "foo:bar": "scripty"\n' + diff --git a/lib/derive-log-level.js b/lib/derive-log-level.js index d5d9721..81797ef 100644 --- a/lib/derive-log-level.js +++ b/lib/derive-log-level.js @@ -1,13 +1,13 @@ -var level = require('./log').levels +var log = require('./log') module.exports = function deriveLogLevel (userOptions) { if (!userOptions) return if (userOptions.logLevel) return userOptions.logLevel - if (userOptions.verbose) return level.VERBOSE + if (userOptions.verbose) return log.verbose - if (userOptions.dryRun) return level.INFO + if (userOptions.dryRun) return log.info - if (userOptions.silent || userOptions.quiet) return level.SILENT + if (userOptions.silent || userOptions.quiet) return log.silent } diff --git a/lib/derive-log-level.test.js b/lib/derive-log-level.test.js index 7843428..9e8055e 100644 --- a/lib/derive-log-level.test.js +++ b/lib/derive-log-level.test.js @@ -1,5 +1,5 @@ var subject = require('./derive-log-level') -var level = require('./log').levels +var log = require('./log') module.exports = { 'does not default': function () { @@ -19,18 +19,18 @@ module.exports = { }, 'verbose preempts dry-run and silent': function () { - assert.equal(subject({ silent: true, dryRun: true, verbose: true }), level.VERBOSE) + assert.equal(subject({ silent: true, dryRun: true, verbose: true }), log.verbose) }, 'dry-run preempts silent': function () { - assert.equal(subject({ silent: true, dryRun: true }), level.INFO) + assert.equal(subject({ silent: true, dryRun: true }), log.info) }, 'silent is read last': function () { - assert.equal(subject({ silent: true }), level.SILENT) + assert.equal(subject({ silent: true }), log.silent) }, 'quiet is alias for silent': function () { - assert.equal(subject({ quiet: true }), level.SILENT) + assert.equal(subject({ quiet: true }), log.silent) } } diff --git a/lib/log.js b/lib/log.js index 4d8c01c..34b81f9 100644 --- a/lib/log.js +++ b/lib/log.js @@ -1,61 +1,52 @@ -var util = require('util') - -var output -var LEVELS = { - VERBOSE: 1, - INFO: 2, - WARN: 3, - ERROR: 4, - SILENT: 5 -} +const util = require('util') -module.exports = { - levels: LEVELS, +const constant = val => () => val - read: function () { - return output - }, +const formatError = args => + args.map(arg => arg instanceof Error ? arg.message : arg) - reset: function () { - output = '' - module.exports.level(LEVELS.INFO) - }, +const loggerWithPrefix = (prefix, writer) => (...args) => + writer()(prefix, util.format(...formatError(args)) + .replace(/(\r?\n)(?=[\s\S]+)/g, `$1${prefix} `)) - level: function (level) { - for (var l in LEVELS) { - var methodName = l.toLowerCase() - if (normalize(level) <= LEVELS[l]) { - module.exports[methodName] = formatError(console.error) - } else { - module.exports[methodName] = silentLogger - } - } - } +const silentLogger = (...args) => { + output += util.format(...args) + '\n' } -module.exports.reset() +let level +let output -// private +module.exports = { + get level () { + return level.toString() + }, -function normalize (level) { - for (var l in LEVELS) { - if (level === LEVELS[l] || - l === String(level).toUpperCase()) { - return LEVELS[l] - } - } + set level (l) { + level = module.exports[String(l).toLowerCase()] + }, - return LEVELS.INFO -} + read: () => output, -function formatError (f) { - return function () { - f.apply(null, Array.from(arguments, function (arg) { - return arg instanceof Error ? arg.message : arg - })) + reset: () => { + output = '' + module.exports.level = 'info' } } -function silentLogger () { - output += util.format.apply(util, arguments) + '\n' -} +;[ + ['verbose', '>'], + ['info', '>'], + ['warn', 'WARN'], + ['error', 'ERR!'], + ['silent'] +].forEach(([name, prefix], index) => { + const logger = loggerWithPrefix(`scripty ${prefix}`, () => + level <= logger ? console.error : silentLogger) + + logger.valueOf = constant(index + 1) + logger.toString = constant(name) + + module.exports[name] = logger +}) + +module.exports.reset() diff --git a/lib/log.test.js b/lib/log.test.js index 3d38c6b..0af4f7e 100644 --- a/lib/log.test.js +++ b/lib/log.test.js @@ -1,5 +1,4 @@ var subject = require('./log') -var LEVEL = subject.levels module.exports = { beforeEach: function () { @@ -9,65 +8,65 @@ module.exports = { writesToStderr: function () { subject.info('foo') - td.verify(console.error('foo')) + td.verify(console.error('scripty >', 'foo')) }, setTheLogLevel: { verbose: function () { - subject.level(LEVEL.VERBOSE) + subject.level = subject.verbose subject.verbose('ity') - td.verify(console.error('ity')) + td.verify(console.error('scripty >', 'ity')) }, info: function () { - subject.level(LEVEL.INFO) + subject.level = subject.info td.when(console.error('ity')).thenThrow(new Error('Should not log verbose calls at INFO level')) subject.verbose('ity') subject.info('mation') - td.verify(console.error('mation')) + td.verify(console.error('scripty >', 'mation')) }, warn: function () { - subject.level(LEVEL.WARN) + subject.level = subject.warn td.when(console.error('mation')).thenThrow(new Error('Should not log info calls at WARN level')) subject.info('mation') subject.warn('ing') - td.verify(console.error('ing')) + td.verify(console.error('scripty WARN', 'ing')) }, error: function () { - subject.level(LEVEL.ERROR) + subject.level = subject.error td.when(console.error('ing')).thenThrow(new Error('Should not log warn calls at ERROR level')) subject.warn('ing') subject.error('fail') - td.verify(console.error('fail')) + td.verify(console.error('scripty ERR!', 'fail')) }, silent: function () { - subject.level(LEVEL.SILENT) + subject.level = subject.silent td.when(console.error('fail')).thenThrow(new Error('Should not log error calls at SILENT level')) subject.error('fail') } }, modeSwitchCapturesLogs: function () { - subject.level(LEVEL.SILENT) + subject.level = subject.silent subject.info('bar') subject.info('baz', 'noz') td.verify(console.error(), { ignoreExtraArgs: true, times: 0 }) - assert.equal(subject.read(), 'bar\nbaz noz\n') + assert.equal(subject.read(), 'scripty > bar\nscripty > baz noz\n') }, resetResetsMode: function () { - subject.level(LEVEL.SILENT) + subject.level = subject.silent subject.reset() subject.info('biz') - td.verify(console.error('biz')) + td.verify(console.error('scripty >', 'biz')) }, resetResetsLog: function () { - subject.level(LEVEL.SILENT) + subject.level = subject.silent + subject.info('lalalal') subject.reset() assert.equal(subject.read(), '') } - } diff --git a/lib/resolve-script/find-executables.js b/lib/resolve-script/find-executables.js index 150a00c..9eb6fc4 100644 --- a/lib/resolve-script/find-executables.js +++ b/lib/resolve-script/find-executables.js @@ -14,10 +14,8 @@ module.exports = function (patterns, cb) { if (itIsExecutable) { cb(er, path.resolve(result)) } else { - log.warn( - 'Warning: scripty - ignoring script "%s" because it' + - ' was not executable. Run `chmod +x "%s" if you want' + - ' scripty to run it.', result, result) + log.warn(`Ignoring script '${result}' because it was not executable.\n` + + `Run \`chmod +x '${result}'\` if you want scripty to run it.`) cb(er, undefined) } }) diff --git a/lib/resolve-script/find-executables.test.js b/lib/resolve-script/find-executables.test.js index 96e719e..370e76f 100644 --- a/lib/resolve-script/find-executables.test.js +++ b/lib/resolve-script/find-executables.test.js @@ -9,7 +9,7 @@ var subject = require('./find-executables') module.exports = { beforeEach: function () { - log.level('silent') + log.level = 'silent' }, noFilesFound: function (done) { subject([base('does-not-exist*')], function (er, result) { @@ -28,9 +28,8 @@ module.exports = { subject([base('file.*')], function (er, result) { assert.deepEqual(result, [base('file.executable')]) assert.includes(log.read(), - 'Warning: scripty - ignoring script "' + base('file.not.executable') + - '" because it was not executable. Run `chmod +x "' + - base('file.not.executable') + '" if you want scripty to run it.' + `scripty WARN ignoring script '${base('file.not.executable')}' because it was not executable.\n` + + `scripty WARN Run \`chmod +x '${base('file.not.executable')}'\` if you want scripty to run it.` ) done(er) }) diff --git a/lib/resolve-script/index.js b/lib/resolve-script/index.js index 4aad760..7178374 100644 --- a/lib/resolve-script/index.js +++ b/lib/resolve-script/index.js @@ -14,11 +14,10 @@ module.exports = function (name, options, cb) { if (ourPaths.length > 0) { cb(er, ourPaths) } else { - cb(new Error( - 'Error: scripty - no script found for npm lifecycle "' + name + '"' + - ' matching either "' + userGlob + '" or "' + ourGlob + '". Either' + - ' define a script or remove "scripty" from "' + name + '" under' + - ' "scripts" in your package.json.' + cb(new Error(`No script found for npm lifecycle '${name}' matching any of:\n` + + ` ${String(userGlob).replace(/,/g, '\n ')}\n` + + ` ${String(ourGlob).replace(/,/g, '\n ')}\n` + + `Either define a script or remove "scripty" from 'scripts.${name}' in your package.json.` ), null) } }) diff --git a/lib/resolve-script/index.test.js b/lib/resolve-script/index.test.js index 12e8453..4075310 100644 --- a/lib/resolve-script/index.test.js +++ b/lib/resolve-script/index.test.js @@ -39,10 +39,9 @@ module.exports = { this.subject('fake', OPTIONS, function (er, result) { assert.equal(er.message, - 'Error: scripty - no script found for npm lifecycle "fake" matching ' + - 'either "glob1" or "glob2". Either define a script or remove ' + - '"scripty" from "fake" under "scripts" in your package.json.' - ) + `No script found for npm lifecycle 'fake' matching any of:\n` + + ` glob1\n glob2\n` + + `Either define a script or remove "scripty" from 'scripts.fake' in your package.json.`) assert.equal(result, null) done(null) }) diff --git a/lib/run/commandify.js b/lib/run/commandify.js deleted file mode 100644 index c93932e..0000000 --- a/lib/run/commandify.js +++ /dev/null @@ -1,9 +0,0 @@ -var _ = require('lodash') - -module.exports = function (func, items, options) { - return _.map(items, function (item) { - return function (cb) { - func(item, options, cb) - } - }) -} diff --git a/lib/run/index.js b/lib/run/index.js index 4839ff3..9309261 100644 --- a/lib/run/index.js +++ b/lib/run/index.js @@ -1,7 +1,8 @@ var _ = require('lodash') +const commandify = (func, items, options) => + items.map(item => cb => func(item, options, cb)) var dryRun = require('./dry-run') -var commandify = require('./commandify') var spawnScript = require('./spawn-script') var all = require('./all') diff --git a/lib/run/print-script.js b/lib/run/print-script.js index ba2c5ba..845ce40 100644 --- a/lib/run/print-script.js +++ b/lib/run/print-script.js @@ -1,25 +1,15 @@ var fs = require('fs') -var _ = require('lodash') - var log = require('../log') module.exports = function (scriptFile) { - log.info('Executing "' + scriptFile + '":\n') - var script = read(scriptFile) - if (script) { - log.verbose(_.map(script.split('\n'), function (line) { - return '> ' + line - }).join('\n') + '\n\n') - } + log.info(`Executing "${scriptFile}":\n`) + log.verbose(`${read(scriptFile)}`) } function read (scriptFile) { try { return fs.readFileSync(scriptFile).toString() } catch (e) { - log.error( - 'Error: scripty - failed trying to read "' + scriptFile + '":\n\n' + - e.message - ) + log.warn(`Failed to read '${scriptFile}':\n${e.message}`) } } diff --git a/lib/run/print-script.test.js b/lib/run/print-script.test.js index 2e41383..37c4271 100644 --- a/lib/run/print-script.test.js +++ b/lib/run/print-script.test.js @@ -4,7 +4,7 @@ var log = require('../log') module.exports = { beforeEach: function () { - log.level('silent') + log.level = 'silent' this.subject = require('./print-script') }, happyPath: function () { @@ -12,16 +12,16 @@ module.exports = { this.subject(script) - assert.includes(log.read(), 'Executing "' + script + '":\n') - assert.includes(log.read(), '> #!/usr/bin/env sh') - assert.includes(log.read(), '> npm test -- --debug-brk') + assert.includes(log.read(), 'scripty > Executing "' + script + '":\n') + assert.includes(log.read(), 'scripty > #!/usr/bin/env sh') + assert.includes(log.read(), 'scripty > npm test -- --debug-brk') }, sadPath: function () { var script = '/silly/nonsense' this.subject(script) - assert.includes(log.read(), 'Error: scripty - failed trying to read "/silly/nonsense":') - assert.includes(log.read(), 'ENOENT') + assert.includes(log.read(), `scripty WARN Failed to read '/silly/nonsense':`) + assert.includes(log.read(), `scripty WARN ENOENT`) } } diff --git a/lib/run/spawn-script.js b/lib/run/spawn-script.js index e8ab093..b05fcb8 100644 --- a/lib/run/spawn-script.js +++ b/lib/run/spawn-script.js @@ -4,17 +4,13 @@ var spawn = require('child_process').spawn module.exports = function (scriptFile, options, cb) { printScript(scriptFile) - var userArgs = options.userArgs - var child = spawn(scriptFile, userArgs, options.spawn) - child.on('close', function (code) { - if (code !== 0) { - cb(new Error( - 'Error: scripty - script "fail" failed by exiting ' + - 'with a non-zero code (' + code + ').' - ), code) - } else { - cb(null, code) - } - }) + + const child = spawn(scriptFile, options.userArgs, options.spawn) + + child.on('close', code => cb(code !== 0 + ? new Error(`script failed: '${scriptFile}'\nexit status: ${code}`) + : null, code) + ) + _.invoke(options, 'spawn.tap', child) } diff --git a/lib/scripty.js b/lib/scripty.js index c52a3b4..5b77dff 100644 --- a/lib/scripty.js +++ b/lib/scripty.js @@ -4,7 +4,7 @@ var run = require('./run') var log = require('./log') module.exports = optionify(function scripty (npmLifecycle, options, cb) { - log.level(options.logLevel) + log.level = options.logLevel resolveScript(npmLifecycle, options.resolve, function (er, scriptFiles) { if (er) return cb(er) diff --git a/test/safe/basic-test.js b/test/safe/basic-test.js index d43c5e0..d275247 100644 --- a/test/safe/basic-test.js +++ b/test/safe/basic-test.js @@ -1,5 +1,6 @@ var runScripty = require('../run-scripty') var log = require('../../lib/log') +const path = require('path') module.exports = { outputAndRunScript: function (done) { @@ -19,7 +20,7 @@ module.exports = { runScripty('not:a:real:thing', {}, function (er, code, stdio) { assert.notEqual(0, code) assert.includes(er.message, - 'Error: scripty - no script found for npm lifecycle "not:a:real:thing"' + `No script found for npm lifecycle 'not:a:real:thing'` ) done(null) @@ -28,10 +29,7 @@ module.exports = { scriptFoundButFailed: function (done) { runScripty('fail', {}, function (er, code, stdio) { assert.notEqual(0, code) - assert.includes(er.message, - 'Error: scripty - script "fail" failed by exiting ' + - 'with a non-zero code (' + code + ').' - ) + assert.includes(er.message, `script failed: '${path.resolve('test/fixtures/user-scripts/fail')}'\nexit status: ${code}`) if (process.platform === 'win32') { assert.includes(stdio.stderr, 'The system cannot find the path specified.') } else { From 8240c256806a2b7b82fee92bcdde16cb56b37c70 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Thu, 20 Dec 2018 16:20:12 -0500 Subject: [PATCH 20/22] Replace homegrown perms checking with fs.access 0.10 doesn't have fs.access and 0.10 was supported in the initial scripty release. We no longer support 0.10 so we can drop this homegrown module. However, there is a quirk in that the old code specifically changed the permission bits, but that didn't necessarily mean the file was actually readable or executable. For instance, a file with an +x but -r is not actually executable. (Since the file needs read to actually execute.) In addition, a non user-executable file with a group exec bit is not actually executable by the node process. Both of these scenarios are covered by fs.access. --- lib/resolve-script/find-executables.js | 35 +++++++-------- lib/resolve-script/find-executables.test.js | 4 +- lib/resolve-script/is-executable.js | 15 ------- lib/resolve-script/is-executable.test.js | 50 --------------------- 4 files changed, 17 insertions(+), 87 deletions(-) delete mode 100644 lib/resolve-script/is-executable.js delete mode 100644 lib/resolve-script/is-executable.test.js diff --git a/lib/resolve-script/find-executables.js b/lib/resolve-script/find-executables.js index 9eb6fc4..02082e0 100644 --- a/lib/resolve-script/find-executables.js +++ b/lib/resolve-script/find-executables.js @@ -1,26 +1,21 @@ var _ = require('lodash') +var async = require('async') +var fs = require('fs') +var path = require('path') var globFirst = require('./glob-first') var log = require('../log') -var path = require('path') -var async = require('async') - -var isExecutable = require('./is-executable') -module.exports = function (patterns, cb) { - globFirst(patterns, function (er, results) { +module.exports = (patterns, cb) => + globFirst(patterns, (er, results) => { if (er) return cb(er) - async.map(results, function (result, cb) { - isExecutable(result, function (er, itIsExecutable) { - if (itIsExecutable) { - cb(er, path.resolve(result)) - } else { - log.warn(`Ignoring script '${result}' because it was not executable.\n` + - `Run \`chmod +x '${result}'\` if you want scripty to run it.`) - cb(er, undefined) - } - }) - }, function (er, results) { - cb(er, _.compact(results)) - }) + + async.map(results, + (result, cb) => fs.access(result, fs.constants.R_OK | fs.constants.X_OK, + er => cb(null, er + ? log.warn(`Ignoring script '${result}' because it was not readable/executable.\n` + + `Run \`chmod u+rx '${result}'\` if you want scripty to run it.`) + : path.resolve(result)) + ), + (er, results) => cb(er, _.compact(results)) + ) }) -} diff --git a/lib/resolve-script/find-executables.test.js b/lib/resolve-script/find-executables.test.js index 370e76f..5798604 100644 --- a/lib/resolve-script/find-executables.test.js +++ b/lib/resolve-script/find-executables.test.js @@ -28,8 +28,8 @@ module.exports = { subject([base('file.*')], function (er, result) { assert.deepEqual(result, [base('file.executable')]) assert.includes(log.read(), - `scripty WARN ignoring script '${base('file.not.executable')}' because it was not executable.\n` + - `scripty WARN Run \`chmod +x '${base('file.not.executable')}'\` if you want scripty to run it.` + `scripty WARN Ignoring script '${base('file.not.executable')}' because it was not readable/executable.\n` + + `scripty WARN Run \`chmod u+rx '${base('file.not.executable')}'\` if you want scripty to run it.` ) done(er) }) diff --git a/lib/resolve-script/is-executable.js b/lib/resolve-script/is-executable.js deleted file mode 100644 index f06d93b..0000000 --- a/lib/resolve-script/is-executable.js +++ /dev/null @@ -1,15 +0,0 @@ -var fs = require('fs') - -module.exports = function (path, cb) { - if (process.platform === 'win32') return cb(null, true) - fs.stat(path, function (er, stats) { - if (er) return cb(er) - var mode = stats.mode - - var owner = mode >> 6 - var group = (mode << 3) >> 6 - var others = (mode << 6) >> 6 - - cb(er, !!(owner & 1) || !!(group & 1) || !!(others & 1)) - }) -} diff --git a/lib/resolve-script/is-executable.test.js b/lib/resolve-script/is-executable.test.js deleted file mode 100644 index 05f3467..0000000 --- a/lib/resolve-script/is-executable.test.js +++ /dev/null @@ -1,50 +0,0 @@ -var path = require('path') -var fs = require('fs') - -var root = path.resolve('test/fixtures/user-scripts/stats') -var subject = require('./is-executable') -module.exports = { - allXIsX: function (done) { - fs.chmodSync(root + '/all-x', '755') - subject(root + '/all-x', function (er, answer) { - assert.equal(answer, true) - done(er) - }) - }, - userXIsX: function (done) { - fs.chmodSync(root + '/owner-x', '744') - subject(root + '/owner-x', function (er, answer) { - assert.equal(answer, true) - done(er) - }) - }, - groupXIsX: function (done) { - fs.chmodSync(root + '/group-x', '654') - subject(root + '/group-x', function (er, answer) { - assert.equal(answer, true) - done(er) - }) - }, - othersXIsX: function (done) { - fs.chmodSync(root + '/other-x', '645') - subject(root + '/other-x', function (er, answer) { - assert.equal(answer, true) - done(er) - }) - }, - noXIsNotX: function (done) { - if (process.platform === 'win32') return done() - fs.chmodSync(root + '/no-x', '644') - subject(root + '/no-x', function (er, answer) { - assert.equal(answer, false) - done(er) - }) - }, - anyWindowsIsAllX: function (done) { - if (process.platform !== 'win32') return done() - subject(root + '/silly-lololo', function (er, answer) { - assert.equal(answer, true) - done(er) - }) - } -} From c8cd2d220e398f32a66175cc6155482518e46d61 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Thu, 20 Dec 2018 21:24:38 -0500 Subject: [PATCH 21/22] Update to config v2 --- .codeclimate.yml | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/.codeclimate.yml b/.codeclimate.yml index b4c9862..a04a7a6 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,17 +1,7 @@ -engines: - duplication: - enabled: true - config: - languages: - - javascript - fixme: - enabled: true +version: 2 -ratings: - paths: - - lib/** - - test/** - -exclude_paths: - - example/**/* - - node_modules/**/* +exclude_patterns: + - example/ + - node_modules/ + - test/ + - "**/*.test.js" From 2b78bf406dc12f9cd150ca179254ac949c25dda1 Mon Sep 17 00:00:00 2001 From: Jason Karns Date: Thu, 20 Dec 2018 22:41:08 -0500 Subject: [PATCH 22/22] Readme docs --- README.md | 28 ++++++++++++++++++++-------- lib/run/dry-run.js | 2 +- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index c583664..4a9170f 100644 --- a/README.md +++ b/README.md @@ -271,25 +271,37 @@ Worth mentioning, like all options this can be set in package.json under a } ``` -### Silent mode +### Log output -In case you don't want to the output to be cluttered by the script contents, you -can run scripty in silent mode: +Scripty is now quieter by default. +The output can be configured to a level of `verbose`, `info`, `warn`, or `error`. +Any logs equal to or higher than the setting are shown. +All logs are printed to STDERR (to aid in redirection and piping). ``` -$ SCRIPTY_SILENT=true npm run publish:danger:stuff +$ SCRIPTY_LOG_LEVEL=verbose npm run publish:danger:stuff ``` -This will omit printing the path and contents of each script the command executes. +This will print the path and contents of each script the command executes. -If you always want scripty to run your scripts silently, you can set it in -your package.json under a `"scripty"` entry: +If you always want scripty to run your scripts at a certain level, +you can set it in your package.json under a `"scripty"` entry: ```json "scripty": { - "silent": true + "logLevel": "warn" } ``` + +`SCRIPTY_SILENT` and `SCRIPTY_QUIET` are aliases for `SCRIPTY_LOG_LEVEL=silent` +`SCRIPTY_VERBOSE` is an alias for `SCRIPTY_LOG_LEVEL=verbose` +(also `"silent": true`, etc in package.json#scripty) + +`SCRIPTY_DRY_RUN=true` implies log level `info` + +Explicit setting from logLevel takes precedence; otherwise, +conflicting values between silent/verbose/dryRun will respect the highest level. + ## Likely questions * **Is this black magic?** - Nope! For once, instilling some convention didn't diff --git a/lib/run/dry-run.js b/lib/run/dry-run.js index 569db1d..13b857e 100644 --- a/lib/run/dry-run.js +++ b/lib/run/dry-run.js @@ -4,7 +4,7 @@ var printScript = require('./print-script') var log = require('../log') module.exports = function (scriptFiles, cb) { - log.info('This is a dry run. Executed scripts would be:\n') + log.info('This is a dry run. Executed scripts would be:') _.map(scriptFiles, printScript) cb(null, 0) }