git

package
v0.0.20 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: MIT Imports: 27 Imported by: 0

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

View Source
const (
	// LargeFileSizeThreshold is the size above which files are considered "large"
	LargeFileSizeThreshold = 2 * 1024 * 1024 // 2MB

)

Variables

View Source
var (
	ErrUnregisteredWorkspacePath = errors.New("workspace is not a registered worktree but still exists on disk")
	ErrWorkspaceCleanupPending   = errors.New("workspace cleanup is still pending")
)
View Source
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.

View Source
var ErrWatchLimit = errors.New("file watcher limit reached")

Functions

func AheadBehind added in v0.0.20

func AheadBehind(repoPath string) (ahead, behind int, err error)

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

func CommitAll(ctx context.Context, workspaceRoot, message string) error

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

func CreateWorkspace(repoPath, workspacePath, branch, base string) error

CreateWorkspace creates a new workspace backed by a git worktree

func DeleteBranch

func DeleteBranch(repoPath, branch string) error

DeleteBranch deletes a git branch

func DiscoverWorkspaces added in v0.0.7

func DiscoverWorkspaces(project *data.Project) ([]data.Workspace, error)

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

func GetBaseBranch(repoPath string) (string, error)

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

func GetCurrentBranch(path string) (string, error)

GetCurrentBranch returns the current branch name

func IsGitRepository

func IsGitRepository(path string) bool

IsGitRepository checks if the given path is a git repository

func IsUnregisteredWorkspacePathError added in v0.0.19

func IsUnregisteredWorkspacePathError(err error) bool

func IsWorkspaceCleanupPendingError added in v0.0.19

func IsWorkspaceCleanupPendingError(err error) bool

func RemoveWorkspace added in v0.0.7

func RemoveWorkspace(repoPath, workspacePath string) error

RemoveWorkspace removes a workspace backed by a git worktree

func RunGitAllowFailureCtx added in v0.0.12

func RunGitAllowFailureCtx(ctx context.Context, dir string, args ...string) (string, error)

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.

func RunGitCtx added in v0.0.12

func RunGitCtx(ctx context.Context, dir string, args ...string) (string, error)

RunGitCtx executes a git command in the specified directory with context.

func RunGitRawCtx added in v0.0.12

func RunGitRawCtx(ctx context.Context, dir string, args ...string) ([]byte, error)

RunGitRawCtx executes a git command and returns raw bytes without trimming. Use this for commands with -z output that use NUL separators.

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

func BranchChangesVsBase(repoPath string) ([]Change, error)

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

func (c *Change) DisplayCode() string

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

func (c *Change) KindString() string

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 DiffMode added in v0.0.3

type DiffMode int

DiffMode specifies which changes to diff

const (
	DiffModeUnstaged DiffMode = iota // Working tree changes (not staged)
	DiffModeStaged                   // Index changes (staged)
	DiffModeBoth                     // Both staged and unstaged
	DiffModeBranch                   // Branch diff vs base
)

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().

func (*Error) Error added in v0.0.20

func (e *Error) Error() string

func (*Error) Unwrap added in v0.0.20

func (e *Error) Unwrap() 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

func (*StatusCache) IsExpired

func (c *StatusCache) IsExpired(ttl time.Duration) bool

IsExpired checks if the cache entry has expired

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL