diff --git a/umu/umu_util.py b/umu/umu_util.py index 930f28c19..8c98cf59d 100644 --- a/umu/umu_util.py +++ b/umu/umu_util.py @@ -5,7 +5,7 @@ from json import load, dump from umu_log import log from pathlib import Path -from shutil import rmtree, move, copy, copytree +from shutil import rmtree, move, copy from umu_plugins import enable_zenity from urllib.request import urlopen from ssl import create_default_context @@ -154,8 +154,7 @@ def _install_umu( ~/.local/share/umu, ~/.local/share/Steam/compatibilitytools.d The tools that will be copied are: - SteamRT, Pressure Vessel, umu-launcher, umu Launcher files, Reaper - and umu_version.json + umu-launcher, umu Launcher files, reaper and umu_version.json """ log.debug("New install detected") log.console("Setting up Unified Launcher for Windows Games on Linux ...") @@ -164,17 +163,17 @@ def _install_umu( # Config log.console(f"Copied {CONFIG} -> {local}") - copy(root.joinpath(CONFIG), local.joinpath(CONFIG)) + _copy(root.joinpath(CONFIG), local.joinpath(CONFIG)) # Reaper log.console(f"Copied reaper -> {local}") - copy(root.joinpath("reaper"), local.joinpath("reaper")) + _copy(root.joinpath("reaper"), local.joinpath("reaper")) # Launcher files for file in root.glob("*.py"): if not file.name.startswith("umu_test"): log.console(f"Copied {file} -> {local}") - copy(file, local.joinpath(file.name)) + _copy(file, local.joinpath(file.name)) local.joinpath("umu-run").symlink_to("umu_run.py") @@ -184,11 +183,9 @@ def _install_umu( # Remove existing files if they exist -- this is a clean install. if steam_compat.joinpath("umu-launcher").is_dir(): rmtree(steam_compat.joinpath("umu-launcher").as_posix()) - copytree( + _copytree( root.joinpath("umu-launcher"), steam_compat.joinpath("umu-launcher"), - dirs_exist_ok=True, - symlinks=True, ) steam_compat.joinpath("umu-launcher", "umu-run").symlink_to( "../../../umu/umu_run.py" @@ -232,7 +229,7 @@ def _update_umu( # Directory is absent if not local.joinpath("reaper").is_file(): log.warning("Reaper not found") - copy(root.joinpath("reaper"), local.joinpath("reaper")) + _copy(root.joinpath("reaper"), local.joinpath("reaper")) log.console(f"Restored {key} to {val}") # Update @@ -240,7 +237,7 @@ def _update_umu( log.console(f"Updating {key} to {val}") local.joinpath("reaper").unlink(missing_ok=True) - copy(root.joinpath("reaper"), local.joinpath("reaper")) + _copy(root.joinpath("reaper"), local.joinpath("reaper")) json_local["umu"]["versions"]["reaper"] = val elif key == "runtime_platform": @@ -288,7 +285,7 @@ def _update_umu( for file in root.glob("*.py"): if not file.name.startswith("umu_test"): local.joinpath(file.name).unlink(missing_ok=True) - copy(file, local.joinpath(file.name)) + _copy(file, local.joinpath(file.name)) # Symlink local.joinpath("umu-run").unlink(missing_ok=True) @@ -305,7 +302,7 @@ def _update_umu( ): is_missing = True log.warning("Missing %s", file.name) - copy(file, local.joinpath(file.name)) + _copy(file, local.joinpath(file.name)) if is_missing: log.console(f"Restored {key} to {val}") @@ -319,11 +316,9 @@ def _update_umu( if not steam_compat.joinpath("umu-launcher").is_dir(): log.warning("umu-launcher not found") - copytree( + _copytree( root.joinpath("umu-launcher"), steam_compat.joinpath("umu-launcher"), - dirs_exist_ok=True, - symlinks=True, ) steam_compat.joinpath("umu-launcher", "umu-run").symlink_to( @@ -335,11 +330,9 @@ def _update_umu( log.console(f"Updating {key} to {val}") rmtree(steam_compat.joinpath("umu-launcher").as_posix()) - copytree( + _copytree( root.joinpath("umu-launcher"), steam_compat.joinpath("umu-launcher"), - dirs_exist_ok=True, - symlinks=True, ) steam_compat.joinpath("umu-launcher", "umu-run").symlink_to( @@ -384,3 +377,29 @@ def _get_json(path: Path, config: str) -> Dict[str, Any]: raise ValueError(err) return json + + +def _copy(src: Path, dst: Path) -> None: + dst.parent.mkdir(parents=True, exist_ok=True) + + if src.is_symlink(): + dst.symlink_to(src.readlink()) + return + + if src.stat().st_mode == 33060: # Read-only permissions + log.debug("Read-only filesystem detected") + log.debug("Added read-write permission to '%s'", dst.name) + copy(src, dst) + dst.chmod(0o644) # Add read-write permissions for user + return + copy(src, dst) + + +def _copytree(src: Path, dest: Path) -> None: + for file in src.iterdir(): + if file.is_dir(): + dest_subdir = dest / file.name + dest_subdir.mkdir(parents=True, exist_ok=True) + _copytree(file, dest_subdir) + else: + _copy(file, dest / file.name)