mirror of
https://github.com/lhns/steam-frame-nix.git
synced 2026-10-06 01:00:13 +02:00
install.sh cleanup: remove what steam-frame-nix wrote outside the Nix store
`install.sh cleanup [--dry-run] (--all | --orphans [--keep <artifact>]...)` knows every file any version wrote outside the store and Home Manager's links, removes only what is provably its own, prints every action and reports everything else as "left alone"; a second run changes nothing. Only bash, coreutils, findutils, grep, sed, awk and jq (all in /usr/bin on SteamOS), so it also works piped from curl after a rollback or with Nix gone. - SteamVR debugger: VRWebHelper.DebuggerEnabled is put back to its value from before (steamvr-debugger.armed; the old empty marker means "absent" and is migrated), only while SteamVR is stopped. While it runs, a runtime drop-in (/run/user/<uid>/systemd/user/steamvr.service.d) runs a /usr/bin-only restore script from /run/user/<uid>/steam-frame-nix when SteamVR stops. - icon fallback links into Breeze and their manifest (dirs only if they held nothing else; hicolor's mtime bumped so Steam rescans). - Firefox: the desktop profile's user.js link, older user.js links and marker-headed copies, and the values they left in prefs.js (only with the profile closed; deferred otherwise). - Jellyfin: the hwdec shim entries in the Flatpak override (devices=all only when it came with them), an empty override file, the old shim copy. - the dashboard patches' saved state: --all only; --orphans removes just stale *.json.tmp files. `install.sh uninstall` runs `cleanup --all` before removing Home Manager (replacing its own ui-patches removal) and names what is deferred; `install.sh status` shows what `cleanup --all` would do. The flake exports it as packages.<system>.cleanup / apps.cleanup (`nix run github:lhns/steam-frame-nix#cleanup -- --all`), and checks.cleanup runs it against fake home and runtime dirs: every artifact next to look-alikes that aren't ours, --dry-run, second runs, SteamVR running (deferral, restore script), the user's own debugger key.
This commit is contained in:
1 parent
7fe68e055c
commit
7255315b73
4 files changed
+711
-17
No files matched your search
@@ -34,18 +34,34 @@
|
||||
firefox = ./modules/firefox.nix;
|
||||
jellyfin = ./modules/jellyfin.nix;
|
||||
};
|
||||
systems = [ "aarch64-linux" "x86_64-linux" ];
|
||||
forSystems = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system});
|
||||
in {
|
||||
homeManagerModules = modules // {
|
||||
default = { imports = builtins.attrValues modules; };
|
||||
};
|
||||
|
||||
# Removes what steam-frame-nix wrote outside the Nix store (install.sh
|
||||
# cleanup): nix run github:lhns/steam-frame-nix#cleanup -- --all
|
||||
packages = forSystems (pkgs: {
|
||||
cleanup = pkgs.callPackage ./modules/cleanup/package.nix { };
|
||||
});
|
||||
apps = nixpkgs.lib.mapAttrs (_: p: {
|
||||
cleanup = {
|
||||
type = "app";
|
||||
program = "${p.cleanup}/bin/steam-frame-nix-cleanup";
|
||||
meta.description = "Remove what steam-frame-nix wrote outside the Nix store";
|
||||
};
|
||||
}) self.packages;
|
||||
|
||||
# Tests of the VR keyboard (text model, corrector, swipe decoder on the
|
||||
# default German + English dictionary) and of the Jellyfin mpv shim:
|
||||
# nix flake check
|
||||
checks = nixpkgs.lib.genAttrs [ "aarch64-linux" "x86_64-linux" ] (system: {
|
||||
jellyfin = import ./modules/jellyfin/check.nix { pkgs = nixpkgs.legacyPackages.${system}; };
|
||||
# default German + English dictionary), the Jellyfin mpv shim and
|
||||
# install.sh cleanup: nix flake check
|
||||
checks = forSystems (pkgs: {
|
||||
cleanup = import ./modules/cleanup/check.nix { inherit pkgs; };
|
||||
jellyfin = import ./modules/jellyfin/check.nix { inherit pkgs; };
|
||||
vr-keyboard = (import ./modules/vr-keyboard/build.nix {
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
inherit pkgs;
|
||||
dictionary = {
|
||||
languages = map (l: l // { keepFrequentAbove = 4.0; }) [
|
||||
{ language = "de"; hunspell = "de_DE"; words = 60000; frequencyOffset = 0.0; }
|
||||
|
||||
+482
-12
@@ -1,8 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
# Install or uninstall Nix + Home Manager on SteamOS (Steam Frame, Steam Deck).
|
||||
# Install or uninstall Nix + Home Manager on SteamOS (Steam Frame, Steam Deck),
|
||||
# and clean up what steam-frame-nix wrote outside the Nix store.
|
||||
#
|
||||
# curl -fsSL https://steam-frame-nix.lhns.de | bash -s -- install
|
||||
# curl -fsSL https://steam-frame-nix.lhns.de | bash -s -- uninstall
|
||||
# curl -fsSL https://steam-frame-nix.lhns.de | bash -s -- cleanup --all
|
||||
#
|
||||
# Run `install.sh --help` for details. Works from a file or piped into bash
|
||||
# (prompts read from /dev/tty).
|
||||
@@ -24,7 +26,7 @@ USER_UNIT_DIR="$CONFIG_HOME/systemd/user"
|
||||
|
||||
USER_NAME="$(id -un)"
|
||||
USER_ID="$(id -u)"
|
||||
OUTER_RUNTIME_DIR="/run/user/$USER_ID"
|
||||
OUTER_RUNTIME_DIR="${STEAM_FRAME_NIX_RUNTIME_DIR:-/run/user/$USER_ID}"
|
||||
|
||||
ASSUME_YES=0
|
||||
RO_RELOCK=0
|
||||
@@ -58,13 +60,30 @@ Commands:
|
||||
Re-running just switches again.
|
||||
|
||||
uninstall [--yes] [--keep-nix]
|
||||
Stop Home Manager's user services, uninstall Home Manager, uninstall
|
||||
Nix (unless --keep-nix) and remove per-user Nix leftovers and the
|
||||
dashboard patches' saved state (~/.local/state/steam-frame-nix/ui-patches).
|
||||
Your configuration directory is never deleted.
|
||||
Stop Home Manager's user services, run 'cleanup --all', uninstall Home
|
||||
Manager, uninstall Nix (unless --keep-nix) and remove per-user Nix
|
||||
leftovers. Your configuration directory is never deleted.
|
||||
|
||||
cleanup [--dry-run] (--all | --orphans [--keep <artifact>]...)
|
||||
Remove what steam-frame-nix (any version) wrote outside the Nix store,
|
||||
only where it is provably its own; everything else is reported as
|
||||
"left alone". Safe to re-run. Needs bash, coreutils, findutils, jq.
|
||||
--all everything, incl. the dashboard patches' saved choices
|
||||
(~/.local/state/steam-frame-nix/ui-patches). Use after
|
||||
rolling back to a generation without steam-frame-nix,
|
||||
or before removing it.
|
||||
--orphans what the configuration no longer uses (run by the Home
|
||||
Manager module on every switch); keeps saved choices.
|
||||
--keep still in use (with --orphans): debugger,
|
||||
firefox-desktop-userjs=<profile>
|
||||
--dry-run only print what would be done
|
||||
SteamVR's VRWebHelper.DebuggerEnabled can't be changed while SteamVR
|
||||
runs; it is then restored when SteamVR stops (a drop-in in
|
||||
/run/user/<uid>, gone at reboot).
|
||||
|
||||
status
|
||||
Show Nix, Home Manager and user service state.
|
||||
Show Nix, Home Manager and user service state, and what
|
||||
'cleanup --all' would remove.
|
||||
|
||||
Options:
|
||||
--yes, -y Don't ask; answer yes to every question.
|
||||
@@ -358,6 +377,453 @@ Next steps:
|
||||
EOF
|
||||
}
|
||||
|
||||
# --- cleanup ----------------------------------------------------------------
|
||||
#
|
||||
# Everything steam-frame-nix (any version) ever wrote outside the Nix store
|
||||
# and Home Manager's own links, and how it is proven to be ours:
|
||||
#
|
||||
# debugger VRWebHelper.DebuggerEnabled in steamvr.vrsettings. Proof:
|
||||
# $SFN_STATE/steamvr-debugger.armed (holds the value before;
|
||||
# older versions: the empty marker steamvr-debugger, value
|
||||
# before = absent). Restored once SteamVR is stopped; while it
|
||||
# runs a runtime drop-in restores it when SteamVR stops.
|
||||
# Also the runtime drop-in and restore script themselves.
|
||||
# icons links hicolor/scalable/apps/<name>.svg -> Breeze in the store
|
||||
# (the icon-fallbacks script of 2026-09; manifest
|
||||
# $SFN_STATE/icon-fallbacks).
|
||||
# firefox user.js in Firefox profiles: links to the desktop profile's
|
||||
# /app/etc/firefox/steam-frame-nix-desktop-user.js, older links
|
||||
# to *-firefox-*user.js and copies starting with FF_MARKER, and
|
||||
# the values they left in prefs.js (only with Firefox closed).
|
||||
# jellyfin the hwdec shim entries in the Jellyfin Flatpak's user override
|
||||
# (nix-flatpak), an empty override file, and the shim copy of
|
||||
# earlier versions (marker $SFN_STATE/jellyfin-hwdec-shim).
|
||||
# ui-state the dashboard patches' saved choices
|
||||
# ($SFN_STATE/ui-patches/<name>.json; --all only, never
|
||||
# --orphans) and stray *.json.tmp files.
|
||||
# dirs $SFN_STATE and $OUTER_RUNTIME_DIR/steam-frame-nix when empty.
|
||||
#
|
||||
# --orphans keeps what the current configuration still uses (--keep ...);
|
||||
# the Home Manager module runs it on every switch. Anything not proven ours
|
||||
# is reported as "left alone" and never touched.
|
||||
|
||||
SFN_STATE="${XDG_STATE_HOME:-$HOME/.local/state}/steam-frame-nix"
|
||||
SFN_DATA="${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||
SFN_RUNTIME="$OUTER_RUNTIME_DIR/steam-frame-nix"
|
||||
VRSETTINGS="$HOME/.config/openvr/config/steamvr.vrsettings"
|
||||
DEBUGGER_ARMED="$SFN_STATE/steamvr-debugger.armed"
|
||||
DEBUGGER_MARKER_V1="$SFN_STATE/steamvr-debugger"
|
||||
DEBUGGER_RESTORE="$SFN_RUNTIME/steamvr-debugger-restore"
|
||||
DEBUGGER_DROPIN="$OUTER_RUNTIME_DIR/systemd/user/steamvr.service.d/50-steam-frame-nix-debugger.conf"
|
||||
ICON_DIR="$SFN_DATA/icons/hicolor/scalable/apps"
|
||||
ICON_MANIFEST="$SFN_STATE/icon-fallbacks"
|
||||
FF_DIR="$HOME/.var/app/org.mozilla.firefox/config/mozilla/firefox"
|
||||
FF_DESKTOP_JS=/app/etc/firefox/steam-frame-nix-desktop-user.js
|
||||
FF_MARKER="// Managed by steam-frame-nix (steamFrame.firefox); rewritten on switch."
|
||||
JF_APP=org.jellyfin.JellyfinDesktop
|
||||
JF_OVERRIDE="$SFN_DATA/flatpak/overrides/$JF_APP"
|
||||
JF_SHIM_COPY="$HOME/.var/app/$JF_APP/mpv-hwdec-shim.so"
|
||||
JF_SHIM_MARKER="$SFN_STATE/jellyfin-hwdec-shim"
|
||||
UI_STATE="$SFN_STATE/ui-patches"
|
||||
|
||||
CLEAN_DRY=0
|
||||
CLEAN_ACTIONS=0
|
||||
CLEAN_DEFERRED=()
|
||||
declare -A CLEAN_GONE=()
|
||||
|
||||
c_do() { CLEAN_ACTIONS=$((CLEAN_ACTIONS + 1)); if (( CLEAN_DRY )); then info "would $1"; return 1; fi; }
|
||||
c_done() { info "$1"; }
|
||||
c_left() { info "left alone: $1"; }
|
||||
c_defer() { CLEAN_DEFERRED+=("$1"); info "deferred: $1"; }
|
||||
|
||||
c_rm() { # path why
|
||||
c_do "remove $1 ($2)" || { CLEAN_GONE[$1]=1; return 0; }
|
||||
rm -f -- "$1" && CLEAN_GONE[$1]=1 && c_done "removed $1 ($2)"
|
||||
}
|
||||
|
||||
# Empty, or will be once the planned removals are done (dry run).
|
||||
c_empty_after() {
|
||||
local e
|
||||
while IFS= read -r -d '' e; do
|
||||
[[ -n ${CLEAN_GONE[$e]:-} ]] || return 1
|
||||
done < <(find "$1" -mindepth 1 -maxdepth 1 -print0 2>/dev/null)
|
||||
}
|
||||
|
||||
c_rmdir() { # dir: removed if empty (after the planned removals)
|
||||
[[ -d $1 && ! -L $1 ]] && c_empty_after "$1" || return 0
|
||||
c_do "remove empty directory $1" || { CLEAN_GONE[$1]=1; return 0; }
|
||||
rmdir -- "$1" && CLEAN_GONE[$1]=1 && c_done "removed empty directory $1"
|
||||
}
|
||||
|
||||
c_write() { # path why: replace the contents with stdin (same inode and mode)
|
||||
local tmp
|
||||
if (( CLEAN_DRY )); then cat >/dev/null; c_do "rewrite $1 ($2)" || true; return 0; fi
|
||||
c_do "rewrite $1 ($2)"
|
||||
tmp="$(mktemp "$1.sfn-XXXXXX")"
|
||||
cat >"$tmp" && cat "$tmp" >"$1"
|
||||
rm -f -- "$tmp"
|
||||
c_done "rewrote $1 ($2)"
|
||||
}
|
||||
|
||||
# systemctl --user of the outer session (overridable for tests).
|
||||
c_systemctl() {
|
||||
if [[ -n ${STEAM_FRAME_NIX_SYSTEMCTL:-} ]]; then "$STEAM_FRAME_NIX_SYSTEMCTL" --user "$@"
|
||||
elif outer_bus_ok; then outer_systemctl "$@"
|
||||
else return 1; fi
|
||||
}
|
||||
|
||||
# running | stopped | unknown
|
||||
steamvr_state() {
|
||||
local s
|
||||
if s="$(c_systemctl show -p ActiveState --value steamvr.service 2>/dev/null)" && [[ -n $s ]]; then
|
||||
case $s in inactive|failed) echo stopped ;; *) echo running ;; esac
|
||||
elif pgrep -u "$USER_ID" -x vrserver >/dev/null 2>&1; then echo running
|
||||
else echo unknown; fi
|
||||
}
|
||||
|
||||
# --- the SteamVR debugger key ---
|
||||
|
||||
# Puts VRWebHelper.DebuggerEnabled back to the value in <armed> ("absent",
|
||||
# "false"; "nofile": the file didn't exist) if it is still true, then removes
|
||||
# <armed>. Standalone (also written into the runtime restore script): bash,
|
||||
# coreutils and jq only.
|
||||
debugger_restore() { # vrsettings armed
|
||||
local f=$1 armed=$2 prior cur tmp filter
|
||||
[[ -f $armed ]] || return 0
|
||||
prior="$(tr -d '[:space:]' <"$armed")"
|
||||
case $prior in
|
||||
false) filter='.VRWebHelper.DebuggerEnabled = false' ;;
|
||||
absent|nofile|'') filter='.VRWebHelper |= del(.DebuggerEnabled) | if .VRWebHelper == {} then del(.VRWebHelper) else . end' ;;
|
||||
*) echo "steam-frame-nix: $armed holds '$prior', not a value it writes; left as is" >&2; return 1 ;;
|
||||
esac
|
||||
if [[ -f $f ]]; then
|
||||
cur="$(jq -r '.VRWebHelper.DebuggerEnabled // "absent"' "$f")" || { echo "steam-frame-nix: can't read $f" >&2; return 1; }
|
||||
if [[ $cur == true ]]; then
|
||||
tmp="$(mktemp "$f.XXXXXX")" || return 1
|
||||
if ! jq --indent 3 "$filter" "$f" >"$tmp"; then rm -f "$tmp"; return 1; fi
|
||||
chmod --reference="$f" "$tmp"
|
||||
mv -f "$tmp" "$f"
|
||||
if [[ $prior == nofile && $(jq -c . "$f") == '{}' ]]; then
|
||||
rm -f "$f"
|
||||
echo "steam-frame-nix: removed $f (created only for VRWebHelper.DebuggerEnabled)"
|
||||
else
|
||||
echo "steam-frame-nix: VRWebHelper.DebuggerEnabled in $f restored (${prior/nofile/absent})"
|
||||
fi
|
||||
else
|
||||
echo "steam-frame-nix: VRWebHelper.DebuggerEnabled in $f is $cur (changed since); left as is"
|
||||
fi
|
||||
fi
|
||||
rm -f "$armed"
|
||||
}
|
||||
|
||||
debugger_restore_script() {
|
||||
# shellcheck disable=SC2016 # literal lines of the script
|
||||
printf '%s\n' '#!/usr/bin/bash' \
|
||||
'# steam-frame-nix: puts SteamVR'"'"'s VRWebHelper.DebuggerEnabled back to its' \
|
||||
'# value from before steam-frame-nix set it. Run by the runtime drop-in' \
|
||||
'# steamvr.service.d/50-steam-frame-nix-debugger.conf when SteamVR stops;' \
|
||||
'# both live in $XDG_RUNTIME_DIR until reboot. /usr/bin tools only.' \
|
||||
'PATH=/usr/bin:/bin${PATH:+:$PATH}'
|
||||
declare -f debugger_restore
|
||||
printf 'debugger_restore %q %q\n' "$VRSETTINGS" "$DEBUGGER_ARMED"
|
||||
}
|
||||
|
||||
debugger_dropin() {
|
||||
printf '%s\n' '# steam-frame-nix: restores VRWebHelper.DebuggerEnabled when SteamVR stops.' \
|
||||
'# Runtime only (gone at reboot).' \
|
||||
'[Service]' \
|
||||
'ExecStopPost=-/usr/bin/bash %t/steam-frame-nix/steamvr-debugger-restore'
|
||||
}
|
||||
|
||||
# Runtime drop-in + script so that stopping SteamVR restores the key, even
|
||||
# after Nix and Home Manager are gone. Returns 0 if it (would have) changed.
|
||||
debugger_ensure_hook() {
|
||||
local changed=1
|
||||
if [[ $(cat "$DEBUGGER_RESTORE" 2>/dev/null) != "$(debugger_restore_script)" ]]; then
|
||||
changed=0
|
||||
if c_do "write the restore script $DEBUGGER_RESTORE"; then
|
||||
mkdir -p "$SFN_RUNTIME"
|
||||
debugger_restore_script >"$DEBUGGER_RESTORE"
|
||||
c_done "wrote the restore script $DEBUGGER_RESTORE"
|
||||
fi
|
||||
fi
|
||||
if [[ $(cat "$DEBUGGER_DROPIN" 2>/dev/null) != "$(debugger_dropin)" ]]; then
|
||||
changed=0
|
||||
if c_do "write the runtime drop-in $DEBUGGER_DROPIN"; then
|
||||
mkdir -p "${DEBUGGER_DROPIN%/*}"
|
||||
debugger_dropin >"$DEBUGGER_DROPIN"
|
||||
c_done "wrote the runtime drop-in $DEBUGGER_DROPIN"
|
||||
c_systemctl daemon-reload || warn "could not reload the user manager; the restore on SteamVR stop needs: systemctl --user daemon-reload"
|
||||
fi
|
||||
fi
|
||||
return $changed
|
||||
}
|
||||
|
||||
debugger_remove_hook() {
|
||||
[[ -f $DEBUGGER_RESTORE ]] && c_rm "$DEBUGGER_RESTORE" "debugger restore script"
|
||||
c_rmdir "$SFN_RUNTIME"
|
||||
[[ -f $DEBUGGER_DROPIN ]] || return 0
|
||||
c_rm "$DEBUGGER_DROPIN" "runtime drop-in of the debugger restore"
|
||||
# The directories only if they held nothing but the drop-in.
|
||||
c_rmdir "${DEBUGGER_DROPIN%/*}"
|
||||
c_rmdir "$OUTER_RUNTIME_DIR/systemd/user"
|
||||
c_rmdir "$OUTER_RUNTIME_DIR/systemd"
|
||||
(( CLEAN_DRY )) || c_systemctl daemon-reload || true
|
||||
return 0
|
||||
}
|
||||
|
||||
clean_debugger() { # keep
|
||||
local keep=$1 prior='' state cur
|
||||
if [[ -f $DEBUGGER_ARMED ]]; then
|
||||
prior="$(tr -d '[:space:]' <"$DEBUGGER_ARMED")"
|
||||
[[ -e $DEBUGGER_MARKER_V1 ]] && c_rm "$DEBUGGER_MARKER_V1" "old debugger marker, superseded by ${DEBUGGER_ARMED##*/}"
|
||||
elif [[ -f $DEBUGGER_MARKER_V1 ]]; then
|
||||
prior=absent
|
||||
if c_do "migrate $DEBUGGER_MARKER_V1 to $DEBUGGER_ARMED (value before: absent)"; then
|
||||
printf 'absent\n' >"$DEBUGGER_ARMED"
|
||||
rm -f -- "$DEBUGGER_MARKER_V1"
|
||||
c_done "migrated $DEBUGGER_MARKER_V1 to $DEBUGGER_ARMED (value before: absent)"
|
||||
else
|
||||
CLEAN_GONE[$DEBUGGER_MARKER_V1]=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z $prior ]]; then
|
||||
if [[ -f $VRSETTINGS ]] && command -v jq >/dev/null 2>&1 \
|
||||
&& [[ $(jq -r '.VRWebHelper.DebuggerEnabled // empty' "$VRSETTINGS" 2>/dev/null) == true ]] \
|
||||
&& (( ! keep )); then
|
||||
c_left "VRWebHelper.DebuggerEnabled = true in $VRSETTINGS (not set by steam-frame-nix)"
|
||||
fi
|
||||
(( keep )) || debugger_remove_hook
|
||||
return 0
|
||||
fi
|
||||
|
||||
command -v jq >/dev/null 2>&1 || { warn "jq not found; VRWebHelper.DebuggerEnabled left as is"; return 0; }
|
||||
state="$(steamvr_state)"
|
||||
if [[ $state == stopped ]]; then
|
||||
cur="$(jq -r '.VRWebHelper.DebuggerEnabled // "absent"' "$VRSETTINGS" 2>/dev/null || echo '?')"
|
||||
if [[ $cur == true ]]; then
|
||||
if c_do "restore VRWebHelper.DebuggerEnabled in $VRSETTINGS (${prior/nofile/absent})"; then
|
||||
debugger_restore "$VRSETTINGS" "$DEBUGGER_ARMED" 2>&1 | sed 's/^steam-frame-nix: / /' \
|
||||
|| warn "restoring VRWebHelper.DebuggerEnabled failed; $DEBUGGER_ARMED kept"
|
||||
fi
|
||||
fi
|
||||
if [[ -f $DEBUGGER_ARMED && ( $cur != true || CLEAN_DRY -eq 1 ) ]]; then
|
||||
c_rm "$DEBUGGER_ARMED" "proof of the debugger key, no longer needed"
|
||||
fi
|
||||
(( keep )) || debugger_remove_hook
|
||||
else
|
||||
# Running (or unknown): SteamVR rewrites the file from memory; restore
|
||||
# when it stops.
|
||||
if [[ $state == unknown ]] && ! c_systemctl --version >/dev/null 2>&1; then
|
||||
c_defer "VRWebHelper.DebuggerEnabled ($VRSETTINGS): user manager not reachable; run this again from the Steam session or with SteamVR stopped"
|
||||
return 0
|
||||
fi
|
||||
debugger_ensure_hook || true
|
||||
(( keep )) || c_defer "VRWebHelper.DebuggerEnabled ($VRSETTINGS) is restored to ${prior/nofile/absent} when SteamVR stops"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# --- icon fallback links ---
|
||||
|
||||
clean_icons() {
|
||||
local l t removed=0
|
||||
for l in "$ICON_DIR"/*.svg; do
|
||||
[[ -L $l ]] || continue
|
||||
t="$(readlink "$l")"
|
||||
case $t in
|
||||
/nix/store/*-breeze-icons-*/share/icons/breeze/apps/*) c_rm "$l" "icon fallback link to Breeze"; removed=1 ;;
|
||||
*-home-manager-files/*) ;;
|
||||
esac
|
||||
done
|
||||
[[ -e $ICON_MANIFEST ]] && c_rm "$ICON_MANIFEST" "icon fallback manifest" && removed=1
|
||||
(( removed )) || return 0
|
||||
# The directories only if they held nothing but our links.
|
||||
c_rmdir "$ICON_DIR"
|
||||
c_rmdir "${ICON_DIR%/*}"
|
||||
c_rmdir "${ICON_DIR%/*/*}"
|
||||
# GTK (Steam) rescans a theme only when a theme dir's mtime changes.
|
||||
if [[ -d ${ICON_DIR%/*/*} && -z ${CLEAN_GONE[${ICON_DIR%/*/*}]:-} ]]; then
|
||||
if c_do "touch ${ICON_DIR%/*/*} (mtime only, so Steam rescans icons)"; then
|
||||
touch -- "${ICON_DIR%/*/*}"; c_done "touched ${ICON_DIR%/*/*} (mtime only, so Steam rescans icons)"
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# --- Firefox user.js ---
|
||||
|
||||
ff_keys() { sed -n 's/^[[:space:]]*user_pref(\("[^"]*"\),.*/\1/p' "$1" 2>/dev/null || true; }
|
||||
ff_in_use() { find /proc/[0-9]*/fd -lname "$1/.parentlock" -print -quit 2>/dev/null | grep -q .; }
|
||||
|
||||
clean_firefox() { # keep_profile ('' = none)
|
||||
local keep=$1 prof name u t kind keys pats left
|
||||
[[ -d $FF_DIR ]] || return 0
|
||||
for prof in "$FF_DIR"/*/; do
|
||||
prof=${prof%/}; name=${prof##*/}; u=$prof/user.js
|
||||
[[ -e $u || -L $u ]] || continue
|
||||
keys=''
|
||||
if [[ -L $u ]]; then
|
||||
t="$(readlink "$u")"
|
||||
case $t in
|
||||
"$FF_DESKTOP_JS")
|
||||
[[ $name == "$keep" ]] && continue
|
||||
kind="desktop profile user.js link"; keys='"full-screen-api.ignore-widgets"' ;;
|
||||
/nix/store/*-firefox-user.js|/nix/store/*-firefox-desktop-user.js)
|
||||
kind="user.js link of an older version"; keys="$(ff_keys "$u")"
|
||||
[[ -e $u ]] || info "note: $t is gone; values it set stay in $prof/prefs.js" ;;
|
||||
*) c_left "$u (link to $t)"; continue ;;
|
||||
esac
|
||||
elif [[ -f $u && $(head -n1 "$u") == "$FF_MARKER" ]]; then
|
||||
kind="user.js copy of an older version"; keys="$(ff_keys "$u")"
|
||||
else
|
||||
c_left "$u (not written by steam-frame-nix)"; continue
|
||||
fi
|
||||
# Firefox stored the values the file set in prefs.js; take them out too.
|
||||
# shellcheck disable=SC2001 # per line
|
||||
pats="$(sed 's/.*/user_pref(&,/' <<<"$keys")"
|
||||
if [[ -n $keys && -f $prof/prefs.js ]] && grep -qF "$pats" "$prof/prefs.js"; then
|
||||
if ff_in_use "$prof"; then
|
||||
c_defer "$u: Firefox is using profile $name; close it and run this again"
|
||||
continue
|
||||
fi
|
||||
left="$(grep -vF "$pats" "$prof/prefs.js" || true)"
|
||||
printf '%s\n' "$left" | c_write "$prof/prefs.js" "values of the $kind: ${keys//$'\n'/ }"
|
||||
fi
|
||||
c_rm "$u" "$kind"
|
||||
c_rmdir "$prof"
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
# --- Jellyfin ---
|
||||
|
||||
# The override with our entries taken out: LD_PRELOAD of the shim,
|
||||
# SFN_MPV_HWDEC, the shim's filesystems entry and, only if one of these was
|
||||
# there, devices=all. Prints "devices=<0|1>" (devices=all removed), then the
|
||||
# result; exit 3 if nothing of ours was found.
|
||||
jf_strip() {
|
||||
awk '
|
||||
function trim(s) { gsub(/^[[:space:]]+|[[:space:]]+$/, "", s); return s }
|
||||
function drop(list, pat, n, a, i, out) {
|
||||
n = split(list, a, ";"); out = ""
|
||||
for (i = 1; i <= n; i++) { a[i] = trim(a[i]); if (a[i] == "") continue
|
||||
if (a[i] ~ pat) { hit = 1; continue } out = out a[i] ";" }
|
||||
return out }
|
||||
FNR == 1 { pass++; sec = "" }
|
||||
/^[[:space:]]*\[/ { sec = trim($0); if (pass == 2) { hdr[++nh] = sec; body[nh] = "" } next }
|
||||
{
|
||||
line = $0; key = trim(substr(line, 1, index(line, "=") - 1)); val = substr(line, index(line, "=") + 1)
|
||||
hit = 0
|
||||
if (sec == "[Environment]" && key == "LD_PRELOAD" && val ~ /^\/nix\/store\/[^\/]*mpv-hwdec-shim[^\/]*\/lib\/mpv-hwdec-shim\.so$/) { hit = 1; line = "" }
|
||||
else if (sec == "[Environment]" && key == "SFN_MPV_HWDEC") { hit = 1; line = "" }
|
||||
else if (sec == "[Context]" && key == "filesystems") {
|
||||
v = drop(val, "^/nix/store/[^/]*mpv-hwdec-shim[^/]*(:ro)?$"); line = (v == "" ? "" : key "=" v) }
|
||||
else if (sec == "[Context]" && key == "devices" && pass == 2 && ours) {
|
||||
v = drop(val, "^all$"); if (hit) devs = 1; line = (v == "" ? "" : key "=" v); hit = 0 }
|
||||
if (pass == 1) { if (hit) ours = 1; next }
|
||||
if (trim(line) == "") next
|
||||
body[nh] = body[nh] line "\n"
|
||||
}
|
||||
END {
|
||||
if (!ours) exit 3
|
||||
print "devices=" (devs ? 1 : 0)
|
||||
for (i = 0; i <= nh; i++) if (body[i] != "") { if (i) printf "%s\n", hdr[i]; printf "%s\n", body[i] }
|
||||
}
|
||||
' "$1" "$1"
|
||||
}
|
||||
|
||||
clean_jellyfin() {
|
||||
local out rc t
|
||||
if [[ -L $JF_OVERRIDE ]]; then
|
||||
t="$(readlink "$JF_OVERRIDE")"
|
||||
[[ $t == *-home-manager-files/* ]] || c_left "$JF_OVERRIDE (link to $t)"
|
||||
elif [[ -f $JF_OVERRIDE ]]; then
|
||||
if [[ -z $(tr -d '[:space:]' <"$JF_OVERRIDE") ]]; then
|
||||
c_rm "$JF_OVERRIDE" "empty Flatpak override"
|
||||
else
|
||||
rc=0; out="$(jf_strip "$JF_OVERRIDE")" || rc=$?
|
||||
if (( rc == 0 )); then
|
||||
[[ ${out%%$'\n'*} == devices=1 ]] && info "devices=all goes too (it came with the hwdec shim entries)"
|
||||
out=${out#*$'\n'}; [[ $out == devices=? ]] && out=''
|
||||
if [[ -z $(tr -d '[:space:]' <<<"$out") ]]; then
|
||||
c_rm "$JF_OVERRIDE" "Flatpak override with only the hwdec shim entries"
|
||||
else
|
||||
printf '%s\n' "$out" | c_write "$JF_OVERRIDE" "hwdec shim entries"
|
||||
warn "$JF_OVERRIDE keeps entries of its own: $(grep -v '^\[' <<<"$out" | grep . | tr '\n' ' ')"
|
||||
fi
|
||||
elif (( rc == 3 )); then
|
||||
c_left "$JF_OVERRIDE (no hwdec shim entries)"
|
||||
else
|
||||
warn "could not read $JF_OVERRIDE; left as is"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [[ -e $JF_SHIM_MARKER ]]; then
|
||||
[[ -e $JF_SHIM_COPY || -L $JF_SHIM_COPY ]] && c_rm "$JF_SHIM_COPY" "hwdec shim copy of an older version"
|
||||
c_rm "$JF_SHIM_MARKER" "its marker"
|
||||
elif [[ -e $JF_SHIM_COPY ]]; then
|
||||
c_left "$JF_SHIM_COPY (no marker $JF_SHIM_MARKER)"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# --- dashboard patch state ---
|
||||
|
||||
clean_ui_state() { # all
|
||||
local f n age=(-mmin +1) # --orphans: not one being written right now
|
||||
[[ -d $UI_STATE ]] || return 0
|
||||
(( $1 )) && age=()
|
||||
while IFS= read -r -d '' f; do
|
||||
c_rm "$f" "unfinished write of the dashboard patch state"
|
||||
done < <(find "$UI_STATE" -maxdepth 1 -type f -name '*.json.tmp' "${age[@]}" -print0)
|
||||
if (( $1 )); then
|
||||
for f in "$UI_STATE"/*.json; do
|
||||
[[ -f $f ]] || continue
|
||||
n=${f##*/}; c_rm "$f" "saved choices of the dashboard patch ${n%.json}"
|
||||
done
|
||||
fi
|
||||
c_rmdir "$UI_STATE"
|
||||
return 0
|
||||
}
|
||||
|
||||
cmd_cleanup() {
|
||||
local mode='' keep_debugger=0 keep_ff='' keeps=0 k
|
||||
while (( $# )); do
|
||||
case $1 in
|
||||
--all) mode=all; shift ;;
|
||||
--orphans) mode=orphans; shift ;;
|
||||
--dry-run|-n) CLEAN_DRY=1; shift ;;
|
||||
--keep)
|
||||
[[ $# -ge 2 ]] || die "--keep needs an artifact"
|
||||
k=$2; shift 2; keeps=$((keeps + 1))
|
||||
case $k in
|
||||
debugger) keep_debugger=1 ;;
|
||||
firefox-desktop-userjs=?*) keep_ff=${k#*=} ;;
|
||||
*) die "cleanup: unknown artifact '$k' for --keep (debugger, firefox-desktop-userjs=<profile>)" ;;
|
||||
esac ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) die "cleanup: unknown option '$1' (see --help)" ;;
|
||||
esac
|
||||
done
|
||||
[[ -n $mode ]] || die "cleanup: --all or --orphans is required (see --help)"
|
||||
[[ $mode == all && $keeps -gt 0 ]] && die "cleanup: --keep only goes with --orphans"
|
||||
need_not_root
|
||||
|
||||
CLEAN_ACTIONS=0; CLEAN_DEFERRED=(); CLEAN_GONE=()
|
||||
step "steam-frame-nix: cleaning up files outside Nix ($mode$( (( CLEAN_DRY )) && echo ', dry run'))"
|
||||
clean_debugger "$keep_debugger"
|
||||
clean_icons
|
||||
clean_firefox "$keep_ff"
|
||||
clean_jellyfin
|
||||
clean_ui_state "$([[ $mode == all ]] && echo 1 || echo 0)"
|
||||
c_rmdir "$SFN_STATE"
|
||||
if [[ $mode == all ]]; then c_rmdir "$SFN_RUNTIME"; fi
|
||||
(( CLEAN_ACTIONS || ${#CLEAN_DEFERRED[@]} )) || info "nothing to clean up"
|
||||
return 0
|
||||
}
|
||||
|
||||
# --- uninstall --------------------------------------------------------------
|
||||
|
||||
# User units installed by Home Manager (unit files resolving into /nix/store).
|
||||
@@ -471,10 +937,6 @@ remove_leftovers() { # keep_nix
|
||||
fi
|
||||
fi
|
||||
remove_path "$state/home-manager"
|
||||
# Saved state of the dashboard UI patches (steam-ui-patches, state = true).
|
||||
# Only this subdirectory: the directory's other files have their own rules.
|
||||
remove_path "$state/steam-frame-nix/ui-patches"
|
||||
rmdir "$state/steam-frame-nix" 2>/dev/null || true
|
||||
if [[ -L $HM_CONFIG_LINK ]]; then
|
||||
info "$HM_CONFIG_LINK pointed to $(readlink "$HM_CONFIG_LINK")"
|
||||
remove_path "$HM_CONFIG_LINK"
|
||||
@@ -512,6 +974,7 @@ cmd_uninstall() {
|
||||
|
||||
load_nix
|
||||
stop_hm_services
|
||||
cmd_cleanup --all
|
||||
remove_hm
|
||||
|
||||
if (( ! keep_nix )); then
|
||||
@@ -534,9 +997,13 @@ cmd_uninstall() {
|
||||
Intentionally left in place:
|
||||
- your configuration (e.g. $DEFAULT_CONFIG_DIR)
|
||||
- files Home Manager renamed to *.hm-backup-<time>
|
||||
- app data, e.g. ~/.local/share/docker, and Flatpak apps
|
||||
- app data, e.g. ~/.local/share/docker, Firefox profiles, and Flatpak apps
|
||||
Log out or reboot so running sessions drop the removed tweaks.
|
||||
EOF
|
||||
if (( ${#CLEAN_DEFERRED[@]} )); then
|
||||
printf '\nNot done yet:\n'
|
||||
printf ' - %s\n' "${CLEAN_DEFERRED[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
# --- status -----------------------------------------------------------------
|
||||
@@ -595,6 +1062,8 @@ cmd_status() {
|
||||
info "user manager not reachable at $OUTER_RUNTIME_DIR"
|
||||
fi
|
||||
info "$(printf '%-30s %s' clipboard-sync "$(pgrep -u "$USER_ID" -x clipboard-sync >/dev/null && echo running || echo 'not running')")"
|
||||
|
||||
cmd_cleanup --dry-run --all
|
||||
}
|
||||
|
||||
# --- main -------------------------------------------------------------------
|
||||
@@ -606,6 +1075,7 @@ main() {
|
||||
install) cmd_install "$@" ;;
|
||||
uninstall) cmd_uninstall "$@" ;;
|
||||
status) cmd_status "$@" ;;
|
||||
cleanup) cmd_cleanup "$@" ;;
|
||||
-h|--help|help) usage ;;
|
||||
'') usage >&2; exit 2 ;;
|
||||
*) printf 'unknown command: %s\n\n' "$cmd" >&2; usage >&2; exit 2 ;;
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
# Checks of `install.sh cleanup` on fake home and runtime dirs: every
|
||||
# artifact any version wrote (removed or restored) next to look-alikes that
|
||||
# aren't ours (left alone), --dry-run changes nothing, a second run changes
|
||||
# nothing, SteamVR running defers the debugger key to a runtime drop-in.
|
||||
{ pkgs }:
|
||||
let
|
||||
cleanup = pkgs.callPackage ./package.nix { };
|
||||
in
|
||||
pkgs.runCommand "cleanup-check" { nativeBuildInputs = [ cleanup pkgs.jq ]; } ''
|
||||
set -euo pipefail
|
||||
fail() { echo "FAIL: $*" >&2; exit 1; }
|
||||
export HOME XDG_RUNTIME_DIR STEAM_FRAME_NIX_RUNTIME_DIR STEAM_FRAME_NIX_SYSTEMCTL
|
||||
unset XDG_STATE_HOME XDG_DATA_HOME XDG_CONFIG_HOME
|
||||
|
||||
# systemctl stub: SteamVR's state from $STUB/state, calls logged.
|
||||
STUB=$PWD/stub; mkdir -p $STUB
|
||||
cat > $STUB/systemctl <<'SH'
|
||||
#!/usr/bin/env bash
|
||||
echo "$*" >> "$STUB/log"
|
||||
case "$*" in *"show -p ActiveState --value steamvr.service"*) cat "$STUB/state" ;; esac
|
||||
SH
|
||||
chmod +x $STUB/systemctl
|
||||
sed -i "1s|.*|#!${pkgs.bash}/bin/bash|" $STUB/systemctl
|
||||
export STUB
|
||||
STEAM_FRAME_NIX_SYSTEMCTL=$STUB/systemctl
|
||||
|
||||
fresh() {
|
||||
root=$PWD/$1; rm -rf $root; mkdir -p $root/home $root/run
|
||||
HOME=$root/home XDG_RUNTIME_DIR=$root/run STEAM_FRAME_NIX_RUNTIME_DIR=$root/run
|
||||
: > $STUB/log; echo inactive > $STUB/state
|
||||
S=$HOME/.local/state/steam-frame-nix
|
||||
V=$HOME/.config/openvr/config/steamvr.vrsettings
|
||||
I=$HOME/.local/share/icons/hicolor/scalable/apps
|
||||
F=$HOME/.var/app/org.mozilla.firefox/config/mozilla/firefox
|
||||
O=$HOME/.local/share/flatpak/overrides
|
||||
mkdir -p $S/ui-patches ''${V%/*} $I $F $O
|
||||
}
|
||||
snap() { (cd $root && find . -printf '%p %y %m %l %T@\n' | sort; find . -type f -exec sha256sum {} + | sort) ; }
|
||||
has() { grep -qF -- "$2" <<< "$1" || fail "output lacks '$2':"$'\n'"$1"; }
|
||||
hasnt() { ! grep -qF -- "$2" <<< "$1" || fail "output has '$2':"$'\n'"$1"; }
|
||||
gone() { for p; do [ ! -e "$p" ] && [ ! -L "$p" ] || fail "still there: $p"; done; }
|
||||
there() { for p; do [ -e "$p" ] || [ -L "$p" ] || fail "missing: $p"; done; }
|
||||
noop() { # a further run changes nothing
|
||||
local before; before=$(snap); res=$(steam-frame-nix-cleanup "$@")
|
||||
[ "$(snap)" = "$before" ] || fail "second run changed files"
|
||||
! grep -Eq '^ +(removed|rewrote|wrote|migrated|touched) | restored \(' <<< "$res" || fail "second run acted:"$'\n'"$res"
|
||||
}
|
||||
|
||||
# --- A: --all, SteamVR stopped: everything ---
|
||||
fresh a
|
||||
printf '{\n "VRWebHelper" : {\n "DebuggerEnabled" : true,\n "DebuggerPort" : 8087\n },\n "steamvr" : {}\n}\n' > $V
|
||||
chmod 600 $V
|
||||
touch $S/steamvr-debugger # marker of the first version
|
||||
mkdir -p $root/run/steam-frame-nix $root/run/systemd/user/steamvr.service.d
|
||||
echo old > $root/run/steam-frame-nix/steamvr-debugger-restore
|
||||
echo old > $root/run/systemd/user/steamvr.service.d/50-steam-frame-nix-debugger.conf
|
||||
echo keep > $root/run/systemd/user/steamvr.service.d/other.conf
|
||||
ln -s /nix/store/00000000000000000000000000000000-breeze-icons-6.30.0/share/icons/breeze/apps/64/utilities-terminal.svg $I/utilities-terminal.svg
|
||||
ln -s /nix/store/00000000000000000000000000000000-home-manager-files/.local/share/icons/hicolor/scalable/apps/hm.svg $I/hm.svg
|
||||
ln -s /somewhere/else.svg $I/other.svg
|
||||
printf 'utilities-terminal\n' > $S/icon-fallbacks
|
||||
mkdir -p $F/desktop $F/a.default $F/b.old $F/c.mine $F/d.busy $F/e.fresh
|
||||
ln -s /app/etc/firefox/steam-frame-nix-desktop-user.js $F/desktop/user.js
|
||||
printf 'user_pref("full-screen-api.ignore-widgets", false);\nuser_pref("other", 1);\n' > $F/desktop/prefs.js
|
||||
printf '%s\nuser_pref("a.b", true);\n' '// Managed by steam-frame-nix (steamFrame.firefox); rewritten on switch.' > $F/a.default/user.js
|
||||
printf 'user_pref("a.b", true);\nuser_pref("c.d", 2);\n' > $F/a.default/prefs.js
|
||||
ln -s /nix/store/00000000000000000000000000000000-firefox-user.js $F/b.old/user.js
|
||||
echo 'user_pref("mine", 1);' > $F/c.mine/user.js
|
||||
printf '%s\nuser_pref("a.b", true);\n' '// Managed by steam-frame-nix (steamFrame.firefox); rewritten on switch.' > $F/d.busy/user.js
|
||||
printf 'user_pref("a.b", true);\n' > $F/d.busy/prefs.js; touch $F/d.busy/.parentlock
|
||||
ln -s /app/etc/firefox/steam-frame-nix-desktop-user.js $F/e.fresh/user.js
|
||||
printf '[Context]\ndevices=all;\nfilesystems=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim:ro;xdg-music:ro;\n\n[Environment]\nLD_PRELOAD=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim/lib/mpv-hwdec-shim.so\nSFN_MPV_HWDEC=v4l2m2m-copy,auto-copy\nFOO=bar\n' > $O/org.jellyfin.JellyfinDesktop
|
||||
printf '[Context]\ndevices=all;\n' > $O/org.example.Other
|
||||
mkdir -p $HOME/.var/app/org.jellyfin.JellyfinDesktop
|
||||
echo so > $HOME/.var/app/org.jellyfin.JellyfinDesktop/mpv-hwdec-shim.so; touch $S/jellyfin-hwdec-shim
|
||||
echo '{"a":1}' > $S/ui-patches/frame-controls.json; echo '{' > $S/ui-patches/vr-cat.json.tmp
|
||||
echo mine > $S/ui-patches/notes.txt
|
||||
|
||||
exec 9< $F/d.busy/.parentlock # Firefox "uses" d.busy
|
||||
before=$(snap)
|
||||
res=$(steam-frame-nix-cleanup --dry-run --all)
|
||||
[ "$(snap)" = "$before" ] || fail "--dry-run changed files"
|
||||
has "$res" "would remove $I/utilities-terminal.svg"
|
||||
has "$res" "would restore VRWebHelper.DebuggerEnabled"
|
||||
hasnt "$res" "removed "
|
||||
! grep -q daemon-reload $STUB/log || fail "--dry-run reloaded systemd"
|
||||
|
||||
res=$(steam-frame-nix-cleanup --all); echo "$res"
|
||||
# debugger: key gone (value before: absent), other keys kept, 3-space indent, mode kept
|
||||
[ "$(jq -c .VRWebHelper $V)" = '{"DebuggerPort":8087}' ] || fail "vrsettings: $(cat $V)"
|
||||
grep -q '^ "VRWebHelper"' $V || fail "indent"
|
||||
[ "$(stat -c %a $V)" = 600 ] || fail "mode"
|
||||
gone $S/steamvr-debugger $S/steamvr-debugger.armed $root/run/steam-frame-nix \
|
||||
$root/run/systemd/user/steamvr.service.d/50-steam-frame-nix-debugger.conf
|
||||
there $root/run/systemd/user/steamvr.service.d/other.conf
|
||||
grep -q daemon-reload $STUB/log || fail "no daemon-reload after removing the drop-in"
|
||||
# icons
|
||||
gone $I/utilities-terminal.svg $S/icon-fallbacks
|
||||
there $I/hm.svg $I/other.svg
|
||||
has "$res" "left alone: $F/c.mine/user.js"
|
||||
# firefox
|
||||
gone $F/desktop/user.js $F/a.default/user.js $F/b.old/user.js $F/e.fresh
|
||||
[ "$(cat $F/desktop/prefs.js)" = 'user_pref("other", 1);' ] || fail "desktop prefs.js: $(cat $F/desktop/prefs.js)"
|
||||
[ "$(cat $F/a.default/prefs.js)" = 'user_pref("c.d", 2);' ] || fail "a.default prefs.js"
|
||||
there $F/c.mine/user.js $F/d.busy/user.js
|
||||
grep -q a.b $F/d.busy/prefs.js || fail "busy profile changed"
|
||||
has "$res" "deferred: $F/d.busy/user.js: Firefox is using profile d.busy"
|
||||
# jellyfin
|
||||
[ "$(cat $O/org.jellyfin.JellyfinDesktop)" = "$(printf '[Context]\nfilesystems=xdg-music:ro;\n\n[Environment]\nFOO=bar')" ] \
|
||||
|| fail "override: $(cat $O/org.jellyfin.JellyfinDesktop)"
|
||||
has "$res" "devices=all goes too"
|
||||
there $O/org.example.Other
|
||||
gone $HOME/.var/app/org.jellyfin.JellyfinDesktop/mpv-hwdec-shim.so $S/jellyfin-hwdec-shim
|
||||
# ui state: ours gone, foreign file kept (so the dirs stay)
|
||||
gone $S/ui-patches/frame-controls.json $S/ui-patches/vr-cat.json.tmp
|
||||
there $S/ui-patches/notes.txt
|
||||
noop --all
|
||||
exec 9<&-
|
||||
res=$(steam-frame-nix-cleanup --all)
|
||||
gone $F/d.busy/user.js
|
||||
[ ! -s $F/d.busy/prefs.js ] || [ -z "$(tr -d '[:space:]' < $F/d.busy/prefs.js)" ] || fail "busy prefs.js after close"
|
||||
rm $S/ui-patches/notes.txt
|
||||
res=$(steam-frame-nix-cleanup --all)
|
||||
gone $S
|
||||
there $HOME/.local/share/icons/hicolor/scalable/apps/hm.svg
|
||||
noop --all
|
||||
echo "A ok"
|
||||
|
||||
# --- B: SteamVR running: deferred to the runtime drop-in ---
|
||||
fresh b
|
||||
printf '{\n "VRWebHelper" : {\n "DebuggerEnabled" : true\n }\n}\n' > $V
|
||||
echo false > $S/steamvr-debugger.armed
|
||||
echo active > $STUB/state
|
||||
res=$(steam-frame-nix-cleanup --all); echo "$res"
|
||||
has "$res" "deferred: VRWebHelper.DebuggerEnabled"
|
||||
[ "$(jq .VRWebHelper.DebuggerEnabled $V)" = true ] || fail "changed while running"
|
||||
there $S/steamvr-debugger.armed $root/run/steam-frame-nix/steamvr-debugger-restore
|
||||
grep -qx 'ExecStopPost=-/usr/bin/bash %t/steam-frame-nix/steamvr-debugger-restore' \
|
||||
$root/run/systemd/user/steamvr.service.d/50-steam-frame-nix-debugger.conf || fail "drop-in"
|
||||
[ "$(grep -c daemon-reload $STUB/log)" = 1 ] || fail "daemon-reload count"
|
||||
noop --all
|
||||
[ "$(grep -c daemon-reload $STUB/log)" = 1 ] || fail "second run reloaded again"
|
||||
# SteamVR stops: ExecStopPost runs the script
|
||||
bash $root/run/steam-frame-nix/steamvr-debugger-restore
|
||||
[ "$(jq -c .VRWebHelper $V)" = '{"DebuggerEnabled":false}' ] || fail "restore: $(cat $V)"
|
||||
gone $S/steamvr-debugger.armed
|
||||
echo inactive > $STUB/state
|
||||
res=$(steam-frame-nix-cleanup --all)
|
||||
gone $root/run/steam-frame-nix $root/run/systemd $S
|
||||
noop --all
|
||||
echo "B ok"
|
||||
|
||||
# --- C: --orphans with keeps ---
|
||||
fresh c
|
||||
printf '{"VRWebHelper":{"DebuggerEnabled":true}}\n' > $V
|
||||
echo absent > $S/steamvr-debugger.armed
|
||||
mkdir -p $F/desktop $F/x.default
|
||||
ln -s /app/etc/firefox/steam-frame-nix-desktop-user.js $F/desktop/user.js
|
||||
ln -s /app/etc/firefox/steam-frame-nix-desktop-user.js $F/x.default/user.js
|
||||
printf '[Context]\ndevices=all;\nfilesystems=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim:ro;\n\n[Environment]\nLD_PRELOAD=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim/lib/mpv-hwdec-shim.so\nSFN_MPV_HWDEC=x\n' > $O/org.jellyfin.JellyfinDesktop
|
||||
mkdir -p $HOME/.var/app/org.jellyfin.JellyfinDesktop
|
||||
echo so > $HOME/.var/app/org.jellyfin.JellyfinDesktop/mpv-hwdec-shim.so # no marker: not ours
|
||||
echo '{"a":1}' > $S/ui-patches/frame-controls.json; echo '{}' > $S/ui-patches/vr-cat.json
|
||||
echo '{' > $S/ui-patches/x.json.tmp; touch -d '-1 hour' $S/ui-patches/x.json.tmp
|
||||
echo '{' > $S/ui-patches/y.json.tmp # being written: kept
|
||||
echo active > $STUB/state
|
||||
res=$(steam-frame-nix-cleanup --orphans --keep debugger --keep firefox-desktop-userjs=desktop); echo "$res"
|
||||
hasnt "$res" "deferred" # kept: the next start re-arms it
|
||||
there $root/run/systemd/user/steamvr.service.d/50-steam-frame-nix-debugger.conf $S/steamvr-debugger.armed
|
||||
there $F/desktop/user.js $S/ui-patches/frame-controls.json $S/ui-patches/vr-cat.json $S/ui-patches/y.json.tmp
|
||||
gone $F/x.default/user.js $O/org.jellyfin.JellyfinDesktop $S/ui-patches/x.json.tmp
|
||||
there $HOME/.var/app/org.jellyfin.JellyfinDesktop/mpv-hwdec-shim.so
|
||||
has "$res" "left alone: $HOME/.var/app/org.jellyfin.JellyfinDesktop/mpv-hwdec-shim.so"
|
||||
noop --orphans --keep debugger --keep firefox-desktop-userjs=desktop
|
||||
# SteamVR stopped (e.g. after a power loss): the key is restored, hook kept
|
||||
echo inactive > $STUB/state
|
||||
res=$(steam-frame-nix-cleanup --orphans --keep debugger --keep firefox-desktop-userjs=desktop)
|
||||
[ "$(jq -c . $V)" = '{}' ] || fail "orphans restore: $(cat $V)"
|
||||
gone $S/steamvr-debugger.armed
|
||||
there $root/run/systemd/user/steamvr.service.d/50-steam-frame-nix-debugger.conf
|
||||
# debugger no longer kept: runtime pieces go
|
||||
res=$(steam-frame-nix-cleanup --orphans --keep firefox-desktop-userjs=desktop)
|
||||
gone $root/run/steam-frame-nix $root/run/systemd
|
||||
noop --orphans --keep firefox-desktop-userjs=desktop
|
||||
there $S/ui-patches/frame-controls.json $HOME/.local/share/icons/hicolor/scalable/apps # not ours
|
||||
! steam-frame-nix-cleanup --all --keep debugger 2>/dev/null || fail "--all --keep accepted"
|
||||
! steam-frame-nix-cleanup --orphans --keep bogus 2>/dev/null || fail "unknown --keep accepted"
|
||||
echo "C ok"
|
||||
|
||||
# --- D: the user's own key is never touched ---
|
||||
fresh d
|
||||
printf '{"VRWebHelper":{"DebuggerEnabled":true}}\n' > $V
|
||||
res=$(steam-frame-nix-cleanup --all)
|
||||
has "$res" "left alone: VRWebHelper.DebuggerEnabled = true"
|
||||
[ "$(jq -c . $V)" = '{"VRWebHelper":{"DebuggerEnabled":true}}' ] || fail "user's key changed"
|
||||
echo "D ok"
|
||||
touch $out
|
||||
''
|
||||
@@ -0,0 +1,10 @@
|
||||
# steam-frame-nix-cleanup: `install.sh cleanup` (see there) with its tools
|
||||
# from nixpkgs. `nix run github:lhns/steam-frame-nix#cleanup -- --all`.
|
||||
{ writeShellApplication, bash, coreutils, findutils, jq, gnugrep, gnused, gawk, procps }:
|
||||
writeShellApplication {
|
||||
name = "steam-frame-nix-cleanup";
|
||||
runtimeInputs = [ bash coreutils findutils jq gnugrep gnused gawk procps ];
|
||||
text = ''
|
||||
exec bash ${../../install.sh} cleanup "$@"
|
||||
'';
|
||||
}
|
||||
Reference in new issue
Block a user