Implement repository hygiene
Add-git seeds a minimal .gitignore (.DS_Store) before the initial stage — the seed rides "Initial board state" and .DS_Store never enters history; an existing .gitignore (or a directory wearing the name) is left alone forever, adoption and repo-nested seed nothing. GitHousekeeping is the periodic loose-object repack: filesystem enumeration of objects/<2hex>/<38hex> (never git_odb_foreach, which would rewrite the whole database into a fresh pack each pass), git_packbuilder_insert one oid at a time, additive pack write — and deletion only after each oid is re-verified against the written pack opened as a standalone one-pack odb with no loose backend. Any failure returns before deleting; the worst case is a stray pack. Nothing prunes, expires, or consolidates — existing packs accumulate, recorded as the accepted cost of never rewriting storage the app didn't write. GitHousekeeper schedules it: git's own 6700 threshold, 8s after session activation (outlasting the launch catch-up), background priority, skipped under pause states, held locks, or an in-flight commit, never retried — the next open tries again. Free tier composes none of it. 20 new tests: full-odb equality, per-oid survival, identical walks, byte+mtime-identical refs/HEAD/working tree, whole-.git identity on every declined pass, and deleting-never-forgets. 2394 tests / 412 suites green; InertGitTests untouched. Closes pro-m1-git-undo. Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -187,16 +187,20 @@ struct HistoryStoreAddGitTests {
|
||||
#expect(tracked.contains("\(Ident.lane1)/\(Ident.card1)/index.md"))
|
||||
}
|
||||
|
||||
@Test("Add-git seeds no `.gitignore` — repository hygiene is a later card")
|
||||
func addGitSeedsNoGitignore() async throws {
|
||||
@Test("Add-git seeds a `.gitignore` into the initial commit")
|
||||
func addGitSeedsTheIgnoreFile() async throws {
|
||||
let fixture = try makeBoard()
|
||||
defer { fixture.tearDown() }
|
||||
|
||||
let git = try #require(HistoryStore.compose(boardRoot: fixture.root, tier: .pro))
|
||||
#expect(await git.addGit())
|
||||
|
||||
#expect(!fixture.exists(".gitignore"))
|
||||
#expect(!GitRepository.trackedPaths(at: fixture.root).contains(".gitignore"))
|
||||
// The one file the app ever writes into a board because of git, and the one moment it writes
|
||||
// it (06 ▸ Repository hygiene). `RepositoryHygieneTests` carries the rest of the rule — the
|
||||
// untouched existing file, the `.DS_Store` that never enters history, adoption seeding
|
||||
// nothing; here it is only the fact that add-git's tree includes it.
|
||||
#expect(fixture.exists(".gitignore"))
|
||||
#expect(GitRepository.trackedPaths(at: fixture.root).contains(".gitignore"))
|
||||
}
|
||||
|
||||
@Test("The root commit is authored by the derived default when the repo names nobody")
|
||||
|
||||
Reference in New Issue
Block a user