mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-23 19:26:33 +00:00
lint
This commit is contained in:
parent
e68dbcf4ee
commit
caf5f10326
@ -74,8 +74,9 @@ permissions.isElevated().then((elevated) => {
|
||||
}
|
||||
|
||||
const progressBars = new Map()
|
||||
let lastStateType
|
||||
let lastStateType = null
|
||||
|
||||
// eslint-disable-next-line require-jsdoc
|
||||
const onProgress = (state) => {
|
||||
state.message = state.active > 1
|
||||
? `${bytes(state.totalSpeed)}/s total, ${bytes(state.speed)}/s x ${state.active}`
|
||||
@ -83,21 +84,25 @@ permissions.isElevated().then((elevated) => {
|
||||
|
||||
state.message = `${state.type === 'flashing' ? 'Flashing' : 'Validating'}: ${state.message}`
|
||||
|
||||
// eslint-disable-next-line no-undefined
|
||||
if (state.percentage === undefined) {
|
||||
state.message += ` - ${bytes(state.bytes)} written`
|
||||
}
|
||||
|
||||
// Update progress bar
|
||||
let progressBar = progressBars.get(state.type)
|
||||
// eslint-disable-next-line no-undefined
|
||||
if (progressBar === undefined) {
|
||||
// Stop the spinner if there is one
|
||||
if ((lastStateType !== undefined) && (lastStateType !== state.type)) {
|
||||
if ((lastStateType !== null) && (lastStateType !== state.type)) {
|
||||
const spinner = progressBars.get(lastStateType)
|
||||
// eslint-disable-next-line no-undefined
|
||||
if ((spinner !== undefined) && (spinner instanceof visuals.Spinner)) {
|
||||
console.log()
|
||||
spinner.stop()
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line no-undefined
|
||||
if (state.percentage === undefined) {
|
||||
progressBar = new visuals.Spinner(state.message)
|
||||
progressBar.start()
|
||||
@ -106,12 +111,10 @@ permissions.isElevated().then((elevated) => {
|
||||
progressBar.update(state)
|
||||
}
|
||||
progressBars.set(state.type, progressBar)
|
||||
} else if (progressBar instanceof visuals.Spinner) {
|
||||
progressBar.spinner.setSpinnerTitle(state.message)
|
||||
} else {
|
||||
if (progressBar instanceof visuals.Spinner) {
|
||||
progressBar.spinner.setSpinnerTitle(state.message)
|
||||
} else {
|
||||
progressBar.update(state)
|
||||
}
|
||||
progressBar.update(state)
|
||||
}
|
||||
lastStateType = state.type
|
||||
}
|
||||
@ -125,28 +128,28 @@ permissions.isElevated().then((elevated) => {
|
||||
scanner.on('error', reject)
|
||||
scanner.start()
|
||||
})
|
||||
.then(() => {
|
||||
return (new sdk.sourceDestination.File(imagePath, sdk.sourceDestination.File.OpenFlags.Read)).getInnerSource()
|
||||
})
|
||||
.then((innerSource) => {
|
||||
// NOTE: Drive can be (String|Array)
|
||||
const destinations = [].concat(answers.drive).map((device) => {
|
||||
const drive = scanner.getBy('device', device)
|
||||
if (drive === undefined) {
|
||||
throw new Error(`No such drive ${device}`)
|
||||
}
|
||||
return drive
|
||||
.then(() => {
|
||||
return (new sdk.sourceDestination.File(imagePath, sdk.sourceDestination.File.OpenFlags.Read)).getInnerSource()
|
||||
})
|
||||
.then((innerSource) => {
|
||||
// NOTE: Drive can be (String|Array)
|
||||
const destinations = _.map([].concat(answers.drive), (device) => {
|
||||
const drive = scanner.getBy('device', device)
|
||||
if (!drive) {
|
||||
throw new Error(`No such drive ${device}`)
|
||||
}
|
||||
return drive
|
||||
})
|
||||
return sdk.multiWrite.pipeSourceToDestinations(
|
||||
innerSource,
|
||||
destinations,
|
||||
(destination, error) => {
|
||||
console.log(`Error "${error}" on ${destination.drive}`)
|
||||
},
|
||||
onProgress,
|
||||
options.check
|
||||
)
|
||||
})
|
||||
return sdk.multiWrite.pipeSourceToDestinations(
|
||||
innerSource,
|
||||
destinations,
|
||||
(destination, error) => {
|
||||
console.log(`Error "${error}" on ${destination.drive}`)
|
||||
},
|
||||
onProgress,
|
||||
options.check
|
||||
)
|
||||
})
|
||||
}).then(({ failures, bytesWritten }) => {
|
||||
let exitCode = EXIT_CODES.SUCCESS
|
||||
|
||||
|
@ -232,13 +232,13 @@ app.run(() => {
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
app.run(($timeout) => {
|
||||
const BLACKLISTED_DRIVES = settings.has('driveBlacklist')
|
||||
? settings.get('driveBlacklist').split(',')
|
||||
: []
|
||||
|
||||
function driveIsAllowed(drive) {
|
||||
// eslint-disable-next-line require-jsdoc
|
||||
const driveIsAllowed = (drive) => {
|
||||
return !(
|
||||
BLACKLISTED_DRIVES.includes(drive.devicePath) ||
|
||||
BLACKLISTED_DRIVES.includes(drive.device) ||
|
||||
@ -246,7 +246,8 @@ app.run(($timeout) => {
|
||||
)
|
||||
}
|
||||
|
||||
function prepareDrive(drive) {
|
||||
// eslint-disable-next-line require-jsdoc,consistent-return
|
||||
const prepareDrive = (drive) => {
|
||||
if (drive instanceof sdk.sourceDestination.BlockDevice) {
|
||||
return drive.drive
|
||||
} else if (drive instanceof sdk.sourceDestination.UsbbootDrive) {
|
||||
@ -261,9 +262,10 @@ app.run(($timeout) => {
|
||||
}
|
||||
}
|
||||
|
||||
function setDrives(drives) {
|
||||
drives = _.values(drives)
|
||||
availableDrives.setDrives(drives)
|
||||
// eslint-disable-next-line require-jsdoc
|
||||
const setDrives = (drives) => {
|
||||
availableDrives.setDrives(_.values(drives))
|
||||
|
||||
// Safely trigger a digest cycle.
|
||||
// In some cases, AngularJS doesn't acknowledge that the
|
||||
// available drives list has changed, and incorrectly
|
||||
@ -271,32 +273,37 @@ app.run(($timeout) => {
|
||||
$timeout()
|
||||
}
|
||||
|
||||
function getDrives() {
|
||||
// eslint-disable-next-line require-jsdoc
|
||||
const getDrives = () => {
|
||||
return _.keyBy(availableDrives.getDrives() || [], 'device')
|
||||
}
|
||||
|
||||
function addDrive(drive) {
|
||||
drive = prepareDrive(drive)
|
||||
if (!driveIsAllowed(drive)) {
|
||||
// eslint-disable-next-line require-jsdoc
|
||||
const addDrive = (drive) => {
|
||||
const preparedDrive = prepareDrive(drive)
|
||||
if (!driveIsAllowed(preparedDrive)) {
|
||||
return
|
||||
}
|
||||
const drives = getDrives()
|
||||
drives[drive.device] = drive
|
||||
drives[preparedDrive.device] = preparedDrive
|
||||
setDrives(drives)
|
||||
}
|
||||
|
||||
function removeDrive(drive) {
|
||||
drive = prepareDrive(drive)
|
||||
// eslint-disable-next-line require-jsdoc
|
||||
const removeDrive = (drive) => {
|
||||
const preparedDrive = prepareDrive(drive)
|
||||
const drives = getDrives()
|
||||
delete drives[drive.device]
|
||||
// eslint-disable-next-line prefer-reflect
|
||||
delete drives[preparedDrive.device]
|
||||
setDrives(drives)
|
||||
}
|
||||
|
||||
function updateDriveProgress(drive, progress) {
|
||||
// eslint-disable-next-line require-jsdoc
|
||||
const updateDriveProgress = (drive, progress) => {
|
||||
const drives = getDrives()
|
||||
const drive_ = drives[drive.device]
|
||||
if (drive !== undefined) {
|
||||
drive.progress = progress
|
||||
const driveInMap = drives[drive.device]
|
||||
if (driveInMap) {
|
||||
driveInMap.progress = progress
|
||||
setDrives(drives)
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ const constraints = require('../../../shared/drive-constraints')
|
||||
const supportedFormats = require('../../../shared/supported-formats')
|
||||
const errors = require('../../../shared/errors')
|
||||
const fileExtensions = require('../../../shared/file-extensions')
|
||||
const utils = require('../../../shared/utils')
|
||||
const settings = require('./settings')
|
||||
|
||||
/**
|
||||
@ -46,7 +45,7 @@ const verifyNoNilFields = (object, fields, name) => {
|
||||
return _.isNil(_.get(object, field))
|
||||
})
|
||||
if (nilFields.length) {
|
||||
throw new Error(`Missing ${name} fields: ${nilFields.join(', ')} ${JSON.stringify(object, null, 4)}`)
|
||||
throw new Error(`Missing ${name} fields: ${nilFields.join(', ')}`)
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +161,7 @@ const storeReducer = (state = DEFAULT_STATE, action) => {
|
||||
|
||||
const drives = action.data
|
||||
|
||||
//if (!_.isArray(drives) || !_.every(drives, _.isPlainObject)) {
|
||||
// If (!_.isArray(drives) || !_.every(drives, _.isPlainObject)) {
|
||||
if (!_.isArray(drives)) {
|
||||
throw errors.createError({
|
||||
title: `Invalid drives: ${drives}`
|
||||
@ -407,6 +406,7 @@ const storeReducer = (state = DEFAULT_STATE, action) => {
|
||||
|
||||
const MINIMUM_IMAGE_SIZE = 0
|
||||
|
||||
// eslint-disable-next-line no-undefined
|
||||
if ((action.data.size !== undefined) && (action.data.size < MINIMUM_IMAGE_SIZE)) {
|
||||
throw errors.createError({
|
||||
title: `Invalid image size: ${action.data.size}`
|
||||
|
@ -21,7 +21,16 @@ const process = require('process')
|
||||
|
||||
const settings = require('../models/settings')
|
||||
|
||||
function includeSystemDrives() {
|
||||
/**
|
||||
* @summary returns true if system drives should be shown
|
||||
* @function
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*
|
||||
* @example
|
||||
* const shouldInclude = includeSystemDrives()
|
||||
*/
|
||||
const includeSystemDrives = () => {
|
||||
return settings.get('unsafeMode') && !settings.get('disableUnsafeMode')
|
||||
}
|
||||
|
||||
@ -31,6 +40,7 @@ const adapters = [
|
||||
|
||||
// Can't use permissions.isElevated() here as it returns a promise and we need to set
|
||||
// module.exports = scanner right now.
|
||||
// eslint-disable-next-line no-magic-numbers
|
||||
if ((process.platform !== 'linux') || (process.geteuid() === 0)) {
|
||||
adapters.push(new sdk.scanner.adapters.UsbbootDeviceAdapter())
|
||||
}
|
||||
|
@ -59,11 +59,11 @@ exports.fromFlashState = (state) => {
|
||||
|
||||
return 'Finishing...'
|
||||
} else if (isFlashing) {
|
||||
// eslint-disable-next-line no-eq-null
|
||||
if (state.percentage != null) {
|
||||
return `${state.percentage}% Flashing`
|
||||
} else {
|
||||
return `${units.bytesToClosestUnit(state.position)} flashed`
|
||||
}
|
||||
return `${units.bytesToClosestUnit(state.position)} flashed`
|
||||
} else if (isValidating) {
|
||||
return `${state.percentage}% Validating`
|
||||
} else if (!isFlashing && !isValidating) {
|
||||
|
@ -90,7 +90,8 @@ exports.currentWindow = electron.remote.getCurrentWindow()
|
||||
* })
|
||||
*/
|
||||
exports.set = (state) => {
|
||||
if (state.percentage != null) {
|
||||
// eslint-disable-next-line no-eq-null
|
||||
if (state.percentage !== null) {
|
||||
exports.currentWindow.setProgressBar(utils.percentageToFloat(state.percentage))
|
||||
}
|
||||
exports.currentWindow.setTitle(getWindowTitle(state))
|
||||
|
@ -159,35 +159,36 @@ module.exports = function (
|
||||
|
||||
const source = new sdk.sourceDestination.File(imagePath, sdk.sourceDestination.File.OpenFlags.Read)
|
||||
source.getInnerSource()
|
||||
.then((innerSource) => {
|
||||
return innerSource.getMetadata()
|
||||
.then((metadata) => {
|
||||
return innerSource.getPartitionTable()
|
||||
.then((partitionTable) => {
|
||||
if (partitionTable !== undefined) {
|
||||
metadata.hasMBR = true
|
||||
metadata.partitions = partitionTable.partitions
|
||||
}
|
||||
$timeout(() => {
|
||||
metadata.path = imagePath
|
||||
metadata.extension = path.extname(imagePath).slice(1)
|
||||
this.selectImage(metadata)
|
||||
.then((innerSource) => {
|
||||
return innerSource.getMetadata()
|
||||
.then((metadata) => {
|
||||
return innerSource.getPartitionTable()
|
||||
.then((partitionTable) => {
|
||||
if (partitionTable) {
|
||||
metadata.hasMBR = true
|
||||
metadata.partitions = partitionTable.partitions
|
||||
}
|
||||
$timeout(() => {
|
||||
metadata.path = imagePath
|
||||
// eslint-disable-next-line no-magic-numbers
|
||||
metadata.extension = path.extname(imagePath).slice(1)
|
||||
this.selectImage(metadata)
|
||||
})
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
const imageError = errors.createUserError({
|
||||
title: 'Error opening image',
|
||||
description: messages.error.openImage(path.basename(imagePath), error.message)
|
||||
})
|
||||
osDialog.showError(imageError)
|
||||
analytics.logException(error)
|
||||
})
|
||||
.then(() => {
|
||||
return innerSource.close()
|
||||
.catch(_.noop)
|
||||
})
|
||||
})
|
||||
})
|
||||
.catch((error) => {
|
||||
const imageError = errors.createUserError({
|
||||
title: 'Error opening image',
|
||||
description: messages.error.openImage(path.basename(imagePath), error.message)
|
||||
})
|
||||
osDialog.showError(imageError)
|
||||
analytics.logException(error)
|
||||
})
|
||||
.then(() => {
|
||||
return innerSource.close()
|
||||
.catch(() => {})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
'use strict'
|
||||
|
||||
const Bluebird = require('bluebird')
|
||||
const _ = require('lodash')
|
||||
const ipc = require('node-ipc')
|
||||
const sdk = require('etcher-sdk')
|
||||
@ -86,44 +85,67 @@ const handleError = (error) => {
|
||||
terminate(EXIT_CODES.GENERAL_ERROR)
|
||||
}
|
||||
|
||||
function lastMapValue(map) {
|
||||
let value
|
||||
for (value of map.values()){
|
||||
/**
|
||||
* @summary returns the last value in a Map
|
||||
* @param {Map} map - map
|
||||
* @returns {Any} the last value of the map (in insertion order)
|
||||
*
|
||||
* @example
|
||||
* const last = lastMapValue(map)
|
||||
*/
|
||||
const lastMapValue = (map) => {
|
||||
let value = null
|
||||
for (value of map.values()) {
|
||||
// eslint-disable-next-line no-empty
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
function writeAndValidate(source, destinations, verify, onProgress, onFail, onFinish, onError) {
|
||||
/**
|
||||
* @summary writes the source to the destinations and valiates the writes
|
||||
* @param {SourceDestination} source - source
|
||||
* @param {SourceDestination[]} destinations - destinations
|
||||
* @param {Boolean} verify - whether to validate the writes or not
|
||||
* @param {Function} onProgress - function to call on progress
|
||||
* @param {Function} onFail - function to call on fail
|
||||
* @param {Function} onFinish - function to call on finish
|
||||
* @param {Function} onError - function to call on error
|
||||
* @returns {Promise<void>}
|
||||
*
|
||||
* @example
|
||||
* writeAndValidate(source, destinations, verify, onProgress, onFail, onFinish, onError)
|
||||
*/
|
||||
const writeAndValidate = (source, destinations, verify, onProgress, onFail, onFinish, onError) => {
|
||||
return source.getInnerSource()
|
||||
.then((innerSource) => {
|
||||
return sdk.multiWrite.pipeSourceToDestinations(
|
||||
innerSource,
|
||||
destinations,
|
||||
onFail,
|
||||
onProgress,
|
||||
verify,
|
||||
)
|
||||
})
|
||||
.then(({ failures, bytesWritten }) => {
|
||||
.then((innerSource) => {
|
||||
return sdk.multiWrite.pipeSourceToDestinations(
|
||||
innerSource,
|
||||
destinations,
|
||||
onFail,
|
||||
onProgress,
|
||||
verify
|
||||
)
|
||||
})
|
||||
.then(({ failures, bytesWritten }) => {
|
||||
// If all destinations errored, treat the last fail as an error
|
||||
if (failures.size === destinations.length) {
|
||||
throw lastMapValue(failures)
|
||||
}
|
||||
const result = {
|
||||
bytesWritten,
|
||||
devices: {
|
||||
failed: failures.size,
|
||||
successful: destinations.length - failures.size,
|
||||
},
|
||||
errors: []
|
||||
}
|
||||
for (const [ destination, error ] of failures) {
|
||||
error.device = destination.drive.device
|
||||
result.errors.push(error)
|
||||
}
|
||||
onFinish(result)
|
||||
})
|
||||
.catch(onError)
|
||||
if (failures.size === destinations.length) {
|
||||
throw lastMapValue(failures)
|
||||
}
|
||||
const result = {
|
||||
bytesWritten,
|
||||
devices: {
|
||||
failed: failures.size,
|
||||
successful: destinations.length - failures.size
|
||||
},
|
||||
errors: []
|
||||
}
|
||||
for (const [ destination, error ] of failures) {
|
||||
error.device = destination.drive.device
|
||||
result.errors.push(error)
|
||||
}
|
||||
onFinish(result)
|
||||
})
|
||||
.catch(onError)
|
||||
}
|
||||
|
||||
ipc.connectTo(IPC_SERVER_ID, () => {
|
||||
@ -152,8 +174,6 @@ ipc.connectTo(IPC_SERVER_ID, () => {
|
||||
terminate(EXIT_CODES.SUCCESS)
|
||||
})
|
||||
|
||||
let writer = null
|
||||
|
||||
ipc.of[IPC_SERVER_ID].on('write', (options) => {
|
||||
/**
|
||||
* @summary Progress handler
|
||||
@ -209,19 +229,21 @@ ipc.connectTo(IPC_SERVER_ID, () => {
|
||||
|
||||
/**
|
||||
* @summary Failure handler (non-fatal errors)
|
||||
* @param {Object} error - MultiDestinationError
|
||||
* @param {SourceDestination} destination - destination
|
||||
* @param {Error} error - error
|
||||
* @example
|
||||
* writer.on('fail', onFail)
|
||||
*/
|
||||
const onFail = (destination, error) => {
|
||||
ipc.of[IPC_SERVER_ID].emit('fail', {
|
||||
device: destination.drive, // TODO: device should be destination
|
||||
// TODO: device should be destination
|
||||
device: destination.drive,
|
||||
error: errors.toJSON(error)
|
||||
})
|
||||
}
|
||||
|
||||
const destinations = _.map(options.destinations, 'device')
|
||||
const dests = options.destinations.map((destination) => {
|
||||
const dests = _.map(options.destinations, (destination) => {
|
||||
return new sdk.sourceDestination.BlockDevice(destination, options.unmountOnSuccess)
|
||||
})
|
||||
const source = new sdk.sourceDestination.File(options.imagePath, sdk.sourceDestination.File.OpenFlags.Read)
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
const sdk = require('etcher-sdk')
|
||||
const _ = require('lodash')
|
||||
// eslint-disable-next-line node/no-extraneous-require
|
||||
const mime = require('mime')
|
||||
const path = require('path')
|
||||
|
||||
@ -40,7 +41,7 @@ exports.getCompressedExtensions = () => {
|
||||
for (const [ mimetype, cls ] of sdk.sourceDestination.SourceDestination.mimetypes.entries()) {
|
||||
if (cls.prototype instanceof sdk.sourceDestination.CompressedSource) {
|
||||
const mtype = mime.getExtension(mimetype)
|
||||
if (mtype != null) {
|
||||
if (mtype !== null) {
|
||||
result.push(mtype)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user