mirror of
https://github.com/lhns/steam-frame-nix.git
synced 2026-10-06 07:00:27 +02:00
Steam keeps VR screenshots (Steam button + trigger) in ~/.local/share/Steam/userdata/<account ID>/760/remote/250820/screenshots, where Dolphin, Gwenview and the file pickers don't look. screenshots (module screenshots, opt-in) links ~/Pictures/<name> (default "SteamVR Screenshots") there. The account ID comes from steamUserId, or, unset, at runtime: the Home Manager link points to <runtimeDir>/steam-frame-nix/screenshots (tmpfs), which the oneshot user service steam-frame-nix-screenshots points to the account last logged in (loginusers.vdf MostRecent, else latest timestamp, else the only userdata folder), on switch, at login and when loginusers.vdf or userdata changes. install.sh cleanup knows the tmpfs link (--keep screenshots while used). Flake checks: account detection on fake Steam dirs; cleanup of the link.
250 lines
14 KiB
Nix
250 lines
14 KiB
Nix
# 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
|
|
mkdir -p $root/run/steam-frame-nix/applications # steamFrame.launchers
|
|
echo '[Desktop Entry]' > $root/run/steam-frame-nix/applications/im.riot.Riot.desktop
|
|
echo x > $root/run/steam-frame-nix/applications/.im.riot.Riot.desktop.sum
|
|
: > $root/run/steam-frame-nix/applications/.lock
|
|
ln -s $HOME/.local/share/Steam/userdata/1/760/remote/250820/screenshots \
|
|
$root/run/steam-frame-nix/screenshots # steamFrame.screenshots
|
|
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
|
|
touch $F/desktop/.parentlock; exec 8< $F/desktop/.parentlock # the wrapper's, Firefox running
|
|
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); 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
|
|
# 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)
|
|
[ "$(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)
|
|
gone $root/run/steam-frame-nix $root/run/systemd
|
|
noop --orphans
|
|
there $S/ui-patches/frame-controls.json $HOME/.local/share/icons/hicolor/scalable/apps # not ours
|
|
exec 8<&- # Firefox closed
|
|
res=$(steam-frame-nix-cleanup --orphans)
|
|
gone $F/desktop/user.js
|
|
# screenshots link: kept while used, a foreign link left alone
|
|
mkdir -p $root/run/steam-frame-nix
|
|
ln -s /x/userdata/1/760/remote/250820/screenshots $root/run/steam-frame-nix/screenshots
|
|
res=$(steam-frame-nix-cleanup --orphans --keep screenshots)
|
|
there $root/run/steam-frame-nix/screenshots
|
|
res=$(steam-frame-nix-cleanup --orphans)
|
|
gone $root/run/steam-frame-nix/screenshots
|
|
ln -s /elsewhere $root/run/steam-frame-nix/screenshots
|
|
res=$(steam-frame-nix-cleanup --orphans)
|
|
has "$res" "left alone: $root/run/steam-frame-nix/screenshots"
|
|
rm -r $root/run/steam-frame-nix
|
|
! 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"
|
|
|
|
# --- E: steamvr-debugger-arm (before each SteamVR start) ---
|
|
arm() { bash ${../../install.sh} steamvr-debugger-arm; }
|
|
fresh e
|
|
printf '{\n "steamvr" : {}\n}\n' > $V
|
|
echo activating > $STUB/state
|
|
res=$(arm); echo "$res"
|
|
[ "$(cat $S/steamvr-debugger.armed)" = absent ] || fail "armed"
|
|
[ "$(jq -c .VRWebHelper $V)" = '{"DebuggerEnabled":true}' ] || fail "arm: $(cat $V)"
|
|
there $root/run/steam-frame-nix/steamvr-debugger-restore
|
|
[ "$(grep -c daemon-reload $STUB/log)" = 1 ] || fail "arm reload"
|
|
before=$(snap); res=$(arm)
|
|
[ "$(snap)" = "$before" ] || fail "second arm changed files"
|
|
[ "$(grep -c daemon-reload $STUB/log)" = 1 ] || fail "second arm reloaded"
|
|
bash $root/run/steam-frame-nix/steamvr-debugger-restore # SteamVR stops
|
|
[ "$(jq -c . $V)" = '{"steamvr":{}}' ] || fail "arm restore: $(cat $V)"
|
|
gone $S/steamvr-debugger.armed
|
|
res=$(arm) # restart: armed again
|
|
[ "$(cat $S/steamvr-debugger.armed)" = absent ] || fail "re-arm"
|
|
bash $root/run/steam-frame-nix/steamvr-debugger-restore
|
|
# the user's own true: never armed, never restored
|
|
printf '{"VRWebHelper":{"DebuggerEnabled":true}}\n' > $V
|
|
res=$(arm); has "$res" "not set by steam-frame-nix"
|
|
gone $S/steamvr-debugger.armed
|
|
# no file yet: created, and removed again if nothing else was added
|
|
rm $V; res=$(arm)
|
|
[ "$(cat $S/steamvr-debugger.armed)" = nofile ] || fail "nofile"
|
|
bash $root/run/steam-frame-nix/steamvr-debugger-restore
|
|
gone $V $S/steamvr-debugger.armed
|
|
echo "E ok"
|
|
touch $out
|
|
''
|