зеркало из https://github.com/docker/kitematic.git
WIP tests
This commit is contained in:
Родитель
cfa6e96286
Коммит
c7d3bffc7f
|
@ -11,10 +11,18 @@ var BrowserWindow = require('browser-window');
|
|||
var ipc = require('ipc');
|
||||
|
||||
var argv = require('minimist')(process.argv);
|
||||
var saveVMOnQuit = false;
|
||||
|
||||
process.env.NODE_PATH = __dirname + '/../node_modules';
|
||||
process.env.RESOURCES_PATH = __dirname + '/../resources';
|
||||
process.chdir(path.join(__dirname, '..'));
|
||||
|
||||
if (argv.integration) {
|
||||
process.env.TEST_TYPE = 'integration';
|
||||
} else {
|
||||
process.env.TEST_TYPE = 'test';
|
||||
}
|
||||
|
||||
app.on('activate-with-no-open-windows', function () {
|
||||
if (mainWindow) {
|
||||
mainWindow.show();
|
||||
|
@ -23,38 +31,35 @@ app.on('activate-with-no-open-windows', function () {
|
|||
});
|
||||
|
||||
app.on('ready', function() {
|
||||
var windowOptions = {
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1000,
|
||||
height: 700,
|
||||
'min-width': 1000,
|
||||
'min-height': 700,
|
||||
resizable: true,
|
||||
frame: false
|
||||
};
|
||||
frame: false,
|
||||
show: false
|
||||
});
|
||||
|
||||
mainWindow = new BrowserWindow(windowOptions);
|
||||
mainWindow.hide();
|
||||
if (argv.test) {
|
||||
mainWindow.loadUrl('file://' + __dirname + '/../specs/specs.html');
|
||||
mainWindow.loadUrl('file://' + __dirname + '/../tests/tests.html');
|
||||
} else {
|
||||
mainWindow.loadUrl('file://' + __dirname + '/../build/index.html');
|
||||
app.on('will-quit', function (e) {
|
||||
if (saveVMOnQuit) {
|
||||
exec('VBoxManage controlvm boot2docker-vm savestate', function (stderr, stdout, code) {});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
process.on('uncaughtException', app.quit);
|
||||
|
||||
var saveVMOnQuit = false;
|
||||
app.on('will-quit', function (e) {
|
||||
if (saveVMOnQuit) {
|
||||
exec('VBoxManage controlvm boot2docker-vm savestate', function (stderr, stdout, code) {});
|
||||
}
|
||||
});
|
||||
|
||||
mainWindow.webContents.on('new-window', function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
mainWindow.webContents.on('did-finish-load', function() {
|
||||
mainWindow.show();
|
||||
if (!argv.test) {
|
||||
mainWindow.show();
|
||||
}
|
||||
mainWindow.focus();
|
||||
mainWindow.setTitle('');
|
||||
|
||||
|
@ -92,12 +97,12 @@ app.on('ready', function() {
|
|||
autoUpdater.quitAndInstall();
|
||||
}
|
||||
});
|
||||
|
||||
autoUpdater.checkForUpdates();
|
||||
}
|
||||
|
||||
ipc.on('vm', function (event, arg) {
|
||||
saveVMOnQuit = arg;
|
||||
});
|
||||
|
||||
autoUpdater.checkForUpdates();
|
||||
});
|
||||
});
|
||||
|
|
31
deps
31
deps
|
@ -1,36 +1,15 @@
|
|||
#!/bin/bash
|
||||
|
||||
BASE="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
PLATFORM='unknown'
|
||||
unamestr=`uname`
|
||||
if [[ "$unamestr" == 'Linux' ]]; then
|
||||
PLATFORM='linux'
|
||||
elif [[ "$unamestr" == 'Darwin' ]]; then
|
||||
PLATFORM='darwin'
|
||||
fi
|
||||
|
||||
export BOOT2DOCKER_CLI_VERSION=$(node -pe "JSON.parse(process.argv[1])['boot2docker-version']" "$(cat $BASE/package.json)")
|
||||
export BOOT2DOCKER_CLI_VERSION_FILE=boot2docker-$BOOT2DOCKER_CLI_VERSION
|
||||
export ATOM_SHELL_VERSION=$(node -pe "JSON.parse(process.argv[1])['atom-shell-version']" "$(cat $BASE/package.json)")
|
||||
export ATOM_SHELL_VERSION_FILE=atom-shell-v$ATOM_SHELL_VERSION-$PLATFORM-x64.zip
|
||||
|
||||
mkdir -p $BASE/cache/$PLATFORM
|
||||
pushd $BASE/cache/$PLATFORM > /dev/null
|
||||
if [ ! -f $ATOM_SHELL_VERSION_FILE ]; then
|
||||
echo "-----> Downloading atom-shell..."
|
||||
rm -rf atom-shell-*
|
||||
curl -L -o $ATOM_SHELL_VERSION_FILE https://github.com/atom/atom-shell/releases/download/v$ATOM_SHELL_VERSION/atom-shell-v$ATOM_SHELL_VERSION-$PLATFORM-x64.zip
|
||||
unzip $ATOM_SHELL_VERSION_FILE
|
||||
fi
|
||||
popd > /dev/null
|
||||
BOOT2DOCKER_CLI_VERSION=$(node -pe "JSON.parse(process.argv[1])['boot2docker-version']" "$(cat $BASE/package.json)")
|
||||
BOOT2DOCKER_CLI_FILE=boot2docker-$BOOT2DOCKER_CLI_VERSION
|
||||
|
||||
pushd $BASE/resources > /dev/null
|
||||
|
||||
if [ ! -f $BOOT2DOCKER_CLI_VERSION_FILE ]; then
|
||||
if [ ! -f $BOOT2DOCKER_CLI_FILE ]; then
|
||||
echo "-----> Downloading Boot2docker CLI..."
|
||||
rm -rf boot2docker-*
|
||||
curl -L -o $BOOT2DOCKER_CLI_VERSION_FILE https://github.com/boot2docker/boot2docker-cli/releases/download/v${BOOT2DOCKER_CLI_VERSION}/boot2docker-v${BOOT2DOCKER_CLI_VERSION}-darwin-amd64
|
||||
chmod +x $BOOT2DOCKER_CLI_VERSION_FILE
|
||||
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
|
||||
|
||||
popd > /dev/null
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
var concat = require('gulp-concat');
|
||||
var cssmin = require('gulp-cssmin');
|
||||
var downloadatomshell = require('gulp-download-atom-shell');
|
||||
var fs = require('fs');
|
||||
var gulp = require('gulp');
|
||||
var gulpif = require('gulp-if');
|
||||
var gutil = require('gulp-util');
|
||||
var http = require('http');
|
||||
var less = require('gulp-less');
|
||||
var livereload = require('gulp-livereload');
|
||||
var plumber = require('gulp-plumber');
|
||||
var react = require('gulp-react');
|
||||
var runSequence = require('run-sequence');
|
||||
var shell = require('gulp-shell');
|
||||
var sourcemaps = require('gulp-sourcemaps');
|
||||
var packagejson = require('./package.json');
|
||||
|
||||
var dependencies = Object.keys(packagejson.dependencies);
|
||||
var devDependencies = Object.keys(packagejson.devDependencies);
|
||||
var options = {
|
||||
dev: process.argv.indexOf('release') === -1 && process.argv.indexOf('test') === -1,
|
||||
test: process.argv.indexOf('test') !== -1,
|
||||
integration: process.argv.indexOf('--integration') !== -1,
|
||||
filename: 'Kitematic.app',
|
||||
name: 'Kitematic'
|
||||
};
|
||||
|
||||
gulp.task('js', function () {
|
||||
gulp.src('src/**/*.js')
|
||||
.pipe(plumber(function(error) {
|
||||
gutil.log(gutil.colors.red('Error (' + error.plugin + '): ' + error.message));
|
||||
// emit the end event, to properly end the task
|
||||
this.emit('end');
|
||||
}))
|
||||
.pipe(react())
|
||||
.pipe(gulp.dest((options.dev || options.test) ? './build' : './dist/osx/' + options.filename + '/Contents/Resources/app/build'))
|
||||
.pipe(gulpif(options.dev, livereload()));
|
||||
});
|
||||
|
||||
gulp.task('images', function() {
|
||||
return gulp.src('images/*')
|
||||
.pipe(gulp.dest(options.dev ? './build' : './dist/osx/' + options.filename + '/Contents/Resources/app/build'))
|
||||
.pipe(gulpif(options.dev, livereload()));
|
||||
});
|
||||
|
||||
gulp.task('styles', function () {
|
||||
return gulp.src('styles/main.less')
|
||||
.pipe(plumber(function(error) {
|
||||
gutil.log(gutil.colors.red('Error (' + error.plugin + '): ' + error.message));
|
||||
// emit the end event, to properly end the task
|
||||
this.emit('end');
|
||||
}))
|
||||
.pipe(gulpif(options.dev, sourcemaps.init()))
|
||||
.pipe(less())
|
||||
.pipe(gulpif(options.dev, sourcemaps.write()))
|
||||
.pipe(gulp.dest(options.dev ? './build' : './dist/osx/' + options.filename + '/Contents/Resources/app/build'))
|
||||
.pipe(gulpif(!options.dev, cssmin()))
|
||||
.pipe(concat('main.css'))
|
||||
.pipe(gulpif(options.dev, livereload()));
|
||||
});
|
||||
|
||||
gulp.task('download', function (cb) {
|
||||
downloadatomshell({
|
||||
version: packagejson['atom-shell-version'],
|
||||
outputDir: 'cache'
|
||||
}, cb);
|
||||
});
|
||||
|
||||
gulp.task('copy', function () {
|
||||
gulp.src('index.html')
|
||||
.pipe(gulp.dest(options.dev ? './build' : './dist/osx/' + options.filename + '/Contents/Resources/app/build'))
|
||||
.pipe(gulpif(options.dev, livereload()));
|
||||
|
||||
gulp.src('fonts/**')
|
||||
.pipe(gulp.dest(options.dev ? './build' : './dist/osx/' + options.filename + '/Contents/Resources/app/build'))
|
||||
.pipe(gulpif(options.dev, livereload()));
|
||||
});
|
||||
|
||||
gulp.task('dist', function (cb) {
|
||||
var stream = gulp.src('').pipe(shell([
|
||||
'rm -Rf ./dist',
|
||||
'mkdir -p ./dist/osx',
|
||||
'cp -R ./cache/Atom.app ./dist/osx/<%= filename %>',
|
||||
'mv ./dist/osx/<%= filename %>/Contents/MacOS/Atom ./dist/osx/<%= filename %>/Contents/MacOS/<%= name %>',
|
||||
'mkdir -p ./dist/osx/<%= filename %>/Contents/Resources/app',
|
||||
'cp -R browser dist/osx/<%= filename %>/Contents/Resources/app',
|
||||
'cp package.json dist/osx/<%= filename %>/Contents/Resources/app/',
|
||||
'mkdir -p dist/osx/<%= filename %>/Contents/Resources/app/resources',
|
||||
'cp -v resources/* dist/osx/<%= filename %>/Contents/Resources/app/resources/ || :',
|
||||
'cp kitematic.icns dist/osx/<%= filename %>/Contents/Resources/atom.icns',
|
||||
'/usr/libexec/PlistBuddy -c "Set :CFBundleVersion <%= version %>" dist/osx/<%= filename %>/Contents/Info.plist',
|
||||
'/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName <%= name %>" dist/osx/<%= filename %>/Contents/Info.plist',
|
||||
'/usr/libexec/PlistBuddy -c "Set :CFBundleName <%= name %>" dist/osx/<%= filename %>/Contents/Info.plist',
|
||||
'/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier <%= bundle %>" dist/osx/<%= filename %>/Contents/Info.plist',
|
||||
'/usr/libexec/PlistBuddy -c "Set :CFBundleExecutable <%= name %>" dist/osx/<%= filename %>/Contents/Info.plist'
|
||||
], {
|
||||
templateData: {
|
||||
filename: options.filename,
|
||||
name: options.name,
|
||||
version: packagejson.version,
|
||||
bundle: 'com.kitematic.app'
|
||||
}
|
||||
}));
|
||||
|
||||
dependencies.forEach(function (d) {
|
||||
stream = stream.pipe(shell([
|
||||
'cp -R node_modules/' + d + ' dist/osx/<%= filename %>/Contents/Resources/app/node_modules/'
|
||||
], {
|
||||
templateData: {
|
||||
filename: options.filename
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
return stream;
|
||||
});
|
||||
|
||||
gulp.task('sign', function () {
|
||||
try {
|
||||
var signing_identity = fs.readFileSync('./identity', 'utf8').trim();
|
||||
return gulp.src('').pipe(shell([
|
||||
'codesign --deep --force --verbose --sign "' + signing_identity + '" ' + options.filename
|
||||
], {
|
||||
cwd: './dist/osx/'
|
||||
}));
|
||||
} catch (error) {
|
||||
gutil.log(gutil.colors.red('Error: ' + error.message));
|
||||
}
|
||||
});
|
||||
|
||||
gulp.task('zip', function () {
|
||||
return gulp.src('').pipe(shell([
|
||||
'ditto -c -k --sequesterRsrc --keepParent ' + options.filename + ' ' + options.name + '-' + packagejson.version + '.zip'
|
||||
], {
|
||||
cwd: './dist/osx/'
|
||||
}));
|
||||
});
|
||||
|
||||
gulp.task('release', function () {
|
||||
runSequence('download', 'dist', ['copy', 'images', 'js', 'styles'], 'sign', 'zip');
|
||||
});
|
||||
|
||||
gulp.task('test', ['download', 'copy', 'js'], function () {
|
||||
var env = process.env;
|
||||
env.NODE_ENV = 'test';
|
||||
if (options.integration) {
|
||||
gulp.src('').pipe(shell(['./cache/Atom.app/Contents/MacOS/Atom . --test --integration'], {
|
||||
env: env
|
||||
}));
|
||||
} else {
|
||||
gulp.src('').pipe(shell(['./cache/Atom.app/Contents/MacOS/Atom . --test'], {
|
||||
env: env
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
gulp.task('default', ['download', 'copy', 'js', 'images', 'styles'], function () {
|
||||
gulp.watch('src/**/*.js', ['js']);
|
||||
gulp.watch('index.html', ['copy']);
|
||||
gulp.watch('styles/**/*.less', ['styles']);
|
||||
gulp.watch('images/**', ['images']);
|
||||
|
||||
livereload.listen();
|
||||
|
||||
var env = process.env;
|
||||
env.NODE_ENV = 'development';
|
||||
gulp.src('').pipe(shell(['./cache/Atom.app/Contents/MacOS/Atom .'], {
|
||||
env: env
|
||||
}));
|
||||
});
|
53
package.json
53
package.json
|
@ -11,13 +11,12 @@
|
|||
},
|
||||
"bugs": "https://github.com/kitematic/kitematic/issues",
|
||||
"scripts": {
|
||||
"start": "rsync ./index.html ./build/ && rsync ./fonts/* ./build/ && rsync ./images/* ./build && jsx --watch src/ build/ & wess -w -m -i ./styles/main.less -o ./build/main.css & wiper -w ./build/**/*.* & npm run start:$(uname) && kill $(pgrep node)",
|
||||
"start:Darwin": "NODE_ENV=development ./cache/darwin/Atom.app/Contents/MacOS/Atom .",
|
||||
"start:Linux": "NODE_ENV=development ./cache/linux/atom .",
|
||||
"test": "jsx --watch src build/ & rsync ./images/* ./build && wess -m -i ./styles/main.less -o ./build/main.css && npm run test:$(uname) && kill $(pgrep node)",
|
||||
"test:Darwin": "NODE_ENV=test ./cache/darwin/Atom.app/Contents/MacOS/Atom . --test",
|
||||
"test:Linux": "NODE_ENV=test ./cache/darwin/atom .",
|
||||
"release": "./release"
|
||||
"start": "gulp",
|
||||
"test": "gulp test --silent",
|
||||
"integration-tests": "gulp test --silent --integration",
|
||||
"all-tests": "npm test && npm run integration-tests",
|
||||
"release": "gulp run release",
|
||||
"preinstall": "./deps"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
|
@ -32,15 +31,17 @@
|
|||
"debug"
|
||||
]
|
||||
},
|
||||
"boot2docker-version": "1.3.2",
|
||||
"boot2docker-version": "1.4.1",
|
||||
"atom-shell-version": "0.21.0",
|
||||
"virtualbox-version": "4.3.20",
|
||||
"virtualbox-filename": "VirtualBox-4.3.20-96996-OSX.dmg",
|
||||
"virtualbox-required-version": "4.3.18",
|
||||
"dependencies": {
|
||||
"ansi-to-html": "0.2.0",
|
||||
"async": "^0.9.0",
|
||||
"bugsnag-js": "^2.4.6",
|
||||
"bugsnag-js": "git+https://git@github.com/bugsnag/bugsnag-js",
|
||||
"dockerode": "2.0.4",
|
||||
"exec": "0.1.2",
|
||||
"gulp-react": "^2.0.0",
|
||||
"jest-cli": "^0.2.1",
|
||||
"jquery": "^2.1.3",
|
||||
"minimist": "^1.1.0",
|
||||
|
@ -57,15 +58,33 @@
|
|||
"underscore": "^1.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^6.2.0",
|
||||
"ecstatic": "^0.5.8",
|
||||
"glob": "^4.0.6",
|
||||
"jasmine-node": "^1.14.5",
|
||||
"jasmine-reporters": "^1.0.1",
|
||||
"jasmine-tagged": "^1.1.2",
|
||||
"jasmine-terminal-reporter": "^0.9.1",
|
||||
"react-tools": "^0.12.2",
|
||||
"wess": "^0.2.2",
|
||||
"wiper": "^1.0.2",
|
||||
"gulp": "^3.8.10",
|
||||
"gulp-atom": "0.0.5",
|
||||
"gulp-concat": "^2.3.4",
|
||||
"gulp-cssmin": "^0.1.6",
|
||||
"gulp-download-atom-shell": "0.0.4",
|
||||
"gulp-if": "^1.2.4",
|
||||
"gulp-imagemin": "^2.0.0",
|
||||
"gulp-less": "^2.0.1",
|
||||
"gulp-livereload": "^2.1.1",
|
||||
"gulp-notify": "^1.4.2",
|
||||
"gulp-plumber": "^0.6.6",
|
||||
"gulp-react": "^2.0.0",
|
||||
"gulp-shell": "^0.2.11",
|
||||
"gulp-sourcemaps": "^1.2.8",
|
||||
"gulp-streamify": "0.0.5",
|
||||
"gulp-uglify": "^0.3.1",
|
||||
"gulp-uglifyjs": "^0.5.0",
|
||||
"gulp-util": "^3.0.0",
|
||||
"reactify": "^0.15.2",
|
||||
"rimraf": "^2.2.8",
|
||||
"run-sequence": "^1.0.2",
|
||||
"time-require": "^0.1.2",
|
||||
"vinyl-source-stream": "^0.1.1",
|
||||
"watchify": "^2.1.1",
|
||||
"zombie": "^2.5.1"
|
||||
}
|
||||
}
|
||||
|
|
35
release
35
release
|
@ -1,35 +0,0 @@
|
|||
#!/bin/bash
|
||||
BASE="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
export NAME=$(node -pe "JSON.parse(process.argv[1])['name']" "$(cat $BASE/package.json)")
|
||||
export VERSION=$(node -pe "JSON.parse(process.argv[1])['version']" "$(cat $BASE/package.json)")
|
||||
export FILENAME=$NAME.app
|
||||
export BUNDLE=com.kitematic.app
|
||||
|
||||
rm -Rf ./dist
|
||||
mkdir -p ./dist/osx
|
||||
cp -R ./cache/Atom.app ./dist/osx/$FILENAME
|
||||
mv ./dist/osx/$FILENAME/Contents/MacOS/Atom ./dist/osx/$FILENAME/Contents/MacOS/$NAME
|
||||
mkdir -p ./dist/osx/$FILENAME/Contents/Resources/app
|
||||
cp -R browser dist/osx/$FILENAME/Contents/Resources/app
|
||||
cp package.json dist/osx/$FILENAME/Contents/Resources/app/
|
||||
mkdir -p dist/osx/$FILENAME/Contents/Resources/app/resources
|
||||
mkdir -p dist/osx/$FILENAME/Contents/Resources/app/node_modules
|
||||
cp -v resources/* dist/osx/$FILENAME/Contents/Resources/app/resources/ || :
|
||||
cp kitematic.icns dist/osx/$FILENAME/Contents/Resources/atom.icns
|
||||
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $VERSION" dist/osx/$FILENAME/Contents/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $NAME" dist/osx/$FILENAME/Contents/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set :CFBundleName $NAME" dist/osx/$FILENAME/Contents/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $BUNDLE" dist/osx/$FILENAME/Contents/Info.plist
|
||||
/usr/libexec/PlistBuddy -c "Set :CFBundleExecutable $NAME" dist/osx/$FILENAME/Contents/Info.plist
|
||||
|
||||
rsync ./index.html ./dist/osx/$FILENAME/Contents/Resources/app/build/
|
||||
rsync ./fonts/* ./dist/osx/$FILENAME/Contents/Resources/app/build/
|
||||
rsync ./images/* ./dist/osx/$FILENAME/Contents/Resources/app/build/
|
||||
jsx src/ ./dist/osx/$FILENAME/Contents/Resources/app/build/
|
||||
wess -m -i ./styles/main.less -o ./dist/osx/$FILENAME/Contents/Resources/app/build/main.css
|
||||
|
||||
if [ -f $BASE/identity ]; then
|
||||
codesign --deep --force --verbose --sign "$(cat $BASE/identity)" ./dist/osx/$FILENAME
|
||||
fi
|
||||
|
||||
ditto -c -k --sequesterRsrc --keepParent ./dist/osx/$FILENAME ./dist/osx/$NAME-$VERSION.zip
|
Двоичный файл не отображается.
|
@ -1,8 +0,0 @@
|
|||
var ContainerStore = require('../build/ContainerStore');
|
||||
var TestUtils = require('react/addons').TestUtils;
|
||||
|
||||
describe('ContainerStore', function() {
|
||||
it('returns an empty array initially', function() {
|
||||
expect(ContainerStore.containers()).toEqual({});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,26 @@
|
|||
window.jasmineRequire = require('./jasmine-2.1.3/jasmine');
|
||||
require('./jasmine-2.1.3/jasmine-html');
|
||||
require('./jasmine-2.1.3/boot');
|
||||
var consoleReporter = require('./jasmine-2.1.3/console');
|
||||
var app = require('remote').require('app');
|
||||
|
||||
jasmine.getEnv().addReporter(new consoleReporter.ConsoleReporter()({
|
||||
showColors: true,
|
||||
timer: new jasmine.Timer(),
|
||||
print: function() {
|
||||
process.stdout.write.apply(process.stdout, arguments);
|
||||
},
|
||||
onComplete: function () {
|
||||
app.quit();
|
||||
}
|
||||
}));
|
||||
|
||||
console.log('hi');
|
||||
var fs = require('fs');
|
||||
var tests = fs.readdirSync('./tests').filter(function (f) {
|
||||
return f.indexOf('-' + process.env.TEST_TYPE) !== -1;
|
||||
});
|
||||
|
||||
tests.forEach(function (t) {
|
||||
require('./' + t);
|
||||
});
|
15
src/Main.js
15
src/Main.js
|
@ -6,19 +6,18 @@ var docker = require('./docker');
|
|||
var router = require('./router');
|
||||
var boot2docker = require('./boot2docker');
|
||||
var ContainerStore = require('./ContainerStore');
|
||||
var SetupStore = require('./ContainerStore');
|
||||
var Menu = require('./Menu');
|
||||
var remote = require('remote');
|
||||
var app = remote.require('app');
|
||||
var ipc = require('ipc');
|
||||
|
||||
|
||||
var Route = Router.Route;
|
||||
var NotFoundRoute = Router.NotFoundRoute;
|
||||
var DefaultRoute = Router.DefaultRoute;
|
||||
var Link = Router.Link;
|
||||
var RouteHandler = Router.RouteHandler;
|
||||
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
var script = document.createElement('script');
|
||||
script.type = 'text/javascript';
|
||||
|
@ -28,8 +27,16 @@ if (process.env.NODE_ENV === 'development') {
|
|||
}
|
||||
|
||||
if (!window.location.hash.length || window.location.hash === '#/') {
|
||||
router.run(function (Handler) {
|
||||
React.render(<Handler/>, document.body);
|
||||
SetupStore.run(function (err) {
|
||||
boot2docker.ip(function (err, ip) {
|
||||
docker.setHost(ip);
|
||||
router.transitionTo('containers');
|
||||
ContainerStore.init(function () {
|
||||
router.run(function (Handler) {
|
||||
React.render(<Handler/>, document.body);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
boot2docker.ip(function (err, ip) {
|
||||
|
|
|
@ -5,133 +5,9 @@ var async = require('async');
|
|||
var assign = require('object-assign');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var boot2docker = require('./Boot2Docker');
|
||||
var virtualbox = require('./Virtualbox');
|
||||
var util = require('./Util');
|
||||
var docker = require('./Docker');
|
||||
var ContainerStore = require('./ContainerStore');
|
||||
|
||||
var setupSteps = [
|
||||
{
|
||||
run: function (callback, progressCallback) {
|
||||
console.log(util.supportDir());
|
||||
var installed = virtualbox.installed();
|
||||
if (!installed) {
|
||||
util.download('https://s3.amazonaws.com/kite-installer/' + virtualbox.INSTALLER_FILENAME, path.join(util.supportDir(), virtualbox.INSTALLER_FILENAME), virtualbox.INSTALLER_CHECKSUM, function (err) {
|
||||
if (err) {callback(err); return;}
|
||||
virtualbox.install(function (err) {
|
||||
if (!virtualbox.installed()) {
|
||||
callback('VirtualBox could not be installed. The installation either failed or was cancelled. Please try closing all VirtualBox instances and try again.');
|
||||
} else {
|
||||
callback(err);
|
||||
}
|
||||
});
|
||||
}, function (progress) {
|
||||
progressCallback(progress);
|
||||
});
|
||||
} else {
|
||||
virtualbox.version(function (err, installedVersion) {
|
||||
if (err) {callback(err); return;}
|
||||
if (util.compareVersions(installedVersion, virtualbox.REQUIRED_VERSION) < 0) {
|
||||
// Download a newer version of Virtualbox
|
||||
util.downloadFile(Setup.BASE_URL + virtualbox.INSTALLER_FILENAME, path.join(util.getResourceDir(), virtualbox.INSTALLER_FILENAME), virtualbox.INSTALLER_CHECKSUM, function (err) {
|
||||
if (err) {callback(err); return;}
|
||||
virtualbox.kill(function (err) {
|
||||
if (err) {callback(err); return;}
|
||||
virtualbox.install(function (err) {
|
||||
if (err) {callback(err); return;}
|
||||
virtualbox.version(function (err, installedVersion) {
|
||||
if (err) {callback(err); return;}
|
||||
if (util.compareVersions(installedVersion, virtualbox.REQUIRED_VERSION) < 0) {
|
||||
callback('VirtualBox could not be installed. The installation either failed or was cancelled. Please try closing all VirtualBox instances and try again.');
|
||||
} else {
|
||||
callback(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}, function (progress) {
|
||||
progressCallback(progress);
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
message: 'Downloading VirtualBox...'
|
||||
},
|
||||
{
|
||||
run: function (callback) {
|
||||
virtualbox.deleteVM('kitematic-vm', function (err, removed) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
callback();
|
||||
});
|
||||
},
|
||||
message: 'Cleaning up existing Docker VM...'
|
||||
},
|
||||
|
||||
// Initialize Boot2Docker if necessary.
|
||||
{
|
||||
run: function (callback) {
|
||||
boot2docker.exists(function (err, exists) {
|
||||
if (err) { callback(err); return; }
|
||||
if (!exists) {
|
||||
boot2docker.init(function (err) {
|
||||
callback(err);
|
||||
});
|
||||
} else {
|
||||
if (!boot2docker.sshKeyExists()) {
|
||||
callback('Boot2Docker SSH key doesn\'t exist. Fix by removing the existing Boot2Docker VM and re-run the installer. This usually occurs because an old version of Boot2Docker is installed.');
|
||||
} else {
|
||||
boot2docker.isoVersion(function (err, version) {
|
||||
if (err || util.compareVersions(version, boot2docker.version()) < 0) {
|
||||
boot2docker.stop(function(err) {
|
||||
boot2docker.upgrade(function (err) {
|
||||
callback(err);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
message: 'Setting up the Docker VM...'
|
||||
},
|
||||
{
|
||||
run: function (callback) {
|
||||
boot2docker.waitWhileStatus('saving', function (err) {
|
||||
boot2docker.status(function (err, status) {
|
||||
if (err) {callback(err); return;}
|
||||
if (status !== 'running') {
|
||||
boot2docker.start(function (err) {
|
||||
callback(err);
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
message: 'Starting the Docker VM...'
|
||||
},
|
||||
{
|
||||
run: function (callback) {
|
||||
boot2docker.ip(function (err, ip) {
|
||||
if (err) {callback(err); return;}
|
||||
console.log('Setting host IP to: ' + ip);
|
||||
docker.setHost(ip);
|
||||
callback(err);
|
||||
});
|
||||
},
|
||||
message: 'Detecting Docker VM...'
|
||||
}
|
||||
];
|
||||
var SetupStore = require('./SetupStore');
|
||||
|
||||
var Setup = React.createClass({
|
||||
mixins: [ Router.Navigation ],
|
||||
|
@ -140,6 +16,14 @@ var Setup = React.createClass({
|
|||
message: '',
|
||||
progress: 0
|
||||
};
|
||||
},
|
||||
componentWillMount: function () {
|
||||
SetupStore.on(SetupStore.PROGRESS_EVENT, this.update);
|
||||
},
|
||||
componentDidMount: function () {
|
||||
},
|
||||
update: function () {
|
||||
|
||||
},
|
||||
render: function () {
|
||||
var radial;
|
||||
|
@ -165,53 +49,6 @@ var Setup = React.createClass({
|
|||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
componentWillMount: function () {
|
||||
this.setState({});
|
||||
},
|
||||
componentDidMount: function () {
|
||||
var self = this;
|
||||
this.setup(function (err) {
|
||||
if (!err) {
|
||||
boot2docker.ip(function (err, ip) {
|
||||
docker.setHost(ip);
|
||||
ContainerStore.init(function () {
|
||||
self.transitionTo('containers');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
setup: function (callback) {
|
||||
var self = this;
|
||||
var currentStep = 0;
|
||||
async.eachSeries(setupSteps, function (step, callback) {
|
||||
console.log('Performing step ' + currentStep);
|
||||
self.setState({progress: 0});
|
||||
self.setState({message: step.message});
|
||||
step.run(function (err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
currentStep += 1;
|
||||
callback();
|
||||
}
|
||||
}, function (progress) {
|
||||
self.setState({progress: progress});
|
||||
});
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
// if any of the steps fail
|
||||
console.log('Kitematic setup failed at step ' + currentStep);
|
||||
console.log(err);
|
||||
self.setState({error: err.message});
|
||||
callback(err);
|
||||
} else {
|
||||
// Setup Finished
|
||||
console.log('Setup finished.');
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
var EventEmitter = require('events').EventEmitter;
|
||||
var assign = require('object-assign');
|
||||
var async = require('async');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var exec = require('exec');
|
||||
var boot2docker = require('./Boot2Docker');
|
||||
var virtualbox = require('./Virtualbox');
|
||||
var setupUtil = require('./SetupUtil');
|
||||
var packagejson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
|
||||
|
||||
var _currentStep = null;
|
||||
var _error = null;
|
||||
var _progress = null;
|
||||
|
||||
var SetupStore = assign(EventEmitter.prototype, {
|
||||
PROGRESS_EVENT: 'setup_progress',
|
||||
STEP_EVENT: 'setup_step',
|
||||
ERROR_EVENT: 'setup_error',
|
||||
downloadVirtualboxStep: {
|
||||
_download: function (callback, progressCallback) {
|
||||
setupUtil.virtualboxSHA256(packagejson['virtualbox-version'], packagejson['virtualbox-filename'], function (err, checksum) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
var url = 'http://download.virtualbox.org/virtualbox/' + packagejson['virtualbox-version'] + '/' + packagejson['virtualbox-filename'];
|
||||
var downloadPath = path.join(setupUtil.supportDir(), packagejson['virtualbox-filename']);
|
||||
setupUtil.download(url, downloadPath, checksum, function (err) {
|
||||
callback(err);
|
||||
}, function (progress) {
|
||||
progressCallback(progress);
|
||||
});
|
||||
});
|
||||
},
|
||||
run: function (callback, progressCallback) {
|
||||
if (virtualbox.installed()) {
|
||||
virtualbox.version(function (err, version) {
|
||||
if (err) {callback(err); return;}
|
||||
if (setupUtil.compareVersions(version, packagejson['virtualbox-required-version']) < 0) {
|
||||
this._download(callback, progressCallback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this._download(callback, progressCallback);
|
||||
}
|
||||
},
|
||||
name: 'downloading_virtualbox',
|
||||
message: 'Downloading Virtualbox',
|
||||
},
|
||||
installVirtualboxStep: {
|
||||
_install: function (callback) {
|
||||
exec(['hdiutil', 'attach', path.join(setupUtil.supportDir(), 'VirtualBox-4.3.20-96996-OSX.dmg')], function (stderr, stdout, code) {
|
||||
if (code) {
|
||||
callback(stderr);
|
||||
return;
|
||||
}
|
||||
var iconPath = path.join(setupUtil.resourceDir(), 'kitematic.icns');
|
||||
setupUtil.isSudo(function (err, isSudo) {
|
||||
sudoCmd = isSudo ? ['sudo'] : [path.join(setupUtil.resourceDir(), 'cocoasudo'), '--icon=' + iconPath, '--prompt=Kitematic requires administrative privileges to install VirtualBox and copy itself to the Applications folder.'];
|
||||
sudoCmd.push.apply(sudoCmd, ['installer', '-pkg', '/Volumes/VirtualBox/VirtualBox.pkg', '-target', '/']);
|
||||
exec(sudoCmd, function (stderr, stdout, code) {
|
||||
if (code) {
|
||||
console.log(stderr);
|
||||
console.log(stdout);
|
||||
callback('Could not install virtualbox.');
|
||||
} else {
|
||||
exec(['hdiutil', 'detach', '/Volumes/VirtualBox'], function(stderr, stdout, code) {
|
||||
if (code) {
|
||||
callback(stderr);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
run: function (callback) {
|
||||
var self = this;
|
||||
if (virtualbox.installed()) {
|
||||
virtualbox.version(function (err, version) {
|
||||
if (setupUtil.compareVersions(version, packagejson['virtualbox-required-version']) < 0) {
|
||||
virtualbox.kill(function (err) {
|
||||
if (err) {callback(err); return;}
|
||||
self._install(function(err) {
|
||||
callback(err);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
self._install(function(err) {
|
||||
callback(err);
|
||||
});
|
||||
}
|
||||
},
|
||||
name: 'installing_virtualbox',
|
||||
message: 'Installing VirtualBox',
|
||||
},
|
||||
cleanupKitematicStep: {
|
||||
run: function (callback) {
|
||||
virtualbox.vmdestroy('kitematic-vm', function (err, removed) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
callback();
|
||||
});
|
||||
},
|
||||
name: 'cleanup_kitematic',
|
||||
message: 'Cleaning up existing Kitematic install...'
|
||||
},
|
||||
initBoot2DockerStep: {
|
||||
run: function (callback) {
|
||||
boot2docker.exists(function (err, exists) {
|
||||
if (err) { callback(err); return; }
|
||||
if (!exists) {
|
||||
boot2docker.init(function (err) {
|
||||
callback(err);
|
||||
});
|
||||
} else {
|
||||
if (!boot2docker.sshKeyExists()) {
|
||||
callback('Boot2Docker SSH key doesn\'t exist. Fix by removing the existing Boot2Docker VM and re-run the installer. This usually occurs because an old version of Boot2Docker is installed.');
|
||||
} else {
|
||||
boot2docker.isoVersion(function (err, version) {
|
||||
if (err || setupUtil.compareVersions(version, boot2docker.version()) < 0) {
|
||||
boot2docker.stop(function(err) {
|
||||
boot2docker.upgrade(function (err) {
|
||||
callback(err);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
name: 'init_boot2docker',
|
||||
message: 'Setting up the Docker VM...'
|
||||
},
|
||||
startBoot2DockerStep: {
|
||||
run: function (callback) {
|
||||
boot2docker.waitWhileStatus('saving', function (err) {
|
||||
boot2docker.status(function (err, status) {
|
||||
if (err) {callback(err); return;}
|
||||
if (status !== 'running') {
|
||||
boot2docker.start(function (err) {
|
||||
callback(err);
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
name: 'start_boot2docker',
|
||||
message: 'Starting the Docker VM...'
|
||||
},
|
||||
step: function () {
|
||||
return _currentStep;
|
||||
},
|
||||
progress: function () {
|
||||
return _progress;
|
||||
},
|
||||
run: function (callback) {
|
||||
var self = this;
|
||||
var steps = [this.downloadVirtualboxStep, this.installVirtualboxStep, this.cleanupKitematicStep, this.initBoot2DockerStep, this.startBoot2DockerStep];
|
||||
async.eachSeries(steps, function (step, callback) {
|
||||
console.log(step.name);
|
||||
_currentStep = step;
|
||||
_progress = null;
|
||||
step.run(function (err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
self.emit(self.STEP_EVENT);
|
||||
callback();
|
||||
}
|
||||
}, function (progress) {
|
||||
self.emit(self.PROGRESS_EVENT, progress);
|
||||
_progress = progress;
|
||||
});
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
self.emit(self.ERROR_EVENT, _error);
|
||||
callback(err);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = SetupStore;
|
|
@ -1,13 +1,13 @@
|
|||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var nodeCrypto = require('crypto');
|
||||
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 Util = {
|
||||
var SetupUtil = {
|
||||
supportDir: function (callback) {
|
||||
var dirs = ['Application\ Support', 'Kitematic'];
|
||||
var dirs = ['Library', 'Application\ Support', 'Kitematic'];
|
||||
var acc = process.env.HOME;
|
||||
dirs.forEach(function (d) {
|
||||
acc = path.join(acc, d);
|
||||
|
@ -17,6 +17,19 @@ var Util = {
|
|||
});
|
||||
return acc;
|
||||
},
|
||||
resourceDir: function (callback) {
|
||||
return process.env.RESOURCES_PATH;
|
||||
},
|
||||
isSudo: function (callback) {
|
||||
exec(['sudo', '-n', '-u', 'root', 'true'], function (stderr, stdout, code) {
|
||||
if (code) {
|
||||
callback(stderr);
|
||||
} else {
|
||||
var isSudo = stderr.indexOf('a password is required') === -1;
|
||||
callback(null, isSudo);
|
||||
}
|
||||
});
|
||||
},
|
||||
download: function (url, filename, checksum, callback, progressCallback) {
|
||||
var doDownload = function () {
|
||||
progress(request({
|
||||
|
@ -37,8 +50,7 @@ var Util = {
|
|||
|
||||
// Compare checksum to see if it already exists first
|
||||
if (fs.existsSync(filename)) {
|
||||
var existingChecksum = nodeCrypto.createHash('sha256').update(fs.readFileSync(filename), 'utf8').digest('hex');
|
||||
console.log(existingChecksum);
|
||||
var existingChecksum = crypto.createHash('sha256').update(fs.readFileSync(filename), 'utf8').digest('hex');
|
||||
if (existingChecksum !== checksum) {
|
||||
fs.unlinkSync(filename);
|
||||
doDownload();
|
||||
|
@ -49,6 +61,22 @@ var Util = {
|
|||
doDownload();
|
||||
}
|
||||
},
|
||||
virtualboxSHA256: function (version, filename, callback) {
|
||||
var checksumUrl = 'http://dlc-cdn.sun.com/virtualbox/' + version + '/SHA256SUMS';
|
||||
request(checksumUrl, function (error, response, body) {
|
||||
if (error) {
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
var checksums = body.split('\n').map(function (line) {
|
||||
return line.split(' *');
|
||||
}).reduce(function (obj, pair) {
|
||||
obj[pair[1]] = pair[0];
|
||||
return obj;
|
||||
}, {});
|
||||
callback(null, checksums[filename]);
|
||||
});
|
||||
},
|
||||
compareVersions: function (v1, v2, options) {
|
||||
var lexicographical = options && options.lexicographical,
|
||||
zeroExtend = options && options.zeroExtend,
|
||||
|
@ -100,4 +128,4 @@ var Util = {
|
|||
}
|
||||
};
|
||||
|
||||
module.exports = Util;
|
||||
module.exports = SetupUtil;
|
|
@ -5,32 +5,18 @@ var async = require('async');
|
|||
var util = require('./Util');
|
||||
|
||||
var VirtualBox = {
|
||||
REQUIRED_VERSION: '4.3.18',
|
||||
INCLUDED_VERSION: '4.3.18',
|
||||
INSTALLER_FILENAME: 'virtualbox-4.3.18.pkg',
|
||||
INSTALLER_CHECKSUM: '5836c94481c460c648b9216386591a2915293ac86b9bb6c57746637796af6af2',
|
||||
command: function () {
|
||||
return '/usr/bin/VBoxManage';
|
||||
},
|
||||
installed: function () {
|
||||
return fs.existsSync('/usr/bin/VBoxManage') && fs.existsSync('/Applications/VirtualBox.app/Contents/MacOS/VirtualBox');
|
||||
},
|
||||
install: function (callback) {
|
||||
// -W waits for the process to close before finishing.
|
||||
exec('open -W ' + path.join(util.supportDir(), this.INSTALLER_FILENAME).replace(' ', '\\ '), function (stderr, stdout, code) {
|
||||
if (code) {
|
||||
callback(stderr);
|
||||
return;
|
||||
}
|
||||
callback(null);
|
||||
});
|
||||
},
|
||||
version: function (callback) {
|
||||
if (!this.installed()) {
|
||||
callback('VirtualBox not installed.');
|
||||
return;
|
||||
}
|
||||
exec('/usr/bin/VBoxManage -v', function (stderr, stdout, code) {
|
||||
exec([this.command(), '-v'], function (stderr, stdout, code) {
|
||||
if (code) {
|
||||
callback(stderr);
|
||||
return;
|
||||
|
@ -44,12 +30,12 @@ var VirtualBox = {
|
|||
callback(null, match[1]);
|
||||
});
|
||||
},
|
||||
saveVMs: function (callback) {
|
||||
poweroff: function (callback) {
|
||||
if (!this.installed()) {
|
||||
callback('VirtualBox not installed.');
|
||||
return;
|
||||
}
|
||||
exec('/usr/bin/VBoxManage list runningvms | sed -E \'s/.*\\{(.*)\\}/\\1/\' | xargs -L1 -I {} /usr/bin/VBoxManage controlvm {} savestate', function (stderr, stdout, code) {
|
||||
exec(this.command() + ' list runningvms | sed -E \'s/.*\\{(.*)\\}/\\1/\' | xargs -L1 -I {} ' + this.command() + ' controlvm {} acpipowerbutton', function (stderr, stdout, code) {
|
||||
if (code) {
|
||||
callback(stderr);
|
||||
} else {
|
||||
|
@ -58,7 +44,7 @@ var VirtualBox = {
|
|||
});
|
||||
},
|
||||
kill: function (callback) {
|
||||
this.saveRunningVMs(function (err) {
|
||||
this.poweroff(function (err) {
|
||||
if (err) {callback(err); return;}
|
||||
exec('pkill VirtualBox', function (stderr, stdout, code) {
|
||||
if (code) {callback(stderr); return;}
|
||||
|
@ -69,7 +55,7 @@ var VirtualBox = {
|
|||
});
|
||||
});
|
||||
},
|
||||
vmState: function (name, callback) {
|
||||
vmstate: function (name, callback) {
|
||||
exec(this.command() + ' showvminfo ' + name + ' --machinereadable', function (stderr, stdout, code) {
|
||||
if (code) { callback(stderr); return; }
|
||||
var match = stdout.match(/VMState="(\w+)"/);
|
||||
|
@ -80,8 +66,9 @@ var VirtualBox = {
|
|||
callback(null, match[1]);
|
||||
});
|
||||
},
|
||||
deleteVM:function (name, callback) {
|
||||
VirtualBox.vmState(name, function (err, state) {
|
||||
vmdestroy: function (name, callback) {
|
||||
var self = this;
|
||||
this.vmstate(name, function (err, state) {
|
||||
// No VM found
|
||||
if (err) { callback(null, false); return; }
|
||||
exec('/usr/bin/VBoxManage controlvm ' + name + ' acpipowerbutton', function (stderr, stdout, code) {
|
||||
|
@ -91,7 +78,7 @@ var VirtualBox = {
|
|||
async.until(function () {
|
||||
return state === 'poweroff';
|
||||
}, function (callback) {
|
||||
VirtualBox.vmState(name, function (err, newState) {
|
||||
self.vmstate(name, function (err, newState) {
|
||||
if (err) { callback(err); return; }
|
||||
state = newState;
|
||||
setTimeout(callback, 250);
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
var virtualbox = require('../build/Virtualbox');
|
||||
var SetupStore = require('../build/SetupStore');
|
||||
var setupUtil = require('../build/SetupUtil');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var child_process = require('child_process');
|
||||
var exec = require('exec');
|
||||
var rimraf = require('rimraf');
|
||||
var packagejson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
|
||||
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300000; // 5 minutes
|
||||
|
||||
describe('Setup', function () {
|
||||
describe('without virtualbox installed or downloaded', function () {
|
||||
var virtualboxFile = path.join(setupUtil.supportDir(), packagejson['virtualbox-filename']);
|
||||
beforeEach(function () {
|
||||
if (fs.existsSync(virtualboxFile)) {
|
||||
fs.unlinkSync(virtualboxFile);
|
||||
}
|
||||
spyOn(virtualbox, 'installed').andCallFake(function (callback) {
|
||||
callback(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('downloads virtualbox', function (done) {
|
||||
SetupStore.downloadVirtualboxStep.run(function (err) {
|
||||
expect(err).toBeFalsy();
|
||||
expect(fs.existsSync(virtualboxFile)).toBe(true);
|
||||
done();
|
||||
}, function (progress) {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with virtualbox downloaded but not installed', function () {
|
||||
beforeEach(function (done) {
|
||||
// 5 minute timeout per test
|
||||
|
||||
SetupStore.downloadVirtualboxStep.run(function (err) {
|
||||
if (virtualbox.installed()) {
|
||||
virtualbox.kill(function (callback) {
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
}, function (progress) {});
|
||||
});
|
||||
|
||||
it('does install virtualbox', function (done) {
|
||||
SetupStore.installVirtualboxStep.run(function (err) {
|
||||
expect(err).toBeFalsy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with virtualbox installed', function () {
|
||||
|
||||
// Before each teardown the boot2docker VM, keys and anything else
|
||||
|
||||
describe('and with a kitematic vm', function () {
|
||||
|
||||
});
|
||||
|
||||
describe('and without a boot2docker vm', function () {
|
||||
|
||||
});
|
||||
|
||||
describe('and with an old boot2docker vm', function () {
|
||||
|
||||
});
|
||||
|
||||
describe('and with a very old boot2docker vm', function () {
|
||||
|
||||
});
|
||||
|
||||
describe('and with a boot2docker vm running', function () {
|
||||
|
||||
});
|
||||
|
||||
describe('and with a boot2docker vm but with no ssh keys', function () {
|
||||
|
||||
});
|
||||
|
||||
describe('and with a boot2docker vm being powered off', function () {
|
||||
|
||||
});
|
||||
|
||||
describe('and with a boot2docker vm being removed', function () {
|
||||
|
||||
});
|
||||
|
||||
describe('and with a boot2docker vm initialized but not running', function () {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
var setupUtil = require('../build/SetupUtil');
|
||||
|
||||
describe('SetupUtils', function() {
|
||||
it('returns live sha256 checksum for a given virtualbox version & filename', function (done) {
|
||||
setupUtil.virtualboxSHA256('4.3.20', 'VirtualBox-4.3.20-96996-OSX.dmg', function (err, checksum) {
|
||||
expect(checksum).toBe('744e77119a640a5974160213c9912568a3d88dbd06a2fc6b6970070941732705');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -57,8 +57,6 @@ getJasmineRequireObj().ConsoleReporter = function() {
|
|||
},
|
||||
failedSuites = [];
|
||||
|
||||
print('ConsoleReporter is deprecated and will be removed in a future version.');
|
||||
|
||||
this.jasmineStarted = function() {
|
||||
specCount = 0;
|
||||
failureCount = 0;
|
До Ширина: | Высота: | Размер: 1.5 KiB После Ширина: | Высота: | Размер: 1.5 KiB |
|
@ -4,7 +4,6 @@
|
|||
<link rel="stylesheet" href="jasmine-2.1.3/jasmine.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script src="specs.js"></script>
|
||||
<script src="http://localhost:35729"></script>
|
||||
<script src="tests.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -2,19 +2,22 @@ window.jasmineRequire = require('./jasmine-2.1.3/jasmine');
|
|||
require('./jasmine-2.1.3/jasmine-html');
|
||||
require('./jasmine-2.1.3/boot');
|
||||
var consoleReporter = require('./jasmine-2.1.3/console');
|
||||
var app = require('remote').require('app');
|
||||
|
||||
jasmine.getEnv().addReporter(new consoleReporter.ConsoleReporter()({
|
||||
showColors: true,
|
||||
timer: new jasmine.Timer(),
|
||||
print: function() {
|
||||
console.log(arguments);
|
||||
process.stdout.write.apply(process.stdout, arguments);
|
||||
},
|
||||
onComplete: function () {
|
||||
app.quit();
|
||||
}
|
||||
}));
|
||||
|
||||
var fs = require('fs');
|
||||
var tests = fs.readdirSync('./specs').filter(function (f) {
|
||||
return f.indexOf('-spec') !== -1;
|
||||
var tests = fs.readdirSync('./tests').filter(function (f) {
|
||||
return f.indexOf('-' + process.env.TEST_TYPE) !== -1;
|
||||
});
|
||||
|
||||
tests.forEach(function (t) {
|
|
@ -0,0 +1,245 @@
|
|||
#!/bin/bash
|
||||
# $Id: VirtualBox_Uninstall.tool 89624 2013-10-07 16:13:23Z bird $
|
||||
## @file
|
||||
# VirtualBox Uninstaller Script.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (C) 2007-2013 Oracle Corporation
|
||||
#
|
||||
# This file is part of VirtualBox Open Source Edition (OSE), as
|
||||
# available from http://www.virtualbox.org. This file is free software;
|
||||
# you can redistribute it and/or modify it under the terms of the GNU
|
||||
# General Public License (GPL) as published by the Free Software
|
||||
# Foundation, in version 2 as it comes in the "COPYING" file of the
|
||||
# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
||||
# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
||||
#
|
||||
|
||||
# Override any funny stuff from the user.
|
||||
export PATH="/bin:/usr/bin:/sbin:/usr/sbin:$PATH"
|
||||
|
||||
#
|
||||
# Display a simple welcome message first.
|
||||
#
|
||||
echo ""
|
||||
echo "Welcome to the VirtualBox uninstaller script."
|
||||
echo ""
|
||||
|
||||
#
|
||||
# Check for arguments and display
|
||||
#
|
||||
my_default_prompt=0
|
||||
if test "$#" != "0"; then
|
||||
if test "$#" != "1" -o "$1" != "--unattended"; then
|
||||
echo "Error: Unknown argument(s): $*"
|
||||
echo ""
|
||||
echo "Usage: uninstall.sh [--unattended]"
|
||||
echo ""
|
||||
echo "If the '--unattended' option is not given, you will be prompted"
|
||||
echo "for a Yes/No before doing the actual uninstallation."
|
||||
echo ""
|
||||
exit 4;
|
||||
fi
|
||||
my_default_prompt="Yes"
|
||||
fi
|
||||
|
||||
#
|
||||
# Collect directories and files to remove.
|
||||
# Note: Do NOT attempt adding directories or filenames with spaces!
|
||||
#
|
||||
declare -a my_directories
|
||||
declare -a my_files
|
||||
|
||||
# Users files first
|
||||
test -f "${HOME}/Library/LaunchAgents/org.virtualbox.vboxwebsrv.plist" && my_files+=("${HOME}/Library/LaunchAgents/org.virtualbox.vboxwebsrv.plist")
|
||||
|
||||
test -d /Library/StartupItems/VirtualBox/ && my_directories+=("/Library/StartupItems/VirtualBox/")
|
||||
test -d /Library/Receipts/VBoxStartupItems.pkg/ && my_directories+=("/Library/Receipts/VBoxStartupItems.pkg/")
|
||||
|
||||
test -d "/Library/Application Support/VirtualBox/LaunchDaemons/" && my_directories+=("/Library/Application Support/VirtualBox/LaunchDaemons/")
|
||||
test -d "/Library/Application Support/VirtualBox/VBoxDrv.kext/" && my_directories+=("/Library/Application Support/VirtualBox/VBoxDrv.kext/")
|
||||
test -d "/Library/Application Support/VirtualBox/VBoxUSB.kext/" && my_directories+=("/Library/Application Support/VirtualBox/VBoxUSB.kext/")
|
||||
test -d "/Library/Application Support/VirtualBox/VBoxNetFlt.kext/" && my_directories+=("/Library/Application Support/VirtualBox/VBoxNetFlt.kext/")
|
||||
test -d "/Library/Application Support/VirtualBox/VBoxNetAdp.kext/" && my_directories+=("/Library/Application Support/VirtualBox/VBoxNetAdp.kext/")
|
||||
# Pre 4.3.0rc1 locations:
|
||||
test -d /Library/Extensions/VBoxDrv.kext/ && my_directories+=("/Library/Extensions/VBoxDrv.kext/")
|
||||
test -d /Library/Extensions/VBoxUSB.kext/ && my_directories+=("/Library/Extensions/VBoxUSB.kext/")
|
||||
test -d /Library/Extensions/VBoxNetFlt.kext/ && my_directories+=("/Library/Extensions/VBoxNetFlt.kext/")
|
||||
test -d /Library/Extensions/VBoxNetAdp.kext/ && my_directories+=("/Library/Extensions/VBoxNetAdp.kext/")
|
||||
# Tiger support is obsolete, but we leave it here for a clean removing of older
|
||||
# VirtualBox versions
|
||||
test -d /Library/Extensions/VBoxDrvTiger.kext/ && my_directories+=("/Library/Extensions/VBoxDrvTiger.kext/")
|
||||
test -d /Library/Extensions/VBoxUSBTiger.kext/ && my_directories+=("/Library/Extensions/VBoxUSBTiger.kext/")
|
||||
test -d /Library/Receipts/VBoxKEXTs.pkg/ && my_directories+=("/Library/Receipts/VBoxKEXTs.pkg/")
|
||||
|
||||
test -f /usr/bin/VirtualBox && my_files+=("/usr/bin/VirtualBox")
|
||||
test -f /usr/bin/VBoxManage && my_files+=("/usr/bin/VBoxManage")
|
||||
test -f /usr/bin/VBoxVRDP && my_files+=("/usr/bin/VBoxVRDP")
|
||||
test -f /usr/bin/VBoxHeadless && my_files+=("/usr/bin/VBoxHeadless")
|
||||
test -f /usr/bin/vboxwebsrv && my_files+=("/usr/bin/vboxwebsrv")
|
||||
test -f /usr/bin/VBoxBalloonCtrl && my_files+=("/usr/bin/VBoxBalloonCtrl")
|
||||
test -f /usr/bin/VBoxAutostart && my_files+=("/usr/bin/VBoxAutostart")
|
||||
test -f /usr/bin/vbox-img && my_files+=("/usr/bin/vbox-img")
|
||||
test -d /Library/Receipts/VirtualBoxCLI.pkg/ && my_directories+=("/Library/Receipts/VirtualBoxCLI.pkg/")
|
||||
test -f /Library/LaunchDaemons/org.virtualbox.startup.plist && my_files+=("/Library/LaunchDaemons/org.virtualbox.startup.plist")
|
||||
|
||||
test -d /Applications/VirtualBox.app/ && my_directories+=("/Applications/VirtualBox.app/")
|
||||
test -d /Library/Receipts/VirtualBox.pkg/ && my_directories+=("/Library/Receipts/VirtualBox.pkg/")
|
||||
|
||||
# legacy
|
||||
test -d /Library/Receipts/VBoxDrv.pkg/ && my_directories+=("/Library/Receipts/VBoxDrv.pkg/")
|
||||
test -d /Library/Receipts/VBoxUSB.pkg/ && my_directories+=("/Library/Receipts/VBoxUSB.pkg/")
|
||||
|
||||
# python stuff
|
||||
python_versions="2.3 2.5 2.6 2.7"
|
||||
for p in $python_versions; do
|
||||
test -f /Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.py && my_files+=("/Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.py")
|
||||
test -f /Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.pyc && my_files+=("/Library/Python/$p/site-packages/vboxapi/VirtualBox_constants.pyc")
|
||||
test -f /Library/Python/$p/site-packages/vboxapi/__init__.py && my_files+=("/Library/Python/$p/site-packages/vboxapi/__init__.py")
|
||||
test -f /Library/Python/$p/site-packages/vboxapi/__init__.pyc && my_files+=("/Library/Python/$p/site-packages/vboxapi/__init__.pyc")
|
||||
test -f /Library/Python/$p/site-packages/vboxapi-1.0-py$p.egg-info && my_files+=("/Library/Python/$p/site-packages/vboxapi-1.0-py$p.egg-info")
|
||||
test -d /Library/Python/$p/site-packages/vboxapi/ && my_directories+=("/Library/Python/$p/site-packages/vboxapi/")
|
||||
done
|
||||
|
||||
#
|
||||
# Collect KEXTs to remove.
|
||||
# Note that the unload order is significant.
|
||||
#
|
||||
declare -a my_kexts
|
||||
for kext in org.virtualbox.kext.VBoxUSB org.virtualbox.kext.VBoxNetFlt org.virtualbox.kext.VBoxNetAdp org.virtualbox.kext.VBoxDrv; do
|
||||
if /usr/sbin/kextstat -b $kext -l | grep -q $kext; then
|
||||
my_kexts+=("$kext")
|
||||
fi
|
||||
done
|
||||
|
||||
#
|
||||
# Collect packages to forget
|
||||
#
|
||||
my_pb='org\.virtualbox\.pkg\.'
|
||||
my_pkgs=`/usr/sbin/pkgutil --pkgs="${my_pb}vboxkexts|${my_pb}vboxstartupitems|${my_pb}virtualbox|${my_pb}virtualboxcli"`
|
||||
|
||||
#
|
||||
# Did we find anything to uninstall?
|
||||
#
|
||||
if test -z "${my_directories[*]}" -a -z "${my_files[*]}" -a -z "${my_kexts[*]}" -a -z "$my_pkgs"; then
|
||||
echo "No VirtualBox files, directories, KEXTs or packages to uninstall."
|
||||
echo "Done."
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
#
|
||||
# Look for running VirtualBox processes and warn the user
|
||||
# if something is running. Since deleting the files of
|
||||
# running processes isn't fatal as such, we will leave it
|
||||
# to the user to choose whether to continue or not.
|
||||
#
|
||||
# Note! comm isn't supported on Tiger, so we make -c to do the stripping.
|
||||
#
|
||||
my_processes="`ps -axco 'pid uid command' | grep -wEe '(VirtualBox|VirtualBoxVM|VBoxManage|VBoxHeadless|vboxwebsrv|VBoxXPCOMIPCD|VBoxSVC|VBoxNetDHCP|VBoxNetNAT)' | grep -vw grep | grep -vw VirtualBox_Uninstall.tool | tr '\n' '\a'`";
|
||||
if test -n "$my_processes"; then
|
||||
echo 'Warning! Found the following active VirtualBox processes:'
|
||||
echo "$my_processes" | tr '\a' '\n'
|
||||
echo ""
|
||||
echo "We recommend that you quit all VirtualBox processes before"
|
||||
echo "uninstalling the product."
|
||||
echo ""
|
||||
if test "$my_default_prompt" != "Yes"; then
|
||||
echo "Do you wish to continue none the less (Yes/No)?"
|
||||
read my_answer
|
||||
if test "$my_answer" != "Yes" -a "$my_answer" != "YES" -a "$my_answer" != "yes"; then
|
||||
echo "Aborting uninstall. (answer: '$my_answer')".
|
||||
exit 2;
|
||||
fi
|
||||
echo ""
|
||||
my_answer=""
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# Display the files and directories that will be removed
|
||||
# and get the user's consent before continuing.
|
||||
#
|
||||
if test -n "${my_files[*]}" -o -n "${my_directories[*]}"; then
|
||||
echo "The following files and directories (bundles) will be removed:"
|
||||
for file in "${my_files[@]}"; do echo " $file"; done
|
||||
for dir in "${my_directories[@]}"; do echo " $dir"; done
|
||||
echo ""
|
||||
fi
|
||||
if test -n "${my_kexts[*]}"; then
|
||||
echo "And the following KEXTs will be unloaded:"
|
||||
for kext in "${my_kexts[@]}"; do echo " $kext"; done
|
||||
echo ""
|
||||
fi
|
||||
if test -n "$my_pkgs"; then
|
||||
echo "And the traces of following packages will be removed:"
|
||||
for kext in $my_pkgs; do echo " $kext"; done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if test "$my_default_prompt" != "Yes"; then
|
||||
echo "Do you wish to uninstall VirtualBox (Yes/No)?"
|
||||
read my_answer
|
||||
if test "$my_answer" != "Yes" -a "$my_answer" != "YES" -a "$my_answer" != "yes"; then
|
||||
echo "Aborting uninstall. (answer: '$my_answer')".
|
||||
exit 2;
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#
|
||||
# Unregister has to be done before the files are removed.
|
||||
#
|
||||
LSREGISTER=/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister
|
||||
if [ -e ${LSREGISTER} ]; then
|
||||
${LSREGISTER} -u /Applications/VirtualBox.app > /dev/null
|
||||
${LSREGISTER} -u /Applications/VirtualBox.app/Contents/Resources/vmstarter.app > /dev/null
|
||||
fi
|
||||
|
||||
#
|
||||
# Display the sudo usage instructions and execute the command.
|
||||
#
|
||||
echo "The uninstallation processes requires administrative privileges"
|
||||
echo "because some of the installed files cannot be removed by a normal"
|
||||
echo "user. You may be prompted for your password now..."
|
||||
echo ""
|
||||
|
||||
if test -n "${my_files[*]}" -o -n "${my_directories[*]}"; then
|
||||
/usr/bin/sudo -p "Please enter %u's password:" /bin/rm -Rf "${my_files[@]}" "${my_directories[@]}"
|
||||
my_rc=$?
|
||||
if test "$my_rc" -ne 0; then
|
||||
echo "An error occurred durning 'sudo rm', there should be a message above. (rc=$my_rc)"
|
||||
test -x /usr/bin/sudo || echo "warning: Cannot find /usr/bin/sudo or it's not an executable."
|
||||
test -x /bin/rm || echo "warning: Cannot find /bin/rm or it's not an executable"
|
||||
echo ""
|
||||
echo "The uninstall failed. Please retry."
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
|
||||
my_rc=0
|
||||
for kext in "${my_kexts[@]}"; do
|
||||
echo unloading $kext
|
||||
/usr/bin/sudo -p "Please enter %u's password (unloading $kext):" /sbin/kextunload -m $kext
|
||||
my_rc2=$?
|
||||
if test "$my_rc2" -ne 0; then
|
||||
echo "An error occurred durning 'sudo /sbin/kextunload -m $kext', there should be a message above. (rc=$my_rc2)"
|
||||
test -x /usr/bin/sudo || echo "warning: Cannot find /usr/bin/sudo or it's not an executable."
|
||||
test -x /sbin/kextunload || echo "warning: Cannot find /sbin/kextunload or it's not an executable"
|
||||
my_rc=$my_rc2
|
||||
fi
|
||||
done
|
||||
if test "$my_rc" -eq 0; then
|
||||
echo "Successfully unloaded VirtualBox kernel extensions."
|
||||
else
|
||||
echo "Failed to unload one or more KEXTs, please reboot the machine to complete the uninstall."
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# Cleaning up pkgutil database
|
||||
for my_pkg in $my_pkgs; do
|
||||
/usr/bin/sudo -p "Please enter %u's password (removing $my_pkg):" /usr/sbin/pkgutil --forget "$my_pkg"
|
||||
done
|
||||
|
||||
echo "Done."
|
||||
exit 0;
|
Загрузка…
Ссылка в новой задаче