Skip to content

Commit

Permalink
[Fix] Use runRunnerCommand to fix issue with spaces enabling egl-sync…
Browse files Browse the repository at this point in the history
… (#2964)

* Use runRunnerCommand to fix issue with spaces enabling egl-sync

* Address feedback: order options, constant, safeparse
  • Loading branch information
arielj authored and flavioislima committed Oct 26, 2023
1 parent e9d3e27 commit 6b788e2
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 35 deletions.
34 changes: 1 addition & 33 deletions src/backend/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import {
appendFileSync,
constants,
existsSync,
mkdirSync,
rmSync,
unlinkSync,
watch,
Expand Down Expand Up @@ -1541,38 +1540,7 @@ ipcMain.handle(
)

ipcMain.handle('egsSync', async (event, args) => {
if (isWindows) {
const egl_manifestPath =
'C:\\ProgramData\\Epic\\EpicGamesLauncher\\Data\\Manifests'

if (!existsSync(egl_manifestPath)) {
mkdirSync(egl_manifestPath, { recursive: true })
}
}

const linkArgs = isWindows
? `--enable-sync`
: `--enable-sync --egl-wine-prefix ${args}`
const unlinkArgs = `--unlink`
const isLink = args !== 'unlink'
const command = isLink ? linkArgs : unlinkArgs
const { bin, dir } = getLegendaryBin()
const legendary = path.join(dir, bin)

try {
const { stderr, stdout } = await execAsync(
`${legendary} egl-sync ${command} -y`
)
logInfo(`${stdout}`, LogPrefix.Legendary)
if (stderr.includes('ERROR')) {
logError(`${stderr}`, LogPrefix.Legendary)
return 'Error'
}
return `${stdout} - ${stderr}`
} catch (error) {
logError(error, LogPrefix.Legendary)
return 'Error'
}
return LegendaryLibraryManager.toggleGamesSync(args)
})

ipcMain.handle('syncGOGSaves', async (event, gogSaves, appName, arg) =>
Expand Down
16 changes: 16 additions & 0 deletions src/backend/storeManagers/legendary/commands/egl_sync.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Path } from './base'

interface EglSyncCommand {
subcommand: 'egl-sync'
'--egl-manifest-path'?: Path
'--egl-wine-prefix'?: Path
'--enable-sync'?: true
'--disable-sync'?: true
'--one-shot'?: true
'--import-only'?: true
'--export-only'?: true
'--migrate'?: true
'--unlink'?: true
}

export default EglSyncCommand
46 changes: 46 additions & 0 deletions src/backend/storeManagers/legendary/commands/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { PositiveInteger } from './base'

import InstallCommand from './install'
import LaunchCommand from './launch'
import ListCommand from './list'
import InfoCommand from './info'
import MoveCommand from './move'
import SyncSavesCommand from './sync_saves'
import StatusCommand from './status'
import EosOverlayCommand from './eos_overlay'
import UninstallCommand from './uninstall'
import ImportCommand from './import'
import CleanupCommand from './cleanup'
import AuthCommand from './auth'
import EglSyncCommand from './egl_sync'

interface BaseLegendaryCommand {
'-v'?: true
'--debug'?: true
'-y'?: true
'--yes'?: true
'-V'?: true
'--version'?: true
'-J'?: true
'--pretty-json'?: true
'-A'?: PositiveInteger
'--api-timeout'?: PositiveInteger
}

export type LegendaryCommand = BaseLegendaryCommand &
(
| { subcommand: undefined }
| InstallCommand
| LaunchCommand
| ListCommand
| InfoCommand
| MoveCommand
| SyncSavesCommand
| StatusCommand
| EosOverlayCommand
| UninstallCommand
| ImportCommand
| CleanupCommand
| AuthCommand
| EglSyncCommand
)
116 changes: 114 additions & 2 deletions src/backend/storeManagers/legendary/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
createAbortController,
deleteAbortController
} from '../../utils/aborthandler/aborthandler'
import { existsSync, readFileSync, readdirSync } from 'graceful-fs'
import { existsSync, mkdirSync, readFileSync, readdirSync } from 'graceful-fs'

import {
GameInfo,
Expand Down Expand Up @@ -32,7 +32,8 @@ import {
legendaryLogFile,
legendaryMetadata,
isLinux,
userHome
userHome,
isWindows
} from '../../constants'
import {
logDebug,
Expand Down Expand Up @@ -767,3 +768,114 @@ export async function getGameSdl(
return []
}
}

/**
* Toggles the EGL synchronization on/off based on arguments
* @param path_or_action On Windows: "unlink" (turn off), "windows" (turn on). On linux/mac: "unlink" (turn off), any other string (prefix path)
* @returns string with stdout + stderr, or error message
*/
export async function toggleGamesSync(path_or_action: string) {
if (isWindows) {
const egl_manifestPath =
'C:\\ProgramData\\Epic\\EpicGamesLauncher\\Data\\Manifests'

if (!existsSync(egl_manifestPath)) {
mkdirSync(egl_manifestPath, { recursive: true })
}
}

const command: LegendaryCommand = {
subcommand: 'egl-sync',
'-y': true
}

if (path_or_action === 'unlink') {
command['--unlink'] = true
} else {
command['--enable-sync'] = true
if (!isWindows) {
const pathParse = Path.safeParse(path_or_action)
if (pathParse.success) {
command['--egl-wine-prefix'] = pathParse.data
} else {
return 'Error'
}
}
}

const { error, stderr, stdout } = await runRunnerCommand(
command,
createAbortController('toggle-sync')
)

deleteAbortController('toggle-sync')

if (error) {
logError(['Failed to toggle EGS-Sync', error], LogPrefix.Legendary)
return 'Error'
} else {
logInfo(`${stdout}`, LogPrefix.Legendary)
if (stderr.includes('ERROR') || stderr.includes('error')) {
logError(`${stderr}`, LogPrefix.Legendary)
return 'Error'
}
return `${stdout} - ${stderr}`
}
}

/*
* Converts a LegendaryCommand to a parameter list passable to Legendary
* @param command
*/
export function commandToArgsArray(command: LegendaryCommand): string[] {
const commandParts: string[] = []

if (command.subcommand) commandParts.push(command.subcommand)

// Some commands need special handling
switch (command.subcommand) {
case 'install':
commandParts.push(command.appName)
if (command.sdlList) {
commandParts.push('--install-tag=')
for (const sdlTag of command.sdlList)
commandParts.push('--install-tag', sdlTag)
}
break
case 'launch':
commandParts.push(command.appName)
if (command.extraArguments)
commandParts.push(...shlex.split(command.extraArguments))
break
case 'info':
case 'sync-saves':
case 'uninstall':
commandParts.push(command.appName)
break
case 'move':
commandParts.push(command.appName, command.newBasePath)
break
case 'eos-overlay':
commandParts.push(command.action)
break
case 'import':
commandParts.push(command.appName, command.installationDirectory)
break
}

// Append parameters (anything starting with -)
for (const [parameter, value] of Object.entries(
command
) as Entries<LegendaryCommand>) {
if (!parameter.startsWith('-')) continue
if (!value) continue
// Boolean values (specifically `true`) have to be handled differently
// Parameters that have a boolean type are just signified
// by the parameter being present, they don't have a value.
// Thus, we only add the key (parameter) here, instead of the key & value
if (value === true) commandParts.push(parameter)
else commandParts.push(parameter, value.toString())
}

return commandParts
}

0 comments on commit 6b788e2

Please sign in to comment.