Skip to content

Commit e55f0bf

Browse files
committed
feat(init): auto-update .gitignore so static.md is trackable
A common onboarding stumble: user follows the README, runs `revive init`, then `git add .revive/static.md` — git silently skips the file because their .gitignore has `.revive/*` (or similar) and no exception. The "checked in" workflow the README documents quietly fails. `cmd_init` now calls `maybe_update_gitignore` after writing static.md. Logic: - Skip silently if not in a git repo, no .gitignore exists, or `git check-ignore` says the file is already trackable. - Otherwise append a small canonical block: .revive/* !.revive/static.md with a header comment explaining what gets tracked vs not. - Re-run `git check-ignore`. If a directory-level `.revive/` rule still suppresses the un-ignore (git semantics: `!` cannot rescue a file inside a fully-ignored directory), print a warning telling the user how to fix it. 4 new tests cover: no .gitignore (no-op), `.revive/*` (append + verify trackable), already-correct (idempotent — line count unchanged), `.revive/` directory rule (warning emitted, exit 0 preserved).
1 parent f27d72d commit e55f0bf

2 files changed

Lines changed: 72 additions & 0 deletions

File tree

bin/revive

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,39 @@ cmd_init() {
697697
else
698698
echo "created: $STATIC_FILE"
699699
fi
700+
701+
maybe_update_gitignore
702+
}
703+
704+
# If $STATIC_FILE would currently be gitignored, append the canonical
705+
# exception block to .gitignore so the file can actually be tracked. Stays
706+
# silent when not in a git repo, when there's no .gitignore yet, or when
707+
# static.md is already trackable. If a directory-level `.revive/` rule
708+
# blocks the un-ignore from taking effect, surface a clear warning instead
709+
# of silently leaving the file untracked.
710+
maybe_update_gitignore() {
711+
git rev-parse --git-dir >/dev/null 2>&1 || return 0
712+
[[ -f .gitignore ]] || return 0
713+
git check-ignore -q "$STATIC_FILE" 2>/dev/null || return 0
714+
715+
cat >> .gitignore <<'GITIGNORE'
716+
717+
# revive: .revive/static.md is the curated STATIC layer (checked in);
718+
# other .revive/ contents are local runtime state.
719+
.revive/*
720+
!.revive/static.md
721+
GITIGNORE
722+
723+
if git check-ignore -q "$STATIC_FILE" 2>/dev/null; then
724+
cat >&2 <<MSG
725+
warning: $STATIC_FILE is still gitignored after appending the canonical
726+
exception. A directory-level rule (\`.revive/\` or \`.revive\`) earlier in
727+
.gitignore is likely blocking the un-ignore — replace it with
728+
\`.revive/*\` + \`!.revive/static.md\`, or run \`git add -f $STATIC_FILE\`.
729+
MSG
730+
else
731+
echo "updated: .gitignore (un-ignored $STATIC_FILE)"
732+
fi
700733
}
701734

702735
# Build a prompt that a coding agent (Claude Code / Cursor / Aider / any

tests/revive.bats

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,3 +1430,42 @@ JSON
14301430
run "$REVIVE" help
14311431
[[ "$output" == *"mark-compact"* ]] || return 1
14321432
}
1433+
1434+
# --- init: gitignore auto-update ---
1435+
1436+
@test "init does nothing to .gitignore when there is none" {
1437+
run "$REVIVE" init
1438+
[ "$status" -eq 0 ] || return 1
1439+
[ ! -f .gitignore ] || return 1
1440+
}
1441+
1442+
@test "init appends exception when .revive/* is gitignored without exception" {
1443+
printf '.revive/*\n' > .gitignore
1444+
run "$REVIVE" init
1445+
[ "$status" -eq 0 ] || return 1
1446+
[[ "$output" == *"un-ignored"* ]] || return 1
1447+
run cat .gitignore
1448+
[[ "$output" == *"!.revive/static.md"* ]] || return 1
1449+
# static.md is now actually trackable
1450+
run git check-ignore -q .revive/static.md
1451+
[ "$status" -ne 0 ] || return 1
1452+
}
1453+
1454+
@test "init leaves .gitignore alone when static.md is already trackable" {
1455+
printf '.revive/*\n!.revive/static.md\n' > .gitignore
1456+
local before
1457+
before=$(wc -l < .gitignore)
1458+
run "$REVIVE" init
1459+
[ "$status" -eq 0 ] || return 1
1460+
local after
1461+
after=$(wc -l < .gitignore)
1462+
[ "$before" -eq "$after" ] || return 1
1463+
}
1464+
1465+
@test "init warns when a directory-level .revive/ rule blocks the un-ignore" {
1466+
printf '.revive/\n' > .gitignore
1467+
run "$REVIVE" init
1468+
# init still exits 0 — warning is informational, not fatal
1469+
[ "$status" -eq 0 ] || return 1
1470+
[[ "$output" == *"still gitignored"* ]] || return 1
1471+
}

0 commit comments

Comments
 (0)