Documentation
¶
Overview ¶
Package worktree manages per-session git worktrees rooted under <repo>/.jungi/state/worktrees/<id>/. Each session that opens against a directory inside a git repository gets its own checked-out tree on a dedicated jungi/<id> branch, so concurrent sessions in the same repo work in isolation without trampling each other's index, working files, or branch state.
The package shells out directly via os/exec rather than going through internal/tools/runshell: runshell.Execute imposes a 30s default timeout (overridable per-invocation) and 10 KiB output truncation that are wrong for git operations, and it routes through the sandbox — which is circular when the sandbox is rooted inside the worktree we are trying to create.
Index ¶
Constants ¶
const BranchPrefix = "jungi/"
BranchPrefix is prepended to every jungi-managed branch so they are trivially recognisable in `git branch` output and grep-friendly when correlating with session log files (which share the UUID suffix).
Variables ¶
This section is empty.
Functions ¶
func RepoRoot ¶
RepoRoot resolves the canonical working-tree root for workDir by asking git, returning ("", false, nil) when workDir is not inside any git working tree. Other errors (e.g. workDir does not exist, git not installed) propagate.
Used by session.Manager to decide whether a new session should be hosted in a worktree or just run directly against the user-selected directory.
Types ¶
type Handle ¶
type Handle struct {
// RepoRoot is the absolute path to the canonical working tree that
// owns the .git directory the worktree shares.
RepoRoot string
// Path is the absolute path to the worktree's root directory.
Path string
// Branch is the branch checked out in the worktree, including the
// jungi/ prefix.
Branch string
}
Handle owns the identity of a single worktree. It is cheap to copy and safe to share across goroutines: all methods invoke git as a subprocess, never touching package-level state.
func Create ¶
Create adds a new worktree at <repoRoot>/.jungi/state/worktrees/<id>/ on a fresh branch jungi/<id> branched off the current HEAD of repoRoot.
On first use in a repo, also creates .jungi/ and .jungi/.gitignore so the state/ subdir is excluded from version control. Existing .jungi/ and .jungi/.gitignore are left untouched.
Returns a Handle pinning the resulting worktree. Caller is responsible for calling Prune when the session ends.
func (Handle) MapSubpath ¶
MapSubpath translates a path under repoRoot to the equivalent path under the worktree, preserving any subdirectory the user originally selected. Returns the worktree path itself when sourceWorkDir is exactly the repo root.
Both sides are resolved through EvalSymlinks before the relative path is computed so that macOS's /var → /private/var aliasing — and any user-managed symlinks pointing into the repo — don't trick filepath.Rel into reporting paths as "outside" the root.
Used by session.Manager so that a session opened against <repo>/internal/foo runs inside <worktree>/internal/foo rather than the worktree root.
func (Handle) Prune ¶
Prune removes the worktree directory and deletes its branch. When force is true, the underlying `git worktree remove --force` and `git branch -D` will discard uncommitted changes and unmerged commits respectively — the caller is expected to have obtained user confirmation first.
Returns an error if either step fails. Branch deletion is attempted even when worktree removal fails so partial state is cleaned up as far as possible.
type Status ¶
type Status struct {
// UncommittedFiles is the list of path entries reported by
// `git status --porcelain` — modifications, additions, deletions,
// and untracked files alike. Names are repo-relative.
UncommittedFiles []string
// UnpushedCommits is the number of commits on the worktree branch
// that are not reachable from any remote-tracking ref. In a repo
// without remotes, every commit on the branch counts as unpushed —
// which is the correct conservative answer.
UnpushedCommits int
}
Status reports what would be lost if the worktree were pruned. A zero-valued Status (no uncommitted files, no unpushed commits) means a prune is safe; the TUI uses IsDirty to decide whether to require user confirmation.
Source Files
¶
- worktree.go