summaryrefslogtreecommitdiff
path: root/py_modules/lsfg_vk
diff options
context:
space:
mode:
Diffstat (limited to 'py_modules/lsfg_vk')
-rw-r--r--py_modules/lsfg_vk/flatpak_profile_service.py60
-rw-r--r--py_modules/lsfg_vk/flatpak_service.py87
-rw-r--r--py_modules/lsfg_vk/plugin.py2
3 files changed, 28 insertions, 121 deletions
diff --git a/py_modules/lsfg_vk/flatpak_profile_service.py b/py_modules/lsfg_vk/flatpak_profile_service.py
index 9d2d104..3919159 100644
--- a/py_modules/lsfg_vk/flatpak_profile_service.py
+++ b/py_modules/lsfg_vk/flatpak_profile_service.py
@@ -1,6 +1,5 @@
from __future__ import annotations
-import re
from typing import Any, Dict
from .configuration import ConfigurationService
@@ -17,10 +16,6 @@ class FlatpakProfileService:
"enableZink",
)
BOOLEAN_FIELDS = STATE_FIELDS[1:]
- DXVK_FRAME_RATE_SEGMENT = re.compile(
- r"^(?:dxvk\.maxFrameRate|dxgi\.maxFrameRate|d3d9\.maxFrameRate)\s*=",
- re.IGNORECASE,
- )
def __init__(
self,
@@ -64,14 +59,6 @@ class FlatpakProfileService:
raise RuntimeError("Flatpak application is not owned by this plugin")
return state, entry
- def _baseline_content(self, app_id: str, entry: Dict[str, Any]) -> str:
- if not entry.get("override_existed"):
- return ""
- path = self.flatpak_service._backup_path(app_id)
- if path.is_symlink() or not path.is_file():
- raise RuntimeError("Flatpak override backup is unavailable")
- return path.read_text(encoding="utf-8")
-
@staticmethod
def _environment_value(content: str, key: str) -> str:
section = None
@@ -87,31 +74,14 @@ class FlatpakProfileService:
return value
return ""
- @classmethod
- def _dxvk_config(cls, baseline: str, frame_rate: int) -> str:
- existing = cls._environment_value(baseline, "DXVK_CONFIG")
- parts = [part.strip() for part in existing.split(";") if part.strip()]
- parts = [part for part in parts if not cls.DXVK_FRAME_RATE_SEGMENT.match(part)]
- if frame_rate > 0:
- parts.append(f"dxvk.maxFrameRate = {frame_rate}")
- return "; ".join(parts)
-
- def _restore_baseline(self, app_id: str, entry: Dict[str, Any]) -> None:
- existed, current = self.flatpak_service._snapshot_override(app_id)
- current_hash = self.flatpak_service._sha256(current) if existed else self.flatpak_service._sha256(b"")
- if current_hash != entry.get("managed_sha256"):
- raise RuntimeError("Flatpak override changed after preparation; refusing to overwrite unrelated settings")
- path = self.flatpak_service._override_path(app_id)
- if entry.get("override_existed"):
- self.flatpak_service._write_file(path, self._baseline_content(app_id, entry))
- else:
- path.unlink(missing_ok=True)
+ @staticmethod
+ def _dxvk_config(frame_rate: int) -> str:
+ return f"dxvk.maxFrameRate = {frame_rate}" if frame_rate > 0 else ""
def _apply_state(self, app_id: str, workaround_state: Dict[str, Any]) -> Dict[str, Any]:
workaround_state = self._validate_state(workaround_state)
- _, entry = self._state_entry(app_id)
- baseline = self._baseline_content(app_id, entry)
- self._restore_baseline(app_id, entry)
+ self._state_entry(app_id)
+ self.flatpak_service._reset_app_override(app_id)
prepared = self.flatpak_service.prepare_app(app_id)
if not prepared.get("success") or not prepared.get("owned"):
raise RuntimeError(prepared.get("error") or "Could not restore plugin-owned Flatpak preparation")
@@ -137,21 +107,17 @@ class FlatpakProfileService:
"--env=MESA_LOADER_DRIVER_OVERRIDE=zink",
"--env=GALLIUM_DRIVER=zink",
])
- dxvk_config = self._dxvk_config(baseline, workaround_state["dxvkFrameRate"])
+ dxvk_config = self._dxvk_config(workaround_state["dxvkFrameRate"])
if dxvk_config:
args.append(f"--env=DXVK_CONFIG={dxvk_config}")
args.append(app_id)
result = self.flatpak_service._run_flatpak_command(args, capture_output=True, text=True)
if result.returncode != 0:
raise OSError(result.stderr.strip() or f"Could not apply Flatpak workarounds for {app_id}")
- existed, managed = self.flatpak_service._snapshot_override(app_id)
- if not existed:
- raise RuntimeError(f"Flatpak override for {app_id} was not created")
state = self.flatpak_service._read_state()
entry = state["prepared_apps"].get(app_id)
if not isinstance(entry, dict):
raise RuntimeError("Flatpak application ownership state disappeared")
- entry["managed_sha256"] = self.flatpak_service._sha256(managed)
entry["workaround_state"] = workaround_state
self.flatpak_service._write_state(state)
return workaround_state
@@ -345,15 +311,13 @@ class FlatpakProfileService:
config = self.configuration_service.get_flatpak_config(app_id)
if not config.get("exists"):
continue
- existed, content = self.flatpak_service._snapshot_override(app_id)
- if not existed or self.flatpak_service._sha256(content) != entry.get("managed_sha256"):
- continue
+ shown = self.flatpak_service._run_flatpak_command(
+ ["override", "--user", "--show", app_id],
+ capture_output=True,
+ text=True,
+ )
profile = self.configuration_service.flatpak_profile_name(app_id)
- try:
- text = content.decode("utf-8")
- except UnicodeDecodeError:
- continue
- if self._environment_value(text, "LSFGVK_PROFILE") == profile:
+ if shown.returncode == 0 and self._environment_value(shown.stdout, "LSFGVK_PROFILE") == profile:
enabled.add(app_id)
if not enabled:
return {"success": True, "message": "", "error": None, "apps": []}
diff --git a/py_modules/lsfg_vk/flatpak_service.py b/py_modules/lsfg_vk/flatpak_service.py
index f2ed90c..200a998 100644
--- a/py_modules/lsfg_vk/flatpak_service.py
+++ b/py_modules/lsfg_vk/flatpak_service.py
@@ -1,6 +1,5 @@
from __future__ import annotations
-import hashlib
import json
import os
import pwd
@@ -36,10 +35,6 @@ class FlatpakService(BaseService):
def ownership_path(self) -> Path:
return self.config_dir / self.OWNERSHIP_FILENAME
- @property
- def backup_dir(self) -> Path:
- return self.config_dir / "flatpak-overrides"
-
def _clean_env(self) -> Dict[str, str]:
env = os.environ.copy()
env.pop("LD_LIBRARY_PATH", None)
@@ -77,6 +72,7 @@ class FlatpakService(BaseService):
if runuser is None:
raise FileNotFoundError("runuser command not available")
command = [runuser, "--user", user.pw_name, "--", *command]
+ kwargs.setdefault("timeout", 300 if args and args[0] in ("install", "uninstall") else 30)
return subprocess.run(command, env=env, **kwargs)
@classmethod
@@ -170,10 +166,6 @@ class FlatpakService(BaseService):
self._validate_app_id(app_id)
if not isinstance(entry, dict):
raise RuntimeError("Invalid Flatpak app ownership metadata")
- if type(entry.get("override_existed")) is not bool:
- raise RuntimeError("Invalid Flatpak app ownership metadata")
- if not isinstance(entry.get("managed_sha256"), str):
- raise RuntimeError("Invalid Flatpak app ownership metadata")
return data
def _write_state(self, state: Dict[str, object]) -> None:
@@ -181,8 +173,6 @@ class FlatpakService(BaseService):
apps = state.get("prepared_apps", {})
if not branches and not apps:
self.ownership_path.unlink(missing_ok=True)
- if self.backup_dir.exists() and not any(self.backup_dir.iterdir()):
- self.backup_dir.rmdir()
return
self._write_file(
self.ownership_path,
@@ -196,12 +186,14 @@ class FlatpakService(BaseService):
def _override_path(self, app_id: str) -> Path:
return self.user_home / ".local/share/flatpak/overrides" / self._validate_app_id(app_id)
- def _backup_path(self, app_id: str) -> Path:
- return self.backup_dir / f"{self._validate_app_id(app_id)}.ini"
-
- @staticmethod
- def _sha256(content: bytes) -> str:
- return hashlib.sha256(content).hexdigest()
+ def _reset_app_override(self, app_id: str) -> None:
+ result = self._run_flatpak_command(
+ ["override", "--user", "--reset", self._validate_app_id(app_id)],
+ capture_output=True,
+ text=True,
+ )
+ if result.returncode != 0:
+ raise OSError(result.stderr.strip() or f"Could not reset Flatpak override for {app_id}")
@staticmethod
def _parse_process_start_time(stat_content: str) -> Optional[int]:
@@ -226,16 +218,6 @@ class FlatpakService(BaseService):
return None
return cls._parse_process_start_time(stat_content)
- def _snapshot_override(self, app_id: str) -> tuple[bool, bytes]:
- path = self._override_path(app_id)
- if path.is_symlink():
- raise RuntimeError("Flatpak override path is a symlink")
- if not path.exists():
- return False, b""
- if not path.is_file():
- raise RuntimeError("Flatpak override path is not a regular file")
- return True, path.read_bytes()
-
def _resolve_runtime(self, app_id: str) -> tuple[str, str]:
self._validate_app_id(app_id)
if not self.check_flatpak_available():
@@ -517,28 +499,9 @@ class FlatpakService(BaseService):
raise RuntimeError(extension.get("error") or f"Could not install Flatpak runtime {branch}")
state = self._read_state()
apps = state["prepared_apps"]
- status = self._app_override_status(app_id)
- if status["prepared"] and app_id not in apps:
- return self._success_response(
- dict,
- "Flatpak application is already prepared outside this plugin",
- app_id=app_id,
- runtime=runtime,
- runtime_branch=branch,
- prepared=True,
- owned=False,
- )
if app_id not in apps:
- existed, original = self._snapshot_override(app_id)
- backup = self._backup_path(app_id)
- if existed:
- self._write_file(backup, original.decode("utf-8"))
- else:
- backup.unlink(missing_ok=True)
- apps[app_id] = {
- "override_existed": existed,
- "managed_sha256": "",
- }
+ self._reset_app_override(app_id)
+ apps[app_id] = {}
result = self._run_flatpak_command(
[
"override",
@@ -556,13 +519,8 @@ class FlatpakService(BaseService):
)
if result.returncode != 0:
raise OSError(result.stderr.strip() or f"Could not prepare Flatpak app {app_id}")
- status = self._app_override_status(app_id)
- if not status["prepared"]:
+ if not self._app_override_status(app_id)["prepared"]:
raise RuntimeError(f"Flatpak preparation did not become visible for {app_id}")
- existed, managed = self._snapshot_override(app_id)
- if not existed:
- raise RuntimeError(f"Flatpak override for {app_id} was not created")
- apps[app_id]["managed_sha256"] = self._sha256(managed)
self._write_state(state)
return self._success_response(
dict,
@@ -582,8 +540,7 @@ class FlatpakService(BaseService):
with self._lock:
state = self._read_state()
apps = state["prepared_apps"]
- entry = apps.get(app_id)
- if entry is None:
+ if app_id not in apps:
return self._success_response(
dict,
"Flatpak application is not plugin-owned; existing overrides were preserved",
@@ -591,26 +548,12 @@ class FlatpakService(BaseService):
prepared=self._app_override_status(app_id)["prepared"],
owned=False,
)
- existed, current = self._snapshot_override(app_id)
- current_hash = self._sha256(current) if existed else self._sha256(b"")
- if current_hash != entry["managed_sha256"]:
- raise RuntimeError(
- "Flatpak override changed after preparation; refusing to overwrite unrelated settings"
- )
- override_path = self._override_path(app_id)
- backup_path = self._backup_path(app_id)
- if entry["override_existed"]:
- if not backup_path.is_file() or backup_path.is_symlink():
- raise RuntimeError("Flatpak override backup is unavailable")
- self._write_file(override_path, backup_path.read_text(encoding="utf-8"))
- else:
- override_path.unlink(missing_ok=True)
- backup_path.unlink(missing_ok=True)
+ self._reset_app_override(app_id)
apps.pop(app_id, None)
self._write_state(state)
return self._success_response(
dict,
- "Plugin-owned Flatpak preparation removed",
+ "Plugin-owned Flatpak override reset",
app_id=app_id,
prepared=False,
owned=False,
diff --git a/py_modules/lsfg_vk/plugin.py b/py_modules/lsfg_vk/plugin.py
index c63e3a9..eed7fd7 100644
--- a/py_modules/lsfg_vk/plugin.py
+++ b/py_modules/lsfg_vk/plugin.py
@@ -219,4 +219,4 @@ class Plugin:
os.path.join(decky.DECKY_HOME, "lossless-scaling-vk"),
os.path.join(decky.DECKY_USER_HOME, ".local", "share", "decky-lossless-scaling-vk"),
)
- decky.logger.info("decky-lsfg-vk plugin migrations completed")
+ decky.logger.info("decky-lsfg-vk plugin migrations completed") \ No newline at end of file