Documentation
¶
Overview ¶
Package git wraps the git CLI for amux's worktree-per-workspace model: creating and removing worktrees and branches, computing diffs, and watching the working tree for changes.
Index ¶
- Constants
- Variables
- func AheadBehind(repoPath string) (ahead, behind int, err error)
- func CommitAll(ctx context.Context, workspaceRoot, message string) error
- func CreateWorkspace(repoPath, workspacePath, branch, base string) error
- func DeleteBranch(repoPath, branch string) error
- func DiscoverWorkspaces(project *data.Project) ([]data.Workspace, error)
- func GetBaseBranch(repoPath string) (string, error)
- func GetCurrentBranch(path string) (string, error)
- func IsGitRepository(path string) bool
- func IsUnregisteredWorkspacePathError(err error) bool
- func IsWorkspaceCleanupPendingError(err error) bool
- func RemoveWorkspace(repoPath, workspacePath string) error
- func RunGitAllowFailureCtx(ctx context.Context, dir string, args ...string) (string, error)
- func RunGitCtx(ctx context.Context, dir string, args ...string) (string, error)
- func RunGitRawCtx(ctx context.Context, dir string, args ...string) ([]byte, error)
- type Change
- type ChangeKind
- type DiffLine
- type DiffLineKind
- type DiffMode
- type DiffResult
- type Error
- type FileWatcher
- type Hunk
- type StatusCache
- type StatusManager
- type StatusResult
Constants ¶
const ( // LargeFileSizeThreshold is the size above which files are considered "large" LargeFileSizeThreshold = 2 * 1024 * 1024 // 2MB )
Variables ¶
var ( ErrUnregisteredWorkspacePath = errors.New("workspace is not a registered worktree but still exists on disk") ErrWorkspaceCleanupPending = errors.New("workspace cleanup is still pending") )
var ErrEmptyCommitMessage = errors.New("commit message cannot be empty")
ErrEmptyCommitMessage is returned by CommitAll when the message is blank. The UI must supply a non-empty message; commit-all never invents one.
var ErrWatchLimit = errors.New("file watcher limit reached")
Functions ¶
func AheadBehind ¶ added in v0.0.20
AheadBehind reports how many commits HEAD is ahead of and behind the workspace's base branch, using the same base resolution as GetBranchFileDiff/BranchChangesVsBase (GetBaseBranch) so all three agree on what "base" means for a workspace. Read-only. When no base branch can be determined (e.g. no candidate/remote branch exists), the GetBaseBranch error is returned unchanged so callers can tell "nothing to compare against" apart from a real git failure.
func CommitAll ¶ added in v0.0.20
CommitAll stages every change in workspaceRoot — tracked, untracked, and deletions via `git add -A` — and commits them with message via `git commit -m <message>`. Both git invocations run through the hardened RunGitCtx, so they inherit filteredGitEnv, the hooks/fsmonitor neutralization (hardenedGitArgs), the context timeout, and structured *Error on failure.
message is passed as the argv value of -m and is never shell-interpolated, so a message beginning with '-' cannot be reparsed as a git flag. An empty or whitespace-only message is rejected with ErrEmptyCommitMessage.
This is commit-only by design: no merge, push, force, amend, autostash, or base-branch checkout. The commit lands on whatever branch workspaceRoot has checked out. A clean tree is not special-cased here — `git commit` exits non-zero on an empty index and that structured error is returned; callers pre-check StatusResult.Clean before invoking to avoid the raw git error.
func CreateWorkspace ¶ added in v0.0.7
CreateWorkspace creates a new workspace backed by a git worktree
func DeleteBranch ¶
DeleteBranch deletes a git branch
func DiscoverWorkspaces ¶ added in v0.0.7
DiscoverWorkspaces discovers git worktrees for a project. Returns workspaces with minimal fields populated (Name, Branch, Repo, Root). The caller should merge with stored metadata to get full workspace data.
func GetBaseBranch ¶ added in v0.0.3
GetBaseBranch returns the base branch (main, master, or the default branch). All returned branches are verified to exist locally. Returns an error if no default branch can be determined.
func GetCurrentBranch ¶
GetCurrentBranch returns the current branch name
func IsGitRepository ¶
IsGitRepository checks if the given path is a git repository
func IsUnregisteredWorkspacePathError ¶ added in v0.0.19
func IsWorkspaceCleanupPendingError ¶ added in v0.0.19
func RemoveWorkspace ¶ added in v0.0.7
RemoveWorkspace removes a workspace backed by a git worktree
func RunGitAllowFailureCtx ¶ added in v0.0.12
RunGitAllowFailureCtx executes git and returns stdout even if exit code is non-zero. Use for commands like `git diff --no-index` which return 1 when differences exist.
Types ¶
type Change ¶ added in v0.0.3
type Change struct {
Path string // Current file path
OldPath string // Original path (for renames/copies)
Kind ChangeKind // Type of change
Staged bool // Whether this change is staged
}
Change represents a single file change in git status
func BranchChangesVsBase ¶ added in v0.0.20
BranchChangesVsBase lists every file that differs between HEAD and merge-base(base, HEAD) — i.e. everything committed on this branch that hasn't landed on base yet. It reuses the same base/merge-base resolution as GetBranchFileDiff (GetBaseBranch, then resolveMergeBase) so "vs base" means the same thing in both places. Read-only: no fetch, merge, or checkout.
func (*Change) DisplayCode ¶ added in v0.0.3
DisplayCode returns a two-character status code for display First char is staged status, second is unstaged status
func (*Change) KindString ¶ added in v0.0.3
KindString returns a display string for the change kind
type ChangeKind ¶ added in v0.0.3
type ChangeKind int
ChangeKind represents the type of change
const ( ChangeModified ChangeKind = iota // File content changed ChangeAdded // New file ChangeDeleted // File removed ChangeRenamed // File renamed ChangeCopied // File copied ChangeUntracked // Untracked file )
type DiffLine ¶ added in v0.0.3
type DiffLine struct {
Kind DiffLineKind
Content string
}
DiffLine represents a single line in a diff
type DiffLineKind ¶ added in v0.0.3
type DiffLineKind int
DiffLineKind represents the type of a diff line
const ( DiffLineContext DiffLineKind = iota // Unchanged context line DiffLineAdd // Added line (green) DiffLineDelete // Deleted line (red) DiffLineHeader // File/hunk header )
type DiffResult ¶ added in v0.0.3
type DiffResult struct {
Path string // File path
Content string // Raw diff content
Hunks []Hunk // Parsed hunks for navigation
Lines []DiffLine // Parsed lines for rendering
Binary bool // True if this is a binary file
Large bool // True if the file is too large to display
Empty bool // True if there are no changes
Error string // Error message if diff failed
}
DiffResult holds parsed diff information for a single file
func GetBranchFileDiff ¶ added in v0.0.3
func GetBranchFileDiff(repoPath, path string) (*DiffResult, error)
GetBranchFileDiff returns the full diff for a single file on the branch
func GetFileDiff ¶ added in v0.0.3
func GetFileDiff(repoPath, path string, mode DiffMode) (*DiffResult, error)
GetFileDiff returns the diff for a specific file
func GetUntrackedFileContent ¶ added in v0.0.3
func GetUntrackedFileContent(repoPath, path string) (*DiffResult, error)
GetUntrackedFileContent returns the content of an untracked file formatted as a diff
func (*DiffResult) AddedLines ¶ added in v0.0.3
func (d *DiffResult) AddedLines() int
AddedLines returns the count of added lines
func (*DiffResult) DeletedLines ¶ added in v0.0.3
func (d *DiffResult) DeletedLines() int
DeletedLines returns the count of deleted lines
func (*DiffResult) HunkCount ¶ added in v0.0.3
func (d *DiffResult) HunkCount() int
HunkCount returns the number of hunks in the diff
type Error ¶ added in v0.0.20
type Error struct {
Command string // joined args, for display
Args []string // exact argv passed to git
// ExitCode is the git process exit code; -1 when the process did not run
// or did not exit normally.
ExitCode int
Stderr string
Err error
}
Error wraps git command errors with structured context: the exact argv, the process exit code, and captured stderr. Callers classify failures by matching ExitCode/Stderr through errors.As instead of parsing the prose of Error().
type FileWatcher ¶
type FileWatcher struct {
// contains filtered or unexported fields
}
FileWatcher watches git directories for changes and triggers status refreshes
func NewFileWatcher ¶
func NewFileWatcher(onChanged func(root string)) (*FileWatcher, error)
NewFileWatcher creates a new file watcher
func (*FileWatcher) Close ¶
func (fw *FileWatcher) Close() error
Close stops the watcher and releases resources
func (*FileWatcher) IsWatching ¶
func (fw *FileWatcher) IsWatching(root string) bool
IsWatching checks if a workspace is being watched
func (*FileWatcher) Run ¶ added in v0.0.5
func (fw *FileWatcher) Run(ctx context.Context) error
run processes file system events Run processes file system events until the context is canceled or the watcher closes.
func (*FileWatcher) Unwatch ¶
func (fw *FileWatcher) Unwatch(root string)
Unwatch stops watching a workspace
func (*FileWatcher) Watch ¶
func (fw *FileWatcher) Watch(root string) error
Watch starts watching a workspace for git changes
type Hunk ¶ added in v0.0.3
type Hunk struct {
OldStart int // Starting line in old file
OldCount int // Number of lines in old file
NewStart int // Starting line in new file
NewCount int // Number of lines in new file
StartLine int // Line index in rendered output (for navigation)
Header string // The full @@ line
}
Hunk represents a single hunk in a diff
type StatusCache ¶
type StatusCache struct {
Status *StatusResult
FetchedAt time.Time
}
StatusCache holds cached git status with TTL
type StatusManager ¶
type StatusManager struct {
// contains filtered or unexported fields
}
StatusManager caches git status results by workspace root with a TTL.
func NewStatusManager ¶
func NewStatusManager() *StatusManager
NewStatusManager creates a new status manager
func (*StatusManager) GetCached ¶
func (m *StatusManager) GetCached(root string) *StatusResult
GetCached returns the cached status for a workspace, or nil if not cached/expired
func (*StatusManager) Invalidate ¶
func (m *StatusManager) Invalidate(root string)
Invalidate removes a workspace from the cache
func (*StatusManager) InvalidateAll ¶
func (m *StatusManager) InvalidateAll()
InvalidateAll clears the entire cache
func (*StatusManager) SetCacheTTL ¶
func (m *StatusManager) SetCacheTTL(ttl time.Duration)
SetCacheTTL sets the cache time-to-live
func (*StatusManager) UpdateCache ¶
func (m *StatusManager) UpdateCache(root string, status *StatusResult)
UpdateCache directly updates the cache with a status result (no fetch)
type StatusResult ¶
type StatusResult struct {
Staged []Change // Changes staged for commit
Unstaged []Change // Changes in working tree (not staged)
Untracked []Change // Untracked files
Clean bool // True if no changes
// Aggregate line-level diff stats
TotalAdded int // Total lines added across all changes
TotalDeleted int // Total lines deleted across all changes
HasLineStats bool
}
StatusResult holds the parsed git status grouped by category
func GetStatus ¶
func GetStatus(repoPath string) (*StatusResult, error)
GetStatus returns the git status for a repository using porcelain v1 -z format This format handles spaces, unicode, and special characters in paths correctly
func GetStatusFast ¶ added in v0.0.15
func GetStatusFast(repoPath string) (*StatusResult, error)
GetStatusFast returns the git status for a repository using only porcelain output. It skips expensive diff --numstat and untracked line counting, so TotalAdded and TotalDeleted will be zero and HasLineStats will be false. Use this on hot paths where only Clean/change lists matter.
func (*StatusResult) AllChanges ¶ added in v0.0.3
func (s *StatusResult) AllChanges() []Change
AllChanges returns all changes as a flat list for backwards compatibility
func (*StatusResult) GetDirtyCount ¶
func (s *StatusResult) GetDirtyCount() int
GetDirtyCount returns the number of unique changed files
func (*StatusResult) GetStatusSummary ¶
func (s *StatusResult) GetStatusSummary() string
GetStatusSummary returns a summary string for the status
Source Files
¶
- branch.go
- diff.go
- doc.go
- file_read.go
- operations.go
- status.go
- status_manager.go
- watcher.go
- workspace.go
- workspace_cleanup.go
- workspace_cleanup_fsm.go
- workspace_cleanup_marker.go
- workspace_cleanup_marker_atomic.go
- workspace_cleanup_recovery.go
- workspace_cleanup_scope.go
- workspace_errors.go
- workspace_retry_metadata_guard.go
- writeback.go