From 621b0503ab698a163d9565f9e6f85e848a63b416 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Wed, 11 Feb 2015 15:09:17 -0800 Subject: [PATCH 1/5] Adding Setup tests and settings fix --- .gitignore | 5 +- __tests__/SetupStore-test.js | 119 +++++++++++++++++++++++ __tests__/Virtualbox-test.js | 8 +- browser/main.js | 9 +- deps | 14 ++- package.json | 19 ++-- src/Main.js | 7 +- src/NewContainer.react.js | 2 +- src/Radial.react.js | 4 +- src/Setup.react.js | 177 +++++++++++------------------------ src/SetupStore.js | 157 ++++++++++++++++++------------- src/SetupUtil.js | 20 +++- src/Util.js | 5 + styles/radial.less | 34 ++++++- styles/setup.less | 1 + 15 files changed, 370 insertions(+), 211 deletions(-) create mode 100644 __tests__/SetupStore-test.js diff --git a/.gitignore b/.gitignore index cd839233db..4316ad2eb7 100644 --- a/.gitignore +++ b/.gitignore @@ -8,13 +8,12 @@ npm-debug.log identity # Resources -resources/boot2docker* +resources/boot2docker-* +resources/docker-* # Cache cache -resources/settings* - # Tests .test settings.json diff --git a/__tests__/SetupStore-test.js b/__tests__/SetupStore-test.js new file mode 100644 index 0000000000..bc44bb4bae --- /dev/null +++ b/__tests__/SetupStore-test.js @@ -0,0 +1,119 @@ +jest.dontMock('../src/SetupStore'); +var setupStore = require('../src/SetupStore'); +var virtualBox = require('../src/VirtualBox'); +var util = require('../src/Util'); +var boot2docker = require('../src/Boot2Docker'); +var setupUtil = require('../src/SetupUtil'); +var Promise = require('bluebird'); + +describe('SetupStore', function () { + describe('download step', function () { + util.packagejson.mockReturnValue({}); + pit('downloads virtualbox if it is not installed', function () { + virtualBox.installed.mockReturnValue(false); + setupUtil.download.mockReturnValue(Promise.resolve()); + return setupStore.steps().downloadVirtualBox.run().then(() => { + // TODO: make sure download was called with the right args + expect(setupUtil.download).toBeCalled(); + }); + }); + + pit('downloads virtualbox if it is installed but has an outdated version', function () { + virtualBox.installed.mockReturnValue(true); + virtualBox.version.mockReturnValue(Promise.resolve('4.3.16')); + setupUtil.compareVersions.mockReturnValue(-1); + setupUtil.download.mockReturnValue(Promise.resolve()); + return setupStore.steps().downloadVirtualBox.run().then(() => { + expect(setupUtil.download).toBeCalled(); + }); + }); + + pit('skips download if virtualbox is already installed', function () { + virtualBox.installed.mockReturnValue(true); + virtualBox.version.mockReturnValue(Promise.resolve('4.3.20')); + setupUtil.download.mockClear(); + setupUtil.download.mockReturnValue(Promise.resolve()); + setupUtil.compareVersions.mockReturnValue(1); + return setupStore.steps().downloadVirtualBox.run().then(() => { + expect(setupUtil.download).not.toBeCalled(); + }); + }); + }); + + describe('install step', function () { + pit('installs virtualbox if it is not installed', function () { + virtualBox.installed.mockReturnValue(false); + virtualBox.killall.mockReturnValue(Promise.resolve()); + setupUtil.isSudo.mockReturnValue(Promise.resolve(false)); + util.exec.mockReturnValue(Promise.resolve()); + return setupStore.steps().installVirtualBox.run().then(() => { + // TODO: make sure that the right install command was executed + expect(util.exec).toBeCalled(); + }); + }); + + pit('installs virtualbox if it is installed but has an outdated version', function () { + virtualBox.installed.mockReturnValue(true); + virtualBox.version.mockReturnValue(Promise.resolve('4.3.16')); + virtualBox.killall.mockReturnValue(Promise.resolve()); + setupUtil.isSudo.mockReturnValue(Promise.resolve(false)); + setupUtil.compareVersions.mockReturnValue(-1); + util.exec.mockReturnValue(Promise.resolve()); + return setupStore.steps().installVirtualBox.run().then(() => { + // TODO: make sure the right install command was executed + expect(virtualBox.killall).toBeCalled(); + expect(util.exec).toBeCalled(); + }); + }); + + pit('skips install if virtualbox is already installed', function () { + virtualBox.installed.mockReturnValue(true); + virtualBox.version.mockReturnValue(Promise.resolve('4.3.20')); + setupUtil.isSudo.mockReturnValue(Promise.resolve(false)); + setupUtil.compareVersions.mockReturnValue(-1); + util.exec.mockReturnValue(Promise.resolve()); + return setupStore.steps().installVirtualBox.run().then(() => { + virtualBox.killall.mockClear(); + util.exec.mockClear(); + expect(virtualBox.killall).not.toBeCalled(); + expect(util.exec).not.toBeCalled(); + }); + }); + }); + + describe('init step', function () { + virtualBox.vmdestroy.mockReturnValue(Promise.resolve()); + pit('inintializes the boot2docker vm if it does not exist', function () { + boot2docker.exists.mockReturnValue(Promise.resolve(false)); + boot2docker.init.mockReturnValue(Promise.resolve()); + return setupStore.steps().initBoot2Docker.run().then(() => { + expect(boot2docker.init).toBeCalled(); + }); + }); + + pit('upgrades the boot2docker vm if it exists and is out of date', function () { + boot2docker.exists.mockReturnValue(Promise.resolve(true)); + boot2docker.isoversion.mockReturnValue('1.0'); + boot2docker.haskeys.mockReturnValue(true); + boot2docker.stop.mockReturnValue(Promise.resolve()); + boot2docker.upgrade.mockReturnValue(Promise.resolve()); + setupUtil.compareVersions.mockReturnValue(-1); + return setupStore.steps().initBoot2Docker.run().then(() => { + boot2docker.init.mockClear(); + expect(boot2docker.init).not.toBeCalled(); + expect(boot2docker.upgrade).toBeCalled(); + }); + }); + }); + + describe('start step', function () { + pit('starts the boot2docker vm if it is not running', function () { + boot2docker.status.mockReturnValue(false); + boot2docker.waitstatus.mockReturnValue(Promise.resolve()); + boot2docker.start.mockReturnValue(Promise.resolve()); + return setupStore.steps().startBoot2Docker.run().then(() => { + expect(boot2docker.start).toBeCalled(); + }); + }); + }); +}); diff --git a/__tests__/Virtualbox-test.js b/__tests__/Virtualbox-test.js index e8f4a2fe72..0357e569b2 100644 --- a/__tests__/Virtualbox-test.js +++ b/__tests__/Virtualbox-test.js @@ -1,11 +1,11 @@ jest.dontMock('../src/Virtualbox'); -var virtualbox = require('../src/Virtualbox'); +var virtualBox = require('../src/Virtualbox'); var util = require('../src/Util'); var Promise = require('bluebird'); -describe('Virtualbox', function () { +describe('VirtualBox', function () { it('returns the right command', function () { - expect(virtualbox.command()).toBe('/usr/bin/VBoxManage'); + expect(virtualBox.command()).toBe('/usr/bin/VBoxManage'); }); describe('version 4.3.20r96996', function () { @@ -13,7 +13,7 @@ describe('Virtualbox', function () { util.exec.mockImplementation(function () { return Promise.resolve('4.3.20r96996'); }); - return virtualbox.version().then(function (version) { + return virtualBox.version().then(function (version) { expect(version).toBe('4.3.20'); }); }); diff --git a/browser/main.js b/browser/main.js index 4ecb4688c8..1a3a6a4852 100644 --- a/browser/main.js +++ b/browser/main.js @@ -6,7 +6,12 @@ var autoUpdater = require('auto-updater'); var BrowserWindow = require('browser-window'); var ipc = require('ipc'); var argv = require('minimist')(process.argv); -var settingsjson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'settings.json'), 'utf8')); +var settingsjson; +try { + settingsjson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'settings.json'), 'utf8')); +} catch (err) { + settingsjson = {}; +} process.env.NODE_PATH = __dirname + '/../node_modules'; process.env.RESOURCES_PATH = __dirname + '/../resources'; @@ -65,7 +70,7 @@ app.on('ready', function() { // Auto Updates if (process.env.NODE_ENV !== 'development' && !argv.test) { - autoUpdater.setFeedUrl('https://updates.kitematic.com/releases/latest?version=' + app.getVersion() + '&beta=' + settingsjson.beta); + autoUpdater.setFeedUrl('https://updates.kitematic.com/releases/latest?version=' + app.getVersion() + '&beta=' + !!settingsjson.beta); autoUpdater.on('checking-for-update', function () { console.log('Checking for update...'); diff --git a/deps b/deps index 7e1cbc3cc2..9f44db32c3 100755 --- a/deps +++ b/deps @@ -2,14 +2,26 @@ BASE="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" BOOT2DOCKER_CLI_VERSION=$(node -pe "JSON.parse(process.argv[1])['boot2docker-version']" "$(cat $BASE/package.json)") BOOT2DOCKER_CLI_FILE=boot2docker-$BOOT2DOCKER_CLI_VERSION +DOCKER_CLI_VERSION=$(node -pe "JSON.parse(process.argv[1])['docker-version']" "$(cat $BASE/package.json)") +DOCKER_CLI_FILE=docker-$DOCKER_CLI_VERSION pushd $BASE/resources > /dev/null if [ ! -f $BOOT2DOCKER_CLI_FILE ]; then echo "-----> Downloading Boot2docker CLI..." rm -rf boot2docker-* - curl -L -o $BOOT2DOCKER_CLI_FILE https://github.com/boot2docker/boot2docker-cli/releases/download/v${BOOT2DOCKER_CLI_VERSION}/boot2docker-v${BOOT2DOCKER_CLI_VERSION}-darwin-amd64 + curl -L -o $BOOT2DOCKER_CLI_FILE https://github.com/boot2docker/boot2docker-cli/releases/download/v$BOOT2DOCKER_CLI_VERSION/boot2docker-v$BOOT2DOCKER_CLI_VERSION-darwin-amd64 chmod +x $BOOT2DOCKER_CLI_FILE fi +if [ ! -f $DOCKER_CLI_FILE ]; then + echo "-----> Downloading Docker CLI..." + rm -rf docker-* + curl -L -o docker-$DOCKER_CLI_VERSION.tgz https://get.docker.com/builds/Darwin/x86_64/docker-$DOCKER_CLI_VERSION.tgz + tar xvzf docker-$DOCKER_CLI_VERSION.tgz --strip=3 + rm docker-$DOCKER_CLI_VERSION.tgz + mv docker docker-$DOCKER_CLI_VERSION + chmod +x $DOCKER_CLI_FILE +fi + popd > /dev/null diff --git a/package.json b/package.json index a7566e1948..f28740e47c 100644 --- a/package.json +++ b/package.json @@ -27,13 +27,19 @@ "jest": { "scriptPreprocessor": "preprocessor.js", "unmockedModulePathPatterns": [ - "node_modules/request", + "tty", + "net", + "crypto", + "stream", + "object-assign", + "underscore", "node_modules/react", "node_modules/bluebird", "node_modules/6to5" ] }, - "boot2docker-version": "1.4.1", + "docker-version": "1.5.0", + "boot2docker-version": "1.5.0", "atom-shell-version": "0.21.1", "virtualbox-version": "4.3.20", "virtualbox-filename": "VirtualBox-4.3.20.pkg", @@ -45,20 +51,17 @@ "bluebird": "^2.9.6", "bugsnag-js": "git+https://git@github.com/bugsnag/bugsnag-js", "dockerode": "2.0.4", + "download": "^4.0.0", "exec": "0.1.2", - "html2canvas": "^0.5.0-alpha2", "jquery": "^2.1.3", "minimist": "^1.1.0", - "node-uuid": "1.4.1", "object-assign": "^2.0.0", - "open": "0.0.5", "react": "^0.12.2", "react-bootstrap": "^0.13.2", "react-retina-image": "^1.1.2", "react-router": "^0.11.6", - "request": "^2.51.0", - "request-progress": "0.3.1", - "request-promise": "^0.3.3", + "request": "^2.53.0", + "request-progress": "^0.3.1", "retina.js": "^1.1.0", "rimraf": "^2.2.8", "underscore": "^1.7.0" diff --git a/src/Main.js b/src/Main.js index 0ea0c28750..87919ac609 100644 --- a/src/Main.js +++ b/src/Main.js @@ -9,7 +9,12 @@ var router = require('./router'); var boot2docker = require('./boot2docker'); var ContainerStore = require('./ContainerStore'); var SetupStore = require('./ContainerStore'); -var settingsjson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'settings.json'), 'utf8')); +var settingsjson; +try { + settingsjson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'settings.json'), 'utf8')); +} catch (err) { + settingsjson = {}; +} if (process.env.NODE_ENV === 'development') { var head = document.getElementsByTagName('head')[0]; diff --git a/src/NewContainer.react.js b/src/NewContainer.react.js index b8e132dfce..fa325242d7 100644 --- a/src/NewContainer.react.js +++ b/src/NewContainer.react.js @@ -194,7 +194,7 @@ var NewContainer = React.createClass({
- Pick an image to create new container. + Select an image to create a new container.
diff --git a/src/Radial.react.js b/src/Radial.react.js index 3eda034f15..011fb1ffd0 100644 --- a/src/Radial.react.js +++ b/src/Radial.react.js @@ -13,7 +13,9 @@ var Radial = React.createClass({ var classes = React.addons.classSet({ 'radial-progress': true, 'radial-spinner': this.props.spin, - 'radial-negative': this.props.error + 'radial-negative': this.props.error, + 'radial-thick': this.props.thick || false, + 'radial-gray': this.props.gray || false }); return (
diff --git a/src/Setup.react.js b/src/Setup.react.js index 5860d4a30f..b89e8f06a2 100644 --- a/src/Setup.react.js +++ b/src/Setup.react.js @@ -21,6 +21,11 @@ var Setup = React.createClass({ componentDidMount: function () { this.update(); }, + componentDidUnmount: function () { + SetupStore.removeListener(SetupStore.PROGRESS_EVENT, this.update); + SetupStore.removeListener(SetupStore.STEP_EVENT, this.update); + SetupStore.removeListener(SetupStore.ERROR_EVENT, this.update); + }, update: function () { this.setState({ progress: SetupStore.percent(), @@ -28,139 +33,67 @@ var Setup = React.createClass({ error: SetupStore.error() }); }, - renderDownloadingVirtualboxStep: function () { - var message = "VirtualBox is being downloaded from Oracle's servers. Kitematic requires VirtualBox to run."; + renderContents: function () { + var img = 'virtualbox.png'; + if (SetupStore.step().name.indexOf('Boot2Docker') !== -1) { + img = 'boot2docker.png'; + } return ( -
-
-
-
- -
- -
-
-
-
-
-

Step 1 out of 4

-

Downloading VirtualBox

-

{message}

-
-
-
- ); - }, - renderInstallingVirtualboxStep: function () { - var message = 'VirtualBox is being installed in the background. We may need you to type in your password to continue.'; - return ( -
-
-
-
- -
- -
-
-
-
-
-

Step 2 out of 4

-

Installing VirtualBox

-

{message}

-
-
-
- ); - }, - renderInitBoot2DockerStep: function () { - var message = 'To run Docker containers on your computer, we are setting up a Linux virtual machine provided by boot2docker.'; - return ( -
-
-
-
- -
- -
-
-
-
-
-

Step 3 out of 4

-

Setting up Docker VM

-

{message}

-
-
-
- ); - }, - renderStartBoot2DockerStep: function () { - var message = 'Kitematic is starting the boot2docker VM. This may take about a minute.'; - return ( -
-
-
-
- -
- -
-
-
-
-
-

Step 4 out of 4

-

Starting Docker VM

-

{message}

-
+
+ +
+
); }, renderStep: function () { - switch(this.state.step) { - case 'download_virtualbox': - return this.renderDownloadingVirtualboxStep(); - case 'install_virtualbox': - return this.renderInstallingVirtualboxStep(); - case 'cleanup_kitematic': - return this.renderInitBoot2DockerStep(); - case 'init_boot2docker': - return this.renderInitBoot2DockerStep(); - case 'start_boot2docker': - return this.renderStartBoot2DockerStep(); - default: - return false; - } - }, - render: function () { - var step = this.renderStep(); - if (this.state.error) { - return ( -
-
-
-
- -
-
-
+ return ( +
+
+
+ {this.renderContents()} +
+
+
+

Step {SetupStore.number()} out of {SetupStore.stepCount()}

+

{SetupStore.step().title}

+

{SetupStore.step().message}

-
-
-

Installation Error

-

We're Sorry!

-

There seem to be an unexpected error with Kitematic:

-

{this.state.error}

+
+
+ ); + }, + renderError: function () { + return ( +
+
+
+
+ +
- ); +
+
+

Installation Error

+

We're Sorry!

+

There seems to have been an unexpected error with Kitematic:

+

{this.state.error.message}

+
+
+
+ ); + }, + render: function () { + if (!SetupStore.step()) { + return false; + } + if (this.state.error) { + return this.renderError(); } else { - return step; + return this.renderStep(); } } }); diff --git a/src/SetupStore.js b/src/SetupStore.js index 2f851eb505..fc41688027 100644 --- a/src/SetupStore.js +++ b/src/SetupStore.js @@ -1,57 +1,74 @@ var EventEmitter = require('events').EventEmitter; var assign = require('object-assign'); -var fs = require('fs'); +var _ = require('underscore'); var path = require('path'); var Promise = require('bluebird'); var boot2docker = require('./Boot2Docker'); -var virtualbox = require('./Virtualbox'); +var virtualBox = require('./VirtualBox'); var setupUtil = require('./SetupUtil'); var util = require('./Util'); -var packagejson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')); -var _percent = 0; +var SUDO_PROMPT = 'Kitematic requires administrative privileges to install VirtualBox.'; var _currentStep = null; var _error = null; -var VIRTUALBOX_FILE = `https://github.com/kitematic/virtualbox/releases/download/${packagejson['virtualbox-version']}/${packagejson['virtualbox-filename']}`; -var SUDO_PROMPT = 'Kitematic requires administrative privileges to install VirtualBox.'; - -var SetupStore = assign(EventEmitter.prototype, { - PROGRESS_EVENT: 'setup_progress', - STEP_EVENT: 'setup_step', - ERROR_EVENT: 'setup_error', - downloadVirtualboxStep: Promise.coroutine(function* () { - if (virtualbox.installed()) { - var version = yield virtualbox.version(); +var _steps = [{ + name: 'downloadVirtualBox', + title: 'Downloading VirtualBox', + message: 'VirtualBox is being downloaded. Kitematic requires VirtualBox to run containers.', + totalPercent: 35, + percent: 0, + run: Promise.coroutine(function* (progressCallback) { + var packagejson = util.packagejson(); + if (virtualBox.installed()) { + var version = yield virtualBox.version(); if (setupUtil.compareVersions(version, packagejson['virtualbox-required-version']) >= 0) { return; } } - yield setupUtil.download(VIRTUALBOX_FILE, path.join(setupUtil.supportDir(), packagejson['virtualbox-filename']), packagejson.checksum, percent => { - _percent = percent; - SetupStore.emit(SetupStore.PROGRESS_EVENT); + var virtualBoxFile = `https://github.com/kitematic/virtualbox/releases/download/${packagejson['virtualbox-version']}/${packagejson['virtualbox-filename']}`; + yield setupUtil.download(virtualBoxFile, path.join(setupUtil.supportDir(), packagejson['virtualbox-filename']), packagejson['virtualbox-checksum'], percent => { + progressCallback(percent); }); - }), - installVirtualboxStep: Promise.coroutine(function* () { - if (virtualbox.installed()) { - var version = yield virtualbox.version(); + }) +}, { + name: 'installVirtualBox', + title: 'Installing VirtualBox', + message: "VirtualBox is being installed in the background. We may need you to type in your password to continue.", + totalPercent: 5, + percent: 0, + seconds: 5, + run: Promise.coroutine(function* () { + var packagejson = util.packagejson(); + if (virtualBox.installed()) { + var version = yield virtualBox.version(); if (setupUtil.compareVersions(version, packagejson['virtualbox-required-version']) >= 0) { return; } - yield virtualbox.killall(); + yield virtualBox.killall(); } var isSudo = yield setupUtil.isSudo(); var iconPath = path.join(setupUtil.resourceDir(), 'kitematic.icns'); var sudoCmd = isSudo ? ['sudo'] : [path.join(setupUtil.resourceDir(), 'cocoasudo'), '--icon=' + iconPath, `--prompt=${SUDO_PROMPT}`]; sudoCmd.push.apply(sudoCmd, ['installer', '-pkg', path.join(setupUtil.supportDir(), packagejson['virtualbox-filename']), '-target', '/']); - yield util.exec(sudoCmd); - }), - cleanupKitematicStep: function () { - return virtualbox.vmdestroy('kitematic-vm'); - }, - initBoot2DockerStep: Promise.coroutine(function* () { + try { + yield util.exec(sudoCmd); + } catch (err) { + console.log('Could not install virtualbox...'); + } + }) +}, { + name: 'initBoot2Docker', + title: 'Setting up Docker VM', + message: "To run Docker containers on your computer, we are setting up a Linux virtual machine provided by boot2docker.", + totalPercent: 15, + percent: 0, + seconds: 11, + run: Promise.coroutine(function* (progressCallback) { + yield virtualBox.vmdestroy('kitematic-vm'); var exists = yield boot2docker.exists(); if (!exists) { + setupUtil.simulateProgress(this.seconds, progressCallback); yield boot2docker.init(); return; } @@ -62,63 +79,77 @@ var SetupStore = assign(EventEmitter.prototype, { var isoversion = boot2docker.isoversion(); if (!isoversion || setupUtil.compareVersions(isoversion, boot2docker.version()) < 0) { + setupUtil.simulateProgress(this.seconds, progressCallback); yield boot2docker.stop(); yield boot2docker.upgrade(); } - }), - startBoot2DockerStep: function () { + }) +}, { + name: 'startBoot2Docker', + title: 'Starting Docker VM', + message: "Kitematic is starting the boot2docker VM. This may take about a minute.", + totalPercent: 45, + percent: 0, + seconds: 35, + run: function (progressCallback) { return boot2docker.waitstatus('saving').then(boot2docker.status).then(status => { + setupUtil.simulateProgress(this.seconds, progressCallback); if (status !== 'running') { return boot2docker.start(); } }); - }, + } +}]; + +var SetupStore = assign(EventEmitter.prototype, { + PROGRESS_EVENT: 'setup_progress', + STEP_EVENT: 'setup_step', + ERROR_EVENT: 'setup_error', step: function () { - if (_currentStep) { - return _currentStep; - } else { - return ''; - } + return _currentStep || _steps[0]; + }, + steps: function () { + return _.indexBy(_steps, 'name'); + }, + stepCount: function () { + return _steps.length; + }, + number: function () { + return _.indexOf(_steps, _currentStep) + 1; }, percent: function () { - return _percent; + var total = 0; + _.each(_steps, step => { + total += step.totalPercent * step.percent / 100; + }); + return Math.min(Math.round(total), 99); }, error: function () { return _error; }, - run: Promise.coroutine(function* () { - var steps = [{ - name: 'download_virtualbox', - run: this.downloadVirtualboxStep - }, { - name: 'install_virtualbox', - run: this.installVirtualboxStep - }, { - name: 'cleanup_kitematic', - run: this.cleanupKitematicStep - }, { - name: 'init_boot2docker', - run: this.initBoot2DockerStep - }, { - name: 'start_boot2docker', - run: this.startBoot2DockerStep - }]; - - _error = null; - for (let step of steps) { - console.log(step.name); - _currentStep = step.name; - _percent = 0; - this.emit(this.STEP_EVENT); + run: Promise.coroutine(function* (startAt) { + startAt = startAt || 0; + for (let step of _steps.slice(startAt)) { + _currentStep = step; + step.percent = 0; try { - yield step.run(); + console.log(step.name); + this.emit(this.STEP_EVENT); + yield step.run(percent => { + if (_currentStep) { + step.percent = percent; + this.emit(this.PROGRESS_EVENT); + } + }); + step.percent = 100; } catch (err) { - console.log(err); + console.log(err.stack); _error = err; this.emit(this.ERROR_EVENT); throw err; } } + _currentStep = null; }) }); diff --git a/src/SetupUtil.js b/src/SetupUtil.js index ab4dbe134b..31931d99b6 100644 --- a/src/SetupUtil.js +++ b/src/SetupUtil.js @@ -1,9 +1,10 @@ +var _ = require('underscore'); +var crypto = require('crypto'); +var exec = require('exec'); +var fs = require('fs'); var request = require('request'); var progress = require('request-progress'); var path = require('path'); -var crypto = require('crypto'); -var fs = require('fs'); -var exec = require('exec'); var Promise = require('bluebird'); var SetupUtil = { @@ -31,18 +32,29 @@ var SetupUtil = { }); }); }, + simulateProgress: function (estimateSeconds, progress) { + var times = _.range(0, estimateSeconds * 1000, 200); + var timers = []; + _.each(times, time => { + var timer = setTimeout(() => { + progress(100 * time / (estimateSeconds * 1000)); + }, time); + timers.push(timer); + }); + }, download: function (url, filename, checksum, percentCallback) { return new Promise((resolve, reject) => { if (fs.existsSync(filename)) { var existingChecksum = crypto.createHash('sha256').update(fs.readFileSync(filename), 'utf8').digest('hex'); if (existingChecksum === checksum) { resolve(); + return; } else { fs.unlinkSync(filename); } } - progress(request({ uri: url, rejectUnauthorized: false }), { throttle: 250 }).on('progress', state => { + progress(request({ uri: url, rejectUnauthorized: false }), { throttle: 10 }).on('progress', state => { if (percentCallback) { percentCallback(state.percent); } diff --git a/src/Util.js b/src/Util.js index b0144372e9..d83cc2fa01 100644 --- a/src/Util.js +++ b/src/Util.js @@ -1,5 +1,7 @@ var exec = require('exec'); var Promise = require('bluebird'); +var fs = require('fs'); +var path = require('path'); module.exports = { exec: function (args) { @@ -14,5 +16,8 @@ module.exports = { }, home: function () { return process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME']; + }, + packagejson: function () { + return JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')); } }; diff --git a/styles/radial.less b/styles/radial.less index 4f68f23bfc..91d2ffb18b 100644 --- a/styles/radial.less +++ b/styles/radial.less @@ -16,13 +16,14 @@ } @circle-size: 140px; - @circle-background: #F2F2F2; + @circle-background: red; @inset-size: @circle-size - 4; @inset-color: white; @transition-length: 1s; // @percentage-color: #3FD899; @percentage-font-size: 24px; @percentage-text-width: 57px; + background: white; margin: 0 auto; width: @circle-size; @@ -84,6 +85,37 @@ background-color: @brand-positive; } + &.radial-thick { + @inset-size: @circle-size - 10; + .inset { + width: @inset-size; + height: @inset-size; + position: absolute; + margin-left: (@circle-size - @inset-size) / 2.0; + margin-top: (@circle-size - @inset-size) / 2.0; + + background-color: @inset-color; + border-radius: 100%; + .percentage { + width: @percentage-text-width; + position: absolute; + top: (@inset-size - @percentage-font-size) / 2.0; + left: (@inset-size - @percentage-text-width) / 2.0; + + line-height: 1; + text-align: center; + + color: @brand-primary; + font-weight: 500; + font-size: @percentage-font-size; + } + } + } + + &.radial-gray { + background: #EEE; + } + @i: 0; @increment: 180deg / 100; .loop (@i) when (@i <= 100) { diff --git a/styles/setup.less b/styles/setup.less index 801d268149..5877f31cc9 100644 --- a/styles/setup.less +++ b/styles/setup.less @@ -63,6 +63,7 @@ p { &.error { color: @brand-danger; + word-wrap: break-word; } margin-top: 20px; } From a8a490ea70f1e696054d8b1042f286724a88e901 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Wed, 11 Feb 2015 15:10:12 -0800 Subject: [PATCH 2/5] Reverting to 1.4.1 for now --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f28740e47c..dbcf32a0ba 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,8 @@ "node_modules/6to5" ] }, - "docker-version": "1.5.0", - "boot2docker-version": "1.5.0", + "docker-version": "1.4.1", + "boot2docker-version": "1.4.1", "atom-shell-version": "0.21.1", "virtualbox-version": "4.3.20", "virtualbox-filename": "VirtualBox-4.3.20.pkg", From e6ea5024b71f68107eef9b03166b478044e9fc03 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Wed, 11 Feb 2015 15:24:29 -0800 Subject: [PATCH 3/5] Temporary removal of VirtualBox --- src/Virtualbox.js | 66 ----------------------------------------------- 1 file changed, 66 deletions(-) delete mode 100644 src/Virtualbox.js diff --git a/src/Virtualbox.js b/src/Virtualbox.js deleted file mode 100644 index a1d20bb427..0000000000 --- a/src/Virtualbox.js +++ /dev/null @@ -1,66 +0,0 @@ -var fs = require('fs'); -var util = require('./Util'); -var Promise = require('bluebird'); - -var VirtualBox = { - command: function () { - return '/usr/bin/VBoxManage'; - }, - installed: function () { - return fs.existsSync('/usr/bin/VBoxManage') && fs.existsSync('/Applications/VirtualBox.app'); - }, - version: function () { - return new Promise((resolve, reject) => { - util.exec([this.command(), '-v']).then(stdout => { - var match = stdout.match(/(\d+\.\d+\.\d+).*/); - if (!match || match.length < 2) { - reject('VBoxManage -v output format not recognized.'); - } - resolve(match[1]); - }).catch(reject); - }); - }, - poweroffall: function () { - if (!this.installed()) { - return Promise.reject('VirtualBox not installed.'); - } - return util.exec(this.command() + ' list runningvms | sed -E \'s/.*\\{(.*)\\}/\\1/\' | xargs -L1 -I {} ' + this.command() + ' controlvm {} poweroff'); - }, - killall: function () { - if (!this.installed()) { - return Promise.reject('VirtualBox not installed.'); - } - return this.poweroffall().then(() => { - return util.exec(['pkill', 'VirtualBox']); - }).then(() => { - return util.exec(['pkill', 'VBox']); - }); - }, - vmstate: function (name) { - return new Promise((resolve, reject) => { - util.exec([this.command(), 'showvminfo', name, '--machinereadable']).then(stdout => { - var match = stdout.match(/VMState="(\w+)"/); - if (!match) { - reject('Could not parse VMState'); - } - resolve(match[1]); - }).catch(reject); - }); - }, - vmdestroy: function (name) { - return Promise.coroutine(function* () { - if (!this.installed()) { - return Promise.reject('VirtualBox not installed.'); - } - try { - var state = yield this.vmstate(name); - if (state === 'running') { - yield util.exec([this.command(), 'controlvm', name, 'poweroff']); - } - yield util.exec([this.command(), 'unregistervm', name, '--delete']); - } catch (err) {} - }.bind(this))(); - } -}; - -module.exports = VirtualBox; From 343332e4c683bbc0c6af9b1f914747a84b99edc2 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Wed, 11 Feb 2015 15:24:45 -0800 Subject: [PATCH 4/5] Adding it back --- src/VirtualBox.js | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/VirtualBox.js diff --git a/src/VirtualBox.js b/src/VirtualBox.js new file mode 100644 index 0000000000..a1d20bb427 --- /dev/null +++ b/src/VirtualBox.js @@ -0,0 +1,66 @@ +var fs = require('fs'); +var util = require('./Util'); +var Promise = require('bluebird'); + +var VirtualBox = { + command: function () { + return '/usr/bin/VBoxManage'; + }, + installed: function () { + return fs.existsSync('/usr/bin/VBoxManage') && fs.existsSync('/Applications/VirtualBox.app'); + }, + version: function () { + return new Promise((resolve, reject) => { + util.exec([this.command(), '-v']).then(stdout => { + var match = stdout.match(/(\d+\.\d+\.\d+).*/); + if (!match || match.length < 2) { + reject('VBoxManage -v output format not recognized.'); + } + resolve(match[1]); + }).catch(reject); + }); + }, + poweroffall: function () { + if (!this.installed()) { + return Promise.reject('VirtualBox not installed.'); + } + return util.exec(this.command() + ' list runningvms | sed -E \'s/.*\\{(.*)\\}/\\1/\' | xargs -L1 -I {} ' + this.command() + ' controlvm {} poweroff'); + }, + killall: function () { + if (!this.installed()) { + return Promise.reject('VirtualBox not installed.'); + } + return this.poweroffall().then(() => { + return util.exec(['pkill', 'VirtualBox']); + }).then(() => { + return util.exec(['pkill', 'VBox']); + }); + }, + vmstate: function (name) { + return new Promise((resolve, reject) => { + util.exec([this.command(), 'showvminfo', name, '--machinereadable']).then(stdout => { + var match = stdout.match(/VMState="(\w+)"/); + if (!match) { + reject('Could not parse VMState'); + } + resolve(match[1]); + }).catch(reject); + }); + }, + vmdestroy: function (name) { + return Promise.coroutine(function* () { + if (!this.installed()) { + return Promise.reject('VirtualBox not installed.'); + } + try { + var state = yield this.vmstate(name); + if (state === 'running') { + yield util.exec([this.command(), 'controlvm', name, 'poweroff']); + } + yield util.exec([this.command(), 'unregistervm', name, '--delete']); + } catch (err) {} + }.bind(this))(); + } +}; + +module.exports = VirtualBox; From 847b4c7cbae0fbc31775b46e68754fc624eb2efa Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Wed, 11 Feb 2015 15:36:55 -0800 Subject: [PATCH 5/5] Fixing VirtualBox case --- __tests__/Virtualbox-test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/__tests__/Virtualbox-test.js b/__tests__/Virtualbox-test.js index 0357e569b2..1a8efa7aab 100644 --- a/__tests__/Virtualbox-test.js +++ b/__tests__/Virtualbox-test.js @@ -1,5 +1,5 @@ -jest.dontMock('../src/Virtualbox'); -var virtualBox = require('../src/Virtualbox'); +jest.dontMock('../src/VirtualBox'); +var virtualBox = require('../src/VirtualBox'); var util = require('../src/Util'); var Promise = require('bluebird');