Merge pull request #1807 from resin-io/patch-1136

feat(gui): Display image size when drive too small

Close #1136
Close #2004
This commit is contained in:
Jonas Hermsmeier 2018-03-21 23:37:22 +01:00 committed by GitHub
commit ad7c8760eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 71 additions and 87 deletions

View File

@ -18,6 +18,8 @@
const _ = require('lodash')
const pathIsInside = require('path-is-inside')
const prettyBytes = require('pretty-bytes')
const messages = require('./messages')
/**
* @summary The default unknown size for things such as images and drives
@ -299,72 +301,6 @@ exports.isDriveSizeLarge = (drive) => {
return _.get(drive, [ 'size' ], UNKNOWN_SIZE) > exports.LARGE_DRIVE_SIZE
}
/**
* @summary Drive/image compatibility status messages.
* @public
* @type {Object}
*
* @description
* Status messages intended to be shown to the user.
*/
exports.COMPATIBILITY_STATUS_MESSAGES = {
/**
* @property {String} SIZE_NOT_RECOMMENDED
* @memberof COMPATIBILITY_STATUS_MESSAGES
*
* @description
* The image and drive compatibility is not recommended; happens when the
* actual drive size is smaller than the image's recommended drive size.
*/
SIZE_NOT_RECOMMENDED: 'Not Recommended',
/**
* @property {String} TOO_SMALL
* @memberof COMPATIBILITY_STATUS_MESSAGES
*
* @description
* The drive is too small for the image.
*/
TOO_SMALL: 'Too Small For Image',
/**
* @property {String} LOCKED
* @memberof COMPATIBILITY_STATUS_MESSAGES
*
* @description
* The drive is locked (e.g. the lock-tab on SD cards) and cannot be written to.
*/
LOCKED: 'Locked',
/**
* @property {String} SYSTEM
* @memberof COMPATIBILITY_STATUS_MESSAGES
*
* @description
* The drive is a system drive and should not be written to.
*/
SYSTEM: 'System Drive',
/**
* @property {String} CONTAINS_IMAGE
* @memberof COMPATIBILITY_STATUS_MESSAGES
*
* @description
* The drive contains the image and therefore cannot be written to.
*/
CONTAINS_IMAGE: 'Drive Contains Image',
/**
* @property {String} LARGE_DRIVE
* @memberof COMPATIBILITY_STATUS_MESSAGES
*
* @description
* The drive is large and therefore likely not a medium you want to write to.
*/
LARGE_DRIVE: 'Large Drive'
}
/**
* @summary Drive/image compatibility status types.
* @public
@ -428,37 +364,39 @@ exports.getDriveImageCompatibilityStatuses = (drive, image) => {
if (exports.isSourceDrive(drive, image)) {
statusList.push({
type: exports.COMPATIBILITY_STATUS_TYPES.ERROR,
message: exports.COMPATIBILITY_STATUS_MESSAGES.CONTAINS_IMAGE
message: messages.compatibility.containsImage()
})
} else if (exports.isDriveLocked(drive)) {
statusList.push({
type: exports.COMPATIBILITY_STATUS_TYPES.ERROR,
message: exports.COMPATIBILITY_STATUS_MESSAGES.LOCKED
message: messages.compatibility.locked()
})
} else if (!_.isNil(drive) && !_.isNil(drive.size) && !exports.isDriveLargeEnough(drive, image)) {
const imageSize = _.get(image, [ 'size', 'final', 'estimation' ]) ? image.size.original : image.size.final.value
const relativeBytes = imageSize - drive.size
statusList.push({
type: exports.COMPATIBILITY_STATUS_TYPES.ERROR,
message: exports.COMPATIBILITY_STATUS_MESSAGES.TOO_SMALL
message: messages.compatibility.tooSmall(prettyBytes(relativeBytes))
})
} else {
if (exports.isSystemDrive(drive)) {
statusList.push({
type: exports.COMPATIBILITY_STATUS_TYPES.WARNING,
message: exports.COMPATIBILITY_STATUS_MESSAGES.SYSTEM
message: messages.compatibility.system()
})
}
if (exports.isDriveSizeLarge(drive)) {
statusList.push({
type: exports.COMPATIBILITY_STATUS_TYPES.WARNING,
message: exports.COMPATIBILITY_STATUS_MESSAGES.LARGE_DRIVE
message: messages.compatibility.largeDrive()
})
}
if (!_.isNil(drive) && !exports.isDriveSizeRecommended(drive, image)) {
statusList.push({
type: exports.COMPATIBILITY_STATUS_TYPES.WARNING,
message: exports.COMPATIBILITY_STATUS_MESSAGES.SIZE_NOT_RECOMMENDED
message: messages.compatibility.sizeNotRecommended()
})
}
}

View File

@ -62,6 +62,41 @@ module.exports = {
`${drive.description} (${drive.displayName})`
].join(' ')
}
},
/**
* @summary Drive compatibility messages
* @namespace compatibility
* @memberof messages
*/
compatibility: {
sizeNotRecommended () {
return 'Not Recommended'
},
tooSmall (additionalSpace) {
return `Insufficient space, additional ${additionalSpace} required`
},
locked () {
return 'Locked'
},
system () {
return 'System Drive'
},
containsImage () {
return 'Drive Contains Image'
},
// The drive is large and therefore likely not a medium you want to write to.
largeDrive () {
return 'Large Drive'
}
},
/**

View File

@ -20,6 +20,7 @@ const m = require('mochainon')
const _ = require('lodash')
const path = require('path')
const constraints = require('../../lib/shared/drive-constraints')
const messages = require('../../lib/shared/messages')
describe('Shared: DriveConstraints', function () {
describe('.isDriveLocked()', function () {
@ -1029,7 +1030,7 @@ describe('Shared: DriveConstraints', function () {
const expectedTuplesSorted = _.sortBy(_.map(expectedTuples, (tuple) => {
return {
type: constraints.COMPATIBILITY_STATUS_TYPES[tuple[0]],
message: constraints.COMPATIBILITY_STATUS_MESSAGES[tuple[1]]
message: messages.compatibility[tuple[1]]()
}
}), [ 'message' ])
const resultTuplesSorted = _.sortBy(resultList, [ 'message' ])
@ -1060,7 +1061,7 @@ describe('Shared: DriveConstraints', function () {
this.image.path = path.join(this.mountpoint, 'rpi.img')
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image)
const expectedTuples = [ [ 'ERROR', 'CONTAINS_IMAGE' ] ]
const expectedTuples = [ [ 'ERROR', 'containsImage' ] ]
expectStatusTypesAndMessagesToBe(result, expectedTuples)
})
@ -1071,7 +1072,7 @@ describe('Shared: DriveConstraints', function () {
this.drive.isSystem = true
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image)
const expectedTuples = [ [ 'WARNING', 'SYSTEM' ] ]
const expectedTuples = [ [ 'WARNING', 'system' ] ]
expectStatusTypesAndMessagesToBe(result, expectedTuples)
})
@ -1082,9 +1083,14 @@ describe('Shared: DriveConstraints', function () {
this.image.size.final.value = this.drive.size + 1
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image)
const expectedTuples = [ [ 'ERROR', 'TOO_SMALL' ] ]
const expected = [
{
message: messages.compatibility.tooSmall('1 B'),
type: constraints.COMPATIBILITY_STATUS_TYPES.ERROR
}
]
expectStatusTypesAndMessagesToBe(result, expectedTuples)
m.chai.expect(result).to.deep.equal(expected)
})
})
@ -1105,7 +1111,7 @@ describe('Shared: DriveConstraints', function () {
this.drive.isReadOnly = true
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image)
const expectedTuples = [ [ 'ERROR', 'LOCKED' ] ]
const expectedTuples = [ [ 'ERROR', 'locked' ] ]
expectStatusTypesAndMessagesToBe(result, expectedTuples)
})
@ -1116,7 +1122,7 @@ describe('Shared: DriveConstraints', function () {
this.image.recommendedDriveSize = this.drive.size + 1
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image)
const expectedTuples = [ [ 'WARNING', 'SIZE_NOT_RECOMMENDED' ] ]
const expectedTuples = [ [ 'WARNING', 'sizeNotRecommended' ] ]
expectStatusTypesAndMessagesToBe(result, expectedTuples)
})
@ -1127,7 +1133,7 @@ describe('Shared: DriveConstraints', function () {
this.drive.size = constraints.LARGE_DRIVE_SIZE + 1
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image)
const expectedTuples = [ [ 'WARNING', 'LARGE_DRIVE' ] ]
const expectedTuples = [ [ 'WARNING', 'largeDrive' ] ]
expectStatusTypesAndMessagesToBe(result, expectedTuples)
})
@ -1154,7 +1160,7 @@ describe('Shared: DriveConstraints', function () {
this.drive.isReadOnly = true
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, null)
const expectedTuples = [ [ 'ERROR', 'LOCKED' ] ]
const expectedTuples = [ [ 'ERROR', 'locked' ] ]
expectStatusTypesAndMessagesToBe(result, expectedTuples)
})
@ -1165,7 +1171,7 @@ describe('Shared: DriveConstraints', function () {
this.drive.isSystem = true
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, null)
const expectedTuples = [ [ 'WARNING', 'SYSTEM' ] ]
const expectedTuples = [ [ 'WARNING', 'system' ] ]
expectStatusTypesAndMessagesToBe(result, expectedTuples)
})
@ -1177,7 +1183,7 @@ describe('Shared: DriveConstraints', function () {
this.image.path = path.join(this.mountpoint, 'rpi.img')
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image)
const expectedTuples = [ [ 'ERROR', 'CONTAINS_IMAGE' ] ]
const expectedTuples = [ [ 'ERROR', 'containsImage' ] ]
expectStatusTypesAndMessagesToBe(result, expectedTuples)
})
@ -1188,7 +1194,7 @@ describe('Shared: DriveConstraints', function () {
this.drive.isReadOnly = true
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image)
const expectedTuples = [ [ 'ERROR', 'LOCKED' ] ]
const expectedTuples = [ [ 'ERROR', 'locked' ] ]
expectStatusTypesAndMessagesToBe(result, expectedTuples)
})
@ -1200,9 +1206,14 @@ describe('Shared: DriveConstraints', function () {
this.drive.isSystem = true
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image)
const expectedTuples = [ [ 'ERROR', 'TOO_SMALL' ] ]
const expected = [
{
message: messages.compatibility.tooSmall('1 B'),
type: constraints.COMPATIBILITY_STATUS_TYPES.ERROR
}
]
expectStatusTypesAndMessagesToBe(result, expectedTuples)
m.chai.expect(result).to.deep.equal(expected)
})
})
@ -1212,7 +1223,7 @@ describe('Shared: DriveConstraints', function () {
this.image.recommendedDriveSize = this.drive.size + 1
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image)
const expectedTuples = [ [ 'WARNING', 'SIZE_NOT_RECOMMENDED' ], [ 'WARNING', 'SYSTEM' ] ]
const expectedTuples = [ [ 'WARNING', 'sizeNotRecommended' ], [ 'WARNING', 'system' ] ]
expectStatusTypesAndMessagesToBe(result, expectedTuples)
})