Documentation
¶
Overview ¶
Package git defines the GitService interface and all types for SSU's git layer.
GitService is the single abstraction through which the Engine and Commands interact with git. Two implementations exist: ExecGit (production, os/exec) and MockGitService (testing, configurable stubs).
Index ¶
- Variables
- func DetectBestBranch(ctx context.Context, svc GitService, dir string, opts BranchDetectOpts) (string, error)
- func IsConflict(err error) bool
- func IsTimeout(err error) bool
- func ResolveBranchForCheckout(ctx context.Context, svc GitService, dir string, opts BranchCheckoutOpts) (string, bool, error)
- type BranchCheckoutOpts
- type BranchDetectOpts
- type BranchPointsAtResult
- type BranchResult
- type CheckoutResult
- type CommitResult
- type ExecGit
- func (g *ExecGit) BranchesPointingAt(ctx context.Context, dir, ref string) (BranchPointsAtResult, error)
- func (g *ExecGit) Checkout(ctx context.Context, dir, branch string) (CheckoutResult, error)
- func (g *ExecGit) CheckoutNewBranch(ctx context.Context, dir, branch, startPoint string) (CheckoutResult, error)
- func (g *ExecGit) Commit(ctx context.Context, dir, message string) (CommitResult, error)
- func (g *ExecGit) CommitsAhead(ctx context.Context, dir, remoteRef string) (int, error)
- func (g *ExecGit) CommitsBehind(ctx context.Context, dir, localRef, remoteRef string) (int, error)
- func (g *ExecGit) CreateTag(ctx context.Context, dir string, opts TagOpts) error
- func (g *ExecGit) CurrentBranch(ctx context.Context, dir string) (BranchResult, error)
- func (g *ExecGit) CurrentSHA(ctx context.Context, dir string) (string, error)
- func (g *ExecGit) DiffIndex(ctx context.Context, dir string) ([]string, error)
- func (g *ExecGit) Fetch(ctx context.Context, dir string, opts FetchOpts) (FetchResult, error)
- func (g *ExecGit) HasLocalChanges(ctx context.Context, dir string) (bool, error)
- func (g *ExecGit) HasRemoteBranch(ctx context.Context, dir, remote, branch string) (bool, error)
- func (g *ExecGit) IncomingChangelog(ctx context.Context, dir, remoteRef string, limit int) ([]string, error)
- func (g *ExecGit) IsAncestor(ctx context.Context, dir, ancestor, descendant string) (bool, error)
- func (g *ExecGit) IsDetachedHead(ctx context.Context, dir string) (bool, error)
- func (g *ExecGit) IsSubmoduleInitialized(rootDir, subPath string) bool
- func (g *ExecGit) ListTags(ctx context.Context, dir string, limit int) ([]string, error)
- func (g *ExecGit) Merge(ctx context.Context, dir, ref string) (MergeResult, error)
- func (g *ExecGit) MergeAbort(ctx context.Context, dir string) error
- func (g *ExecGit) Push(ctx context.Context, dir string, opts PushOpts) (PushResult, error)
- func (g *ExecGit) RefExists(ctx context.Context, dir, ref string) (bool, error)
- func (g *ExecGit) RemoteBranches(ctx context.Context, dir string) ([]RemoteBranch, error)
- func (g *ExecGit) RemovePath(ctx context.Context, rootDir, path string) error
- func (g *ExecGit) ResetHard(ctx context.Context, dir, ref string) error
- func (g *ExecGit) StageFiles(ctx context.Context, dir string, paths []string) error
- func (g *ExecGit) Stash(ctx context.Context, dir string) (StashResult, error)
- func (g *ExecGit) StashPop(ctx context.Context, dir string) (StashResult, error)
- func (g *ExecGit) SubmoduleDeinit(ctx context.Context, rootDir, subPath string) error
- func (g *ExecGit) SubmoduleInit(ctx context.Context, rootDir string, paths []string) error
- func (g *ExecGit) SubmodulePaths(ctx context.Context, rootDir string) ([]string, error)
- func (g *ExecGit) SymbolicRef(ctx context.Context, dir, ref string) (string, error)
- func (g *ExecGit) TrackingBranch(ctx context.Context, dir string) (TrackingInfo, error)
- type FetchOpts
- type FetchResult
- type GitError
- type GitService
- type MergeResult
- type MockGitService
- func (m *MockGitService) BranchesPointingAt(ctx context.Context, dir, ref string) (BranchPointsAtResult, error)
- func (m *MockGitService) Checkout(ctx context.Context, dir, branch string) (CheckoutResult, error)
- func (m *MockGitService) CheckoutNewBranch(ctx context.Context, dir, branch, startPoint string) (CheckoutResult, error)
- func (m *MockGitService) Commit(ctx context.Context, dir, message string) (CommitResult, error)
- func (m *MockGitService) CommitsAhead(ctx context.Context, dir, remoteRef string) (int, error)
- func (m *MockGitService) CommitsBehind(ctx context.Context, dir, localRef, remoteRef string) (int, error)
- func (m *MockGitService) CreateTag(ctx context.Context, dir string, opts TagOpts) error
- func (m *MockGitService) CurrentBranch(ctx context.Context, dir string) (BranchResult, error)
- func (m *MockGitService) CurrentSHA(ctx context.Context, dir string) (string, error)
- func (m *MockGitService) DiffIndex(ctx context.Context, dir string) ([]string, error)
- func (m *MockGitService) Fetch(ctx context.Context, dir string, opts FetchOpts) (FetchResult, error)
- func (m *MockGitService) HasLocalChanges(ctx context.Context, dir string) (bool, error)
- func (m *MockGitService) HasRemoteBranch(ctx context.Context, dir, remote, branch string) (bool, error)
- func (m *MockGitService) IncomingChangelog(ctx context.Context, dir, remoteRef string, limit int) ([]string, error)
- func (m *MockGitService) IsAncestor(ctx context.Context, dir, ancestor, descendant string) (bool, error)
- func (m *MockGitService) IsDetachedHead(ctx context.Context, dir string) (bool, error)
- func (m *MockGitService) IsSubmoduleInitialized(rootDir, subPath string) bool
- func (m *MockGitService) ListTags(ctx context.Context, dir string, limit int) ([]string, error)
- func (m *MockGitService) Merge(ctx context.Context, dir, ref string) (MergeResult, error)
- func (m *MockGitService) MergeAbort(ctx context.Context, dir string) error
- func (m *MockGitService) Push(ctx context.Context, dir string, opts PushOpts) (PushResult, error)
- func (m *MockGitService) RefExists(ctx context.Context, dir, ref string) (bool, error)
- func (m *MockGitService) RemoteBranches(ctx context.Context, dir string) ([]RemoteBranch, error)
- func (m *MockGitService) RemovePath(ctx context.Context, rootDir, path string) error
- func (m *MockGitService) ResetHard(ctx context.Context, dir, ref string) error
- func (m *MockGitService) StageFiles(ctx context.Context, dir string, paths []string) error
- func (m *MockGitService) Stash(ctx context.Context, dir string) (StashResult, error)
- func (m *MockGitService) StashPop(ctx context.Context, dir string) (StashResult, error)
- func (m *MockGitService) SubmoduleDeinit(ctx context.Context, rootDir, subPath string) error
- func (m *MockGitService) SubmoduleInit(ctx context.Context, rootDir string, paths []string) error
- func (m *MockGitService) SubmodulePaths(ctx context.Context, rootDir string) ([]string, error)
- func (m *MockGitService) SymbolicRef(ctx context.Context, dir, ref string) (string, error)
- func (m *MockGitService) TrackingBranch(ctx context.Context, dir string) (TrackingInfo, error)
- type PushOpts
- type PushResult
- type RemoteBranch
- type SemVer
- type StashResult
- type SubmoduleStatus
- type TagOpts
- type TimeoutConfig
- type TrackingInfo
Constants ¶
This section is empty.
Variables ¶
var DefaultBranchPriority = []string{"develop", "master", "main"}
DefaultBranchPriority is the default branch priority chain for detection.
Functions ¶
func DetectBestBranch ¶
func DetectBestBranch(ctx context.Context, svc GitService, dir string, opts BranchDetectOpts) (string, error)
DetectBestBranch implements the smart branch detection algorithm. It follows a strict 5-level priority chain, matching the original bash detect_best_branch() function:
- Override: opts.Override (--branch CLI flag)
- Feature branch: current branch preserved if it has a remote
- Priority chain: first match in opts.PriorityBranches with a remote ref
- Remote HEAD: symbolic ref of remote HEAD (e.g. origin/HEAD -> develop)
- Final fallback: first available remote branch, or "master"
This is a standalone function operating on the GitService interface so it can be fully unit-tested with MockGitService.
func IsConflict ¶
IsConflict reports whether err represents a git merge conflict.
func ResolveBranchForCheckout ¶ added in v1.1.3
func ResolveBranchForCheckout(ctx context.Context, svc GitService, dir string, opts BranchCheckoutOpts) (string, bool, error)
ResolveBranchForCheckout finds the best branch to checkout when HEAD is detached. It queries BranchesPointingAt(HEAD) and picks the best match with priority:
- Local feature branch (not in priority list)
- Local priority branch (develop > master > main)
- Remote feature branch (not in priority list)
- Remote priority branch (develop > master > main)
Returns the branch name, whether it's a local branch, and any error. If no branch points at HEAD, returns ("", false, nil).
Types ¶
type BranchCheckoutOpts ¶ added in v1.1.3
type BranchCheckoutOpts struct {
PriorityBranches []string // Default: ["develop", "master", "main"]
DefaultRemote string // Default: "origin"
}
BranchCheckoutOpts configures branch resolution for checkout.
type BranchDetectOpts ¶
type BranchDetectOpts struct {
Override string // --branch CLI flag (highest priority)
PriorityBranches []string // Default: ["develop", "master", "main"]
DefaultRemote string // Default: "origin"
}
BranchDetectOpts configures the smart branch detection algorithm.
type BranchPointsAtResult ¶ added in v1.1.3
type BranchPointsAtResult struct {
Local []string // Local branch names (e.g. "develop", "feature/foo")
Remote []RemoteBranch // Remote branches (e.g. origin/develop)
}
BranchPointsAtResult holds the branches whose tip equals a given ref.
type BranchResult ¶
type BranchResult struct {
Name string // Branch name, or empty if detached
Detached bool // True when HEAD is detached
Stderr string
}
BranchResult holds the outcome of a current-branch query.
type CheckoutResult ¶
CheckoutResult holds the outcome of a git checkout.
type CommitResult ¶
CommitResult holds the outcome of a git commit.
type ExecGit ¶
type ExecGit struct {
GitBin string // Path to git binary; defaults to "git" if empty.
Timeouts TimeoutConfig // Per-operation timeout configuration.
}
ExecGit implements GitService by shelling out to the git binary via os/exec. Every command uses context.WithTimeout for robust timeout handling and sets GIT_TERMINAL_PROMPT=0 to prevent credential prompt hangs.
func NewExecGit ¶
func NewExecGit() *ExecGit
NewExecGit returns an ExecGit with default timeouts and system git.
func (*ExecGit) BranchesPointingAt ¶ added in v1.1.3
func (*ExecGit) CheckoutNewBranch ¶ added in v1.1.6
func (*ExecGit) CommitsAhead ¶
func (*ExecGit) CommitsBehind ¶
func (*ExecGit) CurrentBranch ¶
func (*ExecGit) CurrentSHA ¶
func (*ExecGit) HasLocalChanges ¶
func (*ExecGit) HasRemoteBranch ¶
func (*ExecGit) IncomingChangelog ¶
func (*ExecGit) IsAncestor ¶ added in v1.1.6
func (*ExecGit) IsDetachedHead ¶
func (*ExecGit) IsSubmoduleInitialized ¶
func (*ExecGit) RemoteBranches ¶
func (*ExecGit) RemovePath ¶ added in v1.1.4
func (*ExecGit) StageFiles ¶
func (*ExecGit) SubmoduleDeinit ¶ added in v1.1.4
func (*ExecGit) SubmoduleInit ¶ added in v1.1.5
func (*ExecGit) SubmodulePaths ¶
func (*ExecGit) SymbolicRef ¶
func (*ExecGit) TrackingBranch ¶
type FetchResult ¶
type FetchResult struct {
Stderr string
}
FetchResult holds the outcome of a git fetch.
type GitError ¶
type GitError struct {
Op string // Operation name: "fetch", "push", "merge", etc.
Stderr string // Raw stderr output from git
Err error // Underlying error (exec.ExitError, context.DeadlineExceeded, etc.)
}
GitError wraps a git operation failure with context.
type GitService ¶
type GitService interface {
// Repository discovery
SubmodulePaths(ctx context.Context, rootDir string) ([]string, error)
IsSubmoduleInitialized(rootDir, subPath string) bool
SubmoduleInit(ctx context.Context, rootDir string, paths []string) error
// Branch and revision queries
CurrentBranch(ctx context.Context, dir string) (BranchResult, error)
CurrentSHA(ctx context.Context, dir string) (string, error)
IsDetachedHead(ctx context.Context, dir string) (bool, error)
RemoteBranches(ctx context.Context, dir string) ([]RemoteBranch, error)
CommitsBehind(ctx context.Context, dir, localRef, remoteRef string) (int, error)
CommitsAhead(ctx context.Context, dir, remoteRef string) (int, error)
HasRemoteBranch(ctx context.Context, dir, remote, branch string) (bool, error)
SymbolicRef(ctx context.Context, dir, ref string) (string, error)
TrackingBranch(ctx context.Context, dir string) (TrackingInfo, error)
RefExists(ctx context.Context, dir, ref string) (bool, error)
IsAncestor(ctx context.Context, dir, ancestor, descendant string) (bool, error)
// Status queries
HasLocalChanges(ctx context.Context, dir string) (bool, error)
IncomingChangelog(ctx context.Context, dir, remoteRef string, limit int) ([]string, error)
// Mutating operations
Fetch(ctx context.Context, dir string, opts FetchOpts) (FetchResult, error)
Checkout(ctx context.Context, dir, branch string) (CheckoutResult, error)
CheckoutNewBranch(ctx context.Context, dir, branch, startPoint string) (CheckoutResult, error)
Merge(ctx context.Context, dir, ref string) (MergeResult, error)
Push(ctx context.Context, dir string, opts PushOpts) (PushResult, error)
Stash(ctx context.Context, dir string) (StashResult, error)
StashPop(ctx context.Context, dir string) (StashResult, error)
MergeAbort(ctx context.Context, dir string) error
ResetHard(ctx context.Context, dir, ref string) error
// Branch queries
BranchesPointingAt(ctx context.Context, dir, ref string) (BranchPointsAtResult, error)
// Submodule removal
SubmoduleDeinit(ctx context.Context, rootDir, subPath string) error
RemovePath(ctx context.Context, rootDir, path string) error
// Root repository operations
DiffIndex(ctx context.Context, dir string) ([]string, error)
StageFiles(ctx context.Context, dir string, paths []string) error
Commit(ctx context.Context, dir, message string) (CommitResult, error)
ListTags(ctx context.Context, dir string, limit int) ([]string, error)
CreateTag(ctx context.Context, dir string, opts TagOpts) error
}
GitService abstracts all git operations SSU needs. Implementations: ExecGit (production), MockGitService (testing).
type MergeResult ¶
type MergeResult struct {
Success bool
Conflict bool // True if merge failed due to conflict
Stderr string
}
MergeResult holds the outcome of a git merge.
type MockGitService ¶
type MockGitService struct {
SubmodulePathsFn func(ctx context.Context, rootDir string) ([]string, error)
IsSubmoduleInitializedFn func(rootDir, subPath string) bool
SubmoduleInitFn func(ctx context.Context, rootDir string, paths []string) error
CurrentBranchFn func(ctx context.Context, dir string) (BranchResult, error)
CurrentSHAFn func(ctx context.Context, dir string) (string, error)
IsDetachedHeadFn func(ctx context.Context, dir string) (bool, error)
RemoteBranchesFn func(ctx context.Context, dir string) ([]RemoteBranch, error)
CommitsBehindFn func(ctx context.Context, dir, localRef, remoteRef string) (int, error)
CommitsAheadFn func(ctx context.Context, dir, remoteRef string) (int, error)
HasRemoteBranchFn func(ctx context.Context, dir, remote, branch string) (bool, error)
SymbolicRefFn func(ctx context.Context, dir, ref string) (string, error)
TrackingBranchFn func(ctx context.Context, dir string) (TrackingInfo, error)
RefExistsFn func(ctx context.Context, dir, ref string) (bool, error)
IsAncestorFn func(ctx context.Context, dir, ancestor, descendant string) (bool, error)
HasLocalChangesFn func(ctx context.Context, dir string) (bool, error)
IncomingChangelogFn func(ctx context.Context, dir, remoteRef string, limit int) ([]string, error)
FetchFn func(ctx context.Context, dir string, opts FetchOpts) (FetchResult, error)
CheckoutFn func(ctx context.Context, dir, branch string) (CheckoutResult, error)
CheckoutNewBranchFn func(ctx context.Context, dir, branch, startPoint string) (CheckoutResult, error)
MergeFn func(ctx context.Context, dir, ref string) (MergeResult, error)
PushFn func(ctx context.Context, dir string, opts PushOpts) (PushResult, error)
StashFn func(ctx context.Context, dir string) (StashResult, error)
StashPopFn func(ctx context.Context, dir string) (StashResult, error)
MergeAbortFn func(ctx context.Context, dir string) error
ResetHardFn func(ctx context.Context, dir, ref string) error
DiffIndexFn func(ctx context.Context, dir string) ([]string, error)
StageFilesFn func(ctx context.Context, dir string, paths []string) error
CommitFn func(ctx context.Context, dir, message string) (CommitResult, error)
ListTagsFn func(ctx context.Context, dir string, limit int) ([]string, error)
CreateTagFn func(ctx context.Context, dir string, opts TagOpts) error
BranchesPointingAtFn func(ctx context.Context, dir, ref string) (BranchPointsAtResult, error)
SubmoduleDeinitFn func(ctx context.Context, rootDir, subPath string) error
RemovePathFn func(ctx context.Context, rootDir, path string) error
}
MockGitService is a test double for GitService. Each method delegates to its corresponding Fn field if non-nil, otherwise returns a sensible default. This allows tests to override only the methods they care about while leaving everything else functional with safe zero-value behavior.
func (*MockGitService) BranchesPointingAt ¶ added in v1.1.3
func (m *MockGitService) BranchesPointingAt(ctx context.Context, dir, ref string) (BranchPointsAtResult, error)
func (*MockGitService) Checkout ¶
func (m *MockGitService) Checkout(ctx context.Context, dir, branch string) (CheckoutResult, error)
func (*MockGitService) CheckoutNewBranch ¶ added in v1.1.6
func (m *MockGitService) CheckoutNewBranch(ctx context.Context, dir, branch, startPoint string) (CheckoutResult, error)
func (*MockGitService) Commit ¶
func (m *MockGitService) Commit(ctx context.Context, dir, message string) (CommitResult, error)
func (*MockGitService) CommitsAhead ¶
func (*MockGitService) CommitsBehind ¶
func (*MockGitService) CurrentBranch ¶
func (m *MockGitService) CurrentBranch(ctx context.Context, dir string) (BranchResult, error)
func (*MockGitService) CurrentSHA ¶
func (*MockGitService) Fetch ¶
func (m *MockGitService) Fetch(ctx context.Context, dir string, opts FetchOpts) (FetchResult, error)
func (*MockGitService) HasLocalChanges ¶
func (*MockGitService) HasRemoteBranch ¶
func (*MockGitService) IncomingChangelog ¶
func (*MockGitService) IsAncestor ¶ added in v1.1.6
func (*MockGitService) IsDetachedHead ¶
func (*MockGitService) IsSubmoduleInitialized ¶
func (m *MockGitService) IsSubmoduleInitialized(rootDir, subPath string) bool
func (*MockGitService) Merge ¶
func (m *MockGitService) Merge(ctx context.Context, dir, ref string) (MergeResult, error)
func (*MockGitService) MergeAbort ¶
func (m *MockGitService) MergeAbort(ctx context.Context, dir string) error
func (*MockGitService) Push ¶
func (m *MockGitService) Push(ctx context.Context, dir string, opts PushOpts) (PushResult, error)
func (*MockGitService) RemoteBranches ¶
func (m *MockGitService) RemoteBranches(ctx context.Context, dir string) ([]RemoteBranch, error)
func (*MockGitService) RemovePath ¶ added in v1.1.4
func (m *MockGitService) RemovePath(ctx context.Context, rootDir, path string) error
func (*MockGitService) ResetHard ¶
func (m *MockGitService) ResetHard(ctx context.Context, dir, ref string) error
func (*MockGitService) StageFiles ¶
func (*MockGitService) Stash ¶
func (m *MockGitService) Stash(ctx context.Context, dir string) (StashResult, error)
func (*MockGitService) StashPop ¶
func (m *MockGitService) StashPop(ctx context.Context, dir string) (StashResult, error)
func (*MockGitService) SubmoduleDeinit ¶ added in v1.1.4
func (m *MockGitService) SubmoduleDeinit(ctx context.Context, rootDir, subPath string) error
func (*MockGitService) SubmoduleInit ¶ added in v1.1.5
func (*MockGitService) SubmodulePaths ¶
func (*MockGitService) SymbolicRef ¶
func (*MockGitService) TrackingBranch ¶
func (m *MockGitService) TrackingBranch(ctx context.Context, dir string) (TrackingInfo, error)
type PushResult ¶
type PushResult struct {
Remote string // Which remote was pushed to
Branch string // Which branch was pushed
NewTracking bool // True if -u was used to set up tracking
Stderr string
}
PushResult holds the outcome of a git push.
type RemoteBranch ¶
RemoteBranch represents a branch on a remote. This is a data type, not an operation result, so it does not carry Stderr.
type SemVer ¶
type SemVer struct {
Major int
Minor int
Patch int
Prerelease string // e.g. "beta.1" (empty if none)
}
SemVer represents a parsed semantic version (major.minor.patch with optional prerelease).
func LatestSemVer ¶
LatestSemVer finds the highest semver tag from a list of tag strings. Non-semver tags are ignored. Returns nil if no valid semver tags found.
func ParseSemVer ¶
ParseSemVer parses a version string like "v1.2.3" or "v1.2.3-beta.1". Returns nil if the string is not a valid semver.
func (SemVer) IncrementPatch ¶
IncrementPatch returns a new SemVer with the patch version bumped and prerelease cleared.
type StashResult ¶
type StashResult struct {
Created bool // For Stash: true if a stash was created; for StashPop: true if pop was applied
Stderr string
}
StashResult holds the outcome of a stash or stash pop operation.
type SubmoduleStatus ¶
type SubmoduleStatus string
SubmoduleStatus represents the state of a submodule.
const ( StatusPending SubmoduleStatus = "pending" StatusCurrent SubmoduleStatus = "current" StatusModified SubmoduleStatus = "modified" StatusAhead SubmoduleStatus = "ahead" StatusConflict SubmoduleStatus = "conflict" StatusMissing SubmoduleStatus = "missing" StatusSkipped SubmoduleStatus = "skipped" StatusError SubmoduleStatus = "error" )
type TagOpts ¶
type TagOpts struct {
Name string // Tag name (e.g. "v1.2.3")
Message string // Annotation message
}
TagOpts configures a git tag creation.
type TimeoutConfig ¶
type TimeoutConfig struct {
Fetch time.Duration // Default 120s -- network bound.
Push time.Duration // Default 60s -- network bound.
Merge time.Duration // Default 30s -- local operation.
Default time.Duration // Default 30s -- for queries like rev-parse, branch -r.
}
TimeoutConfig holds per-operation timeout durations.
func DefaultTimeouts ¶
func DefaultTimeouts() TimeoutConfig
DefaultTimeouts returns a TimeoutConfig with sensible defaults.