mirror of
https://git.srhtnin.garden/sarah/SaraSuite.git
synced 2026-10-14 18:28:11 +02:00
Bundle libsecret for systems without it; first launch keeps Flet's message off the client path
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
61c992f959
commit
5890b52da6
4 files changed
+122
-1
No files matched your search
@@ -18,13 +18,47 @@ Used two ways:
|
||||
case Flet just uses its normal client.
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
OriginalId = b"com.appveyor.flet"
|
||||
# Flet's window needs libsecret, which isn't part of GTK and some systems don't
|
||||
# install. SaraSuite keeps copies of it and what it needs (from its AppImage)
|
||||
# here; MissingLibraries puts the ones this system lacks beside the client.
|
||||
LibrariesDir = Path(os.environ.get("XDG_DATA_HOME") or Path.home() / ".local" / "share") / "SaraSuite" / "Libraries"
|
||||
FallbackLibraries = ("libgpg-error.so.0", "libgcrypt.so.20", "libsecret-1.so.0")
|
||||
CopiesDir = Path.home() / ".cache" / "SaraSuite" / "FletClient"
|
||||
|
||||
|
||||
def _SystemHas(Name: str) -> bool:
|
||||
"""Whether the system has a library (its standard folders and linker
|
||||
cache; the same check as the AppImages' RestoreLibraryPath.py)."""
|
||||
import subprocess
|
||||
|
||||
for Folder in ("/usr/lib64", "/usr/lib", "/lib64", "/lib", "/usr/lib/x86_64-linux-gnu", "/lib/x86_64-linux-gnu"):
|
||||
if (Path(Folder) / Name).exists():
|
||||
return True
|
||||
try:
|
||||
Cache = subprocess.run(["ldconfig", "-p"], capture_output=True, text=True, timeout=10,
|
||||
env={"PATH": "/usr/sbin:/usr/bin:/sbin:/bin"}).stdout
|
||||
except (OSError, subprocess.SubprocessError):
|
||||
return False
|
||||
return any(Line.strip().startswith(Name + " ") for Line in Cache.splitlines())
|
||||
|
||||
|
||||
def AddMissingLibraries(ClientLib: Path) -> None:
|
||||
"""Copies SaraSuite's fallback libraries the system doesn't have into the
|
||||
client's lib folder (it looks there first: its RUNPATH is $ORIGIN/lib)."""
|
||||
if not sys.platform.startswith("linux") or not LibrariesDir.is_dir() or not ClientLib.is_dir():
|
||||
return
|
||||
for Name in FallbackLibraries:
|
||||
Source = LibrariesDir / Name
|
||||
if Source.is_file() and not (ClientLib / Name).exists() and not _SystemHas(Name):
|
||||
shutil.copy2(Source, ClientLib / Name)
|
||||
|
||||
|
||||
def ClientFor(AppId: str) -> str:
|
||||
"""Folder of a client copy whose app ID is AppId ("" if not possible).
|
||||
AppId needs a dot (a GTK rule) and at most 17 characters, the length of
|
||||
@@ -36,6 +70,7 @@ def ClientFor(AppId: str) -> str:
|
||||
from flet_desktop import ensure_client_cached # the program's own Flet version
|
||||
|
||||
Original = Path(ensure_client_cached()) / "flet"
|
||||
AddMissingLibraries(Original / "lib")
|
||||
Binary = (Original / "flet").read_bytes()
|
||||
Copy = CopiesDir / f"{Original.parent.name}-{AppId}" / "flet"
|
||||
Patched = Binary.replace(
|
||||
@@ -64,4 +99,16 @@ def ClientFor(AppId: str) -> str:
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(ClientFor(sys.argv[1]) if len(sys.argv) > 1 else "")
|
||||
# Only the folder goes to stdout, which the launcher reads: Flet's own
|
||||
# messages ("Preparing Flet ... for the first use", written straight to
|
||||
# the file descriptor) go to stderr.
|
||||
sys.stdout.flush()
|
||||
Stdout = os.dup(1)
|
||||
os.dup2(2, 1)
|
||||
try:
|
||||
Folder = ClientFor(sys.argv[1]) if len(sys.argv) > 1 else ""
|
||||
finally:
|
||||
sys.stdout.flush()
|
||||
os.dup2(Stdout, 1)
|
||||
os.close(Stdout)
|
||||
print(Folder)
|
||||
Reference in new issue
Block a user