diff --git a/lib/cli/writer.js b/lib/cli/writer.js index 1539c102..c1f90633 100644 --- a/lib/cli/writer.js +++ b/lib/cli/writer.js @@ -77,7 +77,6 @@ exports.writeImage = (imagePath, drive, options, onProgress) => { }, { check: options.validateWriteOnSuccess, transform: image.transform, - bmap: image.bmap, bytesToZeroOutFromTheBeginning: image.bytesToZeroOutFromTheBeginning }); }).then((writer) => { diff --git a/lib/gui/app.js b/lib/gui/app.js index 5dd097d7..0ad7b2f3 100644 --- a/lib/gui/app.js +++ b/lib/gui/app.js @@ -213,9 +213,7 @@ app.controller('HeaderController', function(SelectionStateModel, OSOpenExternalS * HeaderController.openHelpPage(); */ this.openHelpPage = () => { - const DEFAULT_SUPPORT_URL = 'https://github.com/resin-io/etcher/blob/master/SUPPORT.md'; - const supportUrl = SelectionStateModel.getImageSupportUrl() || DEFAULT_SUPPORT_URL; - OSOpenExternalService.open(supportUrl); + OSOpenExternalService.open('https://github.com/resin-io/etcher/blob/master/SUPPORT.md'); }; }); diff --git a/lib/gui/models/selection-state.js b/lib/gui/models/selection-state.js index 04061eaf..056373cb 100644 --- a/lib/gui/models/selection-state.js +++ b/lib/gui/models/selection-state.js @@ -142,76 +142,6 @@ SelectionStateModel.service('SelectionStateModel', function(DrivesModel) { return _.get(Store.getState().toJS(), 'selection.image.size'); }; - /** - * @summary Get image url - * @function - * @public - * - * @returns {String} image url - * - * @example - * const imageUrl = SelectionStateModel.getImageUrl(); - */ - this.getImageUrl = () => { - return _.get(Store.getState().toJS(), 'selection.image.url'); - }; - - /** - * @summary Get image name - * @function - * @public - * - * @returns {String} image name - * - * @example - * const imageName = SelectionStateModel.getImageName(); - */ - this.getImageName = () => { - return _.get(Store.getState().toJS(), 'selection.image.name'); - }; - - /** - * @summary Get image logo - * @function - * @public - * - * @returns {String} image logo - * - * @example - * const imageLogo = SelectionStateModel.getImageLogo(); - */ - this.getImageLogo = () => { - return _.get(Store.getState().toJS(), 'selection.image.logo'); - }; - - /** - * @summary Get image support url - * @function - * @public - * - * @returns {String} image support url - * - * @example - * const imageSupportUrl = SelectionStateModel.getImageSupportUrl(); - */ - this.getImageSupportUrl = () => { - return _.get(Store.getState().toJS(), 'selection.image.supportUrl'); - }; - - /** - * @summary Get image recommended drive size - * @function - * @public - * - * @returns {String} image recommended drive size - * - * @example - * const imageRecommendedDriveSize = SelectionStateModel.getImageRecommendedDriveSize(); - */ - this.getImageRecommendedDriveSize = () => { - return _.get(Store.getState().toJS(), 'selection.image.recommendedDriveSize'); - }; - /** * @summary Check if there is a selected drive * @function diff --git a/lib/gui/models/store.js b/lib/gui/models/store.js index d62598bc..698acb21 100644 --- a/lib/gui/models/store.js +++ b/lib/gui/models/store.js @@ -249,28 +249,13 @@ const storeReducer = (state, action) => { throw new Error(`Invalid image size: ${action.data.size}`); } - if (action.data.url && !_.isString(action.data.url)) { - throw new Error(`Invalid image url: ${action.data.url}`); - } - - if (action.data.name && !_.isString(action.data.name)) { - throw new Error(`Invalid image name: ${action.data.name}`); - } - - if (action.data.logo && !_.isString(action.data.logo)) { - throw new Error(`Invalid image logo: ${action.data.logo}`); - } - const selectedDevice = state.getIn([ 'selection', 'drive' ]); const selectedDrive = state.get('availableDrives').find((drive) => { return drive.get('device') === selectedDevice; }); return _.attempt(() => { - if (selectedDrive && !_.every([ - constraints.isDriveLargeEnough(selectedDrive.toJS(), action.data), - constraints.isDriveSizeRecommended(selectedDrive.toJS(), action.data) - ])) { + if (selectedDrive && !constraints.isDriveLargeEnough(selectedDrive.toJS(), action.data)) { return storeReducer(state, { type: ACTIONS.REMOVE_DRIVE }); diff --git a/lib/gui/pages/main/controllers/image-selection.js b/lib/gui/pages/main/controllers/image-selection.js index de63e8e3..195876ec 100644 --- a/lib/gui/pages/main/controllers/image-selection.js +++ b/lib/gui/pages/main/controllers/image-selection.js @@ -66,12 +66,6 @@ module.exports = function(SupportedFormatsModel, SelectionStateModel, AnalyticsS } SelectionStateModel.setImage(image); - - // An easy way so we can quickly identify if we're making use of - // certain features without printing pages of text to DevTools. - image.logo = Boolean(image.logo); - image.bmap = Boolean(image.bmap); - AnalyticsService.logEvent('Select image', image); }; diff --git a/lib/gui/pages/main/templates/main.tpl.html b/lib/gui/pages/main/templates/main.tpl.html index 7593698c..60b65708 100644 --- a/lib/gui/pages/main/templates/main.tpl.html +++ b/lib/gui/pages/main/templates/main.tpl.html @@ -43,7 +43,7 @@
- { return accumulator; }, []); -/** - * @summary Extract entry by path - * @function - * @private - * - * @param {String} archive - archive - * @param {String} filePath - entry file path - * @param {Object} options - options - * @param {Object} options.hooks - archive hooks - * @param {Object[]} options.entries - archive entries - * @param {*} [options.default] - entry default value - * @fulfil {*} contents - * @returns {Promise} - * - * extractEntryByPath('my/archive.zip', '_info/logo.svg', { - * hooks: { ... }, - * entries: [ ... ], - * default: '' - * }).then((contents) => { - * console.log(contents); - * }); - */ -const extractEntryByPath = (archive, filePath, options) => { - const fileEntry = _.find(options.entries, (entry) => { - return _.chain(entry.name) - .split('/') - .tail() - .join('/') - .value() === filePath; - }); - - if (!fileEntry) { - return Bluebird.resolve(options.default); - } - - return options.hooks.extractFile(archive, options.entries, fileEntry.name) - .then(rindle.extract); -}; - -/** - * @summary Extract archive metadata - * @function - * @private - * - * @param {String} archive - archive - * @param {String} basePath - metadata base path - * @param {Object} options - options - * @param {Object[]} options.entries - archive entries - * @param {Object} options.hooks - archive hooks - * @fulfil {Object} - metadata - * @returns {Promise} - * - * extractArchiveMetadata('my/archive.zip', '.meta', { - * hooks: { ... }, - * entries: [ ... ] - * }).then((metadata) => { - * console.log(metadata); - * }); - */ -const extractArchiveMetadata = (archive, basePath, options) => { - return Bluebird.props({ - logo: extractEntryByPath(archive, `${basePath}/logo.svg`, options), - instructions: extractEntryByPath(archive, `${basePath}/instructions.markdown`, options), - bmap: extractEntryByPath(archive, `${basePath}/image.bmap`, options), - manifest: _.attempt(() => { - return extractEntryByPath(archive, `${basePath}/manifest.json`, { - hooks: options.hooks, - entries: options.entries, - default: '{}' - }).then((manifest) => { - try { - return JSON.parse(manifest); - } catch (parseError) { - const error = new Error('Invalid archive manifest.json'); - error.description = 'The archive manifest.json file is not valid JSON.'; - throw error; - } - }); - }) - }).then((results) => { - return { - name: results.manifest.name, - version: results.manifest.version, - url: results.manifest.url, - supportUrl: results.manifest.supportUrl, - releaseNotesUrl: results.manifest.releaseNotesUrl, - checksumType: results.manifest.checksumType, - checksum: results.manifest.checksum, - bytesToZeroOutFromTheBeginning: results.manifest.bytesToZeroOutFromTheBeginning, - recommendedDriveSize: results.manifest.recommendedDriveSize, - logo: results.logo, - bmap: results.bmap, - instructions: results.instructions - }; - }); -}; - /** * @summary Extract image from archive * @function @@ -182,25 +75,18 @@ exports.extractImage = (archive, hooks) => { const imageEntry = _.first(imageEntries); - return Bluebird.props({ - imageStream: hooks.extractFile(archive, entries, imageEntry.name), - metadata: extractArchiveMetadata(archive, ARCHIVE_METADATA_BASE_PATH, { - entries, - hooks - }) - }).then((results) => { - results.metadata.stream = results.imageStream; - results.metadata.transform = new PassThroughStream(); - - results.metadata.size = { - original: imageEntry.size, - final: { - estimation: false, - value: imageEntry.size + return hooks.extractFile(archive, entries, imageEntry.name).then((imageStream) => { + return { + stream: imageStream, + transform: new PassThroughStream(), + size: { + original: imageEntry.size, + final: { + estimation: false, + value: imageEntry.size + } } }; - - return results.metadata; }); }); }; diff --git a/lib/image-stream/index.js b/lib/image-stream/index.js index da881cfa..ff04b2c8 100644 --- a/lib/image-stream/index.js +++ b/lib/image-stream/index.js @@ -99,10 +99,7 @@ exports.getFromFilePath = (file) => { * const imageStream = require('./lib/image-stream'); * * imageStream.getImageMetadata('path/to/rpi.img.xz').then((metadata) => { - * console.log(`The image display name is: ${metada.name}`); - * console.log(`The image url is: ${metada.url}`); - * console.log(`The image support url is: ${metada.supportUrl}`); - * console.log(`The image logo is: ${metada.logo}`); + * console.log(`The image original size is: ${metada.size.original}`); * }); */ exports.getImageMetadata = (file) => { diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index ef6ac9e8..9d15fd0a 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -512,16 +512,16 @@ "from": "isarray@0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, - "isstream": { - "version": "0.1.2", - "from": "isstream@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" - }, "isexe": { "version": "1.1.2", "from": "isexe@>=1.1.1 <2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz" }, + "isstream": { + "version": "0.1.2", + "from": "isstream@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" + }, "js-message": { "version": "1.0.5", "from": "js-message@>=1.0.5", @@ -1451,23 +1451,6 @@ "from": "restore-cursor@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz" }, - "rindle": { - "version": "1.3.0", - "from": "rindle@>=1.3.0 <2.0.0", - "resolved": "https://registry.npmjs.org/rindle/-/rindle-1.3.0.tgz", - "dependencies": { - "bluebird": { - "version": "2.11.0", - "from": "bluebird@>=2.10.2 <3.0.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz" - }, - "lodash": { - "version": "3.10.1", - "from": "lodash@>=3.10.1 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz" - } - } - }, "run-async": { "version": "0.1.0", "from": "run-async@>=0.1.0 <0.2.0", @@ -1592,11 +1575,6 @@ "from": "string-template@>=0.2.1 <0.3.0", "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz" }, - "string-to-stream": { - "version": "1.1.0", - "from": "string-to-stream@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/string-to-stream/-/string-to-stream-1.1.0.tgz" - }, "string-width": { "version": "1.0.1", "from": "string-width@>=1.0.1 <2.0.0", diff --git a/package.json b/package.json index 034bd711..dba5e4e8 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,6 @@ "redux-localstorage": "^0.4.1", "resin-cli-form": "^1.4.1", "resin-cli-visuals": "^1.2.8", - "rindle": "^1.3.0", "rx": "^4.1.0", "semver": "^5.1.0", "sudo-prompt": "^6.1.0", @@ -114,6 +113,7 @@ "jsonfile": "^2.3.1", "mochainon": "^1.0.0", "node-sass": "^3.8.0", + "rindle": "^1.3.0", "tmp": "0.0.31", "versionist": "^2.1.0" }, diff --git a/tests/gui/models/selection-state.spec.js b/tests/gui/models/selection-state.spec.js index 4a35113c..a3c10d20 100644 --- a/tests/gui/models/selection-state.spec.js +++ b/tests/gui/models/selection-state.spec.js @@ -47,26 +47,6 @@ describe('Browser: SelectionState', function() { m.chai.expect(SelectionStateModel.getImageSize()).to.be.undefined; }); - it('getImageUrl() should return undefined', function() { - m.chai.expect(SelectionStateModel.getImageUrl()).to.be.undefined; - }); - - it('getImageName() should return undefined', function() { - m.chai.expect(SelectionStateModel.getImageName()).to.be.undefined; - }); - - it('getImageLogo() should return undefined', function() { - m.chai.expect(SelectionStateModel.getImageLogo()).to.be.undefined; - }); - - it('getImageSupportUrl() should return undefined', function() { - m.chai.expect(SelectionStateModel.getImageSupportUrl()).to.be.undefined; - }); - - it('getImageRecommendedDriveSize() should return undefined', function() { - m.chai.expect(SelectionStateModel.getImageRecommendedDriveSize()).to.be.undefined; - }); - it('hasDrive() should return false', function() { const hasDrive = SelectionStateModel.hasDrive(); m.chai.expect(hasDrive).to.be.false; @@ -219,12 +199,7 @@ describe('Browser: SelectionState', function() { beforeEach(function() { this.image = { path: 'foo.img', - size: 999999999, - recommendedDriveSize: 1000000000, - url: 'https://www.raspbian.org', - supportUrl: 'https://www.raspbian.org/forums/', - name: 'Raspbian', - logo: 'Raspbian' + size: 999999999 }; SelectionStateModel.setImage(this.image); @@ -275,51 +250,6 @@ describe('Browser: SelectionState', function() { }); - describe('.getImageUrl()', function() { - - it('should return the image url', function() { - const imageUrl = SelectionStateModel.getImageUrl(); - m.chai.expect(imageUrl).to.equal('https://www.raspbian.org'); - }); - - }); - - describe('.getImageName()', function() { - - it('should return the image name', function() { - const imageName = SelectionStateModel.getImageName(); - m.chai.expect(imageName).to.equal('Raspbian'); - }); - - }); - - describe('.getImageLogo()', function() { - - it('should return the image logo', function() { - const imageLogo = SelectionStateModel.getImageLogo(); - m.chai.expect(imageLogo).to.equal('Raspbian'); - }); - - }); - - describe('.getImageSupportUrl()', function() { - - it('should return the image support url', function() { - const imageSupportUrl = SelectionStateModel.getImageSupportUrl(); - m.chai.expect(imageSupportUrl).to.equal('https://www.raspbian.org/forums/'); - }); - - }); - - describe('.getImageRecommendedDriveSize()', function() { - - it('should return the image recommended drive size', function() { - const imageRecommendedDriveSize = SelectionStateModel.getImageRecommendedDriveSize(); - m.chai.expect(imageRecommendedDriveSize).to.equal(1000000000); - }); - - }); - describe('.hasImage()', function() { it('should return true', function() { @@ -410,36 +340,6 @@ describe('Browser: SelectionState', function() { }).to.throw('Invalid image size: 999999999'); }); - it('should throw if url is defined but its not a string', function() { - m.chai.expect(function() { - SelectionStateModel.setImage({ - path: 'foo.img', - size: 999999999, - url: 1234 - }); - }).to.throw('Invalid image url: 1234'); - }); - - it('should throw if name is defined but its not a string', function() { - m.chai.expect(function() { - SelectionStateModel.setImage({ - path: 'foo.img', - size: 999999999, - name: 1234 - }); - }).to.throw('Invalid image name: 1234'); - }); - - it('should throw if logo is defined but its not a string', function() { - m.chai.expect(function() { - SelectionStateModel.setImage({ - path: 'foo.img', - size: 999999999, - logo: 1234 - }); - }).to.throw('Invalid image logo: 1234'); - }); - it('should de-select a previously selected not-large-enough drive', function() { DrivesModel.setDrives([ { @@ -462,29 +362,6 @@ describe('Browser: SelectionState', function() { SelectionStateModel.removeImage(); }); - it('should de-select a previously selected not-recommended drive', function() { - DrivesModel.setDrives([ - { - device: '/dev/disk1', - name: 'USB Drive', - size: 1200000000, - protected: false - } - ]); - - SelectionStateModel.setDrive('/dev/disk1'); - m.chai.expect(SelectionStateModel.hasDrive()).to.be.true; - - SelectionStateModel.setImage({ - path: 'foo.img', - size: 999999999, - recommendedDriveSize: 1500000000 - }); - - m.chai.expect(SelectionStateModel.hasDrive()).to.be.false; - SelectionStateModel.removeImage(); - }); - }); }); diff --git a/tests/image-stream/data/metadata/zip/rpi-invalid-manifest.zip b/tests/image-stream/data/metadata/zip/rpi-invalid-manifest.zip deleted file mode 100644 index 21a0bbc8..00000000 Binary files a/tests/image-stream/data/metadata/zip/rpi-invalid-manifest.zip and /dev/null differ diff --git a/tests/image-stream/data/metadata/zip/rpi-with-bmap.zip b/tests/image-stream/data/metadata/zip/rpi-with-bmap.zip deleted file mode 100644 index 14cc086b..00000000 Binary files a/tests/image-stream/data/metadata/zip/rpi-with-bmap.zip and /dev/null differ diff --git a/tests/image-stream/data/metadata/zip/rpi-with-instructions.zip b/tests/image-stream/data/metadata/zip/rpi-with-instructions.zip deleted file mode 100644 index 19c75692..00000000 Binary files a/tests/image-stream/data/metadata/zip/rpi-with-instructions.zip and /dev/null differ diff --git a/tests/image-stream/data/metadata/zip/rpi-with-logo.zip b/tests/image-stream/data/metadata/zip/rpi-with-logo.zip deleted file mode 100644 index 5b0158f6..00000000 Binary files a/tests/image-stream/data/metadata/zip/rpi-with-logo.zip and /dev/null differ diff --git a/tests/image-stream/data/metadata/zip/rpi-with-manifest.zip b/tests/image-stream/data/metadata/zip/rpi-with-manifest.zip deleted file mode 100644 index 15289b19..00000000 Binary files a/tests/image-stream/data/metadata/zip/rpi-with-manifest.zip and /dev/null differ diff --git a/tests/image-stream/metadata/zip.spec.js b/tests/image-stream/metadata/zip.spec.js deleted file mode 100644 index 2a07ae0c..00000000 --- a/tests/image-stream/metadata/zip.spec.js +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2016 resin.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -'use strict'; - -const m = require('mochainon'); -const path = require('path'); -const DATA_PATH = path.join(__dirname, '..', 'data'); -const IMAGES_PATH = path.join(DATA_PATH, 'images'); -const ZIP_PATH = path.join(DATA_PATH, 'metadata', 'zip'); -const tester = require('../tester'); -const imageStream = require('../../../lib/image-stream/index'); - -const testMetadataProperty = (archivePath, propertyName, expectedValue) => { - return imageStream.getFromFilePath(archivePath).then((image) => { - m.chai.expect(image[propertyName]).to.deep.equal(expectedValue); - - return imageStream.getImageMetadata(archivePath).then((metadata) => { - m.chai.expect(metadata[propertyName]).to.deep.equal(expectedValue); - }); - }); -}; - -describe('ImageStream: Metadata ZIP', function() { - - this.timeout(10000); - - describe('given an archive with an invalid `manifest.json`', function() { - - tester.expectError( - path.join(ZIP_PATH, 'rpi-invalid-manifest.zip'), - 'Invalid archive manifest.json'); - - describe('.getImageMetadata()', function() { - - it('should be rejected with an error', function(done) { - const image = path.join(ZIP_PATH, 'rpi-invalid-manifest.zip'); - - imageStream.getImageMetadata(image).catch((error) => { - m.chai.expect(error).to.be.an.instanceof(Error); - m.chai.expect(error.message).to.equal('Invalid archive manifest.json'); - done(); - }); - }); - - }); - - }); - - describe('given an archive with a `manifest.json`', function() { - - const archive = path.join(ZIP_PATH, 'rpi-with-manifest.zip'); - - tester.extractFromFilePath( - archive, - path.join(IMAGES_PATH, 'raspberrypi.img')); - - it('should read the manifest name property', function(done) { - testMetadataProperty(archive, 'name', 'Raspberry Pi').asCallback(done); - }); - - it('should read the manifest version property', function(done) { - testMetadataProperty(archive, 'version', '1.0.0').asCallback(done); - }); - - it('should read the manifest url property', function(done) { - testMetadataProperty(archive, 'url', 'https://www.raspberrypi.org').asCallback(done); - }); - - it('should read the manifest supportUrl property', function(done) { - const expectedValue = 'https://www.raspberrypi.org/forums/'; - testMetadataProperty(archive, 'supportUrl', expectedValue).asCallback(done); - }); - - it('should read the manifest releaseNotesUrl property', function(done) { - const expectedValue = 'http://downloads.raspberrypi.org/raspbian/release_notes.txt'; - testMetadataProperty(archive, 'releaseNotesUrl', expectedValue).asCallback(done); - }); - - it('should read the manifest checksumType property', function(done) { - testMetadataProperty(archive, 'checksumType', 'md5').asCallback(done); - }); - - it('should read the manifest checksum property', function(done) { - testMetadataProperty(archive, 'checksum', 'add060b285d512f56c175b76b7ef1bee').asCallback(done); - }); - - it('should read the manifest bytesToZeroOutFromTheBeginning property', function(done) { - testMetadataProperty(archive, 'bytesToZeroOutFromTheBeginning', 512).asCallback(done); - }); - - it('should read the manifest recommendedDriveSize property', function(done) { - testMetadataProperty(archive, 'recommendedDriveSize', 4294967296).asCallback(done); - }); - - }); - - describe('given an archive with a `logo.svg`', function() { - - const archive = path.join(ZIP_PATH, 'rpi-with-logo.zip'); - - const logo = [ - '', - ' Hello World', - '', - '' - ].join('\n'); - - it('should read the logo contents', function(done) { - testMetadataProperty(archive, 'logo', logo).asCallback(done); - }); - - }); - - describe('given an archive with a bmap file', function() { - - const archive = path.join(ZIP_PATH, 'rpi-with-bmap.zip'); - - const bmap = [ - '', - '', - ' 36864 ', - ' 4096 ', - ' 9 ', - ' 4 ', - ' d90f372215cbbef8801caca7b1dd7e587b2142cc ', - ' ', - ' 0-1 ', - ' 7-8 ', - ' ', - '', - '' - ].join('\n'); - - it('should read the bmap contents', function(done) { - testMetadataProperty(archive, 'bmap', bmap).asCallback(done); - }); - - }); - - describe('given an archive with instructions', function() { - - const archive = path.join(ZIP_PATH, 'rpi-with-instructions.zip'); - - const instructions = [ - '# Raspberry Pi Next Steps', - '', - 'Lorem ipsum dolor sit amet.', - '' - ].join('\n'); - - it('should read the instruction contents', function(done) { - testMetadataProperty(archive, 'instructions', instructions).asCallback(done); - }); - - }); - -});