aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-03-11 03:16:40 -0500
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-03-11 03:16:40 -0500
commit360bdaaa2dfb167d42cdd21d0386c440dee634de (patch)
treecbb2e73ffff4cb4266a5a5d09cd3edba1ebdb84f
parentd6e7531b0dccc96fbb859bbd629ad16b756ebb2e (diff)
Sync entire app to ~/.local/share/fluorine/bin/ for stable symlinks
The launcher now deploys the full application (not just Python) to the central data directory on launch. Instance plugin symlinks always point to this stable location instead of the tarball extraction dir, so they survive moves/deletes of the original archive. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
-rwxr-xr-xdocker/build-inner.sh50
-rw-r--r--flake.nix47
2 files changed, 52 insertions, 45 deletions
diff --git a/docker/build-inner.sh b/docker/build-inner.sh
index bd0ed73..d035e34 100755
--- a/docker/build-inner.sh
+++ b/docker/build-inner.sh
@@ -317,7 +317,6 @@ cat > "${OUT_DIR}/fluorine-manager" <<'LAUNCH'
set -euo pipefail
SELF="$(readlink -f "$0")"
HERE="$(cd "$(dirname "$SELF")" && pwd)"
-export PATH="${HERE}:${PATH}"
# Save the original environment so game launches (Proton/Wine) can restore it.
# Without this, our bundled LD_LIBRARY_PATH leaks into game processes and
@@ -327,40 +326,45 @@ export FLUORINE_ORIG_PATH="${PATH}"
export FLUORINE_ORIG_XDG_DATA_DIRS="${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
export FLUORINE_ORIG_QT_PLUGIN_PATH="${QT_PLUGIN_PATH:-}"
-# ── Sync portable Python to data dir (only when outdated) ──
+# ── Sync entire app to ~/.local/share/fluorine/bin/ ──
+# This gives instances a stable symlink target that won't break if the user
+# moves or deletes the original tarball extraction directory.
FLUORINE_DATA="${HOME}/.local/share/fluorine"
-PYTHON_DST="${FLUORINE_DATA}/python"
-PYTHON_SRC="${HERE}/python"
+BIN_DST="${FLUORINE_DATA}/bin"
-if [ -d "${PYTHON_SRC}" ]; then
- CURRENT_VER="$(stat -c '%i:%Y' "${PYTHON_SRC}/bin/python3" 2>/dev/null || echo "unknown")"
- MARKER="${PYTHON_DST}/.version"
+# Use the main binary's mtime as a version fingerprint.
+CURRENT_VER="$(stat -c '%i:%Y' "${HERE}/ModOrganizer-core" 2>/dev/null || echo "unknown")"
+MARKER="${BIN_DST}/.version"
- if [ ! -f "${MARKER}" ] || [ "$(cat "${MARKER}" 2>/dev/null)" != "${CURRENT_VER}" ]; then
- echo "Syncing Python runtime to ${PYTHON_DST}..." >&2
- rm -rf "${PYTHON_DST}"
- mkdir -p "${PYTHON_DST}"
- (cd "${PYTHON_SRC}" && tar --exclude-vcs -cf - .) | (cd "${PYTHON_DST}" && tar -xf -)
- echo "${CURRENT_VER}" > "${MARKER}"
- fi
+if [ ! -f "${MARKER}" ] || [ "$(cat "${MARKER}" 2>/dev/null)" != "${CURRENT_VER}" ]; then
+ echo "Syncing Fluorine to ${BIN_DST}..." >&2
+ rm -rf "${BIN_DST}"
+ mkdir -p "${BIN_DST}"
+ (cd "${HERE}" && tar --exclude-vcs -cf - .) | (cd "${BIN_DST}" && tar -xf -)
+ echo "${CURRENT_VER}" > "${MARKER}"
fi
-export LD_LIBRARY_PATH="${HERE}/lib:${PYTHON_DST}/lib:${LD_LIBRARY_PATH:-}"
-export MO2_BASE_DIR="${HERE}"
-export MO2_PLUGINS_DIR="${HERE}/plugins"
-export MO2_DLLS_DIR="${HERE}/dlls"
-export MO2_PYTHON_DIR="${PYTHON_DST}"
+# Run from the synced location.
+RUN="${BIN_DST}"
+PYTHON_DIR="${RUN}/python"
+
+export PATH="${RUN}:${PATH}"
+export LD_LIBRARY_PATH="${RUN}/lib:${PYTHON_DIR}/lib:${LD_LIBRARY_PATH:-}"
+export MO2_BASE_DIR="${RUN}"
+export MO2_PLUGINS_DIR="${RUN}/plugins"
+export MO2_DLLS_DIR="${RUN}/dlls"
+export MO2_PYTHON_DIR="${PYTHON_DIR}"
# PYTHONHOME is set only for the MO2 process (not exported to children like
# Proton which has its own Python). MO2_PYTHON_DIR lets the
# binary reconstruct it internally.
-MO2_PYTHONHOME="${PYTHON_DST}"
+MO2_PYTHONHOME="${PYTHON_DIR}"
unset PYTHONPATH PYTHONNOUSERSITE PYTHONHOME
# Use bundled Qt6 plugins.
-export QT_PLUGIN_PATH="${HERE}/qt6plugins"
+export QT_PLUGIN_PATH="${RUN}/qt6plugins"
-cd "${HERE}"
-exec env PYTHONHOME="${MO2_PYTHONHOME}" "${HERE}/ModOrganizer-core" "$@"
+cd "${RUN}"
+exec env PYTHONHOME="${MO2_PYTHONHOME}" "${RUN}/ModOrganizer-core" "$@"
LAUNCH
chmod +x "${OUT_DIR}/fluorine-manager"
diff --git a/flake.nix b/flake.nix
index 192f3ee..8c85827 100644
--- a/flake.nix
+++ b/flake.nix
@@ -356,41 +356,44 @@
set -euo pipefail
SELF="$(readlink -f "$0")"
HERE="$(cd "$(dirname "$SELF")" && pwd)"
-export PATH="${HERE}:${PATH}"
export FLUORINE_ORIG_LD_LIBRARY_PATH="${LD_LIBRARY_PATH:-}"
export FLUORINE_ORIG_PATH="${PATH}"
export FLUORINE_ORIG_XDG_DATA_DIRS="${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
export FLUORINE_ORIG_QT_PLUGIN_PATH="${QT_PLUGIN_PATH:-}"
+# Sync entire app to ~/.local/share/fluorine/bin/ so instance plugin
+# symlinks always point to a stable location.
FLUORINE_DATA="${HOME}/.local/share/fluorine"
-PYTHON_DST="${FLUORINE_DATA}/python"
-PYTHON_SRC="${HERE}/python"
+BIN_DST="${FLUORINE_DATA}/bin"
-if [ -d "${PYTHON_SRC}" ]; then
- CURRENT_VER="$(stat -c '%i:%Y' "${PYTHON_SRC}/bin/python3" 2>/dev/null || echo "unknown")"
- MARKER="${PYTHON_DST}/.version"
- if [ ! -f "${MARKER}" ] || [ "$(cat "${MARKER}" 2>/dev/null)" != "${CURRENT_VER}" ]; then
- echo "Syncing Python runtime to ${PYTHON_DST}..." >&2
- rm -rf "${PYTHON_DST}"
- mkdir -p "${PYTHON_DST}"
- (cd "${PYTHON_SRC}" && tar --exclude-vcs -cf - .) | (cd "${PYTHON_DST}" && tar -xf -)
- echo "${CURRENT_VER}" > "${MARKER}"
- fi
+CURRENT_VER="$(stat -c '%i:%Y' "${HERE}/ModOrganizer-core" 2>/dev/null || echo "unknown")"
+MARKER="${BIN_DST}/.version"
+
+if [ ! -f "${MARKER}" ] || [ "$(cat "${MARKER}" 2>/dev/null)" != "${CURRENT_VER}" ]; then
+ echo "Syncing Fluorine to ${BIN_DST}..." >&2
+ rm -rf "${BIN_DST}"
+ mkdir -p "${BIN_DST}"
+ (cd "${HERE}" && tar --exclude-vcs -cf - .) | (cd "${BIN_DST}" && tar -xf -)
+ echo "${CURRENT_VER}" > "${MARKER}"
fi
-export LD_LIBRARY_PATH="${HERE}/lib:${PYTHON_DST}/lib:${LD_LIBRARY_PATH:-}"
-export MO2_BASE_DIR="${HERE}"
-export MO2_PLUGINS_DIR="${HERE}/plugins"
-export MO2_DLLS_DIR="${HERE}/dlls"
-export MO2_PYTHON_DIR="${PYTHON_DST}"
-MO2_PYTHONHOME="${PYTHON_DST}"
+RUN="${BIN_DST}"
+PYTHON_DIR="${RUN}/python"
+
+export PATH="${RUN}:${PATH}"
+export LD_LIBRARY_PATH="${RUN}/lib:${PYTHON_DIR}/lib:${LD_LIBRARY_PATH:-}"
+export MO2_BASE_DIR="${RUN}"
+export MO2_PLUGINS_DIR="${RUN}/plugins"
+export MO2_DLLS_DIR="${RUN}/dlls"
+export MO2_PYTHON_DIR="${PYTHON_DIR}"
+MO2_PYTHONHOME="${PYTHON_DIR}"
unset PYTHONPATH PYTHONNOUSERSITE PYTHONHOME
-export QT_PLUGIN_PATH="${HERE}/qt6plugins"
+export QT_PLUGIN_PATH="${RUN}/qt6plugins"
-cd "${HERE}"
-exec env PYTHONHOME="${MO2_PYTHONHOME}" "${HERE}/ModOrganizer-core" "$@"
+cd "${RUN}"
+exec env PYTHONHOME="${MO2_PYTHONHOME}" "${RUN}/ModOrganizer-core" "$@"
LAUNCH
chmod +x $out/opt/fluorine-manager/fluorine-manager