From 71d5fad2b0e23f98a7b697cd98638a99a386c3ba Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Tue, 4 Apr 2017 09:49:00 -0400 Subject: [PATCH] refactor(image-stream): get rid of rindle (#1246) Signed-off-by: Juan Cruz Viotti --- lib/image-stream/archive.js | 10 ++-- lib/image-stream/utils.js | 35 ++++++++++++ npm-shrinkwrap.json | 22 -------- package.json | 1 - tests/image-stream/archive-hooks/zip.spec.js | 20 +++---- tests/image-stream/tester.js | 6 ++- tests/image-stream/utils.spec.js | 57 ++++++++++++++++++++ 7 files changed, 108 insertions(+), 43 deletions(-) diff --git a/lib/image-stream/archive.js b/lib/image-stream/archive.js index 6a141cc8..df6c59c8 100644 --- a/lib/image-stream/archive.js +++ b/lib/image-stream/archive.js @@ -18,10 +18,10 @@ const path = require('path'); const Bluebird = require('bluebird'); -const rindle = require('rindle'); const _ = require('lodash'); const PassThroughStream = require('stream').PassThrough; const supportedFileTypes = require('./supported'); +const utils = require('./utils'); const errors = require('../shared/errors'); /** @@ -82,7 +82,7 @@ const extractEntryByPath = (archive, filePath, options) => { } return options.hooks.extractFile(archive, options.entries, fileEntry.name) - .then(rindle.extract); + .then(utils.extractStream); }; /** @@ -137,9 +137,9 @@ const extractArchiveMetadata = (archive, basePath, options) => { checksum: results.manifest.checksum, bytesToZeroOutFromTheBeginning: results.manifest.bytesToZeroOutFromTheBeginning, recommendedDriveSize: results.manifest.recommendedDriveSize, - logo: results.logo, - bmap: results.bmap, - instructions: results.instructions + logo: _.invoke(results.logo, [ 'toString' ]), + bmap: _.invoke(results.bmap, [ 'toString' ]), + instructions: _.invoke(results.instructions, [ 'toString' ]) }; }); }; diff --git a/lib/image-stream/utils.js b/lib/image-stream/utils.js index 5f795c5e..5090c5a3 100644 --- a/lib/image-stream/utils.js +++ b/lib/image-stream/utils.js @@ -58,3 +58,38 @@ exports.getArchiveMimeType = (file) => { }); }); }; + +/** + * @summary Extract the data of a readable stream + * @function + * @public + * + * @description + * You should be careful when using this function, since you can only + * extract files that are not bigger than the available computer memory. + * + * @param {StreamReadable} stream - stream + * @fulfil {Buffer} - data + * @returns {Promise} + * + * @example + * const stream = fs.createReadStream('./foo/bar'); + * + * utils.extractStream(stream).then((data) => { + * console.log(data.toString()); + * }); + */ +exports.extractStream = (stream) => { + return new Bluebird((resolve, reject) => { + const chunks = []; + + stream.on('data', (chunk) => { + chunks.push(chunk); + }); + + stream.on('error', reject); + stream.on('end', () => { + resolve(Buffer.concat(chunks)); + }); + }); +}; diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index d998e33d..6da0e6bf 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -5844,23 +5844,6 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", "dev": true }, - "rindle": { - "version": "1.3.0", - "from": "rindle@>=1.3.0 <2.0.0", - "resolved": "https://registry.npmjs.org/rindle/-/rindle-1.3.0.tgz", - "dependencies": { - "bluebird": { - "version": "2.11.0", - "from": "bluebird@>=2.10.2 <3.0.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz" - }, - "lodash": { - "version": "3.10.1", - "from": "lodash@>=3.10.1 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz" - } - } - }, "ripemd160": { "version": "1.0.1", "from": "ripemd160@>=1.0.0 <2.0.0", @@ -6328,11 +6311,6 @@ "from": "string-template@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz" }, - "string-to-stream": { - "version": "1.1.0", - "from": "string-to-stream@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/string-to-stream/-/string-to-stream-1.1.0.tgz" - }, "string-width": { "version": "1.0.1", "from": "string-width@>=1.0.1 <2.0.0", diff --git a/package.json b/package.json index 6fe7ef0e..15049d4b 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,6 @@ "redux-localstorage": "^0.4.1", "resin-cli-form": "^1.4.1", "resin-cli-visuals": "^1.2.8", - "rindle": "^1.3.0", "rx": "^4.1.0", "semver": "^5.1.0", "sudo-prompt": "^6.1.0", diff --git a/tests/image-stream/archive-hooks/zip.spec.js b/tests/image-stream/archive-hooks/zip.spec.js index f6242d1f..733a4de0 100644 --- a/tests/image-stream/archive-hooks/zip.spec.js +++ b/tests/image-stream/archive-hooks/zip.spec.js @@ -18,8 +18,8 @@ const m = require('mochainon'); const path = require('path'); -const rindle = require('rindle'); const zipHooks = require('../../../lib/image-stream/archive-hooks/zip'); +const utils = require('../../../lib/image-stream/utils'); const ZIP_PATH = path.join(__dirname, '..', 'data', 'zip'); describe('ImageStream: Archive hooks: ZIP', function() { @@ -100,12 +100,9 @@ describe('ImageStream: Archive hooks: ZIP', function() { const fileName = 'zip-directory-nested-misc/foo'; zipHooks.getEntries(this.zip).then((entries) => { return zipHooks.extractFile(this.zip, entries, fileName); - }).then((stream) => { - rindle.extract(stream, function(error, data) { - m.chai.expect(error).to.not.exist; - m.chai.expect(data).to.equal('foo\n'); - done(); - }); + }).then(utils.extractStream).then((data) => { + m.chai.expect(data.toString()).to.equal('foo\n'); + done(); }); }); @@ -113,12 +110,9 @@ describe('ImageStream: Archive hooks: ZIP', function() { const fileName = 'zip-directory-nested-misc/hello/there/bar'; zipHooks.getEntries(this.zip).then((entries) => { return zipHooks.extractFile(this.zip, entries, fileName); - }).then((stream) => { - rindle.extract(stream, function(error, data) { - m.chai.expect(error).to.not.exist; - m.chai.expect(data).to.equal('bar\n'); - done(); - }); + }).then(utils.extractStream).then((data) => { + m.chai.expect(data.toString()).to.equal('bar\n'); + done(); }); }); diff --git a/tests/image-stream/tester.js b/tests/image-stream/tester.js index 0ab33469..20647975 100644 --- a/tests/image-stream/tester.js +++ b/tests/image-stream/tester.js @@ -22,7 +22,6 @@ const Bluebird = require('bluebird'); const fileExists = require('file-exists'); const fs = Bluebird.promisifyAll(require('fs')); const tmp = require('tmp'); -const rindle = require('rindle'); const imageStream = require('../../lib/image-stream/index'); const doFilesContainTheSameData = (file1, file2) => { @@ -72,7 +71,10 @@ exports.extractFromFilePath = function(file, image) { .pipe(results.transform) .pipe(fs.createWriteStream(output)); - return rindle.wait(stream); + return new Bluebird((resolve, reject) => { + stream.on('error', reject); + stream.on('close', resolve); + }); }).then(function() { return doFilesContainTheSameData(image, output); }).then(function(areEqual) { diff --git a/tests/image-stream/utils.spec.js b/tests/image-stream/utils.spec.js index bf1c519d..c7ea3199 100644 --- a/tests/image-stream/utils.spec.js +++ b/tests/image-stream/utils.spec.js @@ -18,6 +18,7 @@ const m = require('mochainon'); const path = require('path'); +const StreamReadable = require('stream').Readable; const DATA_PATH = path.join(__dirname, 'data'); const utils = require('../../lib/image-stream/utils'); @@ -67,4 +68,60 @@ describe('ImageStream: Utils', function() { }); + describe('.extractStream()', function() { + + describe('given a stream that emits data', function() { + + beforeEach(function() { + this.stream = new StreamReadable(); + + /* eslint-disable no-underscore-dangle */ + + this.stream._read = function() { + + /* eslint-enable no-underscore-dangle */ + + this.push(Buffer.from('Hello', 'utf8')); + this.push(Buffer.from(' ', 'utf8')); + this.push(Buffer.from('World', 'utf8')); + this.push(null); + }; + }); + + it('should yield the stream data', function(done) { + utils.extractStream(this.stream).then((data) => { + m.chai.expect(data.toString()).to.equal('Hello World'); + done(); + }).catch(done); + }); + + }); + + describe('given a stream that throws an error', function() { + + beforeEach(function() { + this.stream = new StreamReadable(); + + /* eslint-disable no-underscore-dangle */ + + this.stream._read = function() { + + /* eslint-enable no-underscore-dangle */ + + this.emit('error', new Error('stream error')); + }; + }); + + it('should be rejected with the error', function(done) { + utils.extractStream(this.stream).catch((error) => { + m.chai.expect(error).to.be.an.instanceof(Error); + m.chai.expect(error.message).to.equal('stream error'); + done(); + }); + }); + + }); + + }); + });