Change parsing of arguments

- Before, the executable and its options were joined as a single string to be executed. Instead, prefer separating them as distinct arguments. As a result, the command as an Array becomes something like:

['/home/foo/.local/share/ULWGL/ULWGL', '--verb', 'waitforexitandrun', '--', '/home/foo/GE-Proton8-30/proton', 'waitforexitandrun', '/home/foo/foo.exe', '-foo', '-bar', '-baz']
This commit is contained in:
R1kaB3rN 2024-02-12 17:19:58 -08:00
parent 2e8faa1f41
commit 6987fde6c3
No known key found for this signature in database
2 changed files with 26 additions and 13 deletions

View File

@ -6,13 +6,13 @@ from argparse import ArgumentParser, Namespace
import sys import sys
from pathlib import Path from pathlib import Path
import tomllib import tomllib
from typing import Dict, Any, List, Set, Union from typing import Dict, Any, List, Set, Union, Tuple
import ulwgl_plugins import ulwgl_plugins
from re import match from re import match
import subprocess import subprocess
def parse_args() -> Union[Namespace, str]: # noqa: D103 def parse_args() -> Union[Namespace, Tuple[str, List[str]]]: # noqa: D103
opt_args: Set[str] = {"--help", "-h", "--config"} opt_args: Set[str] = {"--help", "-h", "--config"}
exe: str = Path(__file__).name exe: str = Path(__file__).name
usage: str = f""" usage: str = f"""
@ -39,7 +39,7 @@ example usage:
if sys.argv[1:][0] in opt_args: if sys.argv[1:][0] in opt_args:
return parser.parse_args(sys.argv[1:]) return parser.parse_args(sys.argv[1:])
return " ".join(sys.argv[1:]) return (sys.argv[1], sys.argv[2:])
def setup_pfx(path: str) -> None: def setup_pfx(path: str) -> None:
@ -122,7 +122,9 @@ def check_env(
return env return env
def set_env(env: Dict[str, str], args: Union[Namespace, str]) -> Dict[str, str]: def set_env(
env: Dict[str, str], args: Union[Namespace, Tuple[str, List[str]]]
) -> Dict[str, str]:
"""Set various environment variables for the Steam RT. """Set various environment variables for the Steam RT.
Filesystem paths will be formatted and expanded as POSIX Filesystem paths will be formatted and expanded as POSIX
@ -145,12 +147,12 @@ def set_env(env: Dict[str, str], args: Union[Namespace, str]) -> Dict[str, str]:
# EXE # EXE
# Empty string for EXE will be used to create a prefix # Empty string for EXE will be used to create a prefix
if isinstance(args, str) and not args: if isinstance(args, tuple) and isinstance(args[0], str) and not args[0]:
env["EXE"] = "" env["EXE"] = ""
env["STEAM_COMPAT_INSTALL_PATH"] = "" env["STEAM_COMPAT_INSTALL_PATH"] = ""
env["PROTON_VERB"] = "waitforexitandrun" env["PROTON_VERB"] = "waitforexitandrun"
elif isinstance(args, str): elif isinstance(args, tuple):
env["EXE"] = Path(args).expanduser().as_posix() env["EXE"] = Path(args[0]).expanduser().as_posix()
env["STEAM_COMPAT_INSTALL_PATH"] = Path(env["EXE"]).parent.as_posix() env["STEAM_COMPAT_INSTALL_PATH"] = Path(env["EXE"]).parent.as_posix()
else: else:
# Config branch # Config branch
@ -223,7 +225,9 @@ def set_env_toml(env: Dict[str, str], args: Namespace) -> Dict[str, str]:
return env return env
def build_command(env: Dict[str, str], command: List[str]) -> List[str]: def build_command(
env: Dict[str, str], command: List[str], opts: List[str] = None
) -> List[str]:
"""Build the command to be executed.""" """Build the command to be executed."""
paths: List[Path] = [ paths: List[Path] = [
Path(Path().home().as_posix() + "/.local/share/ULWGL/ULWGL"), Path(Path().home().as_posix() + "/.local/share/ULWGL/ULWGL"),
@ -256,6 +260,9 @@ def build_command(env: Dict[str, str], command: List[str]) -> List[str]:
[Path(env.get("PROTONPATH") + "/proton").as_posix(), verb, env.get("EXE")] [Path(env.get("PROTONPATH") + "/proton").as_posix(), verb, env.get("EXE")]
) )
if opts:
command.extend([*opts])
return command return command
@ -282,12 +289,14 @@ def main() -> None: # noqa: D103
"PROTON_VERB": "", "PROTON_VERB": "",
} }
command: List[str] = [] command: List[str] = []
# Represents a valid list of current supported Proton verbs args: Union[Namespace, Tuple[str, List[str]]] = parse_args()
args: Union[Namespace, str] = parse_args() opts: List[str] = None
if isinstance(args, Namespace): if isinstance(args, Namespace):
set_env_toml(env, args) set_env_toml(env, args)
else: else:
# Reference the game options
opts = args[1]
check_env(env) check_env(env)
setup_pfx(env["WINEPREFIX"]) setup_pfx(env["WINEPREFIX"])
@ -301,7 +310,7 @@ def main() -> None: # noqa: D103
for key, val in env.items(): for key, val in env.items():
os.environ[key] = val os.environ[key] = val
build_command(env, command) build_command(env, command, opts)
subprocess.run(command, check=True, stdout=subprocess.PIPE, text=True) subprocess.run(command, check=True, stdout=subprocess.PIPE, text=True)

View File

@ -633,7 +633,7 @@ class TestGameLauncher(unittest.TestCase):
result = None result = None
test_str = "foo" test_str = "foo"
# Replicate the usage WINEPREFIX= PROTONPATH= GAMEID= STORE= PROTON_VERB= ulwgl_run ... # Replicate the usage WINEPREFIX= PROTONPATH= GAMEID= STORE= PROTON_VERB= ulwgl_run foo.exe
with patch("sys.argv", ["", self.test_exe]): with patch("sys.argv", ["", self.test_exe]):
os.environ["WINEPREFIX"] = self.test_file os.environ["WINEPREFIX"] = self.test_file
os.environ["PROTONPATH"] = self.test_file os.environ["PROTONPATH"] = self.test_file
@ -642,8 +642,12 @@ class TestGameLauncher(unittest.TestCase):
os.environ["PROTON_VERB"] = self.test_verb os.environ["PROTON_VERB"] = self.test_verb
# Args # Args
result = ulwgl_run.parse_args() result = ulwgl_run.parse_args()
self.assertIsInstance(result, tuple, "Expected a tuple")
self.assertEqual( self.assertEqual(
result[0:], "./tmp.WMYQiPb9A/foo", "Expected EXE to be unexpanded" result[0], "./tmp.WMYQiPb9A/foo", "Expected EXE to be unexpanded"
)
self.assertFalse(
result[1], "Expected an empty list when passing no options"
) )
# Check # Check
ulwgl_run.check_env(self.env) ulwgl_run.check_env(self.env)