mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-25 12:16:37 +00:00
refactor(image-stream): get rid of read-chunk (#1243)
We also took the opportunity to make `utils.getArchiveMimeType()` asynchronous. Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
This commit is contained in:
parent
d5ec71c5da
commit
4a3a123f42
@ -67,9 +67,7 @@ const errors = require('../shared/errors');
|
|||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
exports.getFromFilePath = (file) => {
|
exports.getFromFilePath = (file) => {
|
||||||
return Bluebird.try(() => {
|
return utils.getArchiveMimeType(file).then((type) => {
|
||||||
const type = utils.getArchiveMimeType(file);
|
|
||||||
|
|
||||||
if (!_.has(handlers, type)) {
|
if (!_.has(handlers, type)) {
|
||||||
throw errors.createUserError('Invalid image', `The ${type} format is not supported`);
|
throw errors.createUserError('Invalid image', `The ${type} format is not supported`);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const readChunk = require('read-chunk');
|
const Bluebird = require('bluebird');
|
||||||
|
const fs = Bluebird.promisifyAll(require('fs'));
|
||||||
const archiveType = require('archive-type');
|
const archiveType = require('archive-type');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,18 +27,34 @@ const archiveType = require('archive-type');
|
|||||||
* @public
|
* @public
|
||||||
*
|
*
|
||||||
* @param {String} file - file path
|
* @param {String} file - file path
|
||||||
* @returns {String} mime type
|
* @fulfil {String} - mime type
|
||||||
|
* @returns {Promise}
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* utils.getArchiveMimeType('path/to/raspberrypi.img.gz');
|
* utils.getArchiveMimeType('path/to/raspberrypi.img.gz').then((mimeType) => {
|
||||||
|
* console.log(mimeType);
|
||||||
|
* });
|
||||||
*/
|
*/
|
||||||
exports.getArchiveMimeType = (file) => {
|
exports.getArchiveMimeType = (file) => {
|
||||||
|
|
||||||
// `archive-type` only needs the first 261 bytes
|
// `archive-type` only needs the first 261 bytes
|
||||||
// See https://github.com/kevva/archive-type
|
// See https://github.com/kevva/archive-type
|
||||||
const MAGIC_NUMBER_BUFFER_START = 0;
|
const ARCHIVE_TYPE_IDENTIFICATION_BYTES_LENGTH = 261;
|
||||||
const MAGIC_NUMBER_BUFFER_END = 261;
|
|
||||||
const chunk = readChunk.sync(file, MAGIC_NUMBER_BUFFER_START, MAGIC_NUMBER_BUFFER_END);
|
|
||||||
|
|
||||||
return _.get(archiveType(chunk), [ 'mime' ], 'application/octet-stream');
|
return Bluebird.using(fs.openAsync(file, 'r').disposer((fileDescriptor) => {
|
||||||
|
return fs.closeAsync(fileDescriptor);
|
||||||
|
}), (fileDescriptor) => {
|
||||||
|
const BUFFER_START = 0;
|
||||||
|
const chunk = new Buffer(ARCHIVE_TYPE_IDENTIFICATION_BYTES_LENGTH);
|
||||||
|
|
||||||
|
return fs.readAsync(
|
||||||
|
fileDescriptor,
|
||||||
|
chunk,
|
||||||
|
BUFFER_START,
|
||||||
|
ARCHIVE_TYPE_IDENTIFICATION_BYTES_LENGTH,
|
||||||
|
null
|
||||||
|
).then(() => {
|
||||||
|
return _.get(archiveType(chunk), [ 'mime' ], 'application/octet-stream');
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
5
npm-shrinkwrap.json
generated
5
npm-shrinkwrap.json
generated
@ -5521,11 +5521,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"read-chunk": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"from": "read-chunk@>=2.0.0 <3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.0.0.tgz"
|
|
||||||
},
|
|
||||||
"read-only-stream": {
|
"read-only-stream": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"from": "read-only-stream@>=2.0.0 <3.0.0",
|
"from": "read-only-stream@>=2.0.0 <3.0.0",
|
||||||
|
@ -90,7 +90,6 @@
|
|||||||
"node-ipc": "^8.9.2",
|
"node-ipc": "^8.9.2",
|
||||||
"node-stream-zip": "^1.3.4",
|
"node-stream-zip": "^1.3.4",
|
||||||
"path-is-inside": "^1.0.2",
|
"path-is-inside": "^1.0.2",
|
||||||
"read-chunk": "^2.0.0",
|
|
||||||
"redux": "^3.5.2",
|
"redux": "^3.5.2",
|
||||||
"redux-localstorage": "^0.4.1",
|
"redux-localstorage": "^0.4.1",
|
||||||
"resin-cli-form": "^1.4.1",
|
"resin-cli-form": "^1.4.1",
|
||||||
|
@ -25,29 +25,44 @@ describe('ImageStream: Utils', function() {
|
|||||||
|
|
||||||
describe('.getArchiveMimeType()', function() {
|
describe('.getArchiveMimeType()', function() {
|
||||||
|
|
||||||
it('should return application/x-bzip2 for a bz2 archive', function() {
|
it('should resolve application/x-bzip2 for a bz2 archive', function(done) {
|
||||||
const file = path.join(DATA_PATH, 'bz2', 'raspberrypi.img.bz2');
|
const file = path.join(DATA_PATH, 'bz2', 'raspberrypi.img.bz2');
|
||||||
m.chai.expect(utils.getArchiveMimeType(file)).to.equal('application/x-bzip2');
|
utils.getArchiveMimeType(file).then((type) => {
|
||||||
|
m.chai.expect(type).to.equal('application/x-bzip2');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return application/x-xz for a xz archive', function() {
|
it('should resolve application/x-xz for a xz archive', function(done) {
|
||||||
const file = path.join(DATA_PATH, 'xz', 'raspberrypi.img.xz');
|
const file = path.join(DATA_PATH, 'xz', 'raspberrypi.img.xz');
|
||||||
m.chai.expect(utils.getArchiveMimeType(file)).to.equal('application/x-xz');
|
utils.getArchiveMimeType(file).then((type) => {
|
||||||
|
m.chai.expect(type).to.equal('application/x-xz');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return application/gzip for a gz archive', function() {
|
it('should resolve application/gzip for a gz archive', function(done) {
|
||||||
const file = path.join(DATA_PATH, 'gz', 'raspberrypi.img.gz');
|
const file = path.join(DATA_PATH, 'gz', 'raspberrypi.img.gz');
|
||||||
m.chai.expect(utils.getArchiveMimeType(file)).to.equal('application/gzip');
|
utils.getArchiveMimeType(file).then((type) => {
|
||||||
|
m.chai.expect(type).to.equal('application/gzip');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return application/zip for a zip archive', function() {
|
it('should resolve application/zip for a zip archive', function(done) {
|
||||||
const file = path.join(DATA_PATH, 'zip', 'zip-directory-rpi-only.zip');
|
const file = path.join(DATA_PATH, 'zip', 'zip-directory-rpi-only.zip');
|
||||||
m.chai.expect(utils.getArchiveMimeType(file)).to.equal('application/zip');
|
utils.getArchiveMimeType(file).then((type) => {
|
||||||
|
m.chai.expect(type).to.equal('application/zip');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return application/octet-stream for an uncompress image', function() {
|
it('should resolve application/octet-stream for an uncompress image', function(done) {
|
||||||
const file = path.join(DATA_PATH, 'images', 'raspberrypi.img');
|
const file = path.join(DATA_PATH, 'images', 'raspberrypi.img');
|
||||||
m.chai.expect(utils.getArchiveMimeType(file)).to.equal('application/octet-stream');
|
utils.getArchiveMimeType(file).then((type) => {
|
||||||
|
m.chai.expect(type).to.equal('application/octet-stream');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user