Skip to content

Commit

Permalink
Add support for XZ compressed images
Browse files Browse the repository at this point in the history
This PR introduces `etcher-image-stream`:

https://github.com/resin-io-modules/etcher-image-stream

a module that will handle support for decompression, URL streaming, and
any other way to get a source of data to write in Etcher.

Most of the changes in this PR are because XZ decompression includes a
native dependency (no pure JS implementations out there for now), so we
had to tweak various things for the dependency to work correctly on
Etcher/Electron.

See: #325
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
  • Loading branch information
jviotti committed Apr 27, 2016
1 parent a88cab2 commit f83c5f2
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 26 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -2,7 +2,7 @@ language: cpp
sudo: false

env:
- NODE_VERSION="4"
- NODE_VERSION="5"
os:
- linux
- osx
Expand Down
4 changes: 4 additions & 0 deletions README.md
Expand Up @@ -27,6 +27,10 @@ Developing

You can manually run the application with the following steps:

- Install [NodeJS v5.10.0](https://nodejs.org/en/).

Sadly we need to enforce the same NodeJS version that the Electron version we use is running to avoid module version mismatches when building native dependencies (`electron-rebuild` doesn't seem to be enough).

- Clone the repository.

```sh
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Expand Up @@ -11,7 +11,7 @@ cache:
# what combinations to test
environment:
matrix:
- nodejs_version: 4
- nodejs_version: 5

install:
- ps: Install-Product node $env:nodejs_version x64
Expand Down
9 changes: 3 additions & 6 deletions lib/gui/dialog.js
Expand Up @@ -19,6 +19,7 @@
const electron = require('electron');
const Bluebird = require('bluebird');
const zipImage = require('resin-zip-image');
const imageStream = require('etcher-image-stream');
const packageJSON = require('../../package.json');

/**
Expand Down Expand Up @@ -46,12 +47,8 @@ exports.selectImage = function() {
properties: [ 'openFile' ],
filters: [
{
name: 'IMG/ISO/ZIP',
extensions: [
'zip',
'img',
'iso'
]
name: 'OS Images',
extensions: imageStream.supportedFileTypes
}
]
}, function(files) {
Expand Down
44 changes: 27 additions & 17 deletions lib/src/writer.js
Expand Up @@ -17,10 +17,10 @@
'use strict';

const imageWrite = require('resin-image-write');
const imageStream = require('etcher-image-stream');
const zipImage = require('resin-zip-image');
const Bluebird = require('bluebird');
const umount = Bluebird.promisifyAll(require('umount'));
const fs = require('fs');
const os = require('os');
const isWindows = os.platform() === 'win32';

Expand All @@ -33,28 +33,37 @@ if (isWindows) {
* @function
* @private
*
* @description
* This function adds a custom `.length` property
* to the stream which equals the image size in bytes.
*
* @param {String} image - path to image
* @returns {ReadableStream} image stream
* @fulfil {Object} - image stream
* @returns {Promise}
*
* @example
* const stream = writer.getImageStream('foo/bar/baz.img');
* writer.getImageStream('foo/bar/baz.img').then(function(image) {
* console.log(image.size);
*
* if (image.transform) {
* stream.pipe(image.transform).pipe(output);
* } else {
* stream.pipe(output);
* }
* });
*/
exports.getImageStream = function(image) {
if (zipImage.isZip(image)) {
if (!zipImage.isValidZipImage(image)) {
return Bluebird.reject(new Error('Invalid zip image'));
}

return zipImage.extractImage(image);
return zipImage.extractImage(image).then(function(stream) {
return {
stream: stream,
size: stream.length,
transform: null
};
});
}

let stream = fs.createReadStream(image);
stream.length = fs.statSync(image).size;
return Bluebird.resolve(stream);
return imageStream.getFromFilePath(image);
};

/**
Expand All @@ -66,7 +75,7 @@ exports.getImageStream = function(image) {
* See https://github.com/resin-io/resin-image-write for information
* about the `state` object passed to `onProgress` callback.
*
* @param {String} image - path to image
* @param {String} imagePath - path to image
* @param {Object} drive - drive
* @param {Object} options - options
* @param {Boolean} [options.unmountOnSuccess=false] - unmount on success
Expand All @@ -88,13 +97,14 @@ exports.getImageStream = function(image) {
* console.log('Done!');
* });
*/
exports.writeImage = function(image, drive, options, onProgress) {
exports.writeImage = function(imagePath, drive, options, onProgress) {
return umount.umountAsync(drive.device).then(function() {
return exports.getImageStream(image);
}).then(function(stream) {
return imageWrite.write(drive.device, stream, {
return exports.getImageStream(imagePath);
}).then(function(image) {
return imageWrite.write(drive.device, image.stream, {
check: options.validateWriteOnSuccess,
size: stream.length
size: image.size,
transform: image.transform
});
}).then(function(writer) {
return new Bluebird(function(resolve, reject) {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -56,15 +56,16 @@
"bootstrap-sass": "^3.3.5",
"chalk": "^1.1.3",
"drivelist": "^3.0.0",
"etcher-image-stream": "^1.1.0",
"flexboxgrid": "^6.3.0",
"is-elevated": "^1.0.0",
"lodash": "^4.5.1",
"ngstorage": "^0.3.10",
"open": "0.0.5",
"resin-image-write": "^4.0.0",
"resin-cli-errors": "^1.2.0",
"resin-cli-form": "^1.4.1",
"resin-cli-visuals": "^1.2.8",
"resin-image-write": "^4.0.0",
"resin-zip-image": "^1.1.2",
"sudo-prompt": "^3.1.0",
"trackjs": "^2.1.16",
Expand Down

0 comments on commit f83c5f2

Please sign in to comment.