Merge pull request #46 from resin-io/jviotti/fix/40/windows-eject

Eject Windows drives after successful burning
This commit is contained in:
Juan Cruz Viotti 2015-11-23 23:30:03 -04:00
commit 915646d706
7 changed files with 52 additions and 25 deletions

View File

@ -65,7 +65,7 @@ app.controller('AppController', function($q, DriveScannerService, SelectionState
this.selectDrive = function(drive) { this.selectDrive = function(drive) {
self.selection.setDrive(drive); self.selection.setDrive(drive);
console.debug('Drive selected: ' + drive); console.debug('Drive selected: ' + drive.device);
}; };
this.platform = window.process.platform; this.platform = window.process.platform;
@ -76,7 +76,7 @@ app.controller('AppController', function($q, DriveScannerService, SelectionState
// otherwise Windows throws EPERM // otherwise Windows throws EPERM
self.scanner.stop(); self.scanner.stop();
console.debug('Burning ' + image + ' to ' + drive); console.debug('Burning ' + image + ' to ' + drive.device);
return self.writer.burn(image, drive).then(function() { return self.writer.burn(image, drive).then(function() {
console.debug('Done!'); console.debug('Done!');
}); });
@ -371,13 +371,15 @@ imageWriter.service('ImageWriterService', function($q, $timeout) {
* This function is extracted for testing purposes. * This function is extracted for testing purposes.
* *
* @param {String} image - image path * @param {String} image - image path
* @param {String} drive - drive device * @param {Object} drive - drive
* @param {Function} onProgress - in progress callback (state) * @param {Function} onProgress - in progress callback (state)
* *
* @returns {Promise} * @returns {Promise}
* *
* @example * @example
* ImageWriter.performWrite('path/to/image.img', '/dev/disk2', function(state) { * ImageWriter.performWrite('path/to/image.img', {
* device: '/dev/disk2'
* }, function(state) {
* console.log(state.percentage); * console.log(state.percentage);
* }); * });
*/ */
@ -394,12 +396,14 @@ imageWriter.service('ImageWriterService', function($q, $timeout) {
* This function will update `.progress` with the current writing percentage. * This function will update `.progress` with the current writing percentage.
* *
* @param {String} image - image path * @param {String} image - image path
* @param {String} drive - drive device * @param {Object} drive - drive
* *
* @returns {Promise} * @returns {Promise}
* *
* @example * @example
* ImageWriterService.burn('foo.img', '/dev/disk').then(function() { * ImageWriterService.burn('foo.img', {
* device: '/dev/disk2'
* }).then(function() {
* console.log('Write completed!'); * console.log('Write completed!');
* }); * });
*/ */
@ -520,10 +524,12 @@ selectionState.service('SelectionStateService', function() {
* @function * @function
* @public * @public
* *
* @param {String} drive - drive * @param {Object} drive - drive
* *
* @example * @example
* SelectionStateService.setDrive('/dev/disk2'); * SelectionStateService.setDrive({
* device: '/dev/disk2'
* });
*/ */
this.setDrive = function(drive) { this.setDrive = function(drive) {
selection.drive = drive; selection.drive = drive;
@ -548,7 +554,7 @@ selectionState.service('SelectionStateService', function() {
* @function * @function
* @public * @public
* *
* @returns {String} drive * @returns {Object} drive
* *
* @example * @example
* var drive = SelectionStateService.getDrive(); * var drive = SelectionStateService.getDrive();

View File

@ -64,7 +64,7 @@ app.controller('AppController', function($q, DriveScannerService, SelectionState
this.selectDrive = function(drive) { this.selectDrive = function(drive) {
self.selection.setDrive(drive); self.selection.setDrive(drive);
console.debug('Drive selected: ' + drive); console.debug('Drive selected: ' + drive.device);
}; };
this.platform = window.process.platform; this.platform = window.process.platform;
@ -75,7 +75,7 @@ app.controller('AppController', function($q, DriveScannerService, SelectionState
// otherwise Windows throws EPERM // otherwise Windows throws EPERM
self.scanner.stop(); self.scanner.stop();
console.debug('Burning ' + image + ' to ' + drive); console.debug('Burning ' + image + ' to ' + drive.device);
return self.writer.burn(image, drive).then(function() { return self.writer.burn(image, drive).then(function() {
console.debug('Done!'); console.debug('Done!');
}); });

View File

@ -108,13 +108,15 @@ imageWriter.service('ImageWriterService', function($q, $timeout) {
* This function is extracted for testing purposes. * This function is extracted for testing purposes.
* *
* @param {String} image - image path * @param {String} image - image path
* @param {String} drive - drive device * @param {Object} drive - drive
* @param {Function} onProgress - in progress callback (state) * @param {Function} onProgress - in progress callback (state)
* *
* @returns {Promise} * @returns {Promise}
* *
* @example * @example
* ImageWriter.performWrite('path/to/image.img', '/dev/disk2', function(state) { * ImageWriter.performWrite('path/to/image.img', {
* device: '/dev/disk2'
* }, function(state) {
* console.log(state.percentage); * console.log(state.percentage);
* }); * });
*/ */
@ -131,12 +133,14 @@ imageWriter.service('ImageWriterService', function($q, $timeout) {
* This function will update `.progress` with the current writing percentage. * This function will update `.progress` with the current writing percentage.
* *
* @param {String} image - image path * @param {String} image - image path
* @param {String} drive - drive device * @param {Object} drive - drive
* *
* @returns {Promise} * @returns {Promise}
* *
* @example * @example
* ImageWriterService.burn('foo.img', '/dev/disk').then(function() { * ImageWriterService.burn('foo.img', {
* device: '/dev/disk2'
* }).then(function() {
* console.log('Write completed!'); * console.log('Write completed!');
* }); * });
*/ */

View File

@ -45,10 +45,12 @@ selectionState.service('SelectionStateService', function() {
* @function * @function
* @public * @public
* *
* @param {String} drive - drive * @param {Object} drive - drive
* *
* @example * @example
* SelectionStateService.setDrive('/dev/disk2'); * SelectionStateService.setDrive({
* device: '/dev/disk2'
* });
*/ */
this.setDrive = function(drive) { this.setDrive = function(drive) {
selection.drive = drive; selection.drive = drive;
@ -73,7 +75,7 @@ selectionState.service('SelectionStateService', function() {
* @function * @function
* @public * @public
* *
* @returns {String} drive * @returns {Object} drive
* *
* @example * @example
* var drive = SelectionStateService.getDrive(); * var drive = SelectionStateService.getDrive();

View File

@ -54,7 +54,7 @@
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li ng-repeat="drive in app.scanner.drives"> <li ng-repeat="drive in app.scanner.drives">
<a href="#" ng-click="app.selectDrive(drive.device)"> <a href="#" ng-click="app.selectDrive(drive)">
<!-- Show drive letter instead of phsycal drive name on Windows --> <!-- Show drive letter instead of phsycal drive name on Windows -->
<span ng-if="app.platform == 'win32'">Drive {{ drive.mountpoint }}\ - {{ drive.size }}</span> <span ng-if="app.platform == 'win32'">Drive {{ drive.mountpoint }}\ - {{ drive.size }}</span>
@ -72,7 +72,7 @@
</div> </div>
<div ng-show="app.selection.hasDrive()"> <div ng-show="app.selection.hasDrive()">
<span>{{ app.selection.getDrive() }}</span> <span>{{ app.selection.getDrive().device }}</span>
</div> </div>
</div> </div>
</div> </div>

View File

@ -25,6 +25,12 @@ var imageWrite = require('resin-image-write');
var Promise = require('bluebird'); var Promise = require('bluebird');
var umount = Promise.promisifyAll(require('umount')); var umount = Promise.promisifyAll(require('umount'));
var fs = require('fs'); var fs = require('fs');
var os = require('os');
var isWindows = os.platform() === 'win32';
if (isWindows) {
var removedrive = Promise.promisifyAll(require('removedrive'));
}
/** /**
* @summary Get image readable stream * @summary Get image readable stream
@ -59,13 +65,15 @@ exports.getImageStream = function(image) {
* about the `state` object passed to `onProgress` callback. * about the `state` object passed to `onProgress` callback.
* *
* @param {String} image - path to image * @param {String} image - path to image
* @param {String} drive - drive device * @param {Object} drive - drive
* @param {Function} onProgress - on progress callback (state) * @param {Function} onProgress - on progress callback (state)
* *
* @returns {Promise} * @returns {Promise}
* *
* @example * @example
* writer.writeImage('path/to/image.img', '/dev/disk2', function(state) { * writer.writeImage('path/to/image.img', {
* device: '/dev/disk2'
* }, function(state) {
* console.log(state.percentage); * console.log(state.percentage);
* }).then(function() { * }).then(function() {
* console.log('Done!'); * console.log('Done!');
@ -74,9 +82,9 @@ exports.getImageStream = function(image) {
exports.writeImage = function(image, drive, onProgress) { exports.writeImage = function(image, drive, onProgress) {
'use strict'; 'use strict';
return umount.umountAsync(drive).then(function() { return umount.umountAsync(drive.device).then(function() {
var stream = exports.getImageStream(image); var stream = exports.getImageStream(image);
return imageWrite.write(drive, stream); return imageWrite.write(drive.device, stream);
}).then(function(writer) { }).then(function(writer) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
writer.on('progress', onProgress); writer.on('progress', onProgress);
@ -84,6 +92,10 @@ exports.writeImage = function(image, drive, onProgress) {
writer.on('done', resolve); writer.on('done', resolve);
}); });
}).then(function() { }).then(function() {
return umount.umountAsync(drive); if (isWindows && drive.mountpoint) {
return removedrive.ejectAsync(drive.mountpoint);
} else {
return umount.umountAsync(drive.device);
}
}); });
}; };

View File

@ -16,6 +16,9 @@
}, },
"author": "Juan Cruz Viotti <juan@resin.io>", "author": "Juan Cruz Viotti <juan@resin.io>",
"license": "MIT", "license": "MIT",
"optionalDependencies": {
"removedrive": "^1.0.0"
},
"dependencies": { "dependencies": {
"angular": "^1.4.6", "angular": "^1.4.6",
"angular-ui-bootstrap": "^0.14.2", "angular-ui-bootstrap": "^0.14.2",