An unopenable repository fails loudly — the standing row, the paused surface, the honest heal
Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
@@ -13,9 +13,21 @@ import os
|
||||
/// fact about how the next commit is shaped (`GitRepository.initialCommitSubject`), never a reason
|
||||
/// to stop.
|
||||
///
|
||||
/// The cases are libgit2's own `git_repository_state`, which reads exactly the marker files 06
|
||||
/// names (`MERGE_HEAD`, `rebase-merge/`, `rebase-apply/`, `CHERRY_PICK_HEAD`) plus the two this
|
||||
/// Seven of the cases are libgit2's own `git_repository_state`, which reads exactly the marker files
|
||||
/// 06 names (`MERGE_HEAD`, `rebase-merge/`, `rebase-apply/`, `CHERRY_PICK_HEAD`) plus the two this
|
||||
/// version has no story for but must not commit over either (`REVERT_HEAD`, `BISECT_LOG`).
|
||||
///
|
||||
/// **The eighth is the app's own reading, and it is a pause by ruling** (06 ▸ Rules, "A `.git` that
|
||||
/// isn't a valid repository still reads as git mode — and fails loudly", ruled 2026-07-31): a `.git`
|
||||
/// libgit2 cannot open at all is not a repository *state* — there is no repository to be in one —
|
||||
/// but the posture it calls for is this one, verbatim: "the whole git surface paused (the
|
||||
/// abnormal-states posture below)". Putting it in this vocabulary is what makes that true
|
||||
/// structurally rather than by a rule somebody has to keep: every consumer of a pause already holds
|
||||
/// the auto-commit debounce (`GitAutoCommitter.execute`), disables Undo/Redo and the branch controls
|
||||
/// (`GitHistoryProvider.isHeld`, `GitBranchSwitcher.perform`), skips housekeeping
|
||||
/// (`GitHousekeeper.runNow`), and names the state in the popover — so `.unreadable` inherits all of
|
||||
/// it by construction, including the standing pause's own 15 s re-read, which is what heals it
|
||||
/// mid-session (`GitAutoCommitter.holdRecheckInterval`).
|
||||
public enum GitRepositoryPause: String, Sendable, Equatable, CaseIterable {
|
||||
case detachedHead
|
||||
case merge
|
||||
@@ -25,6 +37,13 @@ public enum GitRepositoryPause: String, Sendable, Equatable, CaseIterable {
|
||||
case rebase
|
||||
case applyMailbox
|
||||
|
||||
/// **The repository could not be opened** — a corrupt `.git`, a worktree pointer aimed at
|
||||
/// nothing, or a repository this engine has no support for (a SHA-256 one, 06 ▸ Repository
|
||||
/// hygiene: "an adopted SHA-256 repo the engine cannot open takes the corrupt-repo loud-failure
|
||||
/// path"). Never a fall to mode none: detection is presence-shaped, so the board stays in git
|
||||
/// mode and this is what git mode *reads* like while the repository is unreadable.
|
||||
case unreadable
|
||||
|
||||
/// What the popover will say — **the branch-switching card's surface, phrased here** so the
|
||||
/// engine-side hold and the sentence that explains it cannot drift apart (06 ▸ Rules ▸ Abnormal
|
||||
/// repo states: "the popover's git section names the state plainly … and says resolving it
|
||||
@@ -38,6 +57,11 @@ public enum GitRepositoryPause: String, Sendable, Equatable, CaseIterable {
|
||||
case .bisect: "a bisect is in progress"
|
||||
case .rebase: "a rebase is in progress"
|
||||
case .applyMailbox: "a patch application is in progress"
|
||||
// The clause the failure family reads with ("Adding git to this board failed: …",
|
||||
// `GitBranchOperation`'s held case), in the same voice as its siblings. The *popover's*
|
||||
// sentence for this state is its own and says more (`BoardGitBranchSurface.unreadableNote`):
|
||||
// unlike every pause above it, nothing is in progress and no tool is coming to finish it.
|
||||
case .unreadable: "this board's git repository can't be read"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -262,13 +286,29 @@ enum GitCommitOperation {
|
||||
/// "the check runs at open and again before every flush, so finishing the operation in a
|
||||
/// terminal resumes the pipeline without ceremony").
|
||||
///
|
||||
/// A repository that cannot be opened at all reads as no pause, not unborn, not locked — the
|
||||
/// same shrug every read in `GitRepository` gives an unopenable repo, and the commit attempt
|
||||
/// that follows will fail honestly with libgit2's own message rather than on a guess made here.
|
||||
/// **A repository that cannot be opened at all is `.unreadable`** — a pause, not a shrug (06 ▸
|
||||
/// Rules, the corrupt-`.git` loud failure, ruled 2026-07-31). This line used to answer "no pause,
|
||||
/// not unborn, not locked" and let the commit attempt that followed fail with libgit2's own
|
||||
/// message; under the ruling that is exactly backwards — the failure must be loud *before* a
|
||||
/// write is attempted, and nothing may be attempted against a repository the app cannot open
|
||||
/// ("Lanework leaves the repository untouched").
|
||||
///
|
||||
/// Because every caller of this function already branches on `pause`, that one word is the whole
|
||||
/// of the pause wiring: the flush holds, housekeeping skips, the interrupted-operation recovery
|
||||
/// defers, and the popover's `refreshPause` learns it.
|
||||
/// **Presence-shaped, exactly as detection is**: `.unreadable` is what a root `.git` that will
|
||||
/// not open reads like, and a board with no `.git` at all is not in git mode in the first place
|
||||
/// — it keeps the old no-pause answer, so a caller outside git mode (`GitHousekeeping.run`'s own
|
||||
/// `.noRepository` reading, a storeless test) is not told a repository it does not have is
|
||||
/// paused.
|
||||
nonisolated static func reading(at boardRoot: URL) -> GitRepositoryReading {
|
||||
_ = startUp
|
||||
guard let repository = open(boardRoot) else {
|
||||
return GitRepositoryReading(pause: nil, isUnborn: false, isIndexLocked: false)
|
||||
return GitRepositoryReading(
|
||||
pause: BoardGitMode.hasGitEntry(at: boardRoot) ? .unreadable : nil,
|
||||
isUnborn: false,
|
||||
isIndexLocked: false
|
||||
)
|
||||
}
|
||||
defer { git_repository_free(repository) }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user