Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
ccebuild: install timers, and the services their timers activate
Two gaps a crate shipping a scheduled job walks straight into, both
found shipping cce-system-interface's restic backup:
- timers.target was missing from USER_UNIT_TARGETS, so a .timer with
the only [Install] target a timer can sensibly have was classified
as neither user nor system and installed nowhere.
- A timer-activated .service legitimately carries no [Install], and
the no-[Install] fallback excludes .service outright — so the timer
installed while the unit it triggers was silently dropped, which
fails at 02:30 rather than at install time. The exclusion now lifts
only when a sibling .timer/.socket/.path exists, keyed on the
sibling so a stray service file is still skipped.
Verified no-op for every unit shipped today: the tree contains exactly
one no-[Install] .service (the new one), and nothing else declares
timers.target.
Co-Authored-By: Claude Fable 5 <[email protected]>
scripts/ccebuild | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/scripts/ccebuild b/scripts/ccebuild
index cac2115..a993e8f 100755
--- a/scripts/ccebuild
+++ b/scripts/ccebuild
@@ -24,7 +24,7 @@ EXCLUDE=(vk-smoke)
# whole crate, so its user units silently never installed — the same
# hand-maintained-list failure this script exists to avoid. Matching is exact:
# graphical.target and graphical-session.target are different targets.
-USER_UNIT_TARGETS=(default.target graphical-session.target cce-session.target)
+USER_UNIT_TARGETS=(default.target graphical-session.target cce-session.target timers.target)
PREFIX="${CCE_PREFIX:-$HOME/.local}"
BINDIR="$PREFIX/bin"
@@ -107,7 +107,7 @@ unit_wanted_by() {
# User-session unit files shipped by crates (system units excluded — see above).
user_units() {
- local unit wanted t match
+ local unit wanted t match base
unit_files | while read -r unit; do
wanted=$(unit_wanted_by "$unit")
if [ -z "$wanted" ]; then
@@ -120,7 +120,21 @@ user_units() {
# .service is deliberately NOT eligible for this fallback —
# still requiring WantedBy there keeps the classification of
# every unit shipped today bit-for-bit unchanged.
- case "$unit" in *.service) continue ;; esac
+ # .service is deliberately NOT eligible for this fallback,
+ # with ONE exception: a service activated by a sibling
+ # .timer/.socket/.path. That pair is how a scheduled or
+ # socket-activated job is expressed and the service half
+ # legitimately carries no [Install] — without this, shipping a
+ # timer installed the timer and silently dropped the unit it
+ # triggers. Keyed on the sibling so a stray service file is
+ # still skipped.
+ case "$unit" in
+ *.service)
+ base=${unit%.service}
+ [ -f "$base.timer" ] || [ -f "$base.socket" ] \
+ || [ -f "$base.path" ] || continue
+ ;;
+ esac
printf '%s\n' "$unit"
continue
fi