electron-updater
Advanced tools
Comparing version 0.0.4 to 0.0.5
136
index.js
@@ -6,12 +6,27 @@ var commands = require('./lib/commands.js'), | ||
ipc = require('ipc'), | ||
AppDirectory = require('appdirectory') | ||
minimist = require('minimist'), | ||
launch = require('./lib/launch.js'), | ||
directory = require('./lib/directory.js'), | ||
file = require('./lib/file.js') | ||
var i = process.argv.indexOf('--electron-update') | ||
if (i > 0) { | ||
var app = require('app'), | ||
BrowserWindow = require('browser-window') | ||
function _launch(args) { | ||
console.log('relaunching app.') | ||
var child = spawn(args.exe, args.argv, { | ||
detached: true, | ||
cwd: args.cwd, | ||
stdio: [ 'ignore', 'pipe', 'pipe'] // out, err] | ||
}); | ||
child.unref(); | ||
} | ||
var args = JSON.parse(process.argv[i + 1]) | ||
var argv = minimist(process.argv.slice(2)) | ||
if (argv['electron-update']) { | ||
var relaunch = typeof argv.relaunch === 'boolean' ? argv.relaunch : true | ||
var encodedArgs = argv['electron-update'] | ||
var decodedArgs = new Buffer(encodedArgs, 'base64').toString('ascii') | ||
var args = JSON.parse(decodedArgs) | ||
// { | ||
// name: appName, | ||
// exe: process.execPath, | ||
// cwd: process.cwd(), | ||
@@ -21,5 +36,24 @@ // argv: process.argv | ||
app.on('ready', function () { | ||
var appDir = directory.appDir(args.appName) | ||
var pendingUpdatePath = path.join(appDir, '.update') | ||
var _updateLog = path.join(appDir, 'update.log') | ||
var _log = console.log | ||
console.log = function (line) { | ||
_log(line) | ||
fs.appendFile(_updateLog, '- ' + line + '\n') | ||
} | ||
var win = new BrowserWindow({ | ||
console.log('updating...') | ||
console.log('args: ' + util.inspect(argv)) | ||
console.log('relaunch: ' + relaunch) | ||
// Flag an update as pending | ||
file.touch(pendingUpdatePath, 'INPROGRESS', function (err) { | ||
if(err) return console.log(err) | ||
// Attempt to actually udpate now. | ||
var app = require('app') | ||
var BrowserWindow = require('browser-window') | ||
var win = new BrowserWindow({ | ||
width: 400, | ||
@@ -29,30 +63,66 @@ height: 100, | ||
}) | ||
win.loadUrl('file://' + __dirname + '/update.html') | ||
ipc.on('initialize', function (event, arg) { | ||
event.sender.send('initialize', args) | ||
}) | ||
win.loadUrl('file://' + __dirname + '/update.html') | ||
ipc.on('initialize', function (event, arg) { | ||
event.sender.send('initialize', args) | ||
}) | ||
var _log = console.log | ||
console.log = function (line) { | ||
_log(line) | ||
fs.appendFile('update.log', line + '\n') | ||
} | ||
commands.update(process.cwd(), function (err) { | ||
if(err) return console.log(err) | ||
var dirs = new AppDirectory(args.appName) | ||
var appDir = path.dirname(dirs.userData()) | ||
var updateFile = path.join(appDir, '.update') | ||
fs.unlink(updateFile, function () { | ||
var execPath = args.argv.shift() | ||
var child = spawn(execPath, args.argv, { | ||
detached: true, | ||
cwd: args.cwd, | ||
stdio: [ 'ignore', 'pipe', 'pipe'] // out, err] | ||
}); | ||
child.unref(); | ||
if(err) { | ||
// If the update fails for security reasons, then we have to attempt to relaunch this process | ||
// with the right permissions. | ||
if(err.code === 'EPERM') { | ||
console.log('No permission to update, elevating...') | ||
console.log('restarting app!') | ||
app.quit() | ||
}) | ||
var elevatedArgs = process.argv.slice(1) | ||
// Tell the elevated process not to relaunch, we will relaunch from this process when its done. | ||
elevatedArgs.push('--no-relaunch') | ||
// relaunch self as an elevated process | ||
launch.elevate(args.appName, process.execPath, elevatedArgs, process.cwd(), function (err) { | ||
if(err) return console.log(err) | ||
// Watch for changes to the .update file, it will become empty when the update succeeds. | ||
fs.watchFile(pendingUpdatePath, {persistent: true, interval:500}, function () { | ||
fs.readFile(pendingUpdatePath, {encoding:'utf8'}, function (err, contents) { | ||
if(err) return console.log(err) | ||
if(contents === '') { | ||
// When update is done the file will be changed to have empty content | ||
fs.unwatchFile(pendingUpdatePath) | ||
if (relaunch) { | ||
console.log('relaunching from unelevated process.') | ||
_launch(args) | ||
} | ||
app.quit() | ||
} else if(contents === 'PENDING') { | ||
// Going back to a PENDING state means that the elevated process | ||
// failed to update for an unexpected reason. In that case | ||
// just shutdown and wait for the next attempt. | ||
fs.unwatchFile(pendingUpdatePath) | ||
app.quit() | ||
} | ||
}) | ||
}) | ||
}) | ||
} else { | ||
console.log('update failed for an unexected reason.') | ||
console.log(err) | ||
file.touch(pendingUpdatePath, 'PENDING', function () { | ||
app.quit() | ||
}) | ||
} | ||
} else { | ||
// Update was successful! | ||
console.log('updated succeeded!') | ||
file.touch(pendingUpdatePath, '', function (err) { | ||
if(err) console.log(err) | ||
// If the app was already running as admin, this flag will be missing. Go ahead and re-launch the app. | ||
if(relaunch) { | ||
console.log('relaunching app.') | ||
_launch(args) | ||
} | ||
app.quit() | ||
}) | ||
} | ||
}) | ||
@@ -59,0 +129,0 @@ }) |
@@ -113,11 +113,13 @@ var util = require('util'), | ||
cwd: process.cwd(), | ||
exe: process.execPath, | ||
argv: process.argv | ||
}) | ||
var child = spawn(tmpExecPath, [updateDir, '--electron-update', args], { | ||
detached: true, | ||
cwd: appDir, | ||
stdio: [ 'ignore', 'pipe', 'pipe'] // out, err] | ||
}) | ||
child.unref() | ||
callback() | ||
var encodedArgs = new Buffer(args).toString('base64') | ||
var child = spawn(tmpExecPath, [updateDir, '--electron-update=' + encodedArgs], { | ||
detached: true, | ||
cwd: appDir, | ||
stdio: ['ignore', 'ignore', 'ignore'] | ||
}) | ||
child.unref() | ||
callback() | ||
}) | ||
@@ -132,6 +134,8 @@ } | ||
} | ||
if(!callback) callback = function (err) { if(err) console.log(err) } | ||
appDir = appDir || path.dirname(process.mainModule.filename) | ||
context.load(appDir, function (err, ctx) { | ||
if(err) return callback(err) | ||
if(ctx.pendingUpdate) { | ||
if(ctx.updatePending) { | ||
// If there is a pending update, do a full update instead of starting the app. | ||
@@ -144,2 +148,8 @@ // This is set when a dependency update is available. | ||
}) | ||
} else if(ctx.updateInProgress) { | ||
// This can happen if the user tries to re-launch the app while an update is | ||
// currently in progress. In that case just report updateRequired so that | ||
// the user closes the app right away. | ||
that.emit('updateRequired') | ||
callback() | ||
} else { | ||
@@ -163,3 +173,3 @@ isValid(appDir, function (err, valid) { | ||
var pendingUpdatePath = path.join(appData, '.update') | ||
file.touch(pendingUpdatePath, function (err) { | ||
file.touch(pendingUpdatePath, 'PENDING', function (err) { | ||
if(err) return callback(err) | ||
@@ -166,0 +176,0 @@ that.emit('updateAvailable') |
@@ -54,4 +54,5 @@ var directory = require('./directory.js'), | ||
channel = channel || 'latest' | ||
fs.stat(pendingUpdatePath, function (err, stat) { | ||
var pendingUpdate = !err && stat.isFile() | ||
fs.readFile(pendingUpdatePath, {encoding: 'utf8'}, function (err, updateContents) { | ||
var updatePending = !err && updateContents === 'PENDING' | ||
var updateInProgress = !err && updateContents === 'INPROGRESS' | ||
callback(null, { | ||
@@ -62,3 +63,4 @@ name: name, | ||
dev: dev, | ||
pendingUpdate: pendingUpdate, | ||
updatePending: updatePending, | ||
updateInProgress: updateInProgress, | ||
registry: registry, | ||
@@ -65,0 +67,0 @@ appDir: appDir, |
@@ -6,2 +6,3 @@ var directory = require('./directory.js'), | ||
util = require('util'), | ||
async = require('async'), | ||
AppDirectory = require('appdirectory') | ||
@@ -8,0 +9,0 @@ |
var fs = require('fs') | ||
path = require('path') | ||
async = require('async') | ||
os = require('os') | ||
var fs = require('fs'), | ||
path = require('path'), | ||
async = require('async'), | ||
os = require('os'), | ||
AppDirectory = require('appdirectory') | ||
function remove(directory, callback) { | ||
@@ -41,5 +44,11 @@ fs.lstat(directory, function (err, stat) { | ||
function appDir(appName) { | ||
var dirs = new AppDirectory(appName) | ||
return path.dirname(dirs.userData()) | ||
} | ||
module.exports = { | ||
create: create, | ||
remove: remove | ||
remove: remove, | ||
appDir: appDir | ||
} |
@@ -26,10 +26,12 @@ var fs = process.versions.electron ? require('original-fs') : require('fs'), | ||
function touch(name, callback) { | ||
function touch(name, contents, callback) { | ||
if(typeof contents === 'function') { | ||
callback = contents | ||
contents = undefined | ||
} | ||
var dir = path.dirname(name) | ||
directory.create(dir, function (err) { | ||
if(err) return callback(err) | ||
fs.open(name, 'a', function (err, fd) { | ||
if(err) return callback(err) | ||
fs.close(fd, callback) | ||
}) | ||
fs.writeFile(name, contents || '', {encoding:'utf8'}, callback) | ||
}) | ||
@@ -36,0 +38,0 @@ } |
{ | ||
"name": "electron-updater", | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"description": "Cross platform auto-updater for electron applications", | ||
@@ -31,3 +31,3 @@ "main": "index.js", | ||
"async": "^0.9.0", | ||
"npm": "2.7.0", | ||
"minimist": "^1.1.1", | ||
"semver": "^4.3.3", | ||
@@ -46,2 +46,2 @@ "spin": "0.0.1", | ||
} | ||
} | ||
} |
@@ -11,7 +11,14 @@ # electron-updater | ||
$ npm install electron-plugins --save | ||
### Related | ||
See the [`electron-builder`](https://www.npmjs.com/package/electron-builder) project for creating installers for | ||
various platforms. | ||
See the [`sinopia`](https://www.npmjs.com/package/sinopia) project for hosting your own npm packages. | ||
## Features | ||
* Cross platform (win32, darwin, linux) | ||
* Update notifications | ||
* Update electron binaries in place | ||
* Update application | ||
* Update your application and dependencies in place | ||
* Download prebuilt binaries per-platform | ||
@@ -18,0 +25,0 @@ * Side-by-Side update of plugins |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
44635
21
1022
109
6
+ Addedminimist@^1.1.1
+ Addedminimist@1.2.8(transitive)
- Removednpm@2.7.0
- Removednpm@2.7.0(transitive)