From d3a34e49a51ce3781dbd237de11b750a7960e9be Mon Sep 17 00:00:00 2001 From: Chris Reeves Date: Sat, 27 Dec 2014 19:26:31 +1100 Subject: [PATCH] quick and dirty pass at caching crc info between starts --- lib/builtins/include.js | 4 +- lib/builtins/map.js | 10 ++- lib/file/link.js | 4 +- lib/nodes/Transformer.js | 140 +++++++++++++++++++++------------------ lib/utils/cleanup.js | 2 +- test/scenarios.js | 1 + 6 files changed, 91 insertions(+), 70 deletions(-) diff --git a/lib/builtins/include.js b/lib/builtins/include.js index e25e798..ea1be22 100644 --- a/lib/builtins/include.js +++ b/lib/builtins/include.js @@ -47,7 +47,9 @@ module.exports = function include ( inputdir, outputdir, options, callback ) { sander.mkdirSync( path.dirname( destpath ) ); try { - symlinkOrCopy( filepath, destpath ); + if ( !sander.existsSync( destpath ) ) { + symlinkOrCopy( filepath, destpath ); + } check(); } catch ( e ) { cb( e ); diff --git a/lib/builtins/map.js b/lib/builtins/map.js index 2529570..dc6f844 100644 --- a/lib/builtins/map.js +++ b/lib/builtins/map.js @@ -36,7 +36,11 @@ module.exports = function map ( inputdir, outputdir, options ) { // If this mapper only accepts certain extensions, and this isn't // one of them, just copy the file if ( options.accept && !~options.accept.indexOf( ext ) ) { - return sander.link( srcpath ).to( destpath ); + if ( !sander.existsSync( destpath ) ) { + return sander.link( srcpath ).to( destpath ); + } else { + return Promise.resolve( true ); + } } return sander.stat( srcpath ).then( function ( stats ) { @@ -57,6 +61,10 @@ module.exports = function map ( inputdir, outputdir, options ) { previous = options.cache[ filename ]; if ( previous && compareBuffers( crc, previous.crc ) ) { + if ( sander.existsSync( destpath ) ) { + return Promise.resolve( true ); + } + promises = [ sander.link( previous.codepath ).to( destpath ) ]; if ( previous.mappath ) { diff --git a/lib/file/link.js b/lib/file/link.js index 52efcba..3def7f4 100644 --- a/lib/file/link.js +++ b/lib/file/link.js @@ -11,7 +11,9 @@ module.exports = function () { var dest = resolve.apply( null, arguments ); return sander.mkdir( path.dirname( dest ) ).then( function () { - symlinkOrCopy( src, dest ); + if ( !sander.existsSync( dest ) ) { + symlinkOrCopy( src, dest ); + } }); } }; diff --git a/lib/nodes/Transformer.js b/lib/nodes/Transformer.js index 989b21d..b94e870 100644 --- a/lib/nodes/Transformer.js +++ b/lib/nodes/Transformer.js @@ -54,76 +54,84 @@ module.exports = Node.extend({ }; outputdir = path.resolve( session.config.gobbledir, node.id, '' + node.counter++ ); - node._ready = sander.mkdir( outputdir ).then( function () { - return node.input.ready().then( function ( inputdir ) { - return queue.add( function ( fulfil, reject ) { - var promise, called, callback, start; - - node.emit( 'info', { - code: 'TRANSFORM_START', - progressIndicator: true, - id: node.id - }); - - start = Date.now(); - - callback = function ( err ) { - var gobbleError, stack, loc; - - if ( called ) { - return; - } - - called = true; - - if ( err ) { - stack = err.stack || new Error().stack; - - loc = extractLocationInfo( err ); - gobbleError = new GobbleError({ - message: 'transformation failed', - id: node.id, - code: 'TRANSFORMATION_FAILED', - original: err, - stack: stack, - file: loc.file, - line: loc.line, - column: loc.column - }); - - reject( gobbleError ); - } - - else { - node.emit( 'info', { - code: 'TRANSFORM_COMPLETE', - id: node.id, - duration: Date.now() - start - }); - - node._cleanup( outputdir ); - fulfil( outputdir ); + node._ready = sander.readFile( transformation.cachedir, '.cacheMap' ).then( function ( cache ) { + node.options.cache = JSON.parse( cache.toString() ); + }, function() { return true; } ).then( function () { + return sander.mkdir( outputdir ).then( function () { + return node.input.ready().then( function ( inputdir ) { + return queue.add( function ( fulfil, reject ) { + var promise, called, callback, start; + + node.emit( 'info', { + code: 'TRANSFORM_START', + progressIndicator: true, + id: node.id + }); + + start = Date.now(); + + callback = function ( err ) { + var gobbleError, stack, loc; + + if ( called ) { + return; + } + + called = true; + + if ( err ) { + stack = err.stack || new Error().stack; + + loc = extractLocationInfo( err ); + + gobbleError = new GobbleError({ + message: 'transformation failed', + id: node.id, + code: 'TRANSFORMATION_FAILED', + original: err, + stack: stack, + file: loc.file, + line: loc.line, + column: loc.column + }); + + reject( gobbleError ); + } + + else { + node.emit( 'info', { + code: 'TRANSFORM_COMPLETE', + id: node.id, + duration: Date.now() - start + }); + + // stash the cache for future + sander.writeFileSync( transformation.cachedir, '.cacheMap', JSON.stringify( node.options.cache || {} ) ); + + node._cleanup( outputdir ); + fulfil( outputdir ); + } + }; + + try { + promise = node.transformer.call( transformation, inputdir, outputdir, assign({}, node.options ), callback ); + + if ( promise && typeof promise.then === 'function' ) { + promise.then( function () { + callback(); // ensure no argument is passed + }).catch( callback ); + } + } catch ( err ) { + callback( err ); } - }; - - try { - promise = node.transformer.call( transformation, inputdir, outputdir, assign({}, node.options ), callback ); + }); + }).catch( function ( err ) { + node._abort(); + queue.abort(); - if ( promise && typeof promise.then === 'function' ) { - promise.then( function () { - callback(); // ensure no argument is passed - }).catch( callback ); - } - } catch ( err ) { - callback( err ); - } + throw err; }); - }).catch( function ( err ) { - node._abort(); - queue.abort(); - - throw err; }); }); } diff --git a/lib/utils/cleanup.js b/lib/utils/cleanup.js index 2e074e4..38349bf 100644 --- a/lib/utils/cleanup.js +++ b/lib/utils/cleanup.js @@ -4,7 +4,7 @@ var sander = require( 'sander' ), module.exports = function cleanup ( dir ) { return sander.mkdir( dir ).then( function () { return sander.readdir( dir ).then( function ( files ) { - var promises = files.map( function ( filename ) { + var promises = files.filter( function ( filename ) { return filename.indexOf( '.cache' ) !== -1; }).map( function ( filename ) { return sander.rimraf( dir, filename ); }); diff --git a/test/scenarios.js b/test/scenarios.js index 8a9e0c4..634a92e 100644 --- a/test/scenarios.js +++ b/test/scenarios.js @@ -88,6 +88,7 @@ module.exports = function () { files = files.filter( function ( file ) { return /-foo$/.test( file ); }); sander.readdir( '.gobble', files[0] ).then( function ( files ) { + files = files.filter( function ( file ) { return file.indexOf( '.cache' ) === -1; }); assert.deepEqual( files, [ '2' ] ); done(); });