Documentation
¶
Overview ¶
Package gitops wraps the git and gh commands needed to read the default branch of a repo and to land a change on it — pushing directly when allowed, or opening an auto-merge PR when the branch is protected. The flow mirrors the proven all-repos-codegrapher.sh script.
Index ¶
- Constants
- func Clone(cloneURL, dest string) error
- func CommitEmpty(repoPath, message string) error
- func CurrentBranch(repoPath string) (string, error)
- func DefaultBranch(repoPath string) (string, error)
- func Fetch(repoPath string) error
- func HasCommits(repoPath string) (bool, error)
- func LocalState(repoPath string) (dirty bool, reason string, err error)
- func OriginURL(repoPath string) (string, error)
- func Pull(repoPath string) error
- func PushSetUpstream(repoPath, branch string) error
- func RemoteHasBranches(repoPath string) (bool, error)
- func SetSkipSync(repoPath string) error
- func ShowFile(repoPath, ref, path string) (content string, ok bool, err error)
- func SkipSync(repoPath string) (bool, error)
- func UnpushedCommits(repoPath string) ([]string, error)
- func UnsetSkipSync(repoPath string) error
- func WorktreeChanged(dir string) (bool, error)
- type LandOptions
- type Mutator
- type Outcome
- type RepoStatus
- type TrackingState
Constants ¶
const SkipSyncKey = "wb.skip-sync"
SkipSyncKey is the git config key marking a repo that wb sync must leave alone. It is always read and written with --local: a plain read falls back to ~/.gitconfig, where one stray key would silently disable sync for the whole fleet.
Variables ¶
This section is empty.
Functions ¶
func CommitEmpty ¶ added in v0.38.0
CommitEmpty creates an empty commit, used to give an unborn branch something to push.
func CurrentBranch ¶ added in v0.38.0
CurrentBranch returns the checked-out branch name of repoPath. A detached HEAD reports an empty name rather than an error, because `git branch --show-current` succeeds there and prints nothing; callers that need a branch to push must reject the empty string themselves.
func DefaultBranch ¶
DefaultBranch returns the remote's default branch (e.g. "main"). It first refreshes origin/HEAD from the remote, because a local clone's cached origin/HEAD can be stale (e.g. the repo was renamed master -> main after the clone was made), which would otherwise yield the wrong branch.
func HasCommits ¶ added in v0.38.0
HasCommits reports whether repoPath's HEAD resolves, i.e. whether the checked-out branch has any commits yet. --verify --quiet exits 1 silently on an unborn branch, where a bare `rev-parse HEAD` would exit 128 and print "fatal: ambiguous argument 'HEAD'" into the error text.
func LocalState ¶
LocalState reports whether repoPath has uncommitted changes (including untracked files) or local commits not present on any remote. The reason string names the first condition found.
func OriginURL ¶ added in v0.38.0
OriginURL returns repoPath's origin remote URL, erroring when no origin is configured.
func Pull ¶
Pull runs `git pull --ff-only --quiet` on the currently checked-out branch of repoPath.
Fast-forward-only is deliberate. A canonical clone must never acquire a merge commit from an unattended fleet sync, and whether a plain `git pull` would merge, rebase, or refuse depends on the machine's pull.rebase setting — so without --ff-only the same divergence rewrites history on one machine and errors on another. Refusing is the only safe answer; the caller classifies the refusal.
func PushSetUpstream ¶ added in v0.38.0
PushSetUpstream pushes branch to origin and sets it as the upstream.
func RemoteHasBranches ¶ added in v0.39.0
RemoteHasBranches reports whether origin publishes any branch at all.
A repository created on GitHub but never pushed to has none, and there is nothing for sync to pull from it — now or on any future run, until someone pushes. That is distinct from a remote that has branches but not the one the local branch tracks, which is a real problem (a renamed or deleted branch) and must keep failing loudly.
func SetSkipSync ¶ added in v0.38.0
SetSkipSync marks repoPath to be skipped by sync.
func ShowFile ¶
ShowFile returns the contents of path at ref (e.g. "origin/main"), and a false ok when the file does not exist at that ref.
func SkipSync ¶ added in v0.38.0
SkipSync reports whether repoPath is marked to be skipped by sync.
Exactly one git exit status means "not marked": 1, for an absent key. Every other failure is a real error and is returned as one — notably 128, which covers both a malformed value and a path that is not a git repository. Swallowing those (as internal/hooks treats `git config --get` failures) would silently resume pulling a repo the user asked wb to leave alone.
func UnpushedCommits ¶ added in v0.40.0
UnpushedCommits lists commits present on some local branch and on no remote-tracking branch, newest first, as `<short-sha> <subject>` lines.
Deliberately every local branch, not just the checked-out one: work is abandoned on a side branch at least as often as on the default one, and a clone holding either is holding work that exists nowhere else.
func UnsetSkipSync ¶ added in v0.38.0
UnsetSkipSync clears the skip marker from repoPath, and is idempotent.
--unset-all rather than --unset: on a key that somehow holds multiple values, --unset exits 5 and leaves every value in place, so the caller would report success on a repo that is still marked. --unset-all clears them all, and exits 5 only when the key is genuinely absent — the no-op case, which is success here.
func WorktreeChanged ¶
WorktreeChanged reports whether the worktree at dir has any uncommitted changes (tracked edits or untracked files), via `git status --porcelain`.
Types ¶
type LandOptions ¶
type LandOptions struct {
DefaultBranch string
CommitMessage string
PRBranch string
PRTitle string
PRBody string
}
LandOptions configures how a change is committed and pushed.
type Mutator ¶
Mutator edits files inside the worktree and reports whether it changed anything along with a human-readable detail.
type Outcome ¶
Outcome describes what Land did.
func Land ¶
func Land(repoPath string, opt LandOptions, mutate Mutator) (Outcome, error)
Land fetches, creates a detached worktree at origin/<default>, runs mutate, and — if it changed files — commits and pushes to the default branch, falling back to a PR with auto-merge when the push is rejected (protected branch).
type RepoStatus ¶
type RepoStatus struct {
Modified []string // tracked files with changes
Untracked []string // untracked files
Conflicted []string // merge-conflict paths
Unpushed []string // `git log --branches --not --remotes --oneline` lines
Stashed []string // `git stash list` lines
}
RepoStatus is git working-tree/history state relevant to sync decisions and to reporting why a repo needs attention.
func Status ¶
func Status(repoPath string) (RepoStatus, error)
Status reads repoPath's working tree, stash, and unpushed-commit state.
func (RepoStatus) Dirty ¶
func (s RepoStatus) Dirty() bool
Dirty reports whether s represents any state — working tree, stash, or unpushed commits — that should block automatically removing an archived repo's local clone.
func (RepoStatus) Summary ¶
func (s RepoStatus) Summary() string
Summary renders a short human-readable description of s, e.g. "3 modified files, 1 untracked file". Empty when nothing is set.
func (RepoStatus) WorkingTreeDirty ¶
func (s RepoStatus) WorkingTreeDirty() bool
WorkingTreeDirty reports whether the working tree itself has changes (modified, untracked, or conflicted files) — the check used to decide whether it is safe to `git pull`.
type TrackingState ¶ added in v0.39.1
type TrackingState struct {
Branch string // checked-out branch, empty when HEAD is detached
Upstream string // e.g. "origin/main", empty when it does not resolve
Ahead int // local commits the upstream does not have
Behind int // upstream commits the local branch does not have
// Configured records whether the branch names an upstream in git config,
// which is not the same as Upstream resolving. A branch configured to
// track a ref the remote no longer publishes has Configured true and
// Upstream empty — a renamed or deleted branch, and a real problem —
// while a branch that names no upstream at all simply has nowhere to
// pull from. Callers must not conflate the two.
Configured bool
}
TrackingState is the checked-out branch's relationship to its upstream, as of the last fetch. It is what sync needs in order to tell a divergence ("each side has commits the other lacks") apart from a genuine fault.
func Tracking ¶ added in v0.39.1
func Tracking(repoPath string) (TrackingState, error)
Tracking reads the checked-out branch's divergence from its upstream.
The counts are only as current as the last fetch. Callers read it after a failed Pull, which has already fetched, so they see current numbers without a second round trip. A missing branch, upstream, or merge base is a state to report, not an error: the zero-ish TrackingState it returns describes exactly the situation the caller has to explain to a human.
func (TrackingState) Diverged ¶ added in v0.39.1
func (t TrackingState) Diverged() bool
Diverged reports whether the branch and its upstream have each moved on with commits the other lacks, so no fast-forward is possible.
func (TrackingState) Summary ¶ added in v0.39.1
func (t TrackingState) Summary() string
Summary renders the state as one short line for a sync report, e.g. "main is 1 ahead, 2 behind origin/main".