diff --git a/Gruntfile.js b/Gruntfile.js index 614c11ba..605b6a33 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -251,7 +251,8 @@ module.exports = function (grunt) { desktop: ['desktop/**/*.js', '!desktop/node_modules/**'], build: ['Gruntfile.js', 'grunt.*.js', 'build/**/*.js', 'webpack.config.js'], plugins: ['plugins/**/*.js'], - util: ['util/**/*.js'] + util: ['util/**/*.js'], + installer: ['package/osx/installer.js'] }, inline: { app: { diff --git a/desktop/main.js b/desktop/main.js index d7a5498b..297109bd 100644 --- a/desktop/main.js +++ b/desktop/main.js @@ -116,7 +116,7 @@ main.on('ready', () => { }) .catch((e) => { electron.dialog.showErrorBox('KeeWeb', 'Error loading app: ' + e); - process.exit(2); + main.exit(2); }); }); main.on('open-file', (e, path) => { @@ -949,7 +949,8 @@ function httpRequest(config, log, onLoad) { function exitAndStartUpdate() { if (pendingUpdateFilePath) { - // TODO: install the update + const { installUpdate } = require('./updater'); + installUpdate(pendingUpdateFilePath); main.exit(0); } } diff --git a/desktop/updater.js b/desktop/updater.js new file mode 100644 index 00000000..c894ecc5 --- /dev/null +++ b/desktop/updater.js @@ -0,0 +1,40 @@ +const path = require('path'); +const fs = require('fs'); +const { spawn, spawnSync } = require('child_process'); +const electron = require('electron'); + +function installUpdate(updateFilePath) { + switch (process.platform) { + case 'darwin': + installDarwinUpdate(updateFilePath); + } +} + +function installDarwinUpdate(updateFilePath) { + const appPath = process.execPath.replace(/\.app\/.*?$/, '.app'); + const installerAppPath = path.join(appPath, 'Contents', 'Installer', 'KeeWeb Installer.app'); + const tempPath = path.join(electron.app.getPath('temp'), 'KeeWeb'); + const tempInstallerPath = path.join(tempPath, 'KeeWeb Installer.app'); + + if (!fs.existsSync(tempPath)) { + fs.mkdirSync(tempPath, { recursive: true }); + } + + spawnSync('rm', ['-rf', tempInstallerPath]); + const res = spawnSync('cp', ['-pRf', installerAppPath, tempInstallerPath]); + if (res.status) { + const copyErr = res.stderr.toString('utf8'); + throw new Error(`Error installing update: ${copyErr}`); + } + + const installerExecutable = path.join(tempInstallerPath, 'Contents', 'MacOS', 'applet'); + spawn( + installerExecutable, + ['--update', `--wait-pid=${process.pid}`, `--dmg=${updateFilePath}`, `--app=${appPath}`], + { + detached: true + } + ).unref(); +} + +module.exports.installUpdate = installUpdate; diff --git a/package/osx/installer.js b/package/osx/installer.js index 1fe22546..42229ff4 100755 --- a/package/osx/installer.js +++ b/package/osx/installer.js @@ -14,7 +14,7 @@ if (args.update) { } const dmg = checkFilePath(args.dmg, 'dmg'); - const target = checkFilePath(args.target, 'app'); + const target = checkFilePath(args.app, 'app'); const targetOwner = app.doShellScript(`stat -f '%Su' ${target}`); const setAdminRights = targetOwner === 'root'; @@ -37,6 +37,7 @@ rm -rf ${tmpDir} scriptOptions.administratorPrivileges = true; } app.doShellScript(script, scriptOptions); + Application(args.app).activate(); } else if (args.install) { app.doShellScript('chown -R 0 /Applications/KeeWeb.app', { administratorPrivileges: true }); } else {