← back to Dw Pitch Followup

.githooks/pre-commit

26 lines

#!/bin/sh
# pre-commit: lint every staged launchd/*.plist so a malformed plist (bad
# schedule, mismatched tags) can never ship silently again. Born 2026-08-06
# after a broken dw-pitch-rebuild.plist (opened <array>, closed </dict>) failed
# to parse, never installed, and froze the pitch board for a week.
#
# Lints the STAGED blob (via git show :file), not the working tree, so a fixed
# working copy can't mask a broken thing you're actually committing.
fail=0
for f in $(git diff --cached --name-only --diff-filter=ACM -- launchd/); do
  case "$f" in *.plist) ;; *) continue ;; esac
  tmp=$(mktemp)
  git show ":$f" > "$tmp" 2>/dev/null
  if ! plutil -lint "$tmp" >/dev/null 2>&1; then
    echo "pre-commit ✗ invalid plist: $f"
    plutil -lint "$tmp" 2>&1 | sed "s|$tmp|$f|"
    fail=1
  fi
  rm -f "$tmp"
done
if [ "$fail" -ne 0 ]; then
  echo "commit blocked — fix the malformed plist(s) above (macOS: plutil -lint <file>)."
  exit 1
fi
exit 0