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;
|
this.updateURL = updateURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkForUpdates () {
|
async checkForUpdates () {
|
||||||
const url = this.updateURL;
|
const url = this.updateURL;
|
||||||
if (!url) {
|
if (!url) {
|
||||||
return this.emitError(new Error('Update URL is not set'));
|
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'));
|
return this.emitError(new Error('Can not find Squirrel'));
|
||||||
}
|
}
|
||||||
this.emit('checking-for-update');
|
this.emit('checking-for-update');
|
||||||
squirrelUpdate.checkForUpdate(url, (error, update) => {
|
try {
|
||||||
if (error != null) {
|
const update = await squirrelUpdate.checkForUpdate(url);
|
||||||
return this.emitError(error);
|
|
||||||
}
|
|
||||||
if (update == null) {
|
if (update == null) {
|
||||||
return this.emit('update-not-available');
|
return this.emit('update-not-available');
|
||||||
}
|
}
|
||||||
this.updateAvailable = true;
|
this.updateAvailable = true;
|
||||||
this.emit('update-available');
|
this.emit('update-available');
|
||||||
squirrelUpdate.update(url, (error) => {
|
|
||||||
if (error != null) {
|
await squirrelUpdate.update(url);
|
||||||
return this.emitError(error);
|
const { releaseNotes, version } = update;
|
||||||
}
|
// Date is not available on Windows, so fake it.
|
||||||
const { releaseNotes, version } = update;
|
const date = new Date();
|
||||||
// Date is not available on Windows, so fake it.
|
this.emit('update-downloaded', {}, releaseNotes, version, date, this.updateURL, () => {
|
||||||
const date = new Date();
|
this.quitAndInstall();
|
||||||
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
|
// 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
|
// 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.
|
||||||
const spawnUpdate = function (args: string[], detached: boolean, callback: Function) {
|
const spawnUpdate = async function (args: string[], options: { detached: boolean }): Promise<string> {
|
||||||
let error: Error, errorEmitted: boolean, stderr: string, stdout: string;
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
try {
|
|
||||||
// Ensure we don't spawn multiple squirrel processes
|
// Ensure we don't spawn multiple squirrel processes
|
||||||
// Process spawned, same args: Attach events to already running process
|
// Process spawned, same args: Attach events to already running process
|
||||||
// Process spawned, different args: Return with error
|
// Process spawned, different args: Return with error
|
||||||
// No process spawned: Spawn new process
|
// No process spawned: Spawn new process
|
||||||
if (spawnedProcess && !isSameArgs(args)) {
|
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) {
|
} else if (!spawnedProcess) {
|
||||||
spawnedProcess = spawn(updateExe, args, {
|
spawnedProcess = spawn(updateExe, args, {
|
||||||
detached: detached,
|
detached: options.detached,
|
||||||
windowsHide: true
|
windowsHide: true
|
||||||
});
|
});
|
||||||
spawnedArgs = args || [];
|
spawnedArgs = args || [];
|
||||||
}
|
}
|
||||||
} catch (error1) {
|
|
||||||
error = error1 as Error;
|
|
||||||
|
|
||||||
// Shouldn't happen, but still guard it.
|
let stdout = '';
|
||||||
process.nextTick(function () {
|
let stderr = '';
|
||||||
return callback(error);
|
|
||||||
|
spawnedProcess.stdout.on('data', (data) => { stdout += data; });
|
||||||
|
spawnedProcess.stderr.on('data', (data) => { stderr += data; });
|
||||||
|
|
||||||
|
spawnedProcess.on('error', (error) => {
|
||||||
|
reject(error);
|
||||||
});
|
});
|
||||||
return;
|
|
||||||
}
|
|
||||||
stdout = '';
|
|
||||||
stderr = '';
|
|
||||||
|
|
||||||
spawnedProcess.stdout.on('data', (data) => { stdout += data; });
|
spawnedProcess.on('exit', function (code, signal) {
|
||||||
spawnedProcess.stderr.on('data', (data) => { stderr += data; });
|
spawnedProcess = undefined;
|
||||||
|
spawnedArgs = [];
|
||||||
|
|
||||||
errorEmitted = false;
|
if (code !== 0) {
|
||||||
spawnedProcess.on('error', (error) => {
|
// Process terminated with error.
|
||||||
errorEmitted = true;
|
reject(new Error(`Command failed: ${signal ?? code}\n${stderr}`));
|
||||||
callback(error);
|
} else {
|
||||||
});
|
// Success.
|
||||||
|
resolve(stdout);
|
||||||
return 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}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Success.
|
|
||||||
callback(null, stdout);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Start an instance of the installed app.
|
// Start an instance of the installed app.
|
||||||
export function processStart () {
|
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.
|
// 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) {
|
export async function checkForUpdate (updateURL: string): Promise<any> {
|
||||||
return spawnUpdate(['--checkForUpdate', updateURL], false, function (error: Error, stdout: string) {
|
const stdout = await spawnUpdate(['--checkForUpdate', updateURL], { detached: false });
|
||||||
let ref, ref1, update;
|
try {
|
||||||
if (error != null) {
|
// Last line of output is the JSON details about the releases
|
||||||
return callback(error);
|
const json = stdout.trim().split('\n').pop();
|
||||||
}
|
return JSON.parse(json!)?.releasesToApply?.pop?.();
|
||||||
try {
|
} catch {
|
||||||
// Last line of output is the JSON details about the releases
|
throw new Error(`Invalid result:\n${stdout}`);
|
||||||
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;
|
|
||||||
} catch {
|
|
||||||
return callback(new Error(`Invalid result:\n${stdout}`));
|
|
||||||
}
|
|
||||||
return callback(null, update);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the application to the latest remote version specified by URL.
|
// Update the application to the latest remote version specified by URL.
|
||||||
export function update (updateURL: string, callback: (error: Error) => void) {
|
export async function update (updateURL: string): Promise<void> {
|
||||||
return spawnUpdate(['--update', updateURL], false, callback);
|
await spawnUpdate(['--update', updateURL], { detached: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is the Update.exe installed with the current application?
|
// Is the Update.exe installed with the current application?
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue