Documentation
¶
Overview ¶
Package git is a minimal wrapper around the `git` CLI for the editor's modified-files panel. It exposes Status (porcelain → typed entries), Diff (HEAD ↔ working-tree contents for one path), and a path validator.
All operations shell out to `git`; `dir` must be an absolute path inside a git repository (or worktree). Errors that mean "this directory is not a git repository" are flattened to ErrNotGitRepo so callers can render a friendly message.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNotGitRepo = errors.New("git: not a git repository")
ErrNotGitRepo is returned by Status/Diff when the target directory is not inside a git working tree (no .git, or `git` reports "not a git repository"). Callers in the HTTP layer translate it to a 200 with `available: false, reason: "not_git_repo"` so the editor can render a neutral empty-state instead of a red error.
Functions ¶
func FindRepoRoot ¶ added in v0.3.2
FindRepoRoot walks parent directories from startDir until it finds a `.git` entry (regular .git directory or a worktree's gitfile pointer), returning "" when no parent in the chain qualifies.
Used by the editor server to recover a run's main repo root when the run record predates the persisted RepoRoot field — we walk up from the run's work_dir (`<repo>/.iterion/worktrees/<id>`) past `.iterion` to the repo itself. Falls back gracefully on legacy or migrated runs whose work_dir no longer resolves locally (returns "" so callers can try the server CWD).
func MergeBase ¶ added in v0.3.2
MergeBase returns the merge base of refA and refB in repoRoot, or "" + nil when the two refs share no common ancestor. Wrapping the failure as a nil-string lets callers treat "no baseline available" as a soft outcome (skip the historical diff) rather than a hard error.
func ValidateRelPath ¶
ValidateRelPath accepts a path coming from an HTTP query and verifies it stays inside the run's working directory. It rejects absolute paths, `..` traversal, and NUL bytes.
The accepted form is a forward-slash relative path. Callers should pass the value straight through to git/os.ReadFile after validation; we do not normalise to OS separators here because git itself uses forward slashes on every platform.
Types ¶
type DiffPayload ¶
type DiffPayload struct {
Path string `json:"path"`
Before *string `json:"before"`
After *string `json:"after"`
Binary bool `json:"binary"`
}
DiffPayload carries the two sides of a file diff for the Monaco DiffEditor. Both fields are nil (omitted in JSON) when the file does not exist on that side: `Before == nil` for untracked/added files, `After == nil` for deleted files. Binary files set Binary = true and leave Before/After nil — the editor swaps in a "binary file not shown" message instead of feeding non-text into Monaco. Status is intentionally absent: the caller already has it from the prior /files listing and feeds it back as UI metadata. Recomputing it here would force a second `git status` scan on every diff click.
func Diff ¶
func Diff(dir, relPath string) (DiffPayload, error)
Diff returns the HEAD content (Before) and current working-tree content (After) of relPath inside dir, suitable for feeding into Monaco's DiffEditor. Either side is nil when the file does not exist there:
- Before == nil: untracked or freshly added (no HEAD blob)
- After == nil: deleted from the worktree
When the content is binary (NUL byte present in either side), Before and After are both nil and Binary is true so the editor can surface a "binary file not shown" placeholder instead of feeding raw bytes into a text editor.
relPath must already have passed ValidateRelPath. dir must be inside a git working tree (else ErrNotGitRepo).
func DiffBetween ¶ added in v0.3.2
func DiffBetween(repoRoot, baseRef, finalRef, relPath string) (DiffPayload, error)
DiffBetween returns the Before (baseRef) and After (finalRef) blob contents for relPath in repoRoot. Either side is nil when the path does not exist at that ref (added on After-only, deleted on Before-only). Binary detection mirrors Diff(): a NUL byte on either side blanks both contents and sets Binary = true so Monaco does not try to render raw bytes.
type FileStatus ¶
type FileStatus struct {
Path string `json:"path"`
Status string `json:"status"` // "M" | "A" | "D" | "R" | "??"
OldPath string `json:"old_path,omitempty"` // populated only when Status == "R"
}
FileStatus is a single entry in the porcelain output, distilled to one effective change per path. The on-disk reality (worktree) wins over the index when both columns disagree — the editor cares about "what would I see if I opened the file right now" more than the staging state.
func Status ¶
func Status(dir string) ([]FileStatus, error)
Status returns one entry per modified/untracked file in dir, derived from `git status --porcelain=v1 -z`. The NUL-terminated form is used so paths containing spaces, newlines, or non-ASCII bytes survive intact.
Renames are reported with both the new path (Path) and the original path (OldPath); other entries leave OldPath empty.
func StatusBetween ¶ added in v0.3.2
func StatusBetween(repoRoot, baseRef, finalRef string) ([]FileStatus, error)
StatusBetween lists files that differ between two commits inside repoRoot, returning entries shaped like the porcelain Status() output so the editor can render them through the same FilesPanel code path.
Used by the modified-files panel after a worktree-using run has finalized and its worktree directory has been torn down: the run's commits are still reachable on the persistent branch in repoRoot's shared .git, so we can recover the diff without the worktree.
baseRef is the commit-ish the run started from (`Run.BaseCommit`); finalRef is the run's terminal commit (`Run.FinalCommit`). Both must resolve in repoRoot — callers should pass full SHAs for stability across branch moves.