diff --git a/docs/file-layout.md b/docs/file-layout.md index 18c4f0f3..9be59863 100644 --- a/docs/file-layout.md +++ b/docs/file-layout.md @@ -248,7 +248,8 @@ the legacy finalization marker from `~/.local/state/omarchy/` into `done/`. finalization. It sources: - `install/config/*.sh` — theme links, lockout limits, lockscreen PAM, - powerprofilesctl shebang fix, docker setup, service enablement, firewall. + powerprofilesctl shebang fix, docker setup, Snapper retention, locate + index tuning, service enablement, firewall. - `install/hardware/all.sh` via `omarchy-setup-hardware` — vendor- and device-specific kernel modules, udev rules, microcode, wireless regdom, ASUS / Framework / Intel / Apple / Lenovo quirks. diff --git a/install/config/locate.sh b/install/config/locate.sh index d532f5df..529fa1ab 100644 --- a/install/config/locate.sh +++ b/install/config/locate.sh @@ -14,9 +14,13 @@ fi # Snapper snapshots are nested subvolumes reached by plain directory # traversal, so without this updatedb indexes the system once per snapshot. -if ! grep -E '^PRUNEPATHS[[:space:]]*=' "$UPDATEDB_CONF_PATH" | grep -qF '/.snapshots'; then - if grep -qE '^PRUNEPATHS[[:space:]]*=[[:space:]]*"' "$UPDATEDB_CONF_PATH"; then - sed -i -E 's|^(PRUNEPATHS[[:space:]]*=[[:space:]]*")|\1/.snapshots |' "$UPDATEDB_CONF_PATH" +# The quotes are optional in updatedb.conf, so read the paths back out of +# whatever quoting the file uses and write the setting in one canonical form. +pruned=$(sed -nE 's|^PRUNEPATHS[[:space:]]*=[[:space:]]*"?([^"]*)"?[[:space:]]*$|\1|p' "$UPDATEDB_CONF_PATH" | tail -n 1) + +if [[ " $pruned " != *" /.snapshots "* ]]; then + if [[ -n $pruned ]]; then + sed -i -E "s|^PRUNEPATHS[[:space:]]*=.*|PRUNEPATHS = \"/.snapshots $pruned\"|" "$UPDATEDB_CONF_PATH" else printf '%s\n' 'PRUNEPATHS = "/.snapshots"' >>"$UPDATEDB_CONF_PATH" fi diff --git a/migrations/1784809451.sh b/migrations/1784809451.sh index 0cf9d1a0..fb59a794 100644 --- a/migrations/1784809451.sh +++ b/migrations/1784809451.sh @@ -1,11 +1,7 @@ echo "Configure locate to skip Btrfs snapshots and index Btrfs subvolumes" OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}" -locate_config_script=/usr/share/omarchy/install/config/locate.sh -if [[ ! -f $locate_config_script ]]; then - locate_config_script="$OMARCHY_PATH/install/config/locate.sh" -fi - +locate_config_script="$OMARCHY_PATH/install/config/locate.sh" UPDATEDB_CONF_PATH="${OMARCHY_UPDATEDB_CONF_PATH:-/etc/updatedb.conf}" as_root() { @@ -17,14 +13,18 @@ as_root() { } [[ -f $UPDATEDB_CONF_PATH ]] || exit 0 +[[ -f $locate_config_script ]] || exit 0 if grep -q '^PRUNE_BIND_MOUNTS = "no"' "$UPDATEDB_CONF_PATH" && - grep -E '^PRUNEPATHS' "$UPDATEDB_CONF_PATH" | grep -qF '/.snapshots'; then + grep -E '^PRUNEPATHS' "$UPDATEDB_CONF_PATH" | grep -qE '(^|[[:space:]"])/\.snapshots([[:space:]"]|$)'; then exit 0 fi as_root env OMARCHY_UPDATEDB_CONF_PATH="$UPDATEDB_CONF_PATH" bash -euo pipefail "$locate_config_script" # Rebuild the index with the new exclusions; pruning /.snapshots turns -# multi-hour runs on snapshot-heavy systems back into one-minute runs. -as_root systemctl start --no-block plocate-updatedb.service >/dev/null 2>&1 || true +# multi-hour runs on snapshot-heavy systems back into one-minute runs. Restart +# rather than start: the machines this targets are the ones with an updatedb +# already grinding through every snapshot, and a run that started before the +# rewrite keeps using the config it read at startup. +as_root systemctl restart --no-block plocate-updatedb.service >/dev/null 2>&1 || true diff --git a/test/shell.d/locate-test.sh b/test/shell.d/locate-test.sh index 700b5bd2..77446103 100644 --- a/test/shell.d/locate-test.sh +++ b/test/shell.d/locate-test.sh @@ -36,7 +36,7 @@ OMARCHY_UPDATEDB_CONF_PATH="$test_tmp/missing.conf" bash -euo pipefail "$config_ pass "locate config tolerates a missing updatedb.conf" # A hand-edited updatedb.conf may drop the settings entirely, or write them -# without the spaces around the "=" that the stock Arch file uses. +# without the spaces around the "=" or the quotes that the stock Arch file uses. conf="$test_tmp/sparse-updatedb.conf" printf '%s\n' 'PRUNENAMES = ".git .hg .svn"' >"$conf" @@ -52,10 +52,28 @@ printf '%s\n' 'PRUNE_BIND_MOUNTS="yes"' 'PRUNEPATHS="/tmp /var/tmp"' >"$conf" OMARCHY_UPDATEDB_CONF_PATH="$conf" bash -euo pipefail "$config_script" >/dev/null grep -qFx 'PRUNE_BIND_MOUNTS = "no"' "$conf" || fail "locate config rewrites an unspaced PRUNE_BIND_MOUNTS" -grep -qFx 'PRUNEPATHS="/.snapshots /tmp /var/tmp"' "$conf" || fail "locate config prunes /.snapshots in an unspaced PRUNEPATHS" +grep -qFx 'PRUNEPATHS = "/.snapshots /tmp /var/tmp"' "$conf" || fail "locate config prunes /.snapshots in an unspaced PRUNEPATHS" [[ $(grep -c '^PRUNEPATHS' "$conf") -eq 1 ]] || fail "locate config keeps a single PRUNEPATHS setting" pass "locate config handles updatedb.conf written without spaces around =" +conf="$test_tmp/unquoted-updatedb.conf" +printf '%s\n' 'PRUNEPATHS = /tmp' >"$conf" + +OMARCHY_UPDATEDB_CONF_PATH="$conf" bash -euo pipefail "$config_script" >/dev/null + +grep -qFx 'PRUNEPATHS = "/.snapshots /tmp"' "$conf" || fail "locate config keeps the paths an unquoted PRUNEPATHS already prunes" +[[ $(grep -c '^PRUNEPATHS' "$conf") -eq 1 ]] || fail "locate config replaces an unquoted PRUNEPATHS instead of adding a second one" +pass "locate config handles updatedb.conf written without quotes" + +# A path that merely ends in /.snapshots is not the root snapshot directory. +conf="$test_tmp/nested-snapshots-updatedb.conf" +printf '%s\n' 'PRUNEPATHS = "/var/lib/machines/.snapshots"' >"$conf" + +OMARCHY_UPDATEDB_CONF_PATH="$conf" bash -euo pipefail "$config_script" >/dev/null + +grep -qFx 'PRUNEPATHS = "/.snapshots /var/lib/machines/.snapshots"' "$conf" || fail "locate config prunes /.snapshots alongside a path that ends in it" +pass "locate config tells /.snapshots apart from a path that ends in it" + locate_migration=$(grep -rl 'Configure locate to skip Btrfs snapshots' "$ROOT/migrations" | head -n 1 || true) [[ -n $locate_migration ]] || fail "locate migration exists" @@ -85,7 +103,7 @@ OMARCHY_UPDATEDB_CONF_PATH="$conf" \ grep -qFx 'PRUNE_BIND_MOUNTS = "no"' "$conf" || fail "locate migration rewrites updatedb.conf" grep -qF 'PRUNEPATHS = "/.snapshots /afs' "$conf" || fail "locate migration prunes /.snapshots" -grep -qFx 'systemctl start --no-block plocate-updatedb.service' "$test_tmp/calls.log" || fail "locate migration rebuilds the locate index without blocking" +grep -qFx 'systemctl restart --no-block plocate-updatedb.service' "$test_tmp/calls.log" || fail "locate migration replaces an in-flight run and rebuilds the index without blocking" pass "locate migration fixes existing installs and rebuilds the index" : >"$test_tmp/calls.log" @@ -98,3 +116,19 @@ OMARCHY_UPDATEDB_CONF_PATH="$conf" \ [[ ! -s $test_tmp/calls.log ]] || fail "locate migration skips already-configured installs" pass "locate migration is a no-op once updatedb.conf is configured" + +# A dev checkout carries migrations from a release whose install scripts the +# checked-out tree may not have yet, and omarchy-migrate runs under set -e. +: >"$test_tmp/calls.log" +conf="$test_tmp/no-config-script-updatedb.conf" +stock_conf "$conf" + +TEST_LOG="$test_tmp/calls.log" \ +PATH="$fake_bin:$PATH" \ +OMARCHY_PATH="$test_tmp/empty" \ +OMARCHY_UPDATEDB_CONF_PATH="$conf" \ + bash -euo pipefail "$locate_migration" >/dev/null || + fail "locate migration survives a tree without the locate config script" + +[[ ! -s $test_tmp/calls.log ]] || fail "locate migration touches nothing without the locate config script" +pass "locate migration is a no-op when the locate config script is missing"