From da072e7621fd57e09d6a60c429f17a4d24c8cd72 Mon Sep 17 00:00:00 2001 From: Alexis Svinartchouk Date: Thu, 14 Feb 2019 16:40:40 +0100 Subject: [PATCH] Remove etcher-cli Change-type: major --- .resinci.json | 11 -- Makefile | 34 ---- README.md | 3 +- bin/etcher | 2 - docs/ARCHITECTURE.md | 27 ---- docs/CLI-INSTALLATION.md | 61 ------- docs/CLI.md | 42 ----- docs/COMMIT-GUIDELINES.md | 5 - docs/CONTRIBUTING.md | 6 - docs/MAINTAINERS.md | 11 -- docs/USER-DOCUMENTATION.md | 4 - lib/cli/README.md | 21 --- lib/cli/etcher.js | 177 --------------------- lib/cli/options.js | 166 ------------------- lib/cli/utils.js | 47 ------ lib/gui/app/models/local-settings.js | 27 +--- npm-shrinkwrap.json | 229 ++++----------------------- package.json | 10 +- 18 files changed, 40 insertions(+), 843 deletions(-) delete mode 100755 bin/etcher delete mode 100644 docs/CLI-INSTALLATION.md delete mode 100644 docs/CLI.md delete mode 100644 lib/cli/README.md delete mode 100644 lib/cli/etcher.js delete mode 100644 lib/cli/options.js delete mode 100644 lib/cli/utils.js diff --git a/.resinci.json b/.resinci.json index 6f308e7c..539de2bf 100644 --- a/.resinci.json +++ b/.resinci.json @@ -1,15 +1,4 @@ { - "node-cli": { - "node": "6.14.4", - "npm_version": "6.7.0", - "main": "lib/cli/etcher.js", - "dependencies": { - "linux": [ - "libudev-dev", - "libusb-1.0-0-dev" - ] - } - }, "electron": { "npm_version": "6.7.0", "dependencies": { diff --git a/Makefile b/Makefile index efed87ae..dd36fbd7 100644 --- a/Makefile +++ b/Makefile @@ -117,32 +117,6 @@ electron-build: assets/dmg/background.tiff | $(BUILD_TEMPORARY_DIRECTORY) -n $(BUILD_TEMPORARY_DIRECTORY)/npm \ -w $(BUILD_TEMPORARY_DIRECTORY) -# --------------------------------------------------------------------- -# CLI -# --------------------------------------------------------------------- - -cli-develop: | $(BUILD_TEMPORARY_DIRECTORY) - $(RESIN_SCRIPTS)/node-cli/install.sh \ - -b $(shell pwd) \ - -r $(TARGET_ARCH) \ - -s $(PLATFORM) \ - -n $(BUILD_TEMPORARY_DIRECTORY)/npm \ - -a $(S3_BUCKET) - -cli-test: - $(RESIN_SCRIPTS)/node-cli/test.sh \ - -b $(shell pwd) - -cli-build: | $(BUILD_TEMPORARY_DIRECTORY) - $(RESIN_SCRIPTS)/electron/build.sh \ - -b $(shell pwd) \ - -r $(TARGET_ARCH) \ - -s $(PLATFORM) \ - -v production \ - -n $(BUILD_TEMPORARY_DIRECTORY)/npm \ - -w $(BUILD_TEMPORARY_DIRECTORY) \ - -a $(S3_BUCKET) - # --------------------------------------------------------------------- # Phony targets # --------------------------------------------------------------------- @@ -158,16 +132,12 @@ TARGETS = \ lint-spell \ test-spectron \ test-gui \ - test-cli \ test \ sanity-checks \ clean \ distclean \ changelog \ webpack \ - cli-develop \ - cli-test \ - cli-build \ electron-develop \ electron-test \ electron-build @@ -219,10 +189,6 @@ test-sdk: electron-mocha $(MOCHA_OPTIONS) \ tests/shared -test-cli: - mocha $(MOCHA_OPTIONS) \ - tests/shared - test: test-gui test-sdk test-spectron help: diff --git a/README.md b/README.md index d92f929a..96e9469b 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ was written correctly and much more. *** -[**Download**][etcher] | [**Support**][SUPPORT] | [**Documentation**][USER-DOCUMENTATION] | [**Contributing**][CONTRIBUTING] | [**Roadmap**][milestones] | [**CLI**][CLI] +[**Download**][etcher] | [**Support**][SUPPORT] | [**Documentation**][USER-DOCUMENTATION] | [**Contributing**][CONTRIBUTING] | [**Roadmap**][milestones] ![Etcher](https://raw.githubusercontent.com/balena-io/etcher/master/screenshot.png) @@ -154,7 +154,6 @@ the [license]. [electron-supported-platforms]: http://electron.atom.io/docs/tutorial/supported-platforms/ [SUPPORT]: https://github.com/balena-io/etcher/blob/master/SUPPORT.md [CONTRIBUTING]: https://github.com/balena-io/etcher/blob/master/docs/CONTRIBUTING.md -[CLI]: https://github.com/balena-io/etcher/blob/master/docs/CLI.md [USER-DOCUMENTATION]: https://github.com/balena-io/etcher/blob/master/docs/USER-DOCUMENTATION.md [milestones]: https://github.com/balena-io/etcher/milestones [newissue]: https://github.com/balena-io/etcher/issues/new diff --git a/bin/etcher b/bin/etcher deleted file mode 100755 index 3656e96b..00000000 --- a/bin/etcher +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env node -require('../lib/cli/etcher'); diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 80a3a9e0..3783d357 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -52,32 +52,6 @@ a system drive. This is the *"main repository"*, from which you're reading this from, which is basically the front-end and glue for all previously listed projects. -Front-ends ----------- - -The main repository consists of the implementation of the Etcher CLI and the -Etcher GUI (the desktop application), located at [`lib/cli/`][cli-dir] and -[`lib/gui/`][gui-dir], respectively. - -In fact, the only front-end that interacts directly with Etcher's backend is -the CLI. The GUI merely forks the CLI and communicates with its child process -to get state information. - -In this sense, you can consider the GUI as being the front-end to the CLI, -which is in turn the front-end to the actual image writing functionality. - -As a way to simplify how the GUI forks the CLI in a packaged and distributed -context, both the CLI and GUI share the same application entry point. This -means that the same Etcher binary can behave as CLI or GUI as needed. - -## Process communication - -As mentioned before, the Etcher GUI forks the CLI and retrieves information -from it to update its state. In order to accomplish this, the Etcher CLI -contains certain features to ease communication: - -- [Well-documented exit codes.][exit-codes] - Summary ------- @@ -89,7 +63,6 @@ be documented instead! [lego-blocks]: https://github.com/sindresorhus/ama/issues/10#issuecomment-117766328 [exit-codes]: https://github.com/balena-io/etcher/blob/master/lib/shared/exit-codes.js -[cli-dir]: https://github.com/balena-io/etcher/tree/master/lib/cli [gui-dir]: https://github.com/balena-io/etcher/tree/master/lib/gui [electron]: http://electron.atom.io [nodejs]: https://nodejs.org diff --git a/docs/CLI-INSTALLATION.md b/docs/CLI-INSTALLATION.md deleted file mode 100644 index 2d8f7fe8..00000000 --- a/docs/CLI-INSTALLATION.md +++ /dev/null @@ -1,61 +0,0 @@ -### macOS and GNU/Linux - -- Extract the `.tar.gz` package by running: - -```sh -tar fvx path/to/cli.tar.gz -``` - -- Move the resulting directory to `/opt/etcher-cli` - -- Add `/opt/etcher-cli` to the `PATH`. For example, add the following to - `.bashrc` or `.zshrc`: - -```sh -export PATH="$PATH:/opt/etcher-cli" -``` - -### Windows - -- Unzip the `.zip` package by right-clicking on it and selecting "Extract All" - -- Move the resulting directory to `C:\etcher-cli` - -- Add `C:\etcher-cli` to the `%PATH%` - - - On Windows 10 and Windows 8 - - Open *Control Panel* - - Open *System* - - Click the *Advanced system settings* link - - Click *Environment Variables* - - Find the `PATH` environment variable, and click *Edit* - - Append `;C:\etcher-cli` to the environment variable value - - Click *OK* - - - On Windows 7 - - Right-click the *My Computer* icon - - Open the *Properties* menu - - Open the *Advanced* tab - - Click *Environment Variables* - - Find the `PATH` environment variable, and click *Edit* - - Append `;C:\etcher-cli` to the environment variable value - - Click *OK* - - - Re-open `cmd.exe`, or PowerShell - -### Running - -```sh -etcher -v -``` - -### Options - -``` - --help, -h show help - --version, -v show version number - --drive, -d drive - --check, -c validate write - --yes, -y confirm non-interactively - --unmount, -u unmount on success -``` diff --git a/docs/CLI.md b/docs/CLI.md deleted file mode 100644 index 8eb59bdb..00000000 --- a/docs/CLI.md +++ /dev/null @@ -1,42 +0,0 @@ -Etcher CLI -========== - -The Etcher CLI is a command-line tool that aims to provide all the benefits of -the Etcher desktop application in a way that can be run from a terminal, or -even used from a script. - -In fact, the Etcher desktop application is simply a wrapper around the CLI, -which is the place where the actual writing logic takes place. - -Installing ----------- - -Head over to [etcher.io/cli][etcher-cli], download the package that corresponds to -your operating system, and then follow the installation instructions there. - -Running -------- - -```sh -etcher -v -``` - -Options -------- - -``` - --help, -h show help - --version, -v show version number - --drive, -d drive - --check, -c validate write - --yes, -y confirm non-interactively - --unmount, -u unmount on success -``` - -Debug mode ----------- - -You can set the `ETCHER_CLI_DEBUG` environment variable to make the Etcher CLI -print error stack traces. - -[etcher-cli]: https://etcher.io/cli diff --git a/docs/COMMIT-GUIDELINES.md b/docs/COMMIT-GUIDELINES.md index be842a7f..f644452c 100644 --- a/docs/COMMIT-GUIDELINES.md +++ b/docs/COMMIT-GUIDELINES.md @@ -56,11 +56,6 @@ The scope is required for types that make sense, such as `feat`, `fix`, `test`, etc. Certain commit types, such as `chore` might not have a clearly defined scope, in which case its better to omit it. -When it applies, the scope must be either `GUI` or `CLI`. - -A commit that takes part in both the GUI and CLI scopes, and makes more logical -sense that way, might entirely omit the scope. - Subject ------- diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index d5c566d0..eecd3292 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -94,12 +94,6 @@ make webpack npm start ``` -#### CLI - -```sh -node bin/etcher -``` - Testing ------- diff --git a/docs/MAINTAINERS.md b/docs/MAINTAINERS.md index f84c5372..d15ff5f7 100644 --- a/docs/MAINTAINERS.md +++ b/docs/MAINTAINERS.md @@ -105,8 +105,6 @@ export ANALYTICS_MIXPANEL_TOKEN="xxxxxx" ./scripts/build/docker/run-command.sh -r x64 -s . -c "make electron-develop && make RELEASE_TYPE=production electron-installer-redhat" # Build AppImages ./scripts/build/docker/run-command.sh -r x64 -s . -c "make electron-develop && make RELEASE_TYPE=production electron-installer-appimage" -# Build CLI -./scripts/build/docker/run-command.sh -r x64 -s . -c "make electron-develop && make RELEASE_TYPE=production cli-installer-tar-gz" # x86 @@ -116,8 +114,6 @@ export ANALYTICS_MIXPANEL_TOKEN="xxxxxx" ./scripts/build/docker/run-command.sh -r x86 -s . -c "make electron-develop && make RELEASE_TYPE=production electron-installer-redhat" # Build AppImages ./scripts/build/docker/run-command.sh -r x86 -s . -c "make electron-develop && make RELEASE_TYPE=production electron-installer-appimage" -# Build CLI -./scripts/build/docker/run-command.sh -r x86 -s . -c "make electron-develop && make RELEASE_TYPE=production cli-installer-tar-gz" ``` #### Mac OS @@ -125,13 +121,9 @@ export ANALYTICS_MIXPANEL_TOKEN="xxxxxx" **ATTENTION:** For production releases you'll need the code-signing key, and set `CSC_NAME` to generate signed binaries on Mac OS. -**NOTE:** The CLI is not code-signed for either at this time. - ```bash make electron-develop -# Build the CLI -make RELEASE_TYPE=production cli-installer-tar-gz # Build the zip make RELEASE_TYPE=production electron-installer-app-zip # Build the dmg @@ -144,14 +136,11 @@ make RELEASE_TYPE=production electron-installer-dmg and set `CSC_LINK`, and `CSC_KEY_PASSWORD` to generate signed binaries on Windows. **NOTE:** -- The CLI is not code-signed for either at this time. - Keep in mind to also generate artifacts for x86, with `TARGET_ARCH=x86`. ```bash make electron-develop -# Build the CLI -make RELEASE_TYPE=production cli-installer-zip # Build the Portable version make RELEASE_TYPE=production electron-installer-portable # Build the Installer diff --git a/docs/USER-DOCUMENTATION.md b/docs/USER-DOCUMENTATION.md index 80582ed6..fe9b30dd 100644 --- a/docs/USER-DOCUMENTATION.md +++ b/docs/USER-DOCUMENTATION.md @@ -208,9 +208,6 @@ Running in older macOS versions Etcher GUI is based on the [Electron][electron] framework, [which only supports macOS 10.9 and newer versions][electron-supported-platforms]. -You can however, run the [Etcher CLI][etcher-cli], which should work in older -platforms. - [balena.io]: https://balena.io [appimage]: http://appimage.org [xwayland]: https://wayland.freedesktop.org/xserver.html @@ -218,7 +215,6 @@ platforms. [diskpart]: https://technet.microsoft.com/en-us/library/cc770877(v=ws.11).aspx [electron]: http://electron.atom.io [electron-supported-platforms]: https://github.com/electron/electron/blob/master/docs/tutorial/supported-platforms.md -[etcher-cli]: https://github.com/balena-io/etcher/blob/master/docs/CLI.md [publishing]: https://github.com/balena-io/etcher/blob/master/docs/PUBLISHING.md [windows-usb-tool]: https://www.microsoft.com/en-us/download/windows-usb-dvd-download-tool [rufus]: https://rufus.akeo.ie diff --git a/lib/cli/README.md b/lib/cli/README.md deleted file mode 100644 index 15cf14f3..00000000 --- a/lib/cli/README.md +++ /dev/null @@ -1,21 +0,0 @@ -Etcher CLI -========== - -The Etcher CLI is a command line interface to the Etcher writer backend, and -currently the only module in the "Etcher" umbrella that makes use of this -backend directly. - -This module also has the task of unmounting the drives before and after -flashing. - -Notice the Etcher CLI is not worried about elevation, and assumes it has enough -permissions to continue, throwing an error otherwise. - -Exit codes ----------- - -The Etcher CLI uses certain exit codes to signal the result of the operation. -These are documented in [`lib/shared/exit-codes.js`][exit-codes] and are also -printed on the Etcher CLI help page. - -[exit-codes]: https://github.com/balena-io/etcher/blob/master/lib/shared/exit-codes.js diff --git a/lib/cli/etcher.js b/lib/cli/etcher.js deleted file mode 100644 index 60fc5b11..00000000 --- a/lib/cli/etcher.js +++ /dev/null @@ -1,177 +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 _ = require('lodash') -const Bluebird = require('bluebird') -const visuals = require('resin-cli-visuals') -const form = require('resin-cli-form') -const bytes = require('pretty-bytes') -const sdk = require('etcher-sdk') - -const utils = require('./utils') -const options = require('./options') -const messages = require('../shared/messages') -const EXIT_CODES = require('../shared/exit-codes') -const errors = require('../shared/errors') -const permissions = require('../shared/permissions') - -/* eslint-disable no-magic-numbers */ - -const ARGV_IMAGE_PATH_INDEX = 0 -const imagePath = options._[ARGV_IMAGE_PATH_INDEX] - -permissions.isElevated().then((elevated) => { - if (!elevated) { - throw errors.createUserError({ - title: messages.error.elevationRequired(), - description: 'This tool requires special permissions to write to external drives' - }) - } - - return form.run([ - { - message: 'Select drive', - type: 'drive', - name: 'drive' - }, - { - message: 'This will erase the selected drive. Are you sure?', - type: 'confirm', - name: 'yes', - default: false - } - ], { - override: { - drive: options.drive, - - // If `options.yes` is `false`, pass `null`, - // otherwise the question will not be asked because - // `false` is a defined value. - yes: options.yes || null - } - }) -}).then((answers) => { - if (!answers.yes) { - throw errors.createUserError({ - title: 'Aborted', - description: 'We can\'t proceed without confirmation' - }) - } - - const progressBars = new Map() - 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}` - : `${bytes(state.totalSpeed)}/s` - - 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 !== 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() - } else { - progressBar = new visuals.Progress(state.message) - progressBar.update(state) - } - progressBars.set(state.type, progressBar) - } else if (progressBar instanceof visuals.Spinner) { - progressBar.spinner.setSpinnerTitle(state.message) - } else { - progressBar.update(state) - } - lastStateType = state.type - } - - const adapter = new sdk.scanner.adapters.BlockDeviceAdapter(() => { - return options.unmount - }) - const scanner = new sdk.scanner.Scanner([ adapter ]) - return new Promise((resolve, reject) => { - scanner.on('ready', resolve) - 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 = _.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 - ) - }) -}).then(({ failures, bytesWritten }) => { - let exitCode = EXIT_CODES.SUCCESS - - if (failures.size > 0) { - exitCode = EXIT_CODES.GENERAL_ERROR - console.log('') - - for (const [ destination, error ] of failures) { - console.log(` - ${destination.drive}: ${error.message}`) - } - } - - process.exit(exitCode) -}).catch((error) => { - return Bluebird.try(() => { - utils.printError(error) - return Bluebird.resolve() - }).then(() => { - if (error.code === 'EVALIDATION') { - process.exit(EXIT_CODES.VALIDATION_ERROR) - } - - process.exit(EXIT_CODES.GENERAL_ERROR) - }) -}) diff --git a/lib/cli/options.js b/lib/cli/options.js deleted file mode 100644 index a8ffff24..00000000 --- a/lib/cli/options.js +++ /dev/null @@ -1,166 +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 _ = require('lodash') -const fs = require('fs') -const yargs = require('yargs') -const utils = require('./utils') -const EXIT_CODES = require('../shared/exit-codes') -const errors = require('../shared/errors') -const packageJSON = require('../../package.json') - -/** - * @summary The minimum required number of CLI arguments - * @constant - * @private - * @type {Number} - */ -const MINIMUM_NUMBER_OF_ARGUMENTS = 1 - -/** - * @summary The index of the image argument - * @constant - * @private - * @type {Number} - */ -const IMAGE_PATH_ARGV_INDEX = 0 - -/** - * @summary The first index that represents an actual option argument - * @constant - * @private - * @type {Number} - * - * @description - * The first arguments are usually the program executable itself, etc. - */ -const OPTIONS_INDEX_START = 2 - -/** - * @summary Parsed CLI options and arguments - * @type {Object} - * @public - */ -module.exports = yargs - - // Don't wrap at all - .wrap(null) - - .demand(MINIMUM_NUMBER_OF_ARGUMENTS, 'Missing image') - - // Usage help - .usage('Usage: $0 [options] ') - .epilogue([ - 'Exit codes:', - _.map(EXIT_CODES, (value, key) => { - const reason = _.map(_.split(key, '_'), _.capitalize).join(' ') - return ` ${value} - ${reason}` - }).join('\n'), - '', - 'If you need help, don\'t hesitate in contacting us at:', - '', - ' GitHub: https://github.com/balena-io/etcher/issues/new', - ' Forums: https://forums.balena.io/c/etcher' - ].join('\n')) - - // Examples - .example('$0 raspberry-pi.img') - .example('$0 --no-check raspberry-pi.img') - .example('$0 -d /dev/disk2 ubuntu.iso') - .example('$0 -d /dev/disk2 -y rpi.img') - - // Help option - .help() - - // Version option - .version(packageJSON.version) - - // Error reporting - .fail((message, error) => { - const errorObject = error || errors.createUserError({ - title: message - }) - - yargs.showHelp() - utils.printError(errorObject) - process.exit(EXIT_CODES.GENERAL_ERROR) - }) - - // Assert that image exists - .check((argv) => { - const imagePath = argv._[IMAGE_PATH_ARGV_INDEX] - - try { - fs.accessSync(imagePath) - } catch (error) { - throw errors.createUserError({ - title: 'Unable to access file', - description: `The image ${imagePath} is not accessible` - }) - } - - return true - }) - - // Assert that if the `yes` flag is provided, the `drive` flag is also provided. - .check((argv) => { - if (argv.yes && !argv.drive) { - throw errors.createUserError({ - title: 'Missing drive', - description: 'You need to explicitly pass a drive when disabling interactively' - }) - } - - return true - }) - - .options({ - help: { - describe: 'show help', - boolean: true, - alias: 'h' - }, - version: { - describe: 'show version number', - boolean: true, - alias: 'v' - }, - drive: { - describe: 'drive', - string: true, - alias: 'd' - }, - check: { - describe: 'validate write', - boolean: true, - alias: 'c', - default: true - }, - yes: { - describe: 'confirm non-interactively', - boolean: true, - alias: 'y' - }, - unmount: { - describe: 'unmount on success', - boolean: true, - alias: 'u', - default: true - } - }) - .parse(process.argv.slice(OPTIONS_INDEX_START)) diff --git a/lib/cli/utils.js b/lib/cli/utils.js deleted file mode 100644 index f9be3581..00000000 --- a/lib/cli/utils.js +++ /dev/null @@ -1,47 +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 chalk = require('chalk') -const errors = require('../shared/errors') - -/** - * @summary Print an error to stderr - * @function - * @public - * - * @param {Error} error - error - * - * @example - * utils.printError(new Error('Oops!')); - */ -exports.printError = (error) => { - const title = errors.getTitle(error) - const description = errors.getDescription(error, { - userFriendlyDescriptionsOnly: true - }) - - console.error(chalk.red(title)) - - if (description) { - console.error(`\n${chalk.red(description)}`) - } - - if (process.env.ETCHER_CLI_DEBUG && error.stack) { - console.error(`\n${chalk.red(error.stack)}`) - } -} diff --git a/lib/gui/app/models/local-settings.js b/lib/gui/app/models/local-settings.js index 90a488f6..94c0387b 100644 --- a/lib/gui/app/models/local-settings.js +++ b/lib/gui/app/models/local-settings.js @@ -19,7 +19,6 @@ const Bluebird = require('bluebird') const fs = require('fs') const path = require('path') -const os = require('os') /** * @summary Number of spaces to indent JSON output with @@ -40,26 +39,12 @@ const JSON_INDENT = 2 * @type {String} */ const USER_DATA_DIR = (() => { - // Electron - if (process.versions.electron) { - // NOTE: The ternary is due to this module being loaded both, - // Electron's main process and renderer process - const electron = require('electron') - return electron.app - ? electron.app.getPath('userData') - : electron.remote.app.getPath('userData') - } - - // CLI - if (process.platform === 'win32') { - return path.join(process.env.APPDATA, 'etcher') - } - - if (process.platform === 'darwin') { - return path.join(os.homedir(), 'Library', 'Application Support', 'etcher') - } - - return path.join(process.env.XDG_CONFIG_HOME || os.homedir(), '.config', 'etcher') + // NOTE: The ternary is due to this module being loaded both, + // Electron's main process and renderer process + const electron = require('electron') + return electron.app + ? electron.app.getPath('userData') + : electron.remote.app.getPath('userData') })() /** diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 334bfa77..7d0349a6 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1654,7 +1654,8 @@ "ansi-escapes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true }, "ansi-gray": { "version": "0.1.1", @@ -3276,15 +3277,11 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, "requires": { "restore-cursor": "^1.0.1" } }, - "cli-spinner": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/cli-spinner/-/cli-spinner-0.2.7.tgz", - "integrity": "sha1-f3hopvUu1aYh1Rac7UKLYYR6l8c=" - }, "cli-table3": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", @@ -3329,11 +3326,6 @@ } } }, - "cli-width": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", - "integrity": "sha1-pNKT72frt7iNSk1CwMzwDE0eNm0=" - }, "cliui": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", @@ -3373,11 +3365,6 @@ } } }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" - }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -3440,15 +3427,6 @@ "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", "dev": true }, - "columnify": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz", - "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", - "requires": { - "strip-ansi": "^3.0.0", - "wcwidth": "^1.0.0" - } - }, "combined-stream": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", @@ -4282,14 +4260,6 @@ } } }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "requires": { - "clone": "^1.0.2" - } - }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -5946,7 +5916,8 @@ "exit-hook": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true }, "expand-brackets": { "version": "2.1.4", @@ -6318,6 +6289,7 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, "requires": { "escape-string-regexp": "^1.0.5", "object-assign": "^4.1.0" @@ -7614,55 +7586,6 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, - "inquirer": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.11.4.tgz", - "integrity": "sha1-geM3ToNhvq/y2XAWIG01nQsy+k0=", - "requires": { - "ansi-escapes": "^1.1.0", - "ansi-regex": "^2.0.0", - "chalk": "^1.0.0", - "cli-cursor": "^1.0.1", - "cli-width": "^1.0.1", - "figures": "^1.3.5", - "lodash": "^3.3.1", - "readline2": "^1.0.1", - "run-async": "^0.1.0", - "rx-lite": "^3.1.2", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - } - } - }, - "inquirer-dynamic-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/inquirer-dynamic-list/-/inquirer-dynamic-list-1.0.0.tgz", - "integrity": "sha1-x13pQj1yCoTRgQc6QKGO6kftC3g=", - "requires": { - "bluebird": "^2.10.2", - "inquirer": "^0.11.0", - "lodash": "^3.10.1" - }, - "dependencies": { - "bluebird": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", - "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" - }, - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - } - } - }, "interpret": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", @@ -7956,7 +7879,8 @@ "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true }, "is-property": { "version": "1.0.2", @@ -9281,11 +9205,6 @@ "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" }, - "moment-duration-format": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/moment-duration-format/-/moment-duration-format-2.2.2.tgz", - "integrity": "sha1-uVdhLeJgFsmtnrYIfAVFc+USd3k=" - }, "mountutils": { "version": "1.3.16", "resolved": "https://registry.npmjs.org/mountutils/-/mountutils-1.3.16.tgz", @@ -9328,7 +9247,8 @@ "mute-stream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=" + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true }, "nan": { "version": "2.12.1", @@ -9883,7 +9803,8 @@ "onetime": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true }, "optimist": { "version": "0.6.1", @@ -10559,11 +10480,6 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, - "progress-bar-formatter": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/progress-bar-formatter/-/progress-bar-formatter-2.0.1.tgz", - "integrity": "sha1-DZfrsWRn4sIwg3NXIXa3w1UeVW4=" - }, "progress-stream": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", @@ -10948,6 +10864,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -11736,82 +11653,6 @@ "resolve-from": "^1.0.0" } }, - "resin-cli-form": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/resin-cli-form/-/resin-cli-form-1.4.2.tgz", - "integrity": "sha512-ksLMak241nJ+/iXIv0WVZclf1tApo6Hf8KHkMnT34IRF+RolhZbzrkPTUCo51v17wJs85R2NdEX4eTnIakmhUQ==", - "requires": { - "bluebird": "^2.9.30", - "inquirer": "^0.11.0", - "lodash": "^4.17.10", - "resin-cli-visuals": "^1.2.0" - }, - "dependencies": { - "bluebird": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", - "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" - } - } - }, - "resin-cli-visuals": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/resin-cli-visuals/-/resin-cli-visuals-1.4.2.tgz", - "integrity": "sha512-N0TDOFrV8mGWNi2wk3Lk202bw3uw7m7ZLpJ1abyWyMEBYRq7YSehArWaJig19PlemfHNpANueaf1VM8TTxoM5Q==", - "requires": { - "bluebird": "^3.5.1", - "chalk": "^2.3.1", - "cli-spinner": "0.2.7", - "columnify": "^1.5.1", - "drivelist": "^6.0.4", - "inquirer": "^0.11.0", - "inquirer-dynamic-list": "^1.0.0", - "is-promise": "^2.1.0", - "lodash": "^3.10.0", - "moment": "^2.10.3", - "moment-duration-format": "^2.2.2", - "progress-bar-formatter": "^2.0.1", - "underscore.string": "^3.1.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "resin-corvus": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/resin-corvus/-/resin-corvus-2.0.1.tgz", @@ -11915,6 +11756,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, "requires": { "exit-hook": "^1.0.0", "onetime": "^1.0.0" @@ -11959,6 +11801,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, "requires": { "once": "^1.3.0" } @@ -11980,7 +11823,8 @@ "rx-lite": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=" + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true }, "rx-lite-aggregates": { "version": "4.0.8", @@ -12965,11 +12809,6 @@ "extend-shallow": "^3.0.0" } }, - "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" - }, "sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", @@ -13568,7 +13407,8 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true }, "through2": { "version": "0.2.3", @@ -13911,15 +13751,6 @@ "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", "dev": true }, - "underscore.string": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz", - "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==", - "requires": { - "sprintf-js": "^1.0.3", - "util-deprecate": "^1.0.2" - } - }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -14408,14 +14239,6 @@ "neo-async": "^2.5.0" } }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "requires": { - "defaults": "^1.0.3" - } - }, "wdio-dot-reporter": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/wdio-dot-reporter/-/wdio-dot-reporter-0.0.10.tgz", @@ -15205,6 +15028,7 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", + "dev": true, "requires": { "cliui": "^4.0.0", "decamelize": "^1.1.1", @@ -15223,17 +15047,20 @@ "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true }, "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, "requires": { "locate-path": "^2.0.0" } @@ -15241,12 +15068,14 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" @@ -15256,6 +15085,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, "requires": { "ansi-regex": "^3.0.0" } @@ -15264,6 +15094,7 @@ "version": "9.0.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "dev": true, "requires": { "camelcase": "^4.1.0" } diff --git a/package.json b/package.json index 538c0e84..5d4c572f 100644 --- a/package.json +++ b/package.json @@ -28,8 +28,7 @@ "watch": "webpack --watch", "concourse-build-electron": "make webpack", "concourse-test": "npx npm@6.7.0 test", - "concourse-test-electron": "npx npm@6.7.0 test", - "concourse-test-node-cli": "make webpack lint-js lint-cpp lint-spell test-cli" + "concourse-test-electron": "npx npm@6.7.0 test" }, "author": "Balena Inc. ", "license": "Apache-2.0", @@ -44,7 +43,6 @@ "bindings": "^1.3.0", "bluebird": "^3.5.3", "bootstrap-sass": "^3.3.6", - "chalk": "^1.1.3", "color": "^2.0.1", "command-join": "^2.0.0", "d3": "^4.13.0", @@ -68,8 +66,6 @@ "redux": "^3.5.2", "rendition": "4.41.1", "request": "^2.81.0", - "resin-cli-form": "^1.4.1", - "resin-cli-visuals": "^1.4.1", "resin-corvus": "^2.0.1", "roboto-fontface": "^0.9.0", "semver": "^5.1.1", @@ -77,8 +73,7 @@ "styled-system": "^3.1.11", "sudo-prompt": "^8.2.3", "uuid": "^3.0.1", - "xml2js": "^0.4.17", - "yargs": "^11.0.0" + "xml2js": "^0.4.17" }, "devDependencies": { "@babel/core": "^7.2.0", @@ -88,6 +83,7 @@ "acorn": "^6.0.5", "angular-mocks": "1.7.6", "babel-loader": "^8.0.4", + "chalk": "^1.1.3", "electron": "3.1.3", "electron-builder": "^20.38.5", "electron-mocha": "^6.0.4",