Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
125 lines
4.3 KiB
Bash
Executable File
125 lines
4.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Idle on Linux: ElyTree rereads neither theme, settings nor repo.
|
|
set -euo pipefail
|
|
|
|
root=$(cd "$(dirname "$0")/../.." && pwd)
|
|
fail() {
|
|
echo "FAIL: $*" >&2
|
|
exit 1
|
|
}
|
|
[ "$(uname)" = Linux ] || {
|
|
echo "SKIP: inotify is Linux"
|
|
exit 0
|
|
}
|
|
[ -n "${WAYLAND_DISPLAY:-}${DISPLAY:-}" ] || {
|
|
echo "SKIP: no display"
|
|
exit 0
|
|
}
|
|
for tool in inotifywait jq git; do
|
|
command -v "$tool" >/dev/null || {
|
|
echo "SKIP: no $tool"
|
|
exit 0
|
|
}
|
|
done
|
|
app=$(cargo build -q --locked --message-format=json --manifest-path "$root/Cargo.toml" -p ely-tree --bin ely-tree |
|
|
jq -r 'select(.reason == "compiler-artifact" and .target.name == "ely-tree") | .executable // empty')
|
|
[ -x "$app" ] || fail "Cargo reported no ElyTree binary"
|
|
|
|
work=$(mktemp -d)
|
|
pid=
|
|
spy=
|
|
trap '[ -z "$pid" ] || kill "$pid" 2>/dev/null; [ -z "$spy" ] || kill "$spy" 2>/dev/null; rm -rf "$work"' EXIT
|
|
current=$work/omarchy/current
|
|
mkdir -p "$current/theme" "$work/data/ElyOffice" "$work/bin"
|
|
cp "$root/crates/ely-ui/tests/fixtures/omarchy/catppuccin.toml" "$current/theme/colors.toml"
|
|
echo catppuccin >"$current/theme.name"
|
|
echo '{"version": 1}' >"$work/data/ElyOffice/settings.json"
|
|
repo=$work/repo
|
|
git init -q "$repo"
|
|
echo one >"$repo/a.txt"
|
|
git -C "$repo" add a.txt
|
|
git -C "$repo" -c user.name=t -c user.email=t@t commit -q -m one
|
|
real=$(command -v git)
|
|
printf '#!/bin/sh\necho "$*" >>"%s"\nexec "%s" "$@"\n' "$work/git.log" "$real" >"$work/bin/git"
|
|
chmod +x "$work/bin/git"
|
|
|
|
ELY_GIT="$work/bin/git" ELY_OMARCHY_DIR="$current" ELY_SMOKE=hold ELY_LOG=info HOME="$work" \
|
|
XDG_DATA_HOME="$work/data" "$app" "$repo" 2>"$work/app.err" &
|
|
pid=$!
|
|
statuses() { if [ -f "$work/git.log" ]; then grep -c '^status' "$work/git.log" || true; else echo 0; fi; }
|
|
for _ in $(seq 120); do
|
|
[ "$(statuses)" -gt 0 ] && break
|
|
kill -0 "$pid" 2>/dev/null || fail "ElyTree quit: $(tail -n 5 "$work/app.err")"
|
|
sleep 0.5
|
|
done
|
|
[ "$(statuses)" -gt 0 ] || fail "ElyTree never read the repo"
|
|
grep -q 'omarchy catppuccin applied' "$work/app.err" || fail "the Omarchy theme was not applied"
|
|
sleep 3
|
|
|
|
# Four quiet seconds: no reads, no git status.
|
|
idle() { # when
|
|
inotifywait -q -m -e open --format '%w%f' "$current" "$current/theme" "$work/data/ElyOffice" >"$work/opens" 2>/dev/null &
|
|
spy=$!
|
|
sleep 1
|
|
local before opens
|
|
before=$(statuses)
|
|
sleep 4
|
|
kill "$spy"
|
|
spy=
|
|
opens=$(grep -c -E '(colors\.toml|theme\.name|settings\.json)$' "$work/opens" || true)
|
|
[ "$opens" -eq 0 ] || fail "ElyTree $1 read the theme or settings $opens times: $(sort "$work/opens" | uniq -c)"
|
|
[ "$(statuses)" -eq "$before" ] || fail "ElyTree $1 ran git status $(($(statuses) - before)) more times"
|
|
echo "linux: ElyTree $1 reads nothing"
|
|
}
|
|
seen() { grep -c "$1" "$work/app.err" || true; }
|
|
logged() { # pattern, what; once more than before
|
|
local before=${3:-0}
|
|
for _ in $(seq 40); do
|
|
[ "$(seen "$1")" -gt "$before" ] && return
|
|
sleep 0.25
|
|
done
|
|
fail "ElyTree missed $2"
|
|
}
|
|
grown() { # what
|
|
for _ in $(seq 40); do
|
|
[ "$(statuses)" -gt "$before" ] && return
|
|
sleep 0.25
|
|
done
|
|
fail "ElyTree missed $1"
|
|
}
|
|
# Writes through a mapping: CLOSE_WRITE, no MODIFY.
|
|
mapped() { # file, old, new
|
|
python3 -I -c 'import mmap, sys
|
|
with open(sys.argv[1], "r+b") as f, mmap.mmap(f.fileno(), 0) as m:
|
|
at = m.find(sys.argv[2].encode())
|
|
assert at >= 0, sys.argv[2]
|
|
m[at:at + len(sys.argv[3])] = sys.argv[3].encode()
|
|
m.flush()' "$@"
|
|
}
|
|
idle "idle after opening"
|
|
|
|
# Omarchy's swap, a settings write, an edit; then quiet again.
|
|
mkdir "$current/next-theme"
|
|
cp "$root/crates/ely-ui/tests/fixtures/omarchy/gruvbox.toml" "$current/next-theme/colors.toml"
|
|
rm -rf "$current/theme"
|
|
mv "$current/next-theme" "$current/theme"
|
|
echo gruvbox >"$current/theme.name"
|
|
logged 'omarchy gruvbox applied' "Omarchy's theme swap"
|
|
echo '{"version": 1, "author": "Tester"}' >"$work/data/ElyOffice/settings.json"
|
|
logged 'settings: changed on disk' "a settings write"
|
|
before=$(statuses)
|
|
echo two >>"$repo/a.txt"
|
|
grown "an edit in the repo"
|
|
sleep 2
|
|
idle "idle after changes"
|
|
|
|
mapped "$current/theme.name" gruvbox Gruvbox
|
|
logged 'omarchy Gruvbox applied' "a mapped theme name"
|
|
changed=$(seen 'settings: changed on disk')
|
|
mapped "$work/data/ElyOffice/settings.json" Tester Testor
|
|
logged 'settings: changed on disk' "a mapped settings write" "$changed"
|
|
before=$(statuses)
|
|
mapped "$repo/a.txt" two Two
|
|
grown "a mapped edit in the repo"
|
|
echo "linux: ElyTree follows mapped writes"
|