diff --git a/README.md b/README.md index ba35961..c74775b 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,27 @@ Pre-built artifacts are published at runnable directly, no Python installation required on the host. Lua support still needs a system `lua` interpreter and the `lua-socket` / `lua-cjson` modules. +* **AppImage** (`Testium--x86_64.AppImage`) — single-file + Linux binary, runnable directly: + + ```sh + chmod +x Testium-*-x86_64.AppImage + ./Testium-*-x86_64.AppImage + ``` + + Requires `libfuse2` on the host (FUSE 2 — distinct from `fuse3`, which + most distros now ship by default): + + | Distro | Package | + |--------|---------| + | Arch / CachyOS / Manjaro | `fuse2` | + | Debian trixie / Ubuntu 24.04+ | `libfuse2t64` | + | Debian bookworm / Ubuntu 22.04 | `libfuse2` | + | Fedora | `fuse-libs` | + + If you can't install libfuse2 (e.g. minimal container), prefix the + invocation with `APPIMAGE_EXTRACT_AND_RUN=1` — the AppImage will + self-extract to `/tmp` on each run instead of FUSE-mounting. * **Flatpak bundle** (`testium.flatpak`) — install with: ```sh diff --git a/src/testium/interpreter/utils/version.py b/src/testium/interpreter/utils/version.py index 8508b95..cec153c 100644 --- a/src/testium/interpreter/utils/version.py +++ b/src/testium/interpreter/utils/version.py @@ -1,10 +1,54 @@ +import atexit import os +import stat import sys +import tempfile from importlib import import_module import interpreter.utils.settings as prefs import api.testium as tm + +# When running inside a Flatpak, the host /usr/bin/git is reachable at +# /run/host/usr/bin/git but linked against host glibc/zlib, which the +# sandbox can't load (``libz-ng.so.2`` not found). gitpython resolves git +# eagerly on import and would crash the whole test run. We install a +# tiny shell wrapper under /tmp that forwards to ``flatpak-spawn --host +# git``, and point gitpython at it via ``GIT_PYTHON_GIT_EXECUTABLE``. +_HOST_GIT_WRAPPER = None + + +def _setup_flatpak_git(): + global _HOST_GIT_WRAPPER + if not os.path.isfile("/.flatpak-info"): + return + if _HOST_GIT_WRAPPER is not None: + return + fd, path = tempfile.mkstemp(prefix="testium-git-host-", suffix=".sh", dir="/tmp") + with os.fdopen(fd, "w") as f: + f.write('#!/bin/sh\nexec flatpak-spawn --host git "$@"\n') + os.chmod(path, stat.S_IRWXU) + _HOST_GIT_WRAPPER = path + atexit.register(_cleanup_flatpak_git) + os.environ["GIT_PYTHON_GIT_EXECUTABLE"] = path + # Silence gitpython's warning if its refresh probe ever still fails; + # the wrapper itself should make the probe succeed. + os.environ.setdefault("GIT_PYTHON_REFRESH", "quiet") + + +def _cleanup_flatpak_git(): + global _HOST_GIT_WRAPPER + if _HOST_GIT_WRAPPER and os.path.isfile(_HOST_GIT_WRAPPER): + try: + os.unlink(_HOST_GIT_WRAPPER) + except OSError: + pass + _HOST_GIT_WRAPPER = None + + +_setup_flatpak_git() + + _cached_versions = {} def repo_rev(path):