From 6cf32e445a5dd384e9caa6e71df943c1bc68caad Mon Sep 17 00:00:00 2001 From: Eugene Mirotin Date: Fri, 24 Mar 2017 12:48:14 +0300 Subject: [PATCH 1/4] isolate the sudo-runnable command --- build/actions/device.js | 24 ++++++++-------- build/actions/help.js | 5 ++-- build/actions/index.js | 3 +- build/actions/internal.js | 35 +++++++++++++++++++++++ build/actions/os.js | 35 ++++++----------------- build/actions/util.js | 35 +++++++++++++++++++++++ build/app.js | 2 ++ build/utils/helpers.js | 55 +++++++++++++++++++++++-------------- doc/cli.markdown | 5 +++- lib/actions/device.coffee | 28 ++++++++----------- lib/actions/help.coffee | 4 +-- lib/actions/index.coffee | 1 + lib/actions/internal.coffee | 37 +++++++++++++++++++++++++ lib/actions/os.coffee | 50 ++++++++++++++++----------------- lib/app.coffee | 3 ++ lib/utils/helpers.coffee | 43 +++++++++++++++++++++-------- 16 files changed, 244 insertions(+), 121 deletions(-) create mode 100644 build/actions/internal.js create mode 100644 build/actions/util.js create mode 100644 lib/actions/internal.coffee diff --git a/build/actions/device.js b/build/actions/device.js index e431a4ae..4d8dff29 100644 --- a/build/actions/device.js +++ b/build/actions/device.js @@ -291,23 +291,23 @@ exports.init = { }).then(resin.models.application.get).then(function(application) { var download; download = function() { - return tmp.tmpNameAsync().then(function(temporalPath) { - return capitano.runAsync("os download " + application.device_type + " --output " + temporalPath + " --version default"); - }).disposer(function(temporalPath) { - return rimraf(temporalPath); + return tmp.tmpNameAsync().then(function(tempPath) { + return capitano.runAsync("os download " + application.device_type + " --output '" + tempPath + "' --version default"); + }).disposer(function(tempPath) { + return rimraf(tempPath); }); }; - return Promise.using(download(), function(temporalPath) { + return Promise.using(download(), function(tempPath) { return capitano.runAsync("device register " + application.app_name).then(resin.models.device.get).tap(function(device) { - var configure; - configure = "os configure " + temporalPath + " " + device.uuid; + var configureCommand; + configureCommand = "os configure '" + tempPath + "' " + device.uuid; if (options.advanced) { - configure += ' --advanced'; + configureCommand += ' --advanced'; } - return capitano.runAsync(configure).then(function() { - var message; - message = 'Initializing a device requires administrative permissions\ngiven that we need to access raw devices directly.\n'; - return helpers.sudo(['os', 'initialize', temporalPath, '--type', application.device_type], message); + return capitano.runAsync(configureCommand).then(function() { + var osInitCommand; + osInitCommand = "os initialize '" + tempPath + "' --type " + application.device_type; + return capitano.runAsync(osInitCommand); })["catch"](function(error) { return resin.models.device.remove(device.uuid)["finally"](function() { throw error; diff --git a/build/actions/help.js b/build/actions/help.js index f43f0083..043d138f 100644 --- a/build/actions/help.js +++ b/build/actions/help.js @@ -60,12 +60,13 @@ general = function(params, options, done) { console.log(messages.reachingOut); console.log('\nPrimary commands:\n'); commands = _.reject(capitano.state.commands, function(command) { - return command.isWildcard(); + return command.hidden || command.isWildcard(); }); groupedCommands = _.groupBy(commands, function(command) { if (command.plugin) { return 'plugins'; - } else if (command.primary) { + } + if (command.primary) { return 'primary'; } return 'secondary'; diff --git a/build/actions/index.js b/build/actions/index.js index e9428efe..af97025b 100644 --- a/build/actions/index.js +++ b/build/actions/index.js @@ -31,5 +31,6 @@ module.exports = { settings: require('./settings'), config: require('./config'), sync: require('./sync'), - ssh: require('./ssh') + ssh: require('./ssh'), + internal: require('./internal') }; diff --git a/build/actions/internal.js b/build/actions/internal.js new file mode 100644 index 00000000..3cbafd7c --- /dev/null +++ b/build/actions/internal.js @@ -0,0 +1,35 @@ +// Generated by CoffeeScript 1.12.4 + +/* +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. + */ +exports.osInit = { + signature: 'internal osinit ', + description: 'do actual init of the device with the preconfigured os image', + help: 'Don\'t use this command directly! Use `resin os initialize ` instead.', + hidden: true, + root: true, + action: function(params, options, done) { + var Promise, helpers, init; + Promise = require('bluebird'); + init = require('resin-device-init'); + helpers = require('../utils/helpers'); + return Promise["try"](function() { + var config; + config = JSON.parse(params.config); + return init.initialize(params.image, params.type, config); + }).then(helpers.osProgressHandler).nodeify(done); + } +}; diff --git a/build/actions/os.js b/build/actions/os.js index 2c6319d6..1b3af674 100644 --- a/build/actions/os.js +++ b/build/actions/os.js @@ -15,7 +15,7 @@ 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. */ -var commandOptions, formatVersion, resolveVersion, stepHandler; +var commandOptions, formatVersion, initWarningMessage, resolveVersion; commandOptions = require('./command-options'); @@ -120,25 +120,6 @@ exports.download = { } }; -stepHandler = function(step) { - var _, bar, helpers, rindle, visuals; - _ = require('lodash'); - rindle = require('rindle'); - visuals = require('resin-cli-visuals'); - helpers = require('../utils/helpers'); - step.on('stdout', _.bind(process.stdout.write, process.stdout)); - step.on('stderr', _.bind(process.stderr.write, process.stderr)); - step.on('state', function(state) { - if (state.operation.command === 'burn') { - return; - } - return console.log(helpers.stateToString(state)); - }); - bar = new visuals.Progress('Writing Device OS'); - step.on('burn', _.bind(bar.update, bar)); - return rindle.wait(step); -}; - exports.configure = { signature: 'os configure ', description: 'configure an os image', @@ -176,16 +157,18 @@ exports.configure = { override: override }); }).then(function(answers) { - return init.configure(params.image, params.uuid, answers).then(stepHandler); + return init.configure(params.image, params.uuid, answers).then(helpers.osProgressHandler); }); }).nodeify(done); } }; +initWarningMessage = 'Note: Initializing the device may ask for administrative permissions\nbecause we need to access the raw devices directly.'; + exports.initialize = { signature: 'os initialize ', description: 'initialize an os image', - help: 'Use this command to initialize a previously configured operating system image.\n\nExamples:\n\n $ resin os initialize ../path/rpi.img --type \'raspberry-pi\'', + help: "Use this command to initialize a device with previously configured operating system image.\n\n" + initWarningMessage + "\n\nExamples:\n\n $ resin os initialize ../path/rpi.img --type 'raspberry-pi'", permission: 'user', options: [ commandOptions.yes, { @@ -201,16 +184,14 @@ exports.initialize = { alias: 'd' } ], - root: true, action: function(params, options, done) { - var Promise, form, helpers, init, patterns, umount; + var Promise, form, helpers, patterns, umount; Promise = require('bluebird'); umount = Promise.promisifyAll(require('umount')); form = require('resin-cli-form'); - init = require('resin-device-init'); patterns = require('../utils/patterns'); helpers = require('../utils/helpers'); - console.info('Initializing device'); + console.info("Initializing device\n\n" + initWarningMessage); return helpers.getManifest(params.image, options.type).then(function(manifest) { var ref; return (ref = manifest.initialization) != null ? ref.options : void 0; @@ -228,7 +209,7 @@ exports.initialize = { message = "This will erase " + answers.drive + ". Are you sure?"; return patterns.confirm(options.yes, message)["return"](answers.drive).then(umount.umountAsync); }).tap(function(answers) { - return init.initialize(params.image, options.type, answers).then(stepHandler); + return helpers.sudo(['internal', 'osinit', params.image, options.type, JSON.stringify(answers)]); }).then(function(answers) { if (answers.drive == null) { return; diff --git a/build/actions/util.js b/build/actions/util.js new file mode 100644 index 00000000..7b1984bd --- /dev/null +++ b/build/actions/util.js @@ -0,0 +1,35 @@ +// Generated by CoffeeScript 1.12.4 + +/* +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. + */ +exports.osInit = { + signature: 'util osinit ', + description: 'do actual init of the device with the preconfigured os image', + help: 'Don\'t use this command directly! Use `resin os initialize ` instead.', + hidden: true, + root: true, + action: function(params, options, done) { + var Promise, helpers, init; + Promise = require('bluebird'); + init = require('resin-device-init'); + helpers = require('../utils/helpers'); + return Promise["try"](function() { + var config; + config = JSON.parse(params.config); + return init.initialize(params.image, params.type, config); + }).then(helpers.osProgressHandler).nodeify(done); + } +}; diff --git a/build/app.js b/build/app.js index e03c8a61..0c711194 100644 --- a/build/app.js +++ b/build/app.js @@ -179,6 +179,8 @@ capitano.command(actions.local.scan); capitano.command(actions.local.stop); +capitano.command(actions.internal.osInit); + update.notify(); plugins.register(/^resin-plugin-(.+)$/).then(function() { diff --git a/build/utils/helpers.js b/build/utils/helpers.js index ee1b949b..56a897ec 100644 --- a/build/utils/helpers.js +++ b/build/utils/helpers.js @@ -15,37 +15,27 @@ 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. */ -var Promise, _, capitano, chalk, imagefs, os, president, resin, rindle; +var Promise, capitano, president; Promise = require('bluebird'); capitano = Promise.promisifyAll(require('capitano')); -_ = require('lodash'); - -_.str = require('underscore.string'); - president = Promise.promisifyAll(require('president')); -resin = require('resin-sdk-preconfigured'); - -imagefs = require('resin-image-fs'); - -rindle = require('rindle'); - -os = require('os'); - -chalk = require('chalk'); - exports.getGroupDefaults = function(group) { + var _; + _ = require('lodash'); return _.chain(group).get('options').map(function(question) { return [question.name, question["default"]]; }).object().value(); }; exports.stateToString = function(state) { - var percentage, result; - percentage = _.str.lpad(state.percentage, 3, '0') + '%'; + var _str, chalk, percentage, result; + _str = require('underscore.string'); + chalk = require('chalk'); + percentage = _str.lpad(state.percentage, 3, '0') + '%'; result = (chalk.blue(percentage)) + " " + (chalk.cyan(state.operation.command)); switch (state.operation.command) { case 'copy': @@ -59,16 +49,22 @@ exports.stateToString = function(state) { } }; -exports.sudo = function(command, message) { - command = _.union(_.take(process.argv, 2), command); - console.log(message); +exports.sudo = function(command) { + var _, os; + _ = require('lodash'); + os = require('os'); if (os.platform() !== 'win32') { - console.log('Type your computer password to continue'); + console.log('If asked please type your computer password to continue'); } + command = _.union(_.take(process.argv, 2), command); return president.executeAsync(command); }; exports.getManifest = function(image, deviceType) { + var imagefs, resin, rindle; + rindle = require('rindle'); + imagefs = require('resin-image-fs'); + resin = require('resin-sdk-preconfigured'); return imagefs.read({ image: image, partition: { @@ -79,3 +75,20 @@ exports.getManifest = function(image, deviceType) { return resin.models.device.getManifestBySlug(deviceType); }); }; + +exports.osProgressHandler = function(step) { + var bar, rindle, visuals; + rindle = require('rindle'); + visuals = require('resin-cli-visuals'); + step.on('stdout', process.stdout.write.bind(process.stdout)); + step.on('stderr', process.stderr.write.bind(process.stderr)); + step.on('state', function(state) { + if (state.operation.command === 'burn') { + return; + } + return console.log(exports.stateToString(state)); + }); + bar = new visuals.Progress('Writing Device OS'); + step.on('burn', bar.update.bind(bar)); + return rindle.wait(step); +}; diff --git a/doc/cli.markdown b/doc/cli.markdown index 5a0f1d0d..04bca322 100644 --- a/doc/cli.markdown +++ b/doc/cli.markdown @@ -830,7 +830,10 @@ show advanced commands ## os initialize <image> -Use this command to initialize a previously configured operating system image. +Use this command to initialize a device with previously configured operating system image. + +Note: Initializing the device may ask for administrative permissions +because we need to access the raw devices directly. Examples: diff --git a/lib/actions/device.coffee b/lib/actions/device.coffee index d0290550..07048160 100644 --- a/lib/actions/device.coffee +++ b/lib/actions/device.coffee @@ -392,27 +392,23 @@ exports.init = .then (application) -> download = -> - tmp.tmpNameAsync().then (temporalPath) -> + tmp.tmpNameAsync().then (tempPath) -> # TODO: allow version selection - capitano.runAsync("os download #{application.device_type} --output #{temporalPath} --version default") - .disposer (temporalPath) -> - return rimraf(temporalPath) + capitano.runAsync("os download #{application.device_type} --output '#{tempPath}' --version default") + .disposer (tempPath) -> + return rimraf(tempPath) - Promise.using download(), (temporalPath) -> + Promise.using download(), (tempPath) -> capitano.runAsync("device register #{application.app_name}") .then(resin.models.device.get) .tap (device) -> - configure = "os configure #{temporalPath} #{device.uuid}" - configure += ' --advanced' if options.advanced - capitano.runAsync(configure).then -> - message = ''' - Initializing a device requires administrative permissions - given that we need to access raw devices directly. - - ''' - - helpers.sudo([ 'os', 'initialize', temporalPath, '--type', application.device_type ], message) - + configureCommand = "os configure '#{tempPath}' #{device.uuid}" + if options.advanced + configureCommand += ' --advanced' + capitano.runAsync(configureCommand) + .then -> + osInitCommand = "os initialize '#{tempPath}' --type #{application.device_type}" + capitano.runAsync(osInitCommand) # Make sure the device resource is removed if there is an # error when configuring or initializing a device image .catch (error) -> diff --git a/lib/actions/help.coffee b/lib/actions/help.coffee index 0c3f7430..d5519189 100644 --- a/lib/actions/help.coffee +++ b/lib/actions/help.coffee @@ -54,12 +54,12 @@ general = (params, options, done) -> # We do not want the wildcard command # to be printed in the help screen. commands = _.reject capitano.state.commands, (command) -> - return command.isWildcard() + return command.hidden or command.isWildcard() groupedCommands = _.groupBy commands, (command) -> if command.plugin return 'plugins' - else if command.primary + if command.primary return 'primary' return 'secondary' diff --git a/lib/actions/index.coffee b/lib/actions/index.coffee index 31c391d1..c0822784 100644 --- a/lib/actions/index.coffee +++ b/lib/actions/index.coffee @@ -31,3 +31,4 @@ module.exports = config: require('./config') sync: require('./sync') ssh: require('./ssh') + internal: require('./internal') diff --git a/lib/actions/internal.coffee b/lib/actions/internal.coffee new file mode 100644 index 00000000..ae013075 --- /dev/null +++ b/lib/actions/internal.coffee @@ -0,0 +1,37 @@ +### +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. +### + +# These are internal commands we want to be runnable from the outside +# One use-case for this is spawning the minimal operation with root priviledges + +exports.osInit = + signature: 'internal osinit ' + description: 'do actual init of the device with the preconfigured os image' + help: ''' + Don't use this command directly! Use `resin os initialize ` instead. + ''' + hidden: true + root: true + action: (params, options, done) -> + Promise = require('bluebird') + init = require('resin-device-init') + helpers = require('../utils/helpers') + + return Promise.try -> + config = JSON.parse(params.config) + init.initialize(params.image, params.type, config) + .then(helpers.osProgressHandler) + .nodeify(done) diff --git a/lib/actions/os.coffee b/lib/actions/os.coffee index 5980a7b0..56d90648 100644 --- a/lib/actions/os.coffee +++ b/lib/actions/os.coffee @@ -133,25 +133,6 @@ exports.download = console.info('The image was downloaded successfully') .nodeify(done) -stepHandler = (step) -> - _ = require('lodash') - rindle = require('rindle') - visuals = require('resin-cli-visuals') - helpers = require('../utils/helpers') - - step.on('stdout', _.bind(process.stdout.write, process.stdout)) - step.on('stderr', _.bind(process.stderr.write, process.stderr)) - - step.on 'state', (state) -> - return if state.operation.command is 'burn' - console.log(helpers.stateToString(state)) - - bar = new visuals.Progress('Writing Device OS') - - step.on('burn', _.bind(bar.update, bar)) - - return rindle.wait(step) - exports.configure = signature: 'os configure ' description: 'configure an os image' @@ -192,19 +173,26 @@ exports.configure = return form.run(questions, { override }) .then (answers) -> - init.configure(params.image, params.uuid, answers).then(stepHandler) + init.configure(params.image, params.uuid, answers).then(helpers.osProgressHandler) .nodeify(done) +initWarningMessage = ''' + Note: Initializing the device may ask for administrative permissions + because we need to access the raw devices directly. +''' + exports.initialize = signature: 'os initialize ' description: 'initialize an os image' - help: ''' - Use this command to initialize a previously configured operating system image. + help: """ + Use this command to initialize a device with previously configured operating system image. + + #{initWarningMessage} Examples: $ resin os initialize ../path/rpi.img --type 'raspberry-pi' - ''' + """ permission: 'user' options: [ commandOptions.yes @@ -222,16 +210,18 @@ exports.initialize = alias: 'd' } ] - root: true action: (params, options, done) -> Promise = require('bluebird') umount = Promise.promisifyAll(require('umount')) form = require('resin-cli-form') - init = require('resin-device-init') patterns = require('../utils/patterns') helpers = require('../utils/helpers') - console.info('Initializing device') + console.info(""" + Initializing device + + #{initWarningMessage} + """) helpers.getManifest(params.image, options.type) .then (manifest) -> return manifest.initialization?.options @@ -246,7 +236,13 @@ exports.initialize = .return(answers.drive) .then(umount.umountAsync) .tap (answers) -> - return init.initialize(params.image, options.type, answers).then(stepHandler) + return helpers.sudo([ + 'internal' + 'osinit' + params.image + options.type + JSON.stringify(answers) + ]) .then (answers) -> return if not answers.drive? umount.umountAsync(answers.drive).tap -> diff --git a/lib/app.coffee b/lib/app.coffee index 22a27ea0..64ca7861 100644 --- a/lib/app.coffee +++ b/lib/app.coffee @@ -142,6 +142,9 @@ capitano.command(actions.local.ssh) capitano.command(actions.local.scan) capitano.command(actions.local.stop) +# ---------- Internal utils ---------- +capitano.command(actions.internal.osInit) + update.notify() plugins.register(/^resin-plugin-(.+)$/).then -> diff --git a/lib/utils/helpers.coffee b/lib/utils/helpers.coffee index df7df50d..f138d91b 100644 --- a/lib/utils/helpers.coffee +++ b/lib/utils/helpers.coffee @@ -16,16 +16,11 @@ limitations under the License. Promise = require('bluebird') capitano = Promise.promisifyAll(require('capitano')) -_ = require('lodash') -_.str = require('underscore.string') president = Promise.promisifyAll(require('president')) -resin = require('resin-sdk-preconfigured') -imagefs = require('resin-image-fs') -rindle = require('rindle') -os = require('os') -chalk = require('chalk') exports.getGroupDefaults = (group) -> + _ = require('lodash') + return _.chain(group) .get('options') .map (question) -> @@ -34,7 +29,10 @@ exports.getGroupDefaults = (group) -> .value() exports.stateToString = (state) -> - percentage = _.str.lpad(state.percentage, 3, '0') + '%' + _str = require('underscore.string') + chalk = require('chalk') + + percentage = _str.lpad(state.percentage, 3, '0') + '%' result = "#{chalk.blue(percentage)} #{chalk.cyan(state.operation.command)}" switch state.operation.command @@ -47,16 +45,20 @@ exports.stateToString = (state) -> else throw new Error("Unsupported operation: #{state.operation.type}") -exports.sudo = (command, message) -> - command = _.union(_.take(process.argv, 2), command) - console.log(message) +exports.sudo = (command) -> + _ = require('lodash') + os = require('os') if os.platform() isnt 'win32' - console.log('Type your computer password to continue') + console.log('If asked please type your computer password to continue') + command = _.union(_.take(process.argv, 2), command) return president.executeAsync(command) exports.getManifest = (image, deviceType) -> + rindle = require('rindle') + imagefs = require('resin-image-fs') + resin = require('resin-sdk-preconfigured') # Attempt to read manifest from the first # partition, but fallback to the API if @@ -70,3 +72,20 @@ exports.getManifest = (image, deviceType) -> .then(JSON.parse) .catch -> resin.models.device.getManifestBySlug(deviceType) + +exports.osProgressHandler = (step) -> + rindle = require('rindle') + visuals = require('resin-cli-visuals') + + step.on('stdout', process.stdout.write.bind(process.stdout)) + step.on('stderr', process.stderr.write.bind(process.stderr)) + + step.on 'state', (state) -> + return if state.operation.command is 'burn' + console.log(exports.stateToString(state)) + + bar = new visuals.Progress('Writing Device OS') + + step.on('burn', bar.update.bind(bar)) + + return rindle.wait(step) From 08b3db717ede4507eaa62b383911e15e23388963 Mon Sep 17 00:00:00 2001 From: Eugene Mirotin Date: Mon, 27 Mar 2017 12:14:55 +0300 Subject: [PATCH 2/4] use individual methods promisification instead of promisifyAll --- build/actions/auth.js | 7 ++--- build/actions/config.js | 42 +++++++++++++++--------------- build/actions/device.js | 17 ++++++------ build/actions/keys.js | 6 ++--- build/actions/local/configure.js | 10 ++++--- build/actions/local/flash.js | 18 ++++++------- build/actions/os.js | 8 +++--- build/actions/wizard.js | 12 ++++----- build/app.js | 10 ++++--- build/events.js | 8 +++--- build/utils/helpers.js | 11 +++----- lib/actions/auth.coffee | 4 +-- lib/actions/config.coffee | 32 +++++++++++------------ lib/actions/device.coffee | 15 ++++++----- lib/actions/keys.coffee | 5 ++-- lib/actions/local/configure.coffee | 8 +++--- lib/actions/local/flash.coffee | 16 ++++++------ lib/actions/os.coffee | 6 ++--- lib/actions/wizard.coffee | 10 +++---- lib/app.coffee | 7 ++--- lib/events.coffee | 5 ++-- lib/utils/helpers.coffee | 5 ++-- 22 files changed, 135 insertions(+), 127 deletions(-) diff --git a/build/actions/auth.js b/build/actions/auth.js index c2af94ad..8f7c0355 100644 --- a/build/actions/auth.js +++ b/build/actions/auth.js @@ -49,10 +49,9 @@ exports.login = { ], primary: true, action: function(params, options, done) { - var Promise, _, auth, capitano, form, login, messages, patterns, resin; + var Promise, _, auth, form, login, messages, patterns, resin; _ = require('lodash'); Promise = require('bluebird'); - capitano = Promise.promisifyAll(require('capitano')); resin = require('resin-sdk-preconfigured'); auth = require('resin-cli-auth'); form = require('resin-cli-form'); @@ -77,8 +76,10 @@ exports.login = { return auth.login(); } return patterns.askLoginType().then(function(loginType) { + var capitanoRunAsync; if (loginType === 'register') { - return capitano.runAsync('signup'); + capitanoRunAsync = Promise.promisify(require('capitano').run); + return capitanoRunAsync('signup'); } options[loginType] = true; return login(options); diff --git a/build/actions/config.js b/build/actions/config.js index 442a1947..89777de9 100644 --- a/build/actions/config.js +++ b/build/actions/config.js @@ -40,15 +40,15 @@ exports.read = { permission: 'user', root: true, action: function(params, options, done) { - var Promise, config, prettyjson, umount, visuals; + var Promise, config, prettyjson, umountAsync, visuals; Promise = require('bluebird'); config = require('resin-config-json'); visuals = require('resin-cli-visuals'); - umount = Promise.promisifyAll(require('umount')); + umountAsync = Promise.promisify(require('umount').umount); prettyjson = require('prettyjson'); return Promise["try"](function() { return options.drive || visuals.drive('Select the device drive'); - }).tap(umount.umountAsync).then(function(drive) { + }).tap(umountAsync).then(function(drive) { return config.read(drive, options.type); }).tap(function(configJSON) { return console.info(prettyjson.render(configJSON)); @@ -77,21 +77,21 @@ exports.write = { permission: 'user', root: true, action: function(params, options, done) { - var Promise, _, config, umount, visuals; + var Promise, _, config, umountAsync, visuals; Promise = require('bluebird'); _ = require('lodash'); config = require('resin-config-json'); visuals = require('resin-cli-visuals'); - umount = Promise.promisifyAll(require('umount')); + umountAsync = Promise.promisify(require('umount').umount); return Promise["try"](function() { return options.drive || visuals.drive('Select the device drive'); - }).tap(umount.umountAsync).then(function(drive) { + }).tap(umountAsync).then(function(drive) { return config.read(drive, options.type).then(function(configJSON) { console.info("Setting " + params.key + " to " + params.value); _.set(configJSON, params.key, params.value); return configJSON; }).tap(function() { - return umount.umountAsync(drive); + return umountAsync(drive); }).then(function(configJSON) { return config.write(drive, options.type, configJSON); }); @@ -122,16 +122,16 @@ exports.inject = { permission: 'user', root: true, action: function(params, options, done) { - var Promise, config, fs, umount, visuals; + var Promise, config, readFileAsync, umountAsync, visuals; Promise = require('bluebird'); config = require('resin-config-json'); visuals = require('resin-cli-visuals'); - umount = Promise.promisifyAll(require('umount')); - fs = Promise.promisifyAll(require('fs')); + umountAsync = Promise.promisify(require('umount').umount); + readFileAsync = Promise.promisify(require('fs').readFile); return Promise["try"](function() { return options.drive || visuals.drive('Select the device drive'); - }).tap(umount.umountAsync).then(function(drive) { - return fs.readFileAsync(params.file, 'utf8').then(JSON.parse).then(function(configJSON) { + }).tap(umountAsync).then(function(drive) { + return readFileAsync(params.file, 'utf8').then(JSON.parse).then(function(configJSON) { return config.write(drive, options.type, configJSON); }); }).tap(function() { @@ -166,24 +166,24 @@ exports.reconfigure = { permission: 'user', root: true, action: function(params, options, done) { - var Promise, capitano, config, umount, visuals; + var Promise, capitanoRunAsync, config, umountAsync, visuals; Promise = require('bluebird'); config = require('resin-config-json'); visuals = require('resin-cli-visuals'); - capitano = Promise.promisifyAll(require('capitano')); - umount = Promise.promisifyAll(require('umount')); + capitanoRunAsync = Promise.promisify(require('capitano').run); + umountAsync = Promise.promisify(require('umount').umount); return Promise["try"](function() { return options.drive || visuals.drive('Select the device drive'); - }).tap(umount.umountAsync).then(function(drive) { + }).tap(umountAsync).then(function(drive) { return config.read(drive, options.type).get('uuid').tap(function() { - return umount.umountAsync(drive); + return umountAsync(drive); }).then(function(uuid) { var configureCommand; configureCommand = "os configure " + drive + " " + uuid; if (options.advanced) { configureCommand += ' --advanced'; } - return capitano.runAsync(configureCommand); + return capitanoRunAsync(configureCommand); }); }).then(function() { return console.info('Done'); @@ -205,9 +205,9 @@ exports.generate = { ], permission: 'user', action: function(params, options, done) { - var Promise, _, deviceConfig, form, fs, prettyjson, resin; + var Promise, _, deviceConfig, form, prettyjson, resin, writeFileAsync; Promise = require('bluebird'); - fs = Promise.promisifyAll(require('fs')); + writeFileAsync = Promise.promisify(require('fs').writeFile); resin = require('resin-sdk-preconfigured'); _ = require('lodash'); form = require('resin-cli-form'); @@ -230,7 +230,7 @@ exports.generate = { }); }).then(function(config) { if (options.output != null) { - return fs.writeFileAsync(options.output, JSON.stringify(config)); + return writeFileAsync(options.output, JSON.stringify(config)); } return console.log(prettyjson.render(config)); }).nodeify(done); diff --git a/build/actions/device.js b/build/actions/device.js index 4d8dff29..b9797720 100644 --- a/build/actions/device.js +++ b/build/actions/device.js @@ -274,11 +274,12 @@ exports.init = { ], permission: 'user', action: function(params, options, done) { - var Promise, capitano, helpers, patterns, resin, rimraf, tmp; + var Promise, capitanoRunAsync, helpers, patterns, resin, rimraf, tmp, tmpNameAsync; Promise = require('bluebird'); - capitano = Promise.promisifyAll(require('capitano')); + capitanoRunAsync = Promise.promisify(require('capitano').run); rimraf = Promise.promisify(require('rimraf')); - tmp = Promise.promisifyAll(require('tmp')); + tmp = require('tmp'); + tmpNameAsync = Promise.promisify(tmp.tmpName); tmp.setGracefulCleanup(); resin = require('resin-sdk-preconfigured'); helpers = require('../utils/helpers'); @@ -291,23 +292,23 @@ exports.init = { }).then(resin.models.application.get).then(function(application) { var download; download = function() { - return tmp.tmpNameAsync().then(function(tempPath) { - return capitano.runAsync("os download " + application.device_type + " --output '" + tempPath + "' --version default"); + return tmpNameAsync().then(function(tempPath) { + return capitanoRunAsync("os download " + application.device_type + " --output '" + tempPath + "' --version default"); }).disposer(function(tempPath) { return rimraf(tempPath); }); }; return Promise.using(download(), function(tempPath) { - return capitano.runAsync("device register " + application.app_name).then(resin.models.device.get).tap(function(device) { + return capitanoRunAsync("device register " + application.app_name).then(resin.models.device.get).tap(function(device) { var configureCommand; configureCommand = "os configure '" + tempPath + "' " + device.uuid; if (options.advanced) { configureCommand += ' --advanced'; } - return capitano.runAsync(configureCommand).then(function() { + return capitanoRunAsync(configureCommand).then(function() { var osInitCommand; osInitCommand = "os initialize '" + tempPath + "' --type " + application.device_type; - return capitano.runAsync(osInitCommand); + return capitanoRunAsync(osInitCommand); })["catch"](function(error) { return resin.models.device.remove(device.uuid)["finally"](function() { throw error; diff --git a/build/actions/keys.js b/build/actions/keys.js index de4be222..fd758a93 100644 --- a/build/actions/keys.js +++ b/build/actions/keys.js @@ -72,15 +72,15 @@ exports.add = { help: 'Use this command to associate a new SSH key with your account.\n\nIf `path` is omitted, the command will attempt\nto read the SSH key from stdin.\n\nExamples:\n\n $ resin key add Main ~/.ssh/id_rsa.pub\n $ cat ~/.ssh/id_rsa.pub | resin key add Main', permission: 'user', action: function(params, options, done) { - var Promise, _, capitano, fs, resin; + var Promise, _, capitano, readFileAsync, resin; _ = require('lodash'); Promise = require('bluebird'); - fs = Promise.promisifyAll(require('fs')); + readFileAsync = Promise.promisify(require('fs').readFile); capitano = require('capitano'); resin = require('resin-sdk-preconfigured'); return Promise["try"](function() { if (params.path != null) { - return fs.readFileAsync(params.path, { + return readFileAsync(params.path, { encoding: 'utf8' }); } diff --git a/build/actions/local/configure.js b/build/actions/local/configure.js index 52b86893..dccd6158 100644 --- a/build/actions/local/configure.js +++ b/build/actions/local/configure.js @@ -66,18 +66,20 @@ module.exports = { help: 'Use this command to configure or reconfigure a resinOS drive or image.\n\nExamples:\n\n $ resin local configure /dev/sdc\n $ resin local configure path/to/image.img', root: true, action: function(params, options, done) { - var Promise, _, denymount, inquirer, reconfix, umount; + var Promise, _, denymount, inquirer, isMountedAsync, reconfix, umount, umountAsync; _ = require('lodash'); Promise = require('bluebird'); - umount = Promise.promisifyAll(require('umount')); + umount = require('umount'); + umountAsync = Promise.promisify(umount.umount); + isMountedAsync = Promise.promisify(umount.isMounted); inquirer = require('inquirer'); reconfix = require('reconfix'); denymount = Promise.promisify(require('denymount')); - return umount.isMountedAsync(params.target).then(function(isMounted) { + return isMountedAsync(params.target).then(function(isMounted) { if (!isMounted) { return; } - return umount.umountAsync(params.target); + return umountAsync(params.target); }).then(function() { return denymount(params.target, function(cb) { return reconfix.readConfiguration(CONFIGURATION_SCHEMA, params.target).then(function(data) { diff --git a/build/actions/local/flash.js b/build/actions/local/flash.js index 9e4f8a42..d77ba5f0 100644 --- a/build/actions/local/flash.js +++ b/build/actions/local/flash.js @@ -34,13 +34,13 @@ module.exports = { ], root: true, action: function(params, options, done) { - var Promise, _, chalk, drivelist, form, fs, imageWrite, os, umount, visuals; + var Promise, _, chalk, driveListAsync, form, fs, imageWrite, os, umountAsync, visuals; _ = require('lodash'); os = require('os'); Promise = require('bluebird'); - umount = Promise.promisifyAll(require('umount')); + umountAsync = Promise.promisify(require('umount').umount); fs = Promise.promisifyAll(require('fs')); - drivelist = Promise.promisifyAll(require('drivelist')); + driveListAsync = Promise.promisify(require('drivelist').list); chalk = require('chalk'); visuals = require('resin-cli-visuals'); form = require('resin-cli-form'); @@ -71,7 +71,7 @@ module.exports = { console.log(chalk.red.bold('Aborted image flash')); process.exit(0); } - return drivelist.listAsync().then(function(drives) { + return driveListAsync().then(function(drives) { var selectedDrive; selectedDrive = _.find(drives, { device: answers.drive @@ -87,7 +87,7 @@ module.exports = { write: new visuals.Progress('Flashing'), check: new visuals.Progress('Validating') }; - return umount.umountAsync(selectedDrive.device).then(function() { + return umountAsync(selectedDrive.device).then(function() { return Promise.props({ imageSize: fs.statAsync(params.image).get('size'), imageStream: Promise.resolve(fs.createReadStream(params.image)), @@ -113,12 +113,12 @@ module.exports = { return writer.on('done', resolve); }); }).then(function() { - var removedrive; + var ejectAsync; if ((os.platform() === 'win32') && (selectedDrive.mountpoint != null)) { - removedrive = Promise.promisifyAll(require('removedrive')); - return removedrive.ejectAsync(selectedDrive.mountpoint); + ejectAsync = Promise.promisify(require('removedrive').eject); + return ejectAsync(selectedDrive.mountpoint); } - return umount.umountAsync(selectedDrive.device); + return umountAsync(selectedDrive.device); }); }).asCallback(done); } diff --git a/build/actions/os.js b/build/actions/os.js index 1b3af674..6cc319df 100644 --- a/build/actions/os.js +++ b/build/actions/os.js @@ -185,9 +185,9 @@ exports.initialize = { } ], action: function(params, options, done) { - var Promise, form, helpers, patterns, umount; + var Promise, form, helpers, patterns, umountAsync; Promise = require('bluebird'); - umount = Promise.promisifyAll(require('umount')); + umountAsync = Promise.promisify(require('umount').umount); form = require('resin-cli-form'); patterns = require('../utils/patterns'); helpers = require('../utils/helpers'); @@ -207,14 +207,14 @@ exports.initialize = { return; } message = "This will erase " + answers.drive + ". Are you sure?"; - return patterns.confirm(options.yes, message)["return"](answers.drive).then(umount.umountAsync); + return patterns.confirm(options.yes, message)["return"](answers.drive).then(umountAsync); }).tap(function(answers) { return helpers.sudo(['internal', 'osinit', params.image, options.type, JSON.stringify(answers)]); }).then(function(answers) { if (answers.drive == null) { return; } - return umount.umountAsync(answers.drive).tap(function() { + return umountAsync(answers.drive).tap(function() { return console.info("You can safely remove " + answers.drive + " now"); }); }).nodeify(done); diff --git a/build/actions/wizard.js b/build/actions/wizard.js index 0d313fc5..07f44ee4 100644 --- a/build/actions/wizard.js +++ b/build/actions/wizard.js @@ -21,9 +21,9 @@ exports.wizard = { help: 'Use this command to run a friendly wizard to get started with resin.io.\n\nThe wizard will guide you through:\n\n - Create an application.\n - Initialise an SDCard with the resin.io operating system.\n - Associate an existing project directory with your resin.io application.\n - Push your project to your devices.\n\nExamples:\n\n $ resin quickstart\n $ resin quickstart MyApp', primary: true, action: function(params, options, done) { - var Promise, capitano, patterns, resin; + var Promise, capitanoRunAsync, patterns, resin; Promise = require('bluebird'); - capitano = Promise.promisifyAll(require('capitano')); + capitanoRunAsync = Promise.promisify(require('capitano').run); resin = require('resin-sdk-preconfigured'); patterns = require('../utils/patterns'); return resin.auth.isLoggedIn().then(function(isLoggedIn) { @@ -32,7 +32,7 @@ exports.wizard = { } console.info('Looks like you\'re not logged in yet!'); console.info('Lets go through a quick wizard to get you started.\n'); - return capitano.runAsync('login'); + return capitanoRunAsync('login'); }).then(function() { if (params.name != null) { return; @@ -42,15 +42,15 @@ exports.wizard = { if (hasApplication) { return applicationName; } - return capitano.runAsync("app create " + applicationName); + return capitanoRunAsync("app create " + applicationName); }); }).then(function(applicationName) { return params.name = applicationName; }); }).then(function() { - return capitano.runAsync("device init --application " + params.name); + return capitanoRunAsync("device init --application " + params.name); }).tap(patterns.awaitDevice).then(function(uuid) { - return capitano.runAsync("device " + uuid); + return capitanoRunAsync("device " + uuid); }).then(function() { return resin.models.application.get(params.name); }).then(function(application) { diff --git a/build/app.js b/build/app.js index 0c711194..b14e46a1 100644 --- a/build/app.js +++ b/build/app.js @@ -15,7 +15,7 @@ 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. */ -var Promise, Raven, _, actions, capitano, errors, events, plugins, resin, update; +var Promise, Raven, _, actions, capitano, capitanoExecuteAsync, errors, events, plugins, resin, update; Raven = require('raven'); @@ -30,7 +30,9 @@ _ = require('lodash'); Promise = require('bluebird'); -capitano = Promise.promisifyAll(require('capitano')); +capitano = require('capitano'); + +capitanoExecuteAsync = Promise.promisify(capitano.execute); resin = require('resin-sdk-preconfigured'); @@ -189,10 +191,10 @@ plugins.register(/^resin-plugin-(.+)$/).then(function() { return events.trackCommand(cli).then(function() { var ref, ref1; if ((ref = cli.global) != null ? ref.help : void 0) { - return capitano.executeAsync({ + return capitanoExecuteAsync({ command: "help " + ((ref1 = cli.command) != null ? ref1 : '') }); } - return capitano.executeAsync(cli); + return capitanoExecuteAsync(cli); }); })["catch"](errors.handle); diff --git a/build/events.js b/build/events.js index 8b6117b9..9385b8c2 100644 --- a/build/events.js +++ b/build/events.js @@ -1,5 +1,5 @@ // Generated by CoffeeScript 1.12.4 -var Mixpanel, Promise, _, capitanoState, packageJSON, resin; +var Mixpanel, Promise, _, packageJSON, resin; _ = require('lodash'); @@ -9,8 +9,6 @@ Promise = require('bluebird'); resin = require('resin-sdk-preconfigured'); -capitanoState = Promise.promisifyAll(require('capitano').state); - packageJSON = require('../package.json'); exports.getLoggerInstance = _.memoize(function() { @@ -18,12 +16,14 @@ exports.getLoggerInstance = _.memoize(function() { }); exports.trackCommand = function(capitanoCommand) { + var capitanoStateGetMatchCommandAsync; + capitanoStateGetMatchCommandAsync = Promise.promisify(require('capitano').state.getMatchCommand); return Promise.props({ resinUrl: resin.settings.get('resinUrl'), username: resin.auth.whoami(), mixpanel: exports.getLoggerInstance() }).then(function(data) { - return capitanoState.getMatchCommandAsync(capitanoCommand.command).then(function(command) { + return capitanoStateGetMatchCommandAsync(capitanoCommand.command).then(function(command) { return data.mixpanel.track("[CLI] " + (command.signature.toString()), { distinct_id: data.username, argv: process.argv.join(' '), diff --git a/build/utils/helpers.js b/build/utils/helpers.js index 56a897ec..a8adad61 100644 --- a/build/utils/helpers.js +++ b/build/utils/helpers.js @@ -15,14 +15,10 @@ 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. */ -var Promise, capitano, president; +var Promise; Promise = require('bluebird'); -capitano = Promise.promisifyAll(require('capitano')); - -president = Promise.promisifyAll(require('president')); - exports.getGroupDefaults = function(group) { var _; _ = require('lodash'); @@ -50,14 +46,15 @@ exports.stateToString = function(state) { }; exports.sudo = function(command) { - var _, os; + var _, os, presidentExecuteAsync; _ = require('lodash'); os = require('os'); if (os.platform() !== 'win32') { console.log('If asked please type your computer password to continue'); } command = _.union(_.take(process.argv, 2), command); - return president.executeAsync(command); + presidentExecuteAsync = Promise.promisify(require('president').execute); + return presidentExecuteAsync(command); }; exports.getManifest = function(image, deviceType) { diff --git a/lib/actions/auth.coffee b/lib/actions/auth.coffee index 02317f15..45701a7a 100644 --- a/lib/actions/auth.coffee +++ b/lib/actions/auth.coffee @@ -73,7 +73,6 @@ exports.login = action: (params, options, done) -> _ = require('lodash') Promise = require('bluebird') - capitano = Promise.promisifyAll(require('capitano')) resin = require('resin-sdk-preconfigured') auth = require('resin-cli-auth') form = require('resin-cli-form') @@ -98,7 +97,8 @@ exports.login = return patterns.askLoginType().then (loginType) -> if loginType is 'register' - return capitano.runAsync('signup') + capitanoRunAsync = Promise.promisify(require('capitano').run) + return capitanoRunAsync('signup') options[loginType] = true return login(options) diff --git a/lib/actions/config.coffee b/lib/actions/config.coffee index cbc6a488..4d021751 100644 --- a/lib/actions/config.coffee +++ b/lib/actions/config.coffee @@ -48,12 +48,12 @@ exports.read = Promise = require('bluebird') config = require('resin-config-json') visuals = require('resin-cli-visuals') - umount = Promise.promisifyAll(require('umount')) + umountAsync = Promise.promisify(require('umount').umount) prettyjson = require('prettyjson') Promise.try -> return options.drive or visuals.drive('Select the device drive') - .tap(umount.umountAsync) + .tap(umountAsync) .then (drive) -> return config.read(drive, options.type) .tap (configJSON) -> @@ -94,18 +94,18 @@ exports.write = _ = require('lodash') config = require('resin-config-json') visuals = require('resin-cli-visuals') - umount = Promise.promisifyAll(require('umount')) + umountAsync = Promise.promisify(require('umount').umount) Promise.try -> return options.drive or visuals.drive('Select the device drive') - .tap(umount.umountAsync) + .tap(umountAsync) .then (drive) -> config.read(drive, options.type).then (configJSON) -> console.info("Setting #{params.key} to #{params.value}") _.set(configJSON, params.key, params.value) return configJSON .tap -> - return umount.umountAsync(drive) + return umountAsync(drive) .then (configJSON) -> return config.write(drive, options.type, configJSON) .tap -> @@ -144,14 +144,14 @@ exports.inject = Promise = require('bluebird') config = require('resin-config-json') visuals = require('resin-cli-visuals') - umount = Promise.promisifyAll(require('umount')) - fs = Promise.promisifyAll(require('fs')) + umountAsync = Promise.promisify(require('umount').umount) + readFileAsync = Promise.promisify(require('fs').readFile) Promise.try -> return options.drive or visuals.drive('Select the device drive') - .tap(umount.umountAsync) + .tap(umountAsync) .then (drive) -> - fs.readFileAsync(params.file, 'utf8').then(JSON.parse).then (configJSON) -> + readFileAsync(params.file, 'utf8').then(JSON.parse).then (configJSON) -> return config.write(drive, options.type, configJSON) .tap -> console.info('Done') @@ -196,21 +196,21 @@ exports.reconfigure = Promise = require('bluebird') config = require('resin-config-json') visuals = require('resin-cli-visuals') - capitano = Promise.promisifyAll(require('capitano')) - umount = Promise.promisifyAll(require('umount')) + capitanoRunAsync = Promise.promisify(require('capitano').run) + umountAsync = Promise.promisify(require('umount').umount) Promise.try -> return options.drive or visuals.drive('Select the device drive') - .tap(umount.umountAsync) + .tap(umountAsync) .then (drive) -> config.read(drive, options.type).get('uuid') .tap -> - umount.umountAsync(drive) + umountAsync(drive) .then (uuid) -> configureCommand = "os configure #{drive} #{uuid}" if options.advanced configureCommand += ' --advanced' - return capitano.runAsync(configureCommand) + return capitanoRunAsync(configureCommand) .then -> console.info('Done') .nodeify(done) @@ -241,7 +241,7 @@ exports.generate = permission: 'user' action: (params, options, done) -> Promise = require('bluebird') - fs = Promise.promisifyAll(require('fs')) + writeFileAsync = Promise.promisify(require('fs').writeFile) resin = require('resin-sdk-preconfigured') _ = require('lodash') form = require('resin-cli-form') @@ -271,7 +271,7 @@ exports.generate = return deviceConfig.getByApplication(resource.app_name, answers) .then (config) -> if options.output? - return fs.writeFileAsync(options.output, JSON.stringify(config)) + return writeFileAsync(options.output, JSON.stringify(config)) console.log(prettyjson.render(config)) .nodeify(done) diff --git a/lib/actions/device.coffee b/lib/actions/device.coffee index 07048160..2de9fe2c 100644 --- a/lib/actions/device.coffee +++ b/lib/actions/device.coffee @@ -376,9 +376,10 @@ exports.init = permission: 'user' action: (params, options, done) -> Promise = require('bluebird') - capitano = Promise.promisifyAll(require('capitano')) + capitanoRunAsync = Promise.promisify(require('capitano').run) rimraf = Promise.promisify(require('rimraf')) - tmp = Promise.promisifyAll(require('tmp')) + tmp = require('tmp') + tmpNameAsync = Promise.promisify(tmp.tmpName) tmp.setGracefulCleanup() resin = require('resin-sdk-preconfigured') @@ -392,23 +393,23 @@ exports.init = .then (application) -> download = -> - tmp.tmpNameAsync().then (tempPath) -> + tmpNameAsync().then (tempPath) -> # TODO: allow version selection - capitano.runAsync("os download #{application.device_type} --output '#{tempPath}' --version default") + capitanoRunAsync("os download #{application.device_type} --output '#{tempPath}' --version default") .disposer (tempPath) -> return rimraf(tempPath) Promise.using download(), (tempPath) -> - capitano.runAsync("device register #{application.app_name}") + capitanoRunAsync("device register #{application.app_name}") .then(resin.models.device.get) .tap (device) -> configureCommand = "os configure '#{tempPath}' #{device.uuid}" if options.advanced configureCommand += ' --advanced' - capitano.runAsync(configureCommand) + capitanoRunAsync(configureCommand) .then -> osInitCommand = "os initialize '#{tempPath}' --type #{application.device_type}" - capitano.runAsync(osInitCommand) + capitanoRunAsync(osInitCommand) # Make sure the device resource is removed if there is an # error when configuring or initializing a device image .catch (error) -> diff --git a/lib/actions/keys.coffee b/lib/actions/keys.coffee index ab7e1484..7eae2e09 100644 --- a/lib/actions/keys.coffee +++ b/lib/actions/keys.coffee @@ -107,13 +107,14 @@ exports.add = action: (params, options, done) -> _ = require('lodash') Promise = require('bluebird') - fs = Promise.promisifyAll(require('fs')) + readFileAsync = Promise.promisify(require('fs').readFile) capitano = require('capitano') resin = require('resin-sdk-preconfigured') Promise.try -> - return fs.readFileAsync(params.path, encoding: 'utf8') if params.path? + return readFileAsync(params.path, encoding: 'utf8') if params.path? + # TODO: should this be promisified for consistency? Promise.fromNode (callback) -> capitano.utils.getStdin (data) -> return callback(null, data) diff --git a/lib/actions/local/configure.coffee b/lib/actions/local/configure.coffee index c543f4f6..9a564af3 100644 --- a/lib/actions/local/configure.coffee +++ b/lib/actions/local/configure.coffee @@ -67,14 +67,16 @@ module.exports = action: (params, options, done) -> _ = require('lodash') Promise = require('bluebird') - umount = Promise.promisifyAll(require('umount')) + umount = require('umount') + umountAsync = Promise.promisify(umount.umount) + isMountedAsync = Promise.promisify(umount.isMounted) inquirer = require('inquirer') reconfix = require('reconfix') denymount = Promise.promisify(require('denymount')) - umount.isMountedAsync(params.target).then (isMounted) -> + isMountedAsync(params.target).then (isMounted) -> return if not isMounted - umount.umountAsync(params.target) + umountAsync(params.target) .then -> denymount params.target, (cb) -> reconfix.readConfiguration(CONFIGURATION_SCHEMA, params.target).then (data) -> diff --git a/lib/actions/local/flash.coffee b/lib/actions/local/flash.coffee index 8670ff7a..8814cb30 100644 --- a/lib/actions/local/flash.coffee +++ b/lib/actions/local/flash.coffee @@ -43,15 +43,15 @@ module.exports = _ = require('lodash') os = require('os') Promise = require('bluebird') - umount = Promise.promisifyAll(require('umount')) + umountAsync = Promise.promisify(require('umount').umount) fs = Promise.promisifyAll(require('fs')) - drivelist = Promise.promisifyAll(require('drivelist')) + driveListAsync = Promise.promisify(require('drivelist').list) chalk = require('chalk') visuals = require('resin-cli-visuals') form = require('resin-cli-form') - # XXX: Find a better ES6 module loading story/contract between resin.io modules + # TODO: Find a better ES6 module loading story/contract between resin.io modules require('babel-register')({ only: /etcher-image-write|bmapflash/ presets: ['es2015'] @@ -84,7 +84,7 @@ module.exports = console.log(chalk.red.bold('Aborted image flash')) process.exit(0) - drivelist.listAsync().then (drives) -> + driveListAsync().then (drives) -> selectedDrive = _.find(drives, device: answers.drive) if not selectedDrive? @@ -96,7 +96,7 @@ module.exports = write: new visuals.Progress('Flashing') check: new visuals.Progress('Validating') - umount.umountAsync(selectedDrive.device).then -> + umountAsync(selectedDrive.device).then -> Promise.props imageSize: fs.statAsync(params.image).get('size'), imageStream: Promise.resolve(fs.createReadStream(params.image)) @@ -119,8 +119,8 @@ module.exports = writer.on('done', resolve) .then -> if (os.platform() is 'win32') and selectedDrive.mountpoint? - removedrive = Promise.promisifyAll(require('removedrive')) - return removedrive.ejectAsync(selectedDrive.mountpoint) + ejectAsync = Promise.promisify(require('removedrive').eject) + return ejectAsync(selectedDrive.mountpoint) - return umount.umountAsync(selectedDrive.device) + return umountAsync(selectedDrive.device) .asCallback(done) diff --git a/lib/actions/os.coffee b/lib/actions/os.coffee index 56d90648..ac427326 100644 --- a/lib/actions/os.coffee +++ b/lib/actions/os.coffee @@ -212,7 +212,7 @@ exports.initialize = ] action: (params, options, done) -> Promise = require('bluebird') - umount = Promise.promisifyAll(require('umount')) + umountAsync = Promise.promisify(require('umount').umount) form = require('resin-cli-form') patterns = require('../utils/patterns') helpers = require('../utils/helpers') @@ -234,7 +234,7 @@ exports.initialize = message = "This will erase #{answers.drive}. Are you sure?" patterns.confirm(options.yes, message) .return(answers.drive) - .then(umount.umountAsync) + .then(umountAsync) .tap (answers) -> return helpers.sudo([ 'internal' @@ -245,6 +245,6 @@ exports.initialize = ]) .then (answers) -> return if not answers.drive? - umount.umountAsync(answers.drive).tap -> + umountAsync(answers.drive).tap -> console.info("You can safely remove #{answers.drive} now") .nodeify(done) diff --git a/lib/actions/wizard.coffee b/lib/actions/wizard.coffee index 01870e3c..11182efa 100644 --- a/lib/actions/wizard.coffee +++ b/lib/actions/wizard.coffee @@ -35,7 +35,7 @@ exports.wizard = primary: true action: (params, options, done) -> Promise = require('bluebird') - capitano = Promise.promisifyAll(require('capitano')) + capitanoRunAsync = Promise.promisify(require('capitano').run) resin = require('resin-sdk-preconfigured') patterns = require('../utils/patterns') @@ -43,20 +43,20 @@ exports.wizard = return if isLoggedIn console.info('Looks like you\'re not logged in yet!') console.info('Lets go through a quick wizard to get you started.\n') - return capitano.runAsync('login') + return capitanoRunAsync('login') .then -> return if params.name? patterns.selectOrCreateApplication().tap (applicationName) -> resin.models.application.has(applicationName).then (hasApplication) -> return applicationName if hasApplication - capitano.runAsync("app create #{applicationName}") + capitanoRunAsync("app create #{applicationName}") .then (applicationName) -> params.name = applicationName .then -> - return capitano.runAsync("device init --application #{params.name}") + return capitanoRunAsync("device init --application #{params.name}") .tap(patterns.awaitDevice) .then (uuid) -> - return capitano.runAsync("device #{uuid}") + return capitanoRunAsync("device #{uuid}") .then -> return resin.models.application.get(params.name) .then (application) -> diff --git a/lib/app.coffee b/lib/app.coffee index 64ca7861..90c29a5e 100644 --- a/lib/app.coffee +++ b/lib/app.coffee @@ -24,7 +24,8 @@ Raven.config( _ = require('lodash') Promise = require('bluebird') -capitano = Promise.promisifyAll(require('capitano')) +capitano = require('capitano') +capitanoExecuteAsync = Promise.promisify(capitano.execute) resin = require('resin-sdk-preconfigured') actions = require('./actions') errors = require('./errors') @@ -152,7 +153,7 @@ plugins.register(/^resin-plugin-(.+)$/).then -> events.trackCommand(cli).then -> if cli.global?.help - return capitano.executeAsync(command: "help #{cli.command ? ''}") - capitano.executeAsync(cli) + return capitanoExecuteAsync(command: "help #{cli.command ? ''}") + capitanoExecuteAsync(cli) .catch(errors.handle) diff --git a/lib/events.coffee b/lib/events.coffee index 200fecd3..d4cc64aa 100644 --- a/lib/events.coffee +++ b/lib/events.coffee @@ -2,19 +2,20 @@ _ = require('lodash') Mixpanel = require('mixpanel') Promise = require('bluebird') resin = require('resin-sdk-preconfigured') -capitanoState = Promise.promisifyAll(require('capitano').state) packageJSON = require('../package.json') exports.getLoggerInstance = _.memoize -> return resin.models.config.getMixpanelToken().then(Mixpanel.init) exports.trackCommand = (capitanoCommand) -> + capitanoStateGetMatchCommandAsync = Promise.promisify(require('capitano').state.getMatchCommand) + return Promise.props resinUrl: resin.settings.get('resinUrl') username: resin.auth.whoami() mixpanel: exports.getLoggerInstance() .then (data) -> - return capitanoState.getMatchCommandAsync(capitanoCommand.command).then (command) -> + return capitanoStateGetMatchCommandAsync(capitanoCommand.command).then (command) -> data.mixpanel.track "[CLI] #{command.signature.toString()}", distinct_id: data.username argv: process.argv.join(' ') diff --git a/lib/utils/helpers.coffee b/lib/utils/helpers.coffee index f138d91b..5cfd5390 100644 --- a/lib/utils/helpers.coffee +++ b/lib/utils/helpers.coffee @@ -15,8 +15,6 @@ limitations under the License. ### Promise = require('bluebird') -capitano = Promise.promisifyAll(require('capitano')) -president = Promise.promisifyAll(require('president')) exports.getGroupDefaults = (group) -> _ = require('lodash') @@ -53,7 +51,8 @@ exports.sudo = (command) -> console.log('If asked please type your computer password to continue') command = _.union(_.take(process.argv, 2), command) - return president.executeAsync(command) + presidentExecuteAsync = Promise.promisify(require('president').execute) + return presidentExecuteAsync(command) exports.getManifest = (image, deviceType) -> rindle = require('rindle') From 137473353c990bacbf1bfbadb2641551a7da259c Mon Sep 17 00:00:00 2001 From: Eugene Mirotin Date: Mon, 27 Mar 2017 12:29:40 +0300 Subject: [PATCH 3/4] remove username request from the signup process --- build/actions/auth.js | 6 +----- doc/cli.markdown | 3 +-- lib/actions/auth.coffee | 7 +------ 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/build/actions/auth.js b/build/actions/auth.js index 8f7c0355..1c4e0d5e 100644 --- a/build/actions/auth.js +++ b/build/actions/auth.js @@ -111,7 +111,7 @@ exports.logout = { exports.signup = { signature: 'signup', description: 'signup to resin.io', - help: 'Use this command to signup for a resin.io account.\n\nIf signup is successful, you\'ll be logged in to your new user automatically.\n\nExamples:\n\n $ resin signup\n Email: me@mycompany.com\n Username: johndoe\n Password: ***********\n\n $ resin whoami\n johndoe', + help: 'Use this command to signup for a resin.io account.\n\nIf signup is successful, you\'ll be logged in to your new user automatically.\n\nExamples:\n\n $ resin signup\n Email: johndoe@acme.com\n Password: ***********\n\n $ resin whoami\n johndoe', action: function(params, options, done) { var form, resin, validation; resin = require('resin-sdk-preconfigured'); @@ -125,10 +125,6 @@ exports.signup = { name: 'email', type: 'input', validate: validation.validateEmail - }, { - message: 'Username:', - name: 'username', - type: 'input' }, { message: 'Password:', name: 'password', diff --git a/doc/cli.markdown b/doc/cli.markdown index 04bca322..f8e9995a 100644 --- a/doc/cli.markdown +++ b/doc/cli.markdown @@ -240,8 +240,7 @@ If signup is successful, you'll be logged in to your new user automatically. Examples: $ resin signup - Email: me@mycompany.com - Username: johndoe + Email: johndoe@acme.com Password: *********** $ resin whoami diff --git a/lib/actions/auth.coffee b/lib/actions/auth.coffee index 45701a7a..1de7b9f5 100644 --- a/lib/actions/auth.coffee +++ b/lib/actions/auth.coffee @@ -150,8 +150,7 @@ exports.signup = Examples: $ resin signup - Email: me@mycompany.com - Username: johndoe + Email: johndoe@acme.com Password: *********** $ resin whoami @@ -170,10 +169,6 @@ exports.signup = name: 'email' type: 'input' validate: validation.validateEmail - , - message: 'Username:' - name: 'username' - type: 'input' , message: 'Password:' name: 'password' From 77b30409bb082814d6a0c226b5d18604fc623631 Mon Sep 17 00:00:00 2001 From: Eugene Mirotin Date: Tue, 28 Mar 2017 12:09:58 +0300 Subject: [PATCH 4/4] update resin-device-init to pull in etcher-image-write --- build/utils/helpers.js | 11 ++++++++--- lib/actions/local/flash.coffee | 2 ++ lib/actions/os.coffee | 16 ++++++++++++++++ lib/utils/helpers.coffee | 7 +++++-- package.json | 5 ++++- 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/build/utils/helpers.js b/build/utils/helpers.js index a8adad61..b970e8bd 100644 --- a/build/utils/helpers.js +++ b/build/utils/helpers.js @@ -74,7 +74,7 @@ exports.getManifest = function(image, deviceType) { }; exports.osProgressHandler = function(step) { - var bar, rindle, visuals; + var progressBars, rindle, visuals; rindle = require('rindle'); visuals = require('resin-cli-visuals'); step.on('stdout', process.stdout.write.bind(process.stdout)); @@ -85,7 +85,12 @@ exports.osProgressHandler = function(step) { } return console.log(exports.stateToString(state)); }); - bar = new visuals.Progress('Writing Device OS'); - step.on('burn', bar.update.bind(bar)); + progressBars = { + write: new visuals.Progress('Writing Device OS'), + check: new visuals.Progress('Validating Device OS') + }; + step.on('burn', function(state) { + return progressBars[state.type].update(state); + }); return rindle.wait(step); }; diff --git a/lib/actions/local/flash.coffee b/lib/actions/local/flash.coffee index 8814cb30..5714405a 100644 --- a/lib/actions/local/flash.coffee +++ b/lib/actions/local/flash.coffee @@ -79,6 +79,8 @@ module.exports = # otherwise the question will not be asked because # `false` is a defined value. yes: options.yes || undefined + + # TODO: dedupe with the resin-device-operations .then (answers) -> if answers.yes isnt true console.log(chalk.red.bold('Aborted image flash')) diff --git a/lib/actions/os.coffee b/lib/actions/os.coffee index ac427326..963238b6 100644 --- a/lib/actions/os.coffee +++ b/lib/actions/os.coffee @@ -245,6 +245,22 @@ exports.initialize = ]) .then (answers) -> return if not answers.drive? + + # TODO: resin local makes use of ejectAsync, see below + # DO we need this / should we do that here? + + # getDrive = (drive) -> + # driveListAsync().then (drives) -> + # selectedDrive = _.find(drives, device: drive) + + # if not selectedDrive? + # throw new Error("Drive not found: #{drive}") + + # return selectedDrive + # if (os.platform() is 'win32') and selectedDrive.mountpoint? + # ejectAsync = Promise.promisify(require('removedrive').eject) + # return ejectAsync(selectedDrive.mountpoint) + umountAsync(answers.drive).tap -> console.info("You can safely remove #{answers.drive} now") .nodeify(done) diff --git a/lib/utils/helpers.coffee b/lib/utils/helpers.coffee index 5cfd5390..7ec2c737 100644 --- a/lib/utils/helpers.coffee +++ b/lib/utils/helpers.coffee @@ -83,8 +83,11 @@ exports.osProgressHandler = (step) -> return if state.operation.command is 'burn' console.log(exports.stateToString(state)) - bar = new visuals.Progress('Writing Device OS') + progressBars = + write: new visuals.Progress('Writing Device OS') + check: new visuals.Progress('Validating Device OS') - step.on('burn', bar.update.bind(bar)) + step.on 'burn', (state) -> + progressBars[state.type].update(state) return rindle.wait(step) diff --git a/package.json b/package.json index 73b1cccc..8d8c8b10 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "resin-cli-visuals": "^1.3.0", "resin-config-json": "^1.0.0", "resin-device-config": "^3.0.0", - "resin-device-init": "^2.1.0", + "resin-device-init": "^2.2.0", "resin-image-fs": "^2.1.2", "resin-image-manager": "^4.1.0", "resin-sdk-preconfigured": "^0.1.1", @@ -75,5 +75,8 @@ "unzip2": "^0.2.5", "update-notifier": "^0.6.1", "valid-email": "^0.0.2" + }, + "optionalDependencies": { + "removedrive": "^1.0.0" } }