diff --git a/docs/CLI.md b/docs/CLI.md index 20a3c431..211ecd63 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -43,3 +43,9 @@ Options --yes, -y confirm non-interactively --unmount, -u unmount on success ``` + +Debug mode +---------- + +You can set the `ETCHER_CLI_DEBUG` environment variable to make the Etcher CLI +print error stack traces. diff --git a/lib/cli/utils.js b/lib/cli/utils.js index e8f26dbd..d75a7b4b 100644 --- a/lib/cli/utils.js +++ b/lib/cli/utils.js @@ -31,10 +31,17 @@ const errors = require('../shared/errors'); */ exports.printError = (error) => { const title = errors.getTitle(error); - const description = errors.getDescription(error); + const description = errors.getDescription(error, { + userFriendlyDescriptionsOnly: true + }); console.error(chalk.red(title)); + if (description) { console.error(`\n${chalk.red(description)}`); } + + if (process.env.ETCHER_CLI_DEBUG && error.stack) { + console.error(`\n${chalk.red(error.stack)}`); + } }; diff --git a/lib/shared/errors.js b/lib/shared/errors.js index 6980959a..9ef72256 100644 --- a/lib/shared/errors.js +++ b/lib/shared/errors.js @@ -206,6 +206,8 @@ exports.getTitle = (error) => { * @public * * @param {Error} error - error + * @param {Object} options - options + * @param {Boolean} [options.userFriendlyDescriptionsOnly=false] - only return user friendly descriptions * @returns {String} error description * * @example @@ -213,7 +215,11 @@ exports.getTitle = (error) => { * const description = errors.getDescription(error); * console.log(description); */ -exports.getDescription = (error) => { +exports.getDescription = (error, options = {}) => { + _.defaults(options, { + userFriendlyDescriptionsOnly: false + }); + if (!_.isError(error) && !_.isPlainObject(error)) { return ''; } @@ -227,6 +233,10 @@ exports.getDescription = (error) => { return codeDescription; } + if (options.userFriendlyDescriptionsOnly) { + return ''; + } + if (error.stack) { return error.stack; } diff --git a/tests/shared/errors.spec.js b/tests/shared/errors.spec.js index 55fe61ee..bb01d223 100644 --- a/tests/shared/errors.spec.js +++ b/tests/shared/errors.spec.js @@ -422,6 +422,60 @@ describe('Shared: Errors', function() { m.chai.expect(errors.getDescription(error)).to.equal('Memory error'); }); + describe('given userFriendlyDescriptionsOnly is false', function() { + + it('should return the stack for a basic error', function() { + const error = new Error('Foo'); + m.chai.expect(errors.getDescription(error, { + userFriendlyDescriptionsOnly: false + })).to.equal(error.stack); + }); + + it('should return the stack if the description is an empty string', function() { + const error = new Error('Foo'); + error.description = ''; + m.chai.expect(errors.getDescription(error, { + userFriendlyDescriptionsOnly: false + })).to.equal(error.stack); + }); + + it('should return the stack if the description is a blank string', function() { + const error = new Error('Foo'); + error.description = ' '; + m.chai.expect(errors.getDescription(error, { + userFriendlyDescriptionsOnly: false + })).to.equal(error.stack); + }); + + }); + + describe('given userFriendlyDescriptionsOnly is true', function() { + + it('should return an empty string for a basic error', function() { + const error = new Error('Foo'); + m.chai.expect(errors.getDescription(error, { + userFriendlyDescriptionsOnly: true + })).to.equal(''); + }); + + it('should return an empty string if the description is an empty string', function() { + const error = new Error('Foo'); + error.description = ''; + m.chai.expect(errors.getDescription(error, { + userFriendlyDescriptionsOnly: true + })).to.equal(''); + }); + + it('should return an empty string if the description is a blank string', function() { + const error = new Error('Foo'); + error.description = ' '; + m.chai.expect(errors.getDescription(error, { + userFriendlyDescriptionsOnly: true + })).to.equal(''); + }); + + }); + }); describe('.createError()', function() {