#!/usr/bin/env bash # One IpcHandler per target name. # # `qs ipc call ...` resolves by name, and the handlers are spread # across a shell.qml several hundred lines long -- a second IpcHandler with an # already-used target is exactly the mistake a reader makes there, and it does # not error: one handler silently shadows or conflicts with the other. For the # polkit target that is not cosmetic -- the agent delivers authentication # requests through it, so a shadowed `begin` breaks every password prompt on # the desktop. This nearly shipped once; now it cannot. # # Harness files are excluded: each is its own root, never loaded beside the # shell, so sharing a target with it is not a conflict. set -uo pipefail repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" shell_dir="$repo_dir/config/dot/quickshell" findings=() note() { findings+=("$1"); } # target name file, one line per IpcHandler declaration. The awk pairs # each `IpcHandler {` with the next quoted `target:` line in the same file, # which is how every handler in this codebase is written. declarations="$(find "$shell_dir" -name '*.qml' -not -name '*-harness.qml' -exec awk ' /IpcHandler *{/ { pending = 1 } pending && /target: "/ { match($0, /target: "[^"]+"/) printf "%s\t%s\n", substr($0, RSTART + 9, RLENGTH - 10), FILENAME pending = 0 } ' {} +)" # The scan finding almost nothing means the declaration format changed, not # that the handlers went away -- fail loudly rather than pass on an empty read. total="$(grep -c . <<<"$declarations" || true)" (( total >= 5 )) \ || note "only $total IpcHandler targets were found; the scan no longer matches how handlers are declared" while read -r count target; do [[ -n "$target" ]] || continue if (( count > 1 )); then files="$(awk -F'\t' -v t="$target" '$1 == t { print $2 }' <<<"$declarations" \ | sed "s|$repo_dir/||" | paste -sd ', ')" note "the \"$target\" IPC target is declared $count times ($files); one silently shadows the other" fi done < <(cut -f1 <<<"$declarations" | sort | uniq -c) if (( ${#findings[@]} > 0 )); then printf 'ipc targets contract: %d finding(s)\n' "${#findings[@]}" >&2 printf ' - %s\n' "${findings[@]}" >&2 exit 1 fi printf 'ipc targets contract: PASS (%d targets, each declared once)\n' "$total"