#!/usr/bin/env bash # A settings page is declared in three places that cannot see each other: # # SettingsSidebar.qml the list someone clicks # SettingsShell.qml the switch that decides which component to build # ShellState.qml the allow-list that IPC and the launcher go through # # Miss one and the failure is silent in the worst way. A page missing from the # allow-list does not error -- openSettings() falls back to "home", so the # launcher command opens Settings on the wrong page and logs nothing. That is # exactly what happened when Storage was added. # # Static and read-only; it parses three files. set -uo pipefail repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" shell_dir="$repo_dir/config/dot/quickshell" sidebar="$shell_dir/modules/settings/SettingsSidebar.qml" shell_file="$shell_dir/modules/settings/SettingsShell.qml" state="$shell_dir/services/ShellState.qml" fail() { printf 'settings page registry contract: %s\n' "$1" >&2 exit 1 } for path in "$sidebar" "$shell_file" "$state"; do [[ -r "$path" ]] || fail "missing $path" done listed="$(grep -oE '\{ page: "[a-z-]+"' "$sidebar" | sed 's/.*"\([a-z-]*\)"/\1/' | sort -u)" routed="$(grep -oE 'case "[a-z-]+": return [a-zA-Z]+Page;' "$shell_file" \ | sed 's/case "\([a-z-]*\)".*/\1/' | sort -u)" allowed="$(sed -n 's/.*const allowed = \[\(.*\)\];/\1/p' "$state" \ | tr ',' '\n' | tr -d ' "' | grep -v '^$' | sort -u)" [[ -n "$listed" ]] || fail 'no pages found in the sidebar' [[ -n "$routed" ]] || fail 'no pages found in the shell switch' [[ -n "$allowed" ]] || fail 'no allow-list found in ShellState' # "home" is the fallback: it is routed by `default:` rather than a case, so it # is legitimately absent from the switch. routed="$(printf '%s\nhome\n' "$routed" | sort -u)" missing_route="$(comm -23 <(printf '%s\n' "$listed") <(printf '%s\n' "$routed") | tr '\n' ' ')" [[ -z "${missing_route// }" ]] \ || fail "these pages are in the sidebar but the shell has no case for them, so they render as Home: $missing_route" missing_allow="$(comm -23 <(printf '%s\n' "$listed") <(printf '%s\n' "$allowed") | tr '\n' ' ')" [[ -z "${missing_allow// }" ]] \ || fail "these pages are in the sidebar but not in ShellState's allow-list, so opening them by IPC silently lands on Home: $missing_allow" orphan_allow="$(comm -13 <(printf '%s\n' "$listed") <(printf '%s\n' "$allowed") | tr '\n' ' ')" [[ -z "${orphan_allow// }" ]] \ || fail "ShellState allows pages the sidebar does not have: $orphan_allow" printf 'settings page registry contract: PASS (%d pages agree across three files)\n' \ "$(grep -c . <<<"$listed")"