refactor: AutoUpdater for Windows using async/await (#40289)
This commit is contained in:
parent
1ba535296e
commit
0f68d845f9
2 changed files with 48 additions and 73 deletions
|
@ -34,7 +34,7 @@ class AutoUpdater extends EventEmitter implements Electron.AutoUpdater {
|
|||
this.updateURL = updateURL;
|
||||
}
|
||||
|
||||
checkForUpdates () {
|
||||
async checkForUpdates () {
|
||||
const url = this.updateURL;
|
||||
if (!url) {
|
||||
return this.emitError(new Error('Update URL is not set'));
|
||||
|
@ -43,27 +43,24 @@ class AutoUpdater extends EventEmitter implements Electron.AutoUpdater {
|
|||
return this.emitError(new Error('Can not find Squirrel'));
|
||||
}
|
||||
this.emit('checking-for-update');
|
||||
squirrelUpdate.checkForUpdate(url, (error, update) => {
|
||||
if (error != null) {
|
||||
return this.emitError(error);
|
||||
}
|
||||
try {
|
||||
const update = await squirrelUpdate.checkForUpdate(url);
|
||||
if (update == null) {
|
||||
return this.emit('update-not-available');
|
||||
}
|
||||
this.updateAvailable = true;
|
||||
this.emit('update-available');
|
||||
squirrelUpdate.update(url, (error) => {
|
||||
if (error != null) {
|
||||
return this.emitError(error);
|
||||
}
|
||||
|
||||
await squirrelUpdate.update(url);
|
||||
const { releaseNotes, version } = update;
|
||||
// Date is not available on Windows, so fake it.
|
||||
const date = new Date();
|
||||
this.emit('update-downloaded', {}, releaseNotes, version, date, this.updateURL, () => {
|
||||
this.quitAndInstall();
|
||||
});
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
this.emitError(error as Error);
|
||||
}
|
||||
}
|
||||
|
||||
// Private: Emit both error object and message, this is to keep compatibility
|
||||
|
|
|
@ -15,89 +15,67 @@ const isSameArgs = (args: string[]) => args.length === spawnedArgs.length && arg
|
|||
|
||||
// Spawn a command and invoke the callback when it completes with an error
|
||||
// and the output from standard out.
|
||||
const spawnUpdate = function (args: string[], detached: boolean, callback: Function) {
|
||||
let error: Error, errorEmitted: boolean, stderr: string, stdout: string;
|
||||
|
||||
try {
|
||||
const spawnUpdate = async function (args: string[], options: { detached: boolean }): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Ensure we don't spawn multiple squirrel processes
|
||||
// Process spawned, same args: Attach events to already running process
|
||||
// Process spawned, different args: Return with error
|
||||
// No process spawned: Spawn new process
|
||||
if (spawnedProcess && !isSameArgs(args)) {
|
||||
return callback(`AutoUpdater process with arguments ${args} is already running`);
|
||||
throw new Error(`AutoUpdater process with arguments ${args} is already running`);
|
||||
} else if (!spawnedProcess) {
|
||||
spawnedProcess = spawn(updateExe, args, {
|
||||
detached: detached,
|
||||
detached: options.detached,
|
||||
windowsHide: true
|
||||
});
|
||||
spawnedArgs = args || [];
|
||||
}
|
||||
} catch (error1) {
|
||||
error = error1 as Error;
|
||||
|
||||
// Shouldn't happen, but still guard it.
|
||||
process.nextTick(function () {
|
||||
return callback(error);
|
||||
});
|
||||
return;
|
||||
}
|
||||
stdout = '';
|
||||
stderr = '';
|
||||
let stdout = '';
|
||||
let stderr = '';
|
||||
|
||||
spawnedProcess.stdout.on('data', (data) => { stdout += data; });
|
||||
spawnedProcess.stderr.on('data', (data) => { stderr += data; });
|
||||
|
||||
errorEmitted = false;
|
||||
spawnedProcess.on('error', (error) => {
|
||||
errorEmitted = true;
|
||||
callback(error);
|
||||
reject(error);
|
||||
});
|
||||
|
||||
return spawnedProcess.on('exit', function (code, signal) {
|
||||
spawnedProcess.on('exit', function (code, signal) {
|
||||
spawnedProcess = undefined;
|
||||
spawnedArgs = [];
|
||||
|
||||
// We may have already emitted an error.
|
||||
if (errorEmitted) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Process terminated with error.
|
||||
if (code !== 0) {
|
||||
return callback(`Command failed: ${signal ?? code}\n${stderr}`);
|
||||
}
|
||||
|
||||
// Process terminated with error.
|
||||
reject(new Error(`Command failed: ${signal ?? code}\n${stderr}`));
|
||||
} else {
|
||||
// Success.
|
||||
callback(null, stdout);
|
||||
resolve(stdout);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Start an instance of the installed app.
|
||||
export function processStart () {
|
||||
return spawnUpdate(['--processStartAndWait', exeName], true, function () {});
|
||||
spawnUpdate(['--processStartAndWait', exeName], { detached: true });
|
||||
}
|
||||
|
||||
// Download the releases specified by the URL and write new results to stdout.
|
||||
export function checkForUpdate (updateURL: string, callback: (error: Error | null, update?: any) => void) {
|
||||
return spawnUpdate(['--checkForUpdate', updateURL], false, function (error: Error, stdout: string) {
|
||||
let ref, ref1, update;
|
||||
if (error != null) {
|
||||
return callback(error);
|
||||
}
|
||||
export async function checkForUpdate (updateURL: string): Promise<any> {
|
||||
const stdout = await spawnUpdate(['--checkForUpdate', updateURL], { detached: false });
|
||||
try {
|
||||
// Last line of output is the JSON details about the releases
|
||||
const json = stdout.trim().split('\n').pop();
|
||||
update = (ref = JSON.parse(json!)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === 'function' ? ref1.pop() : undefined : undefined : undefined;
|
||||
return JSON.parse(json!)?.releasesToApply?.pop?.();
|
||||
} catch {
|
||||
return callback(new Error(`Invalid result:\n${stdout}`));
|
||||
throw new Error(`Invalid result:\n${stdout}`);
|
||||
}
|
||||
return callback(null, update);
|
||||
});
|
||||
}
|
||||
|
||||
// Update the application to the latest remote version specified by URL.
|
||||
export function update (updateURL: string, callback: (error: Error) => void) {
|
||||
return spawnUpdate(['--update', updateURL], false, callback);
|
||||
export async function update (updateURL: string): Promise<void> {
|
||||
await spawnUpdate(['--update', updateURL], { detached: false });
|
||||
}
|
||||
|
||||
// Is the Update.exe installed with the current application?
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue