small script to help launch things in flatpak wine
| #!/usr/bin/env python3 | |
| import os | |
| import shlex | |
| from pathlib import Path | |
| class ConfigError(Exception): | |
| pass | |
| ENV_KEEP_VARS = frozenset(["HOME", "PWD", "XAUTHORITY", "DISPLAY", "WAYLAND_DISPLAY"]) | |
| ENV_KEEP_PREFIX = frozenset(["XDG_"]) | |
| def should_keep_var(key: str) -> bool: | |
| if key in ENV_KEEP_VARS: | |
| return True | |
| for prefix in ENV_KEEP_PREFIX: | |
| if key.startswith(prefix): | |
| return True | |
| return False | |
| def build_command( | |
| wine_command: str, | |
| wine_flatpak_app: str, | |
| root_dir_override: str | None = None, | |
| wineprefix_override: str | None = None, | |
| extra_flatpak_arguments: list[str] | None = None, | |
| allow_network: bool = True, | |
| allow_default_filesystem: bool = False, | |
| clean_env: bool = False, | |
| ): | |
| if root_dir_override: | |
| root_dir_raw = root_dir_override | |
| else: | |
| root_dir_raw = os.environ.get("WINE_RUNNER_ROOT") | |
| if not root_dir_raw: | |
| raise ConfigError( | |
| "no root directory defined, use the WINE_RUNNER_ROOT env var or the --root-dir argument" | |
| ) | |
| orig_root = Path(root_dir_raw) | |
| root_dir = orig_root.absolute() | |
| if not root_dir.is_dir(): | |
| raise ConfigError(f"root {root_dir} is not a directory") | |
| if wineprefix_override: | |
| wineprefix_str = wineprefix_override | |
| else: | |
| wineprefix_str = os.environ.get("WINEPREFIX") | |
| if wineprefix_str: | |
| wineprefix = Path(wineprefix_str).absolute() | |
| else: | |
| wineprefix = root_dir / ".wine-prefix" | |
| print(f"using root {root_dir} with prefix {wineprefix}") | |
| if not wineprefix.is_relative_to(root_dir): | |
| print("wineprefix is not under root directory, might not be passed through!") | |
| cwd = Path(".").absolute() | |
| common_args = [ | |
| "run", | |
| f"--cwd={cwd}", | |
| ] | |
| command_prefix: list[str] = [] | |
| if clean_env: | |
| env_cmd = ["env", "-i", "-"] | |
| for k, v in os.environ.items(): | |
| if should_keep_var(k): | |
| env_cmd.append(f"{k}={shlex.quote(v)}") | |
| command_prefix = command_prefix + env_cmd | |
| if not allow_default_filesystem: | |
| common_args += [ | |
| "--nofilesystem=host:reset", | |
| ] | |
| common_args += [ | |
| f"--filesystem={root_dir}", | |
| f"--env=WINEPREFIX={wineprefix}", | |
| ] | |
| if not allow_network: | |
| common_args += [ | |
| "--unshare=network", | |
| ] | |
| if extra_flatpak_arguments: | |
| common_args += extra_flatpak_arguments | |
| argv = command_prefix + ["flatpak"] | |
| argv += common_args | |
| if wine_command == "wine": | |
| pass | |
| elif wine_command == "winetricks": | |
| argv.append("--command=winetricks") | |
| else: | |
| raise ConfigError(f"unknown launcher command {wine_command}") | |
| argv.append(wine_flatpak_app) | |
| return argv | |
| def main(): | |
| import argparse | |
| parser = argparse.ArgumentParser( | |
| formatter_class=argparse.ArgumentDefaultsHelpFormatter | |
| ) | |
| parser.add_argument( | |
| "--wine-flatpak", default="org.winehq.Wine", help="Wine flatpak to use" | |
| ) | |
| parser.add_argument( | |
| "--flatpak-run-arg", | |
| action="append", | |
| help="extra argument to pass to flatpak run", | |
| ) | |
| parser.add_argument( | |
| "--root-dir", | |
| type=str, | |
| help="root path to pass over, overrides the env var WINE_RUNNER_ROOT", | |
| ) | |
| parser.add_argument( | |
| "--allow-default-filesystem", | |
| action="store_true", | |
| help="do not reset filesystem access settings", | |
| ) | |
| parser.add_argument( | |
| "--clean-env", | |
| action="store_true", | |
| help="do not pass environment variables", | |
| ) | |
| parser.add_argument( | |
| "--no-network", action="store_true", help="disable network access" | |
| ) | |
| parser.add_argument( | |
| "--wineprefix", | |
| type=str, | |
| help="wineprefix path, overrides the env var WINEPREFIX", | |
| ) | |
| parser.add_argument( | |
| "-n", "--dry-run", action="store_true", help="do not execute anything" | |
| ) | |
| parser.add_argument( | |
| "command", choices=["wine", "winetricks"], help="command to run" | |
| ) | |
| parser.add_argument("args", nargs="*") | |
| args = parser.parse_args() | |
| try: | |
| argv = build_command( | |
| wine_command=args.command, | |
| wine_flatpak_app=args.wine_flatpak, | |
| root_dir_override=args.root_dir, | |
| wineprefix_override=args.wineprefix, | |
| extra_flatpak_arguments=args.flatpak_run_arg, | |
| allow_default_filesystem=args.allow_default_filesystem, | |
| allow_network=not args.no_network, | |
| clean_env=args.clean_env, | |
| ) | |
| except ConfigError as e: | |
| print(str(e)) | |
| return 1 | |
| argv += args.args | |
| cmd_str = shlex.join(argv) | |
| print(f"running:\n {cmd_str}") | |
| if args.dry_run: | |
| print("dry run: not executing command") | |
| else: | |
| os.execvp(argv[0], argv) | |
| return 0 | |
| if __name__ == "__main__": | |
| import sys | |
| sys.exit(main()) |
评论
?
参与讨论