Skip to content

Commit

Permalink
Merge pull request #2886 from ertrzyiks/fix-error-handling-in-routing
Browse files Browse the repository at this point in the history
Add --bail option to handle errors thrown in generate command
  • Loading branch information
JLHwung authored Jan 7, 2018
2 parents 14e498d + c63c38c commit db081ab
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 3 deletions.
1 change: 1 addition & 0 deletions lib/hexo/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ RouteStream.prototype._read = function() {
}
}).catch(function(err) {
self.emit('error', err);
self.push(null);
});
};

Expand Down
23 changes: 21 additions & 2 deletions lib/plugins/console/generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ var prettyHrtime = require('pretty-hrtime');
var chalk = require('chalk');
var tildify = require('tildify');
var Transform = require('stream').Transform;
var PassThrough = require('stream').PassThrough;
var _ = require('lodash');
var util = require('hexo-util');

Expand All @@ -15,6 +16,7 @@ var join = pathFn.join;
function generateConsole(args) {
args = args || {};
var force = args.f || args.force;
var bail = args.b || args.bail;
var route = this.route;
var publicDir = this.public_dir;
var log = this.log;
Expand Down Expand Up @@ -44,11 +46,12 @@ function generateConsole(args) {
function writeFile(path, force) {
var dest = join(publicDir, path);
var cacheId = 'public/' + path;
var dataStream = wrapDataStream(route.get(path), {bail});
var cacheStream = new CacheStream();
var hashStream = new util.HashStream();

// Get data => Cache data => Calculate hash
return pipeStream(route.get(path), cacheStream, hashStream).then(function() {
return pipeStream(dataStream, cacheStream, hashStream).then(function() {
var cache = Cache.findById(cacheId);
var hash = hashStream.read().toString('hex');

Expand Down Expand Up @@ -86,6 +89,22 @@ function generateConsole(args) {
});
}

function wrapDataStream(dataStream, options) {
var bail = options && options.bail;

// Pass original stream with all data and errors
if (bail === true) {
return dataStream;
}

// Pass all data, but don't populate errors
dataStream.on('error', function(err) {
log.error(err);
});

return dataStream.pipe(new PassThrough());
}

function firstGenerate() {
// Show the loading time
var interval = prettyHrtime(process.hrtime(start));
Expand Down Expand Up @@ -160,7 +179,7 @@ function pipeStream() {
var src = args.shift();

return new Promise(function(resolve, reject) {
var stream = src;
var stream = src.on('error', reject);
var target;

while ((target = args.shift()) != null) {
Expand Down
3 changes: 2 additions & 1 deletion lib/plugins/console/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ module.exports = function(ctx) {
options: [
{name: '-d, --deploy', desc: 'Deploy after generated'},
{name: '-f, --force', desc: 'Force regenerate'},
{name: '-w, --watch', desc: 'Watch file changes'}
{name: '-w, --watch', desc: 'Watch file changes'},
{name: '-b, --bail', desc: 'Raise an error if any unhandled exception is thrown during generation'}
]
}, require('./generate'));

Expand Down
63 changes: 63 additions & 0 deletions test/scripts/console/generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,67 @@ describe('generate', () => {
result[0].should.eql('bb');
result[1].should.eql('cc');
}));

it('proceeds after error when bail option is not set', () => {
hexo.extend.renderer.register('err', 'html', () => Promise.reject(new Error('Testing unhandled exception')));
hexo.extend.generator.register('test_page', () =>
[
{
path: 'testing-path',
layout: 'post',
data: {}
}
]
);

return Promise.all([
fs.writeFile(pathFn.join(hexo.theme_dir, 'layout', 'post.err'), 'post')
]).then(() => {
return generate();
});
});

it('proceeds after error when bail option is set to false', () => {
hexo.extend.renderer.register('err', 'html', () => Promise.reject(new Error('Testing unhandled exception')));
hexo.extend.generator.register('test_page', () =>
[
{
path: 'testing-path',
layout: 'post',
data: {}
}
]
);

return Promise.all([
fs.writeFile(pathFn.join(hexo.theme_dir, 'layout', 'post.err'), 'post')
]).then(() => {
return generate({bail: false});
});
});

it('breaks after error when bail option is set to true', () => {
hexo.extend.renderer.register('err', 'html', () => Promise.reject(new Error('Testing unhandled exception')));
hexo.extend.generator.register('test_page', () =>
[
{
path: 'testing-path',
layout: 'post',
data: {}
}
]
);

var errorCallback = sinon.spy(err => {
err.should.have.property('message', 'Testing unhandled exception');
});

return Promise.all([
fs.writeFile(pathFn.join(hexo.theme_dir, 'layout', 'post.err'), 'post')
]).then(() => {
return generate({bail: true}).catch(errorCallback).finally(() => {
errorCallback.calledOnce.should.be.true;
});
});
});
});

0 comments on commit db081ab

Please sign in to comment.