win: Make auto-updater really work
Apparently that PR was never tested.
This commit is contained in:
		
					parent
					
						
							
								aeafc46ded
							
						
					
				
			
			
				commit
				
					
						fae2c7bc7a
					
				
			
		
					 2 changed files with 71 additions and 64 deletions
				
			
		|  | @ -1,45 +1,42 @@ | ||||||
|  | app = require 'app' | ||||||
|  | url = require 'url' | ||||||
| {EventEmitter} = require 'events' | {EventEmitter} = require 'events' | ||||||
| SquirrelUpdate = require './auto-updater/squirrel-update-win' | 
 | ||||||
| app            = require 'app' | squirrelUpdate = require './squirrel-update-win' | ||||||
| url            = require 'url' |  | ||||||
| 
 | 
 | ||||||
| class AutoUpdater extends EventEmitter | class AutoUpdater extends EventEmitter | ||||||
| 
 |  | ||||||
|   quitAndInstall: -> |   quitAndInstall: -> | ||||||
|     SquirrelUpdate.processStart -> |     squirrelUpdate.processStart() | ||||||
|       app.quit() |     app.quit() | ||||||
| 
 | 
 | ||||||
|   setFeedUrl: (updateUrl) -> |   setFeedUrl: (updateUrl) -> | ||||||
|     # set feed URL only when it hasn't been set before |     @updateUrl = updateUrl | ||||||
|     unless @updateUrl |  | ||||||
|       @updateUrl = updateUrl |  | ||||||
| 
 | 
 | ||||||
|   checkForUpdates: -> |   checkForUpdates: -> | ||||||
|     throw new Error('Update URL is not set') unless @updateUrl |     return @emitError 'Update URL is not set' unless @updateUrl | ||||||
|  |     return @emitError 'Can not find Squirrel' unless squirrelUpdate.supported() | ||||||
| 
 | 
 | ||||||
|     @emit 'checking-for-update' |     @emit 'checking-for-update' | ||||||
| 
 | 
 | ||||||
|     unless SquirrelUpdate.supported() |     squirrelUpdate.download @updateUrl, (error, update) => | ||||||
|       @emit 'update-not-available' |       return @emitError error if error? | ||||||
|       return |       return @emit 'update-not-available' unless update? | ||||||
| 
 |  | ||||||
|     SquirrelUpdate.download (error, update) => |  | ||||||
|       if error? |  | ||||||
|         @emit 'update-not-available' |  | ||||||
|         return |  | ||||||
| 
 |  | ||||||
|       unless update? |  | ||||||
|         @emit 'update-not-available' |  | ||||||
|         return |  | ||||||
| 
 | 
 | ||||||
|       @emit 'update-available' |       @emit 'update-available' | ||||||
| 
 | 
 | ||||||
|       SquirrelUpdate.update @updateUrl, (error) => |       squirrelUpdate.update @updateUrl, (error) => | ||||||
|         if error? |         return @emitError error if error? | ||||||
|           @emit 'update-not-available' |  | ||||||
|           return |  | ||||||
| 
 | 
 | ||||||
|         # info about the newly installed version and a function any of the event listeners can call to restart the application |         {releaseNotes, version} = update | ||||||
|         @emit 'update-downloaded', {}, update.releaseNotes, update.version, new Date(), @updateUrl, => @quitAndInstall() |         # Following information is not available on Windows, so fake them. | ||||||
|  |         date = new Date | ||||||
|  |         url = @updateUrl | ||||||
| 
 | 
 | ||||||
| module.exports = new AutoUpdater() |         @emit 'update-downloaded', {}, releaseNotes, version, date, url, => @quitAndInstall() | ||||||
|  | 
 | ||||||
|  |   # Private: Emit both error object and message, this is to keep compatibility | ||||||
|  |   # with Old APIs. | ||||||
|  |   emitError: (message) -> | ||||||
|  |     @emit 'error', new Error(message), message | ||||||
|  | 
 | ||||||
|  | module.exports = new AutoUpdater | ||||||
|  |  | ||||||
|  | @ -1,57 +1,67 @@ | ||||||
| ChildProcess = require 'child_process' | fs      = require 'fs' | ||||||
| fs           = require 'fs' | path    = require 'path' | ||||||
| path         = require 'path' | {spawn} = require 'child_process' | ||||||
| 
 | 
 | ||||||
| appFolder             = path.dirname process.execPath # i.e. my-app/app-0.1.13/ | appFolder = path.dirname process.execPath # i.e. my-app/app-0.1.13/ | ||||||
| rootApplicationFolder = path.resolve appFolder, '..'  # i.e. my-app/ | updateExe = path.resolve appFolder, '..', 'Update.exe' # i.e. my-app/Update.exe | ||||||
| updateDotExe          = path.join rootApplicationFolder, 'Update.exe' | exeName   = path.basename process.execPath | ||||||
| exeName               = path.basename process.execPath |  | ||||||
| 
 | 
 | ||||||
| # Spawn a command and invoke the callback when it completes with an error | # Spawn a command and invoke the callback when it completes with an error | ||||||
| # and the output from standard out. | # and the output from standard out. | ||||||
| spawnUpdate = (args, callback) -> | spawnUpdate = (args, detached, callback) -> | ||||||
|   stdout = '' |  | ||||||
| 
 |  | ||||||
|   try |   try | ||||||
|     spawnedProcess = ChildProcess.spawn(updateDotExe, args) |     spawnedProcess = spawn updateExe, args, {detached} | ||||||
|   catch error |   catch error | ||||||
|     # Spawn can throw an error |     # Shouldn't happen, but still guard it. | ||||||
|     process.nextTick -> callback?(error, stdout) |     process.nextTick -> callback error | ||||||
|     return |     return | ||||||
| 
 | 
 | ||||||
|  |   stdout = '' | ||||||
|  |   stderr = '' | ||||||
|   spawnedProcess.stdout.on 'data', (data) -> stdout += data |   spawnedProcess.stdout.on 'data', (data) -> stdout += data | ||||||
|  |   spawnedProcess.stderr.on 'data', (data) -> stderr += data | ||||||
| 
 | 
 | ||||||
|   error = null |   errorEmitted = false | ||||||
|   spawnedProcess.on 'error', (processError) -> error ?= processError |   spawnedProcess.on 'error', (error) -> | ||||||
|   spawnedProcess.on 'close', (code, signal) -> |     errorEmitted = true | ||||||
|     error ?= new Error("Command failed: #{signal ? code}") if code isnt 0 |     callback error | ||||||
|     error?.code ?= code |   spawnedProcess.on 'exit', (code, signal) -> | ||||||
|     error?.stdout ?= stdout |     # We may have already emitted an error. | ||||||
|     callback?(error, stdout) |     return if errorEmitted | ||||||
| 
 | 
 | ||||||
| processStart = (callback) -> |     # Process terminated with error. | ||||||
|   spawnUpdate(['--processStart', exeName], callback) |     if code isnt 0 | ||||||
|  |       return callback "Command failed: #{signal ? code}\n#{stderr}" | ||||||
| 
 | 
 | ||||||
| download = (callback) -> |     # Success. | ||||||
|   spawnUpdate ['--download', @updateUrl], (error, stdout) -> |     callback null, stdout | ||||||
|  | 
 | ||||||
|  | # Start an instance of the installed app. | ||||||
|  | exports.processStart = (callback) -> | ||||||
|  |   spawnUpdate ['--processStart', exeName], true, -> | ||||||
|  | 
 | ||||||
|  | # Download the releases specified by the URL and write new results to stdout. | ||||||
|  | exports.download = (updateUrl, callback) -> | ||||||
|  |   spawnUpdate ['--download', updateUrl], false, (error, stdout) -> | ||||||
|     return callback(error) if error? |     return callback(error) if error? | ||||||
| 
 | 
 | ||||||
|     try |     try | ||||||
|       # Last line of output is the JSON details about the releases |       # Last line of output is the JSON details about the releases | ||||||
|       json   = stdout.trim().split('\n').pop() |       json = stdout.trim().split('\n').pop() | ||||||
|       update = JSON.parse(json)?.releasesToApply?.pop?() |       update = JSON.parse(json)?.releasesToApply?.pop?() | ||||||
|     catch error |     catch | ||||||
|       error.stdout = stdout |       return callback "Invalid result:\n#{stdout}" | ||||||
|       return callback(error) |  | ||||||
| 
 | 
 | ||||||
|     callback(null, update) |     callback null, update | ||||||
| 
 | 
 | ||||||
| update = (updateUrl, callback) -> | # Update the application to the latest remote version specified by URL. | ||||||
|   spawnUpdate ['--update', updateUrl], callback | exports.update = (updateUrl, callback) -> | ||||||
|  |   spawnUpdate ['--update', updateUrl], false, callback | ||||||
| 
 | 
 | ||||||
| # Is the Update.exe installed with the current application? | # Is the Update.exe installed with the current application? | ||||||
| exports.supported = -> | exports.supported = -> | ||||||
|   fs.accessSync(updateDotExe, fs.R_OK) |   try | ||||||
| exports.processStart = processStart |     fs.accessSync updateExe, fs.R_OK | ||||||
| exports.download     = download |     return true | ||||||
| exports.update       = update |   catch | ||||||
|  |     return false | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Cheng Zhao
				Cheng Zhao