Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only try to do EOS operations on a path if there's actually a Wineprefix there #3410

Merged
merged 1 commit into from
Jan 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/backend/storeManagers/legendary/commands/base.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { z } from 'zod'
import path from 'path'
import { hasGame } from '../library'
import { existsSync } from 'graceful-fs'

export const LegendaryAppName = z
.string()
Expand Down Expand Up @@ -35,3 +36,8 @@ export type URL = z.infer<typeof URL>
// FIXME: This doesn't feel right
export const URI = z.union([Path, URL])
export type URI = z.infer<typeof URI>

export const ValidWinePrefix = Path.refine((potPath) =>
existsSync(path.join(potPath, 'user.reg'))
).brand('ValidWinePrefix')
export type ValidWinePrefix = z.infer<typeof ValidWinePrefix>
4 changes: 2 additions & 2 deletions src/backend/storeManagers/legendary/commands/eos_overlay.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { z } from 'zod'
import { LegendaryAppName, NonEmptyString, Path } from './base'
import { LegendaryAppName, NonEmptyString, Path, ValidWinePrefix } from './base'

const EosOverlayAction = z.enum([
'install',
Expand All @@ -15,7 +15,7 @@ interface EosOverlayCommand {
subcommand: 'eos-overlay'
action: EosOverlayAction
'--path'?: Path
'--prefix'?: Path
'--prefix'?: ValidWinePrefix
'--app'?: LegendaryAppName
'--bottle'?: NonEmptyString
}
Expand Down
79 changes: 44 additions & 35 deletions src/backend/storeManagers/legendary/eos_overlay/eos_overlay.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { gameManagerMap } from '../../index'
import { callAbortController } from '../../../utils/aborthandler/aborthandler'
import { dialog } from 'electron'
import { existsSync, readFileSync } from 'graceful-fs'
import { t } from 'i18next'
import { join } from 'path'

import { toolsPath, isLinux, legendaryConfigPath } from '../../../constants'
import { logError, LogPrefix, logWarning } from '../../../logger/logger'
import { runRunnerCommand as runLegendaryCommand } from '../library'
import { verifyWinePrefix } from '../../../launcher'
import { setCurrentDownloadSize } from '../games'
import { Path } from '../commands/base'
import { LegendaryCommand } from '../commands'
import { toolsPath, isLinux, legendaryConfigPath } from 'backend/constants'
import { logError, LogPrefix, logWarning } from 'backend/logger/logger'
import { callAbortController } from 'backend/utils/aborthandler/aborthandler'
import { sendGameStatusUpdate } from 'backend/utils'
import { gameManagerMap } from '../..'
import { LegendaryCommand } from '../commands'
import { Path, ValidWinePrefix } from '../commands/base'
import { setCurrentDownloadSize } from '../games'
import { runRunnerCommand as runLegendaryCommand } from '../library'

import type { Runner } from 'common/types'

const currentVersionPath = join(legendaryConfigPath, 'overlay_version.json')
const installedVersionPath = join(legendaryConfigPath, 'overlay_install.json')
Expand Down Expand Up @@ -185,14 +186,6 @@ async function remove(): Promise<boolean> {
async function enable(
appName: string
): Promise<{ wasEnabled: boolean; installNow?: boolean }> {
let prefix = ''
if (isLinux) {
const gameSettings = await gameManagerMap['legendary'].getSettings(appName)
await verifyWinePrefix(gameSettings)
const { winePrefix, wineVersion } = gameSettings
prefix =
wineVersion.type === 'proton' ? join(winePrefix, 'pfx') : winePrefix
}
if (!isInstalled()) {
const { response } = await dialog.showMessageBox({
title: t('setting.eosOverlay.notInstalledTitle', 'Overlay not installed'),
Expand All @@ -206,11 +199,16 @@ async function enable(
return { wasEnabled: false, installNow: response === 0 }
}

const prefix = await getWinePrefixFolder(appName)
// Can't install the overlay if we don't have a valid prefix
// FIXME: Notify the user about this
if (prefix === false) return { wasEnabled: false }

const command: LegendaryCommand = {
subcommand: 'eos-overlay',
action: 'enable'
}
if (prefix) command['--prefix'] = Path.parse(prefix)
if (prefix) command['--prefix'] = prefix

await runLegendaryCommand(command, {
abortId: eosOverlayAppName,
Expand All @@ -221,19 +219,15 @@ async function enable(
}

async function disable(appName: string) {
let prefix = ''
if (isLinux) {
const { winePrefix, wineVersion } =
await gameManagerMap['legendary'].getSettings(appName)
prefix =
wineVersion.type === 'proton' ? join(winePrefix, 'pfx') : winePrefix
}
const prefix = await getWinePrefixFolder(appName)
// If we don't have a valid prefix anymore, we have nothing to disable
if (prefix === false) return

const command: LegendaryCommand = {
subcommand: 'eos-overlay',
action: 'disable'
}
if (prefix) command['--prefix'] = Path.parse(prefix)
if (prefix) command['--prefix'] = prefix

await runLegendaryCommand(command, {
abortId: eosOverlayAppName,
Expand All @@ -250,22 +244,17 @@ function isInstalled() {
* @param appName required on Linux, does nothing on Windows
* @returns Enabled = True; Disabled = False
*/
async function isEnabled(appName?: string) {
async function isEnabled(appName?: string): Promise<boolean> {
let enabled = false

let prefix = ''
if (isLinux && appName) {
const { winePrefix, wineVersion } =
await gameManagerMap['legendary'].getSettings(appName)
prefix =
wineVersion.type === 'proton' ? join(winePrefix, 'pfx') : winePrefix
}
const prefix = await getWinePrefixFolder(appName)
if (prefix === false) return false

const command: LegendaryCommand = {
subcommand: 'eos-overlay',
action: 'info'
}
if (prefix) command['--prefix'] = Path.parse(prefix)
if (prefix) command['--prefix'] = prefix

await runLegendaryCommand(command, {
abortId: eosOverlayAppName,
Expand All @@ -280,6 +269,26 @@ async function isEnabled(appName?: string) {
return enabled
}

/**
* Returns the path to the "real" Wineprefix folder (where "drive_c" and "user.reg" is) for a game
* @returns null if a prefix can't be returned (we're not on Linux / don't have an AppName)
* @returns false if parsing the prefix path failed (in other words there is a prefix path set, but it doesn't contain a valid prefix)
* @returns ValidWinePrefix (a folder that is verified to contain a Wineprefix) otherwise
*/
async function getWinePrefixFolder(
appName?: string,
runner: Runner = 'legendary'
): Promise<ValidWinePrefix | null | false> {
if (!isLinux || !appName) return null

const { winePrefix, wineVersion } =
await gameManagerMap[runner].getSettings(appName)
const prefixPath =
wineVersion.type === 'proton' ? join(winePrefix, 'pfx') : winePrefix
const maybePrefix = ValidWinePrefix.safeParse(prefixPath)
return maybePrefix.success ? maybePrefix.data : false
}

export {
getStatus,
getLatestVersion,
Expand Down