mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-25 20:26:36 +00:00
Use async/await in flash.js
Avoid a rare race condition leading to "Error: There is already a flash in progress" messages Changelog-entry: Avoid "Error: There is already a flash in progress" errors Change-type: patch
This commit is contained in:
parent
ec015da795
commit
34c98d1dcd
@ -289,7 +289,7 @@ rules:
|
|||||||
- error
|
- error
|
||||||
- anonymous: always
|
- anonymous: always
|
||||||
named: always
|
named: always
|
||||||
asyncArrow: never
|
asyncArrow: always
|
||||||
template-tag-spacing:
|
template-tag-spacing:
|
||||||
- error
|
- error
|
||||||
- always
|
- always
|
||||||
|
@ -31,7 +31,6 @@ const availableDrives = require('../../../models/available-drives')
|
|||||||
const selection = require('../../../models/selection-state')
|
const selection = require('../../../models/selection-state')
|
||||||
|
|
||||||
module.exports = function (
|
module.exports = function (
|
||||||
$q,
|
|
||||||
$state,
|
$state,
|
||||||
$timeout,
|
$timeout,
|
||||||
FlashErrorModalService,
|
FlashErrorModalService,
|
||||||
@ -67,39 +66,34 @@ module.exports = function (
|
|||||||
*
|
*
|
||||||
* @param {Array<Object>} drives - list of drive objects
|
* @param {Array<Object>} drives - list of drive objects
|
||||||
* @param {Object} image - image object
|
* @param {Object} image - image object
|
||||||
* @returns {Promise}
|
* @returns {Promise<Boolean>}
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* displayTailoredWarning(drives, image).then(() => {
|
* displayTailoredWarning(drives, image).then((ok) => {
|
||||||
* console.log('Continue pressed')
|
* if (ok) {
|
||||||
* }).catch(() => {
|
* console.log('No warning was shown or continue was pressed')
|
||||||
* console.log('Change pressed')
|
* } else {
|
||||||
|
* console.log('Change was pressed')
|
||||||
|
* }
|
||||||
* })
|
* })
|
||||||
*/
|
*/
|
||||||
const displayTailoredWarning = (drives, image) => {
|
const displayTailoredWarning = async (drives, image) => {
|
||||||
const warningMessages = _.reduce(drives, (accumMessages, drive) => {
|
const warningMessages = []
|
||||||
|
for (const drive of drives) {
|
||||||
if (constraints.isDriveSizeLarge(drive)) {
|
if (constraints.isDriveSizeLarge(drive)) {
|
||||||
return accumMessages.concat(messages.warning.largeDriveSize(drive))
|
warningMessages.push(messages.warning.largeDriveSize(drive))
|
||||||
} else if (!constraints.isDriveSizeRecommended(drive, image)) {
|
} else if (!constraints.isDriveSizeRecommended(drive, image)) {
|
||||||
return accumMessages.concat(messages.warning.unrecommendedDriveSize(image, drive))
|
warningMessages.push(messages.warning.unrecommendedDriveSize(image, drive))
|
||||||
}
|
}
|
||||||
|
|
||||||
return accumMessages
|
// TODO(Shou): we should consider adding the same warning dialog for system drives and remove unsafe mode
|
||||||
}, [])
|
}
|
||||||
|
|
||||||
if (!warningMessages.length) {
|
if (!warningMessages.length) {
|
||||||
// TODO(Shou): we should consider adding the same warning dialog for system drives and remove unsafe mode
|
return true
|
||||||
return $q.resolve()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return confirmationWarningModal(warningMessages).then((value) => {
|
return confirmationWarningModal(warningMessages)
|
||||||
if (!value) {
|
|
||||||
DriveSelectorService.open()
|
|
||||||
return $q.reject()
|
|
||||||
}
|
|
||||||
|
|
||||||
return $q.resolve()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,35 +112,36 @@ module.exports = function (
|
|||||||
* '/dev/disk5'
|
* '/dev/disk5'
|
||||||
* ])
|
* ])
|
||||||
*/
|
*/
|
||||||
this.flashImageToDrive = () => {
|
this.flashImageToDrive = async () => {
|
||||||
const image = selection.getImage()
|
|
||||||
const devices = selection.getSelectedDevices()
|
const devices = selection.getSelectedDevices()
|
||||||
|
const image = selection.getImage()
|
||||||
if (flashState.isFlashing()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const drives = _.filter(availableDrives.getDrives(), (drive) => {
|
const drives = _.filter(availableDrives.getDrives(), (drive) => {
|
||||||
return _.includes(devices, drive.device)
|
return _.includes(devices, drive.device)
|
||||||
})
|
})
|
||||||
|
|
||||||
const hasDangerStatus = constraints.hasListDriveImageCompatibilityStatus(drives, image)
|
const hasDangerStatus = constraints.hasListDriveImageCompatibilityStatus(drives, image)
|
||||||
|
if (hasDangerStatus) {
|
||||||
|
if (!(await displayTailoredWarning(drives, image))) {
|
||||||
|
DriveSelectorService.open()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const userConfirm = hasDangerStatus ? _.partial(displayTailoredWarning, drives, image) : $q.resolve
|
if (flashState.isFlashing()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Trigger Angular digests along with store updates, as the flash state
|
// Trigger Angular digests along with store updates, as the flash state
|
||||||
// updates. Without this there is essentially no progress to watch.
|
// updates. Without this there is essentially no progress to watch.
|
||||||
const unsubscribe = store.observe($timeout)
|
const unsubscribe = store.observe($timeout)
|
||||||
|
|
||||||
const iconPath = '../../../assets/icon.png'
|
|
||||||
|
|
||||||
userConfirm().then(() => {
|
|
||||||
// Stop scanning drives when flashing
|
// Stop scanning drives when flashing
|
||||||
// otherwise Windows throws EPERM
|
// otherwise Windows throws EPERM
|
||||||
driveScanner.stop()
|
driveScanner.stop()
|
||||||
|
|
||||||
return imageWriter.flash(image.path, drives)
|
const iconPath = '../../../assets/icon.png'
|
||||||
}).then(() => {
|
try {
|
||||||
|
await imageWriter.flash(image.path, drives)
|
||||||
if (!flashState.wasLastFlashCancelled()) {
|
if (!flashState.wasLastFlashCancelled()) {
|
||||||
const flashResults = flashState.getFlashResults()
|
const flashResults = flashState.getFlashResults()
|
||||||
notification.send('Flash complete!', {
|
notification.send('Flash complete!', {
|
||||||
@ -155,7 +150,7 @@ module.exports = function (
|
|||||||
})
|
})
|
||||||
$state.go('success')
|
$state.go('success')
|
||||||
}
|
}
|
||||||
}).catch((error) => {
|
} catch (error) {
|
||||||
// When flashing is cancelled before starting above there is no error
|
// When flashing is cancelled before starting above there is no error
|
||||||
if (!error) {
|
if (!error) {
|
||||||
return
|
return
|
||||||
@ -183,11 +178,11 @@ module.exports = function (
|
|||||||
FlashErrorModalService.show(messages.error.genericFlashError())
|
FlashErrorModalService.show(messages.error.genericFlashError())
|
||||||
exceptionReporter.report(error)
|
exceptionReporter.report(error)
|
||||||
}
|
}
|
||||||
}).finally(() => {
|
} finally {
|
||||||
availableDrives.setDrives([])
|
availableDrives.setDrives([])
|
||||||
driveScanner.start()
|
driveScanner.start()
|
||||||
unsubscribe()
|
unsubscribe()
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user