diff --git a/src/backend/launcher.ts b/src/backend/launcher.ts index 4c239226ba..93a1e10b83 100644 --- a/src/backend/launcher.ts +++ b/src/backend/launcher.ts @@ -65,6 +65,10 @@ import { readFileSync } from 'fs' import { LegendaryCommand } from './storeManagers/legendary/commands' import { commandToArgsArray } from './storeManagers/legendary/library' import { searchForExecutableOnPath } from './utils/os/path' +import { + createAbortController, + deleteAbortController +} from './utils/aborthandler/aborthandler' async function prepareLaunch( gameSettings: GameSettings, @@ -777,7 +781,6 @@ const commandsRunning = {} async function callRunner( commandParts: string[], runner: RunnerProps, - abortController: AbortController, options?: CallRunnerOptions ): Promise { const fullRunnerPath = join(runner.dir, runner.bin) @@ -826,6 +829,9 @@ async function callRunner( return currentPromise } + const abortId = options?.abortId || appName || Math.random().toString() + const abortController = createAbortController(abortId) + let promise = new Promise((res, rej) => { const child = spawn(bin, commandParts, { cwd: runner.dir, @@ -942,6 +948,7 @@ async function callRunner( .finally(() => { // remove from list when done delete commandsRunning[key] + deleteAbortController(abortId) }) // keep track of which commands are running diff --git a/src/backend/save_sync.ts b/src/backend/save_sync.ts index 115d18549f..4ce1398dee 100644 --- a/src/backend/save_sync.ts +++ b/src/backend/save_sync.ts @@ -18,10 +18,6 @@ import { writeFileSync } from 'graceful-fs' import { app } from 'electron' -import { - createAbortController, - deleteAbortController -} from './utils/aborthandler/aborthandler' import { legendaryConfigPath } from './constants' import { join } from 'path' import { gameManagerMap, libraryManagerMap } from 'backend/storeManagers' @@ -80,7 +76,6 @@ async function getDefaultLegendarySavePath(appName: string): Promise { } logInfo(['Computing default save path for', appName], LogPrefix.Legendary) - const abortControllerName = appName + '-savePath' await runLegendaryCommand( { subcommand: 'sync-saves', @@ -89,8 +84,8 @@ async function getDefaultLegendarySavePath(appName: string): Promise { '--skip-download': true, '--accept-path': true }, - createAbortController(abortControllerName), { + abortId: appName + '-savePath', logMessagePrefix: 'Getting default save path', env: gameManagerMap['legendary'].isNative(appName) ? {} @@ -99,7 +94,6 @@ async function getDefaultLegendarySavePath(appName: string): Promise { ) } ) - deleteAbortController(abortControllerName) // If the save path was computed successfully, Legendary will have saved // this path in `installed.json` (so the GameInfo) diff --git a/src/backend/storeManagers/gog/games.ts b/src/backend/storeManagers/gog/games.ts index 4175403b6e..ebd1e8989f 100644 --- a/src/backend/storeManagers/gog/games.ts +++ b/src/backend/storeManagers/gog/games.ts @@ -1,7 +1,3 @@ -import { - createAbortController, - deleteAbortController -} from '../../utils/aborthandler/aborthandler' import { importGame as importGogLibraryGame, refreshInstalled, @@ -148,15 +144,10 @@ export async function importGame( /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ platform: InstallPlatform ): Promise { - const res = await runGogdlCommand( - ['import', folderPath], - createAbortController(appName), - { - logMessagePrefix: `Importing ${appName}` - } - ) - - deleteAbortController(appName) + const res = await runGogdlCommand(['import', folderPath], { + abortId: appName, + logMessagePrefix: `Importing ${appName}` + }) if (res.abort) { return res @@ -314,17 +305,12 @@ export async function install( onInstallOrUpdateOutput(appName, 'installing', data) } - const res = await runGogdlCommand( - commandParts, - createAbortController(appName), - { - logFile: logPath, - onOutput, - logMessagePrefix: `Installing ${appName}` - } - ) - - deleteAbortController(appName) + const res = await runGogdlCommand(commandParts, { + abortId: appName, + logFile: logPath, + onOutput, + logMessagePrefix: `Installing ${appName}` + }) if (res.abort) { return { status: 'abort' } @@ -541,20 +527,15 @@ export async function launch( `Launch Command: ${fullCommand}\n\nGame Log:\n` ) - const { error, abort } = await runGogdlCommand( - commandParts, - createAbortController(appName), - { - env: commandEnv, - wrappers, - logMessagePrefix: `Launching ${gameInfo.title}`, - onOutput: (output: string) => { - if (!logsDisabled) appendFileSync(logFileLocation(appName), output) - } + const { error, abort } = await runGogdlCommand(commandParts, { + abortId: appName, + env: commandEnv, + wrappers, + logMessagePrefix: `Launching ${gameInfo.title}`, + onOutput: (output: string) => { + if (!logsDisabled) appendFileSync(logFileLocation(appName), output) } - ) - - deleteAbortController(appName) + }) if (abort) { return true @@ -618,16 +599,11 @@ export async function repair(appName: string): Promise { ...workers ] - const res = await runGogdlCommand( - commandParts, - createAbortController(appName), - { - logFile: logPath, - logMessagePrefix: `Repairing ${appName}` - } - ) - - deleteAbortController(appName) + const res = await runGogdlCommand(commandParts, { + abortId: appName, + logFile: logPath, + logMessagePrefix: `Repairing ${appName}` + }) if (res.error) { logError(['Failed to repair', `${appName}:`, res.error], LogPrefix.Gog) @@ -676,16 +652,11 @@ export async function syncSaves( logInfo([`Syncing saves for ${gameInfo.title}`], LogPrefix.Gog) - const res = await runGogdlCommand( - commandParts, - createAbortController(appName), - { - logMessagePrefix: `Syncing saves for ${gameInfo.title}`, - onOutput: (output) => (fullOutput += output) - } - ) - - deleteAbortController(appName) + const res = await runGogdlCommand(commandParts, { + abortId: appName, + logMessagePrefix: `Syncing saves for ${gameInfo.title}`, + onOutput: (output) => (fullOutput += output) + }) if (res.error) { logError( @@ -794,17 +765,12 @@ export async function update( onInstallOrUpdateOutput(appName, 'updating', data) } - const res = await runGogdlCommand( - commandParts, - createAbortController(appName), - { - logFile: logPath, - onOutput, - logMessagePrefix: `Updating ${appName}` - } - ) - - deleteAbortController(appName) + const res = await runGogdlCommand(commandParts, { + abortId: appName, + logFile: logPath, + onOutput, + logMessagePrefix: `Updating ${appName}` + }) if (res.abort) { return { status: 'done' } diff --git a/src/backend/storeManagers/gog/library.ts b/src/backend/storeManagers/gog/library.ts index fbf916cc43..ba65f8988b 100644 --- a/src/backend/storeManagers/gog/library.ts +++ b/src/backend/storeManagers/gog/library.ts @@ -41,10 +41,6 @@ import { apiInfoCache } from './electronStores' import { callRunner } from '../../launcher' -import { - createAbortController, - deleteAbortController -} from '../../utils/aborthandler/aborthandler' import { isOnline } from '../../online_monitor' import i18next from 'i18next' @@ -351,15 +347,10 @@ export async function getInstallInfo( installPlatform === 'linux' ? 'windows' : installPlatform ] - const res = await runRunnerCommand( - commandParts, - createAbortController(appName), - { - logMessagePrefix: 'Getting game metadata' - } - ) - - deleteAbortController(appName) + const res = await runRunnerCommand(commandParts, { + abortId: appName, + logMessagePrefix: 'Getting game metadata' + }) if (!res.stdout || res.abort) { logError( @@ -1017,15 +1008,14 @@ export async function getLinuxInstallerInfo(appName: string): Promise< */ export async function runRunnerCommand( commandParts: string[], - abortController: AbortController, options?: CallRunnerOptions ): Promise { const { dir, bin } = getGOGdlBin() const authConfig = join(app.getPath('userData'), 'gog_store', 'auth.json') + return callRunner( ['--auth-config-path', authConfig, ...commandParts], { name: 'gog', logPrefix: LogPrefix.Gog, bin, dir }, - abortController, { ...options, verboseLogFile: gogdlLogFile diff --git a/src/backend/storeManagers/gog/user.ts b/src/backend/storeManagers/gog/user.ts index ea3defbecb..a093991273 100644 --- a/src/backend/storeManagers/gog/user.ts +++ b/src/backend/storeManagers/gog/user.ts @@ -6,10 +6,6 @@ import { configStore } from './electronStores' import { isOnline } from '../../online_monitor' import { UserData } from 'common/types/gog' import { runRunnerCommand } from './library' -import { - createAbortController, - deleteAbortController -} from 'backend/utils/aborthandler/aborthandler' import { gogdlAuthConfig } from 'backend/constants' import { clearCache } from 'backend/utils' @@ -37,13 +33,10 @@ export class GOGUser { logInfo('Logging using GOG credentials', LogPrefix.Gog) // Gets token from GOG basaed on authorization code - const { stdout } = await runRunnerCommand( - ['auth', '--code', code], - createAbortController('gogdl-auth'), - { - logSanitizer: authLogSanitizer - } - ) + const { stdout } = await runRunnerCommand(['auth', '--code', code], { + abortId: 'gogdl-auth', + logSanitizer: authLogSanitizer + }) try { const data: GOGLoginData = JSON.parse(stdout.trim()) @@ -57,7 +50,6 @@ export class GOGUser { ) return { status: 'error' } } - deleteAbortController('gogdl-auth') logInfo('Login Successful', LogPrefix.Gog) configStore.set('isLoggedIn', true) const userDetails = await this.getUserDetails() @@ -116,15 +108,10 @@ export class GOGUser { }) return } - const { stdout } = await runRunnerCommand( - ['auth'], - createAbortController('gogdl-get-credentials'), - { - logSanitizer: authLogSanitizer - } - ) - - deleteAbortController('gogdl-get-credentials') + const { stdout } = await runRunnerCommand(['auth'], { + abortId: 'gogdl-get-credentials', + logSanitizer: authLogSanitizer + }) return JSON.parse(stdout) } diff --git a/src/backend/storeManagers/legendary/eos_overlay/eos_overlay.ts b/src/backend/storeManagers/legendary/eos_overlay/eos_overlay.ts index 90bf1dbdf3..e331494e2f 100644 --- a/src/backend/storeManagers/legendary/eos_overlay/eos_overlay.ts +++ b/src/backend/storeManagers/legendary/eos_overlay/eos_overlay.ts @@ -1,9 +1,5 @@ import { gameManagerMap } from '../../index' -import { - callAbortController, - createAbortController, - deleteAbortController -} from '../../../utils/aborthandler/aborthandler' +import { callAbortController } from '../../../utils/aborthandler/aborthandler' import { dialog } from 'electron' import { existsSync, readFileSync } from 'graceful-fs' import { t } from 'i18next' @@ -76,13 +72,11 @@ async function updateInfo() { await runLegendaryCommand( { subcommand: 'status' }, - createAbortController(eosOverlayAppName), { + abortId: eosOverlayAppName, logMessagePrefix: 'Updating EOS Overlay information' } ) - - deleteAbortController(eosOverlayAppName) } /** @@ -104,8 +98,8 @@ async function install() { action: 'install', '--path': Path.parse(defaultInstallPath) }, - createAbortController(eosOverlayAppName), { + abortId: eosOverlayAppName, logMessagePrefix: 'Getting EOS Overlay install size', onOutput: (output: string) => { const downloadMatch = output.match(/Download size: ([\d.]+) MiB/) @@ -119,8 +113,6 @@ async function install() { } ) - deleteAbortController(eosOverlayAppName) - // The EOS Overlay doesn't support Ctrl-C-pausing, so it's fine to just do this setCurrentDownloadSize(eosOverlayAppName, downloadSize) @@ -132,8 +124,8 @@ async function install() { action: 'install', '--path': Path.parse(defaultInstallPath) }, - createAbortController(eosOverlayAppName), { + abortId: eosOverlayAppName, logMessagePrefix: 'Installing EOS Overlay', onOutput: (output: string) => { gameManagerMap['legendary'].onInstallOrUpdateOutput( @@ -146,8 +138,6 @@ async function install() { } ) - deleteAbortController(eosOverlayAppName) - sendFrontendMessage('gameStatusUpdate', { appName: eosOverlayAppName, runner: 'legendary', @@ -179,12 +169,16 @@ async function remove(): Promise { } await runLegendaryCommand( - { '-y': true, subcommand: 'eos-overlay', action: 'remove' }, - createAbortController(eosOverlayAppName) + { + '-y': true, + subcommand: 'eos-overlay', + action: 'remove' + }, + { + abortId: eosOverlayAppName + } ) - deleteAbortController(eosOverlayAppName) - return true } @@ -218,12 +212,11 @@ async function enable( } if (prefix) command['--prefix'] = Path.parse(prefix) - await runLegendaryCommand(command, createAbortController(eosOverlayAppName), { + await runLegendaryCommand(command, { + abortId: eosOverlayAppName, logMessagePrefix: 'Enabling EOS Overlay' }) - deleteAbortController(eosOverlayAppName) - return { wasEnabled: true } } @@ -243,11 +236,10 @@ async function disable(appName: string) { } if (prefix) command['--prefix'] = Path.parse(prefix) - await runLegendaryCommand(command, createAbortController(eosOverlayAppName), { + await runLegendaryCommand(command, { + abortId: eosOverlayAppName, logMessagePrefix: 'Disabling EOS Overlay' }) - - deleteAbortController(eosOverlayAppName) } function isInstalled() { @@ -277,7 +269,8 @@ async function isEnabled(appName?: string) { } if (prefix) command['--prefix'] = Path.parse(prefix) - await runLegendaryCommand(command, createAbortController(eosOverlayAppName), { + await runLegendaryCommand(command, { + abortId: eosOverlayAppName, onOutput: (data: string) => { if (data.includes('Overlay enabled')) { enabled = data.includes('Yes') @@ -286,8 +279,6 @@ async function isEnabled(appName?: string) { }, logMessagePrefix: 'Checking if EOS Overlay is enabled' }) - - deleteAbortController(eosOverlayAppName) return enabled } diff --git a/src/backend/storeManagers/legendary/games.ts b/src/backend/storeManagers/legendary/games.ts index 80d878cb54..41c56760fd 100644 --- a/src/backend/storeManagers/legendary/games.ts +++ b/src/backend/storeManagers/legendary/games.ts @@ -1,7 +1,3 @@ -import { - createAbortController, - deleteAbortController -} from '../../utils/aborthandler/aborthandler' import { appendFileSync, existsSync } from 'graceful-fs' import axios from 'axios' @@ -513,17 +509,12 @@ export async function update( ) } - const res = await runLegendaryCommand( - command, - createAbortController(appName), - { - logFile: logPath, - onOutput, - logMessagePrefix: `Updating ${appName}` - } - ) - - deleteAbortController(appName) + const res = await runLegendaryCommand(command, { + abortId: appName, + logFile: logPath, + onOutput, + logMessagePrefix: `Updating ${appName}` + }) sendFrontendMessage('gameStatusUpdate', { appName: appName, @@ -600,23 +591,21 @@ export async function install( ) } - let res = await runLegendaryCommand(command, createAbortController(appName), { + let res = await runLegendaryCommand(command, { + abortId: appName, logFile: logPath, onOutput, logMessagePrefix: `Installing ${appName}` }) - deleteAbortController(appName) - // try to run the install again with higher memory limit if (res.stderr.includes('MemoryError:')) { command['--max-shared-memory'] = PositiveInteger.parse(5000) - res = await runLegendaryCommand(command, createAbortController(appName), { + res = await runLegendaryCommand(command, { + abortId: appName, logFile: logPath, onOutput }) - - deleteAbortController(appName) } if (res.abort) { @@ -661,15 +650,10 @@ export async function uninstall({ appName }: RemoveArgs): Promise { '-y': true } - const res = await runLegendaryCommand( - command, - createAbortController(appName), - { - logMessagePrefix: `Uninstalling ${appName}` - } - ) - - deleteAbortController(appName) + const res = await runLegendaryCommand(command, { + abortId: appName, + logMessagePrefix: `Uninstalling ${appName}` + }) if (res.error) { logError( @@ -703,16 +687,11 @@ export async function repair(appName: string): Promise { if (maxWorkers) command['--max-workers'] = PositiveInteger.parse(maxWorkers) if (downloadNoHttps) command['--no-https'] = true - const res = await runLegendaryCommand( - command, - createAbortController(appName), - { - logFile: logPath, - logMessagePrefix: `Repairing ${appName}` - } - ) - - deleteAbortController(appName) + const res = await runLegendaryCommand(command, { + abortId: appName, + logFile: logPath, + logMessagePrefix: `Repairing ${appName}` + }) if (res.error) { logError( @@ -738,11 +717,9 @@ export async function importGame( logInfo(`Importing ${appName}.`, LogPrefix.Legendary) - const res = await runLegendaryCommand(command, createAbortController(appName)) + const res = await runLegendaryCommand(command, { abortId: appName }) addShortcuts(appName) - deleteAbortController(appName) - if (res.error) { logError( ['Failed to import', `${appName}:`, res.error], @@ -778,16 +755,11 @@ export async function syncSaves( } let fullOutput = '' - const res = await runLegendaryCommand( - command, - createAbortController(appName), - { - logMessagePrefix: `Syncing saves for ${getGameInfo(appName).title}`, - onOutput: (output) => (fullOutput += output) - } - ) - - deleteAbortController(appName) + const res = await runLegendaryCommand(command, { + abortId: appName, + logMessagePrefix: `Syncing saves for ${getGameInfo(appName).title}`, + onOutput: (output) => (fullOutput += output) + }) if (res.error) { logError( @@ -908,20 +880,15 @@ export async function launch( `Launch Command: ${fullCommand}\n\nGame Log:\n` ) - const { error } = await runLegendaryCommand( - command, - createAbortController(appName), - { - env: commandEnv, - wrappers: wrappers, - logMessagePrefix: `Launching ${gameInfo.title}`, - onOutput: (output) => { - if (!logsDisabled) appendFileSync(logFileLocation(appName), output) - } + const { error } = await runLegendaryCommand(command, { + abortId: appName, + env: commandEnv, + wrappers: wrappers, + logMessagePrefix: `Launching ${gameInfo.title}`, + onOutput: (output) => { + if (!logsDisabled) appendFileSync(logFileLocation(appName), output) } - ) - - deleteAbortController(appName) + }) if (error) { const showDialog = !`${error}`.includes('appears to be deleted') @@ -960,11 +927,11 @@ export async function forceUninstall(appName: string) { '-y': true, '--keep-files': true }, - createAbortController(appName) + { + abortId: appName + } ) - deleteAbortController(appName) - sendFrontendMessage('refreshLibrary', 'legendary') } catch (error) { logError( diff --git a/src/backend/storeManagers/legendary/library.ts b/src/backend/storeManagers/legendary/library.ts index 205a2071a2..752fc03645 100644 --- a/src/backend/storeManagers/legendary/library.ts +++ b/src/backend/storeManagers/legendary/library.ts @@ -1,7 +1,3 @@ -import { - createAbortController, - deleteAbortController -} from '../../utils/aborthandler/aborthandler' import { existsSync, mkdirSync, readFileSync, readdirSync } from 'graceful-fs' import { @@ -110,17 +106,16 @@ async function refreshLegendary(): Promise { return { stderr: 'Epic offline, unable to update game list', stdout: '' } } - const abortID = 'legendary-refresh' const res = await runRunnerCommand( { subcommand: 'list', '--third-party': true }, - createAbortController(abortID) + { + abortId: 'legendary-refresh' + } ) - deleteAbortController(abortID) - if (res.error) { logError(['Failed to refresh library:', res.error], LogPrefix.Legendary) } @@ -237,9 +232,7 @@ export async function getInstallInfo( if (await isEpicServiceOffline()) { command['--offline'] = true } - const res = await runRunnerCommand(command, createAbortController(appName)) - - deleteAbortController(appName) + const res = await runRunnerCommand(command, { abortId: appName }) if (res.error) { logError(['Failed to get more details:', res.error], LogPrefix.Legendary) @@ -273,17 +266,14 @@ export async function listUpdateableGames(): Promise { return [] } - const abortID = 'legendary-check-updates' const res = await runRunnerCommand( { subcommand: 'list', '--third-party': true }, - createAbortController(abortID), { + abortId: 'legendary-check-updates', logMessagePrefix: 'Checking for game updates' } ) - deleteAbortController(abortID) - if (res.abort) { return [] } @@ -436,11 +426,11 @@ export async function changeGameInstallPath(appName: string, newPath: string) { newBasePath: Path.parse(dirname(newPath)), '--skip-move': true }, - createAbortController(appName) + { + abortId: appName + } ) - deleteAbortController(appName) - if (error) { logError( ['Failed to set install path for', `${appName}:`, error], @@ -653,7 +643,6 @@ export const hasGame = (appName: string) => allGames.has(appName) export async function runRunnerCommand( command: LegendaryCommand, - abortController: AbortController, options?: CallRunnerOptions ): Promise { const { dir, bin } = getLegendaryBin() @@ -673,7 +662,6 @@ export async function runRunnerCommand( return callRunner( commandParts, { name: 'legendary', logPrefix: LogPrefix.Legendary, bin, dir }, - abortController, { ...options, verboseLogFile: legendaryLogFile @@ -778,12 +766,9 @@ export async function toggleGamesSync(path_or_action: string) { } } - const { error, stderr, stdout } = await runRunnerCommand( - command, - createAbortController('toggle-sync') - ) - - deleteAbortController('toggle-sync') + const { error, stderr, stdout } = await runRunnerCommand(command, { + abortId: 'toggle-sync' + }) if (error) { logError(['Failed to toggle EGS-Sync', error], LogPrefix.Legendary) diff --git a/src/backend/storeManagers/legendary/user.ts b/src/backend/storeManagers/legendary/user.ts index 778ba7c405..1ff656694a 100644 --- a/src/backend/storeManagers/legendary/user.ts +++ b/src/backend/storeManagers/legendary/user.ts @@ -1,7 +1,3 @@ -import { - createAbortController, - deleteAbortController -} from '../../utils/aborthandler/aborthandler' import { existsSync, readFileSync } from 'graceful-fs' import { UserInfo } from 'common/types' @@ -23,7 +19,6 @@ export class LegendaryUser { '--code': NonEmptyString.parse(authorizationCode) } - const abortID = 'legendary-login' const errorMessage = ( error: string ): { status: 'failed'; data: undefined } => { @@ -33,15 +28,10 @@ export class LegendaryUser { } try { - const res = await runLegendaryCommand( - command, - createAbortController(abortID), - { - logMessagePrefix: 'Logging in' - } - ) - - deleteAbortController(abortID) + const res = await runLegendaryCommand(command, { + abortId: 'legendary-login', + logMessagePrefix: 'Logging in' + }) if (res.stderr.includes('ERROR: Logging in ')) { return errorMessage(res.stderr) @@ -54,7 +44,6 @@ export class LegendaryUser { const userInfo = this.getUserInfo() return { status: 'done', data: userInfo } } catch (error) { - deleteAbortController(abortID) return errorMessage(`${error}`) } } @@ -62,16 +51,10 @@ export class LegendaryUser { public static async logout() { const command: LegendaryCommand = { subcommand: 'auth', '--delete': true } - const abortID = 'legendary-logout' - const res = await runLegendaryCommand( - command, - createAbortController(abortID), - { - logMessagePrefix: 'Logging out' - } - ) - - deleteAbortController(abortID) + const res = await runLegendaryCommand(command, { + abortId: 'legendary-logout', + logMessagePrefix: 'Logging out' + }) if (res.error || res.abort) { logError( diff --git a/src/backend/storeManagers/nile/games.ts b/src/backend/storeManagers/nile/games.ts index be90a1a1ba..c158b05a67 100644 --- a/src/backend/storeManagers/nile/games.ts +++ b/src/backend/storeManagers/nile/games.ts @@ -25,10 +25,6 @@ import { } from 'backend/logger/logger' import { gamesConfigPath, isWindows } from 'backend/constants' import { GameConfig } from 'backend/game_config' -import { - createAbortController, - deleteAbortController -} from 'backend/utils/aborthandler/aborthandler' import { getRunnerCallWithoutCredentials, launchCleanup, @@ -111,15 +107,11 @@ export async function importGame( platform: InstallPlatform ): Promise { const logPath = join(gamesConfigPath, `${appName}.log`) - const res = await runNileCommand( - ['import', '--path', folderPath, appName], - createAbortController(appName), - { - logFile: logPath, - logMessagePrefix: `Importing ${appName}` - } - ) - deleteAbortController(appName) + const res = await runNileCommand(['import', '--path', folderPath, appName], { + abortId: appName, + logFile: logPath, + logMessagePrefix: `Importing ${appName}` + }) if (res.abort) { return res @@ -256,17 +248,12 @@ export async function install( onInstallOrUpdateOutput(appName, 'installing', data) } - const res = await runNileCommand( - commandParts, - createAbortController(appName), - { - logFile: logPath, - onOutput, - logMessagePrefix: `Installing ${appName}` - } - ) - - deleteAbortController(appName) + const res = await runNileCommand(commandParts, { + abortId: appName, + logFile: logPath, + onOutput, + logMessagePrefix: `Installing ${appName}` + }) if (res.abort) { return { status: 'abort' } @@ -422,20 +409,15 @@ export async function launch( `Launch Command: ${fullCommand}\n\nGame Log:\n` ) - const { error } = await runNileCommand( - commandParts, - createAbortController(appName), - { - env: commandEnv, - wrappers, - logMessagePrefix: `Launching ${gameInfo.title}`, - onOutput(output) { - if (!logsDisabled) appendFileSync(logFileLocation(appName), output) - } + const { error } = await runNileCommand(commandParts, { + abortId: appName, + env: commandEnv, + wrappers, + logMessagePrefix: `Launching ${gameInfo.title}`, + onOutput(output) { + if (!logsDisabled) appendFileSync(logFileLocation(appName), output) } - ) - - deleteAbortController(appName) + }) if (error) { logError(['Error launching game:', error], LogPrefix.Nile) @@ -487,13 +469,12 @@ export async function repair(appName: string): Promise { const logPath = join(gamesConfigPath, `${appName}.log`) const res = await runNileCommand( ['verify', '--path', install_path, appName], - createAbortController(appName), { + abortId: appName, logFile: logPath, logMessagePrefix: `Repairing ${appName}` } ) - deleteAbortController(appName) if (res.error) { logError(['Failed to repair', `${appName}:`, res.error], LogPrefix.Nile) @@ -510,14 +491,10 @@ export async function syncSaves(): Promise { export async function uninstall({ appName }: RemoveArgs): Promise { const commandParts = ['uninstall', appName] - const res = await runNileCommand( - commandParts, - createAbortController(appName), - { - logMessagePrefix: `Uninstalling ${appName}` - } - ) - deleteAbortController(appName) + const res = await runNileCommand(commandParts, { + abortId: appName, + logMessagePrefix: `Uninstalling ${appName}` + }) if (res.error) { logError(['Failed to uninstall', `${appName}:`, res.error], LogPrefix.Nile) @@ -543,17 +520,12 @@ export async function update(appName: string): Promise { onInstallOrUpdateOutput(appName, 'updating', data) } - const res = await runNileCommand( - commandParts, - createAbortController(appName), - { - logFile: logPath, - onOutput, - logMessagePrefix: `Updating ${appName}` - } - ) - - deleteAbortController(appName) + const res = await runNileCommand(commandParts, { + abortId: appName, + logFile: logPath, + onOutput, + logMessagePrefix: `Updating ${appName}` + }) if (res.abort) { return { status: 'abort' } diff --git a/src/backend/storeManagers/nile/library.ts b/src/backend/storeManagers/nile/library.ts index 91aa7a3751..5bfa7f8b65 100644 --- a/src/backend/storeManagers/nile/library.ts +++ b/src/backend/storeManagers/nile/library.ts @@ -12,10 +12,6 @@ import { logInfo, logWarning } from 'backend/logger/logger' -import { - createAbortController, - deleteAbortController -} from 'backend/utils/aborthandler/aborthandler' import { CallRunnerOptions, ExecResult, GameInfo } from 'common/types' import { FuelSchema, @@ -159,12 +155,10 @@ export async function listUpdateableGames(): Promise { } logInfo('Looking for updates...', LogPrefix.Nile) - const abortID = 'nile-list-updates' const { stdout: output } = await runRunnerCommand( ['list-updates', '--json'], - createAbortController(abortID) + { abortId: 'nile-list-updates' } ) - deleteAbortController(abortID) if (!output) { /* @@ -187,13 +181,9 @@ export async function listUpdateableGames(): Promise { async function refreshNile(): Promise { logInfo('Refreshing Amazon Games...', LogPrefix.Nile) - const abortID = 'nile-refresh' - const res = await runRunnerCommand( - ['library', 'sync'], - createAbortController(abortID) - ) - - deleteAbortController(abortID) + const res = await runRunnerCommand(['library', 'sync'], { + abortId: 'nile-refresh' + }) if (res.error) { logError(['Failed to refresh library:', res.error], LogPrefix.Nile) @@ -328,9 +318,8 @@ export async function getInstallInfo( // Get size info from Nile const { stdout: output } = await runRunnerCommand( ['install', '--info', '--json', appName], - createAbortController(appName) + { abortId: appName } ) - deleteAbortController(appName) const { download_size }: NileGameDownloadInfo = JSON.parse(output) const installInfo = { @@ -460,7 +449,6 @@ export function installState(appName: string, state: boolean) { export async function runRunnerCommand( commandParts: string[], - abortController: AbortController, options?: CallRunnerOptions ): Promise { const { dir, bin } = getNileBin() @@ -478,7 +466,6 @@ export async function runRunnerCommand( return callRunner( commandParts, { name: 'nile', logPrefix: LogPrefix.Nile, bin, dir }, - abortController, { ...options, verboseLogFile: nileLogFile diff --git a/src/backend/storeManagers/nile/user.ts b/src/backend/storeManagers/nile/user.ts index c6105d6550..016c6f1625 100644 --- a/src/backend/storeManagers/nile/user.ts +++ b/src/backend/storeManagers/nile/user.ts @@ -1,8 +1,4 @@ import { LogPrefix, logDebug, logError, logInfo } from 'backend/logger/logger' -import { - createAbortController, - deleteAbortController -} from 'backend/utils/aborthandler/aborthandler' import { NileLoginData, NileRegisterData, @@ -32,12 +28,11 @@ export class NileUser { logDebug('Getting login data from Nile', LogPrefix.Nile) const { stdout } = await runRunnerCommand( ['auth', '--login', '--non-interactive'], - createAbortController('nile-auth'), { + abortId: 'nile-auth', logSanitizer: authLogSanitizer } ) - deleteAbortController('nile-auth') const output: NileLoginData = JSON.parse(stdout) logInfo(['Register data is:', output], LogPrefix.Nile) @@ -62,9 +57,8 @@ export class NileUser { '--client-id', client_id ], - createAbortController('nile-login') + { abortId: 'nile-login' } ) - deleteAbortController('nile-login') const successRegex = /\[AUTH_MANAGER]:.*Succesfully registered a device/ if (!successRegex.test(output)) { @@ -94,12 +88,7 @@ export class NileUser { static async logout() { const commandParts = ['auth', '--logout'] - const abortID = 'nile-logout' - const res = await runRunnerCommand( - commandParts, - createAbortController(abortID) - ) - deleteAbortController(abortID) + const res = await runRunnerCommand(commandParts, { abortId: 'nile-logout' }) if (res.abort) { logError('Failed to logout: abort by user'), LogPrefix.Nile diff --git a/src/backend/storeManagers/sideload/library.ts b/src/backend/storeManagers/sideload/library.ts index 9aade127ef..3bc69a1b4a 100644 --- a/src/backend/storeManagers/sideload/library.ts +++ b/src/backend/storeManagers/sideload/library.ts @@ -99,7 +99,6 @@ export async function listUpdateableGames(): Promise { export async function runRunnerCommand( commandParts: string[], - abortController: AbortController, options?: CallRunnerOptions ): Promise { logWarning(`runRunnerCommand not implemented on Sideload Library Manager`) diff --git a/src/backend/storeManagers/storeManagerCommon/games.ts b/src/backend/storeManagers/storeManagerCommon/games.ts index 6197f7a547..86ca37073f 100644 --- a/src/backend/storeManagers/storeManagerCommon/games.ts +++ b/src/backend/storeManagers/storeManagerCommon/games.ts @@ -18,7 +18,10 @@ import { import { access, chmod } from 'fs/promises' import shlex from 'shlex' import { showDialogBoxModalAuto } from '../../dialog/dialog' -import { createAbortController } from '../../utils/aborthandler/aborthandler' +import { + createAbortController, + deleteAbortController +} from '../../utils/aborthandler/aborthandler' import { BrowserWindow, dialog, Menu } from 'electron' import { gameManagerMap } from '../index' @@ -35,7 +38,7 @@ export function logFileLocation(appName: string) { const openNewBrowserGameWindow = async ( browserUrl: string, - abortController: AbortController + abortId: string ): Promise => { const hostname = new URL(browserUrl).hostname @@ -63,6 +66,8 @@ const openNewBrowserGameWindow = async ( browserGame.loadURL(browserUrl) browserGame.on('ready-to-show', () => browserGame.show()) + const abortController = createAbortController(abortId) + abortController.signal.addEventListener('abort', () => { browserGame.close() }) @@ -89,6 +94,7 @@ const openNewBrowserGameWindow = async ( }) browserGame.on('closed', () => { + deleteAbortController(abortId) res(true) }) }) @@ -118,7 +124,7 @@ export async function launchGame( } if (browserUrl) { - return openNewBrowserGameWindow(browserUrl, createAbortController(appName)) + return openNewBrowserGameWindow(browserUrl, appName) } const gameSettings = await getAppSettings(appName) @@ -192,7 +198,6 @@ export async function launchGame( bin: executable, dir: dirname(executable) }, - createAbortController(appName), { env, wrappers, diff --git a/src/backend/utils.ts b/src/backend/utils.ts index c4454a38f4..b6add5718a 100644 --- a/src/backend/utils.ts +++ b/src/backend/utils.ts @@ -1,8 +1,4 @@ -import { - createAbortController, - deleteAbortController, - callAllAbortControllers -} from './utils/aborthandler/aborthandler' +import { callAllAbortControllers } from './utils/aborthandler/aborthandler' import { Runner, WineInstallation, @@ -369,11 +365,10 @@ function clearCache(library?: 'gog' | 'legendary' | 'nile') { installStore.clear() libraryStore.clear() gameInfoStore.clear() - const abortID = 'legendary-cleanup' runLegendaryCommand( { subcommand: 'cleanup' }, - createAbortController(abortID) - ).then(() => deleteAbortController(abortID)) + { abortId: 'legandary-cleanup' } + ) } if (library === 'nile' || !library) { nileInstallStore.clear() @@ -871,12 +866,8 @@ export async function downloadDefaultWine() { progress }) } - const result = await installWineVersion( - release, - onProgress, - createAbortController(release.version).signal - ) - deleteAbortController(release.version) + const result = await installWineVersion(release, onProgress) + if (result === 'success') { let downloadedWine = null try { diff --git a/src/backend/utils/helperBinaries/index.ts b/src/backend/utils/helperBinaries/index.ts index e516d085bf..592fc01f6c 100644 --- a/src/backend/utils/helperBinaries/index.ts +++ b/src/backend/utils/helperBinaries/index.ts @@ -1,20 +1,18 @@ -import { - createAbortController, - deleteAbortController -} from '../aborthandler/aborthandler' import { runRunnerCommand as runLegendaryCommand } from '../../storeManagers/legendary/library' import { runRunnerCommand as runGogdlCommand } from '../../storeManagers/gog/library' import { runRunnerCommand as runNileCommand } from '../../storeManagers/nile/library' async function getLegendaryVersion(): Promise { - const abortID = 'legendary-version' const { stdout, error, abort } = await runLegendaryCommand( - { subcommand: undefined, '--version': true }, - createAbortController(abortID) + { + subcommand: undefined, + '--version': true + }, + { + abortId: 'legendary-version' + } ) - deleteAbortController(abortID) - if (error ?? abort) return 'invalid' // Sample output: @@ -28,13 +26,9 @@ async function getLegendaryVersion(): Promise { } async function getGogdlVersion(): Promise { - const abortID = 'gogdl-version' - const { stdout, error } = await runGogdlCommand( - ['--version'], - createAbortController(abortID) - ) - - deleteAbortController(abortID) + const { stdout, error } = await runGogdlCommand(['--version'], { + abortId: 'gogdl-version' + }) if (error) return 'invalid' @@ -42,12 +36,9 @@ async function getGogdlVersion(): Promise { } async function getNileVersion(): Promise { - const abortID = 'nile-version' - const { stdout, error } = await runNileCommand( - ['--version'], - createAbortController(abortID) - ) - deleteAbortController(abortID) + const { stdout, error } = await runNileCommand(['--version'], { + abortId: 'nile-version' + }) if (error) return 'invalid' diff --git a/src/backend/wine/manager/ipc_handler.ts b/src/backend/wine/manager/ipc_handler.ts index f9ac2c7603..1e5cf3dd94 100644 --- a/src/backend/wine/manager/ipc_handler.ts +++ b/src/backend/wine/manager/ipc_handler.ts @@ -6,10 +6,6 @@ import { updateWineVersionInfos } from './utils' import { logError, LogPrefix } from '../../logger/logger' -import { - createAbortController, - deleteAbortController -} from '../../utils/aborthandler/aborthandler' import { sendFrontendMessage } from '../../main_window' ipcMain.handle('installWineVersion', async (e, release) => { @@ -19,12 +15,7 @@ ipcMain.handle('installWineVersion', async (e, release) => { progress }) } - const result = await installWineVersion( - release, - onProgress, - createAbortController(release.version).signal - ) - deleteAbortController(release.version) + const result = await installWineVersion(release, onProgress) return result }) diff --git a/src/backend/wine/manager/utils.ts b/src/backend/wine/manager/utils.ts index 691beb4411..a04e6730af 100644 --- a/src/backend/wine/manager/utils.ts +++ b/src/backend/wine/manager/utils.ts @@ -17,6 +17,10 @@ import { getAvailableVersions, installVersion } from './downloader/main' import { toolsPath, isMac } from '../../constants' import { sendFrontendMessage } from '../../main_window' import { TypeCheckedStoreBackend } from 'backend/electron_store' +import { + createAbortController, + deleteAbortController +} from 'backend/utils/aborthandler/aborthandler' export const wineDownloaderInfoStore = new TypeCheckedStoreBackend( 'wineDownloaderInfoStore', @@ -85,8 +89,7 @@ async function updateWineVersionInfos( async function installWineVersion( release: WineVersionInfo, - onProgress: (state: State, progress?: ProgressInfo) => void, - abortSignal: AbortSignal + onProgress: (state: State, progress?: ProgressInfo) => void ) { let updatedInfo: WineVersionInfo const variant = release.hasUpdate ? 'update' : 'installation' @@ -108,13 +111,15 @@ async function installWineVersion( ? `${toolsPath}/wine` : `${toolsPath}/proton` + const abortController = createAbortController(release.version) + try { const response = await installVersion({ versionInfo: release as VersionInfo, installDir, overwrite: release.hasUpdate, onProgress: onProgress, - abortSignal: abortSignal + abortSignal: abortController.signal }) updatedInfo = { ...response.versionInfo, @@ -124,13 +129,15 @@ async function installWineVersion( type: release.type } } catch (error) { - if (abortSignal.aborted) { + if (abortController.signal.aborted) { logWarning(error, LogPrefix.WineDownloader) return 'abort' } else { logError(error, LogPrefix.WineDownloader) return 'error' } + } finally { + deleteAbortController(release.version) } // Update stored information diff --git a/src/common/types.ts b/src/common/types.ts index c84364ed6c..5260a63382 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -348,6 +348,7 @@ export interface CallRunnerOptions { env?: Record | NodeJS.ProcessEnv wrappers?: string[] onOutput?: (output: string, child: ChildProcess) => void + abortId?: string } export interface EnviromentVariable {