Documentation
¶
Overview ¶
Package git is the I/O seam between monorel's planning logic and an underlying git repository.
Higher layers (planner, release applier, action orchestrator) take a Repo and never shell out themselves. The default implementation in this package shells out to the `git` CLI; tests use Fake.
Index ¶
- type Exec
- func (e *Exec) Add(paths ...string) error
- func (e *Exec) CheckoutBranch(branch string) error
- func (e *Exec) CheckoutNewBranch(branch, startPoint string) error
- func (e *Exec) Commit(message string) error
- func (e *Exec) CreateTag(name, message string) error
- func (e *Exec) CurrentSHA() (string, error)
- func (e *Exec) DeletedFilesInCommitsMatching(messageGrep string) ([]string, error)
- func (e *Exec) Fetch(remote, ref string) error
- func (e *Exec) HeadCommitMessage() (string, error)
- func (e *Exec) IsClean() (bool, error)
- func (e *Exec) ListTags(prefix string) ([]string, error)
- func (e *Exec) Push(remote, ref string, force bool) error
- func (e *Exec) PushTags(remote string) error
- func (e *Exec) Remove(paths ...string) error
- func (e *Exec) TagsAtHead() ([]string, error)
- type Fake
- func (f *Fake) Add(paths ...string) error
- func (f *Fake) CheckoutBranch(branch string) error
- func (f *Fake) CheckoutNewBranch(branch, startPoint string) error
- func (f *Fake) Commit(message string) error
- func (f *Fake) CreateTag(name, _ string) error
- func (f *Fake) CurrentSHA() (string, error)
- func (f *Fake) DeletedFilesInCommitsMatching(messageGrep string) ([]string, error)
- func (f *Fake) Fetch(remote, ref string) error
- func (f *Fake) HeadCommitMessage() (string, error)
- func (f *Fake) IsClean() (bool, error)
- func (f *Fake) ListTags(prefix string) ([]string, error)
- func (f *Fake) Push(remote, ref string, force bool) error
- func (f *Fake) PushTags(remote string) error
- func (f *Fake) Remove(paths ...string) error
- func (f *Fake) TagsAtHead() ([]string, error)
- type FakeCommit
- type Repo
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Exec ¶
type Exec struct {
// Dir is the working directory git commands run in. Required.
Dir string
// Env is the environment passed to git invocations. Empty means
// inherit os.Environ; tests override this to set GIT_AUTHOR_*
// for deterministic commit metadata.
Env []string
}
Exec is a Repo backed by shell-outs to the `git` CLI in a specific working directory.
Construct via Open; the zero value is not usable (Dir must be set).
func Open ¶
Open returns an Exec rooted at dir. The directory is not validated here; the first git invocation surfaces the error if dir is not inside a git repo.
func (*Exec) CheckoutBranch ¶
CheckoutBranch implements [Repo.CheckoutBranch].
func (*Exec) CheckoutNewBranch ¶ added in v0.15.0
CheckoutNewBranch implements [Repo.CheckoutNewBranch].
func (*Exec) CurrentSHA ¶
CurrentSHA implements [Repo.CurrentSHA].
func (*Exec) DeletedFilesInCommitsMatching ¶ added in v0.8.0
DeletedFilesInCommitsMatching implements [Repo.DeletedFilesInCommitsMatching].
Shells out to `git log --diff-filter=D --name-only --format= --fixed-strings --grep=<messageGrep>`, then dedupes/sorts the result. --fixed-strings makes the grep a literal substring match; --format= suppresses the commit header so stdout is just deleted paths.
func (*Exec) HeadCommitMessage ¶ added in v0.4.0
HeadCommitMessage implements [Repo.HeadCommitMessage].
func (*Exec) TagsAtHead ¶
TagsAtHead implements [Repo.TagsAtHead].
type Fake ¶
type Fake struct {
// Tags is the current set of tags. Order is irrelevant; ListTags
// sorts on output for deterministic comparisons.
Tags []string
// Branch tracks the currently-checked-out branch name.
Branch string
// HeadSHA is what CurrentSHA returns. Tests may set this to
// anything; the default (empty) yields a deterministic placeholder.
HeadSHA string
// Staged is the set of paths Add has been called with since the
// last Commit. Each Commit appends a snapshot to Commits and
// clears Staged.
Staged []string
// Removed records every Remove(paths...) call's paths.
Removed []string
// Commits is one entry per Commit() call: {Message, Files}.
Commits []FakeCommit
// Pushes records every Push call as "<remote>:<ref>[:force]".
Pushes []string
// PushedTags records every PushTags(remote) call.
PushedTags []string
// Dirty toggles IsClean's return value. By default the fake
// reports clean; set Dirty=true to make IsClean return false.
Dirty bool
// FailNext, when non-nil, is returned by the next operation
// regardless of which one. Single-shot: cleared after firing.
// Used to test error-handling paths in higher layers.
FailNext error
// Dir, when non-empty, is the repository root. When set,
// [Fake.Remove] also physically deletes the named paths from disk
// (mirroring `git rm -f`). Tests that verify working-tree state
// after Remove should set Dir; tests that only inspect Removed
// can leave it empty.
Dir string
// contains filtered or unexported fields
}
Fake is an in-memory Repo for unit tests of higher layers.
Operations record into the corresponding fields so tests can assert on them; it doesn't simulate every git invariant. Specifically:
- Add/Remove just track which paths have been touched; there's no actual working tree.
- Commit appends to Commits with the staged paths cleared.
- CreateTag fails on duplicate names (matches git behavior).
Construct with NewFake; the zero value is usable but tests usually want to seed initial tags via NewFake's argument.
func NewFake ¶
NewFake returns an empty in-memory repo with the given initial tags. nil is fine for "no tags yet."
func (*Fake) CheckoutBranch ¶
CheckoutBranch implements [Repo.CheckoutBranch].
func (*Fake) CheckoutNewBranch ¶ added in v0.15.0
CheckoutNewBranch implements [Repo.CheckoutNewBranch]. The fake records the new branch as the current branch; startPoint is observed but not simulated.
func (*Fake) Commit ¶
Commit implements [Repo.Commit]. Appends a FakeCommit with the staged paths and clears Staged.
func (*Fake) CurrentSHA ¶
CurrentSHA implements [Repo.CurrentSHA].
func (*Fake) DeletedFilesInCommitsMatching ¶ added in v0.8.0
DeletedFilesInCommitsMatching implements [Repo.DeletedFilesInCommitsMatching]. Walks the recorded Commits, collecting Deletions from any commit whose Message contains messageGrep as a literal substring.
func (*Fake) Fetch ¶ added in v0.15.0
Fetch implements [Repo.Fetch]. The fake runs the FailNext hook; it does not simulate any state change.
func (*Fake) HeadCommitMessage ¶ added in v0.4.0
HeadCommitMessage implements [Repo.HeadCommitMessage]. Returns the Message of the last FakeCommit in Commits, or "" when no commits have been recorded.
func (*Fake) Remove ¶
Remove implements [Repo.Remove]. Records the paths in Removed. When [Fake.Dir] is set, also physically removes each path from the working tree (mirroring `git rm -f`). Missing files are silently skipped.
func (*Fake) TagsAtHead ¶
TagsAtHead implements [Repo.TagsAtHead]. The fake doesn't track per-tag SHAs; it returns every tag created via CreateTag since the last call to clear (which the fake doesn't have). Tests that need fine-grained "tags pointing at this specific commit" should override this with a custom impl.
type FakeCommit ¶
type FakeCommit struct {
Message string
Files []string
// Deletions are the paths Remove(...) recorded for this commit.
// Subset of Files. Tracked separately so
// DeletedFilesInCommitsMatching can answer accurately without
// the fake needing to know each path's add-vs-delete state.
Deletions []string
}
FakeCommit is one recorded commit on a Fake.
type Repo ¶
type Repo interface {
// ListTags returns every tag whose name starts with prefix. An
// empty prefix returns all tags. Order is unspecified; callers
// that need semver order sort with semver.Compare.
ListTags(prefix string) ([]string, error)
// TagsAtHead returns every tag pointing at the current HEAD
// commit (i.e. `git tag --points-at HEAD`). Used by `monorel
// publish` to find which tags to create provider Releases for.
// Order is unspecified.
TagsAtHead() ([]string, error)
// CurrentSHA returns the SHA at HEAD.
CurrentSHA() (string, error)
// HeadCommitMessage returns the full commit message of HEAD
// (subject + body, including any trailers). Used by `monorel tag`
// to read the trailers `monorel apply` writes for downstream
// tag creation.
HeadCommitMessage() (string, error)
// Add stages the named paths. No-op when paths is empty.
Add(paths ...string) error
// Remove unstages and deletes the named paths from the working
// tree (i.e. `git rm`). Used to consume changeset files at
// release time.
Remove(paths ...string) error
// Commit creates a commit with the given message at HEAD.
// Returns an error if there is nothing staged.
Commit(message string) error
// CreateTag creates an annotated tag at HEAD. message is the
// tag annotation; pass an empty string for a lightweight tag.
CreateTag(name, message string) error
// Push pushes ref to remote (e.g. Push("origin", "main") or
// Push("origin", "monorel/release"). force=true uses --force-
// with-lease so a stale local view doesn't clobber an upstream
// update we don't know about.
Push(remote, ref string, force bool) error
// PushTags pushes every local tag to remote. monorel pushes
// tags after the release commit lands so the order in the
// remote's reflog is "commit, then its tags."
PushTags(remote string) error
// Fetch updates remote-tracking refs for ref from remote
// (`git fetch --no-tags <remote> <ref>`). Used by the auto
// orchestrator to refresh origin/<base-branch> before creating
// monorel/release from it. Empty ref fetches every ref the
// remote advertises.
//
// Tags are not auto-fetched (--no-tags); the auto orchestrator
// only needs the refs that affect the release branch's plan.
// Call ListTags or a separate fetch if you need them.
Fetch(remote, ref string) error
// CheckoutBranch checks out branch, creating it from the
// current HEAD if it doesn't exist (`git checkout -B`). For
// creating a branch from a non-HEAD start point (e.g. a remote
// tracking ref), use [Repo.CheckoutNewBranch].
CheckoutBranch(branch string) error
// CheckoutNewBranch creates branch at startPoint and checks it
// out (`git checkout -B <branch> <startPoint>`). Used by the
// auto orchestrator to create monorel/release from the freshly
// fetched origin/<base>.
CheckoutNewBranch(branch, startPoint string) error
// IsClean reports whether the working tree has no uncommitted
// or untracked changes (i.e. `git status --porcelain` is empty).
// Pre-release safety check: monorel refuses to run release on
// a dirty tree.
IsClean() (bool, error)
// DeletedFilesInCommitsMatching returns the union of every file
// path deleted (`--diff-filter=D`) by a commit whose subject or
// body literally contains messageGrep. The substring match is
// case-sensitive and does NOT use regex.
//
// Used by `monorel doctor` to scan past `chore(release):`
// commits for the changeset filenames they consumed, so a
// stale-branch + squash-merge revival can be detected.
//
// Order: deduplicated, sorted lexicographically. Includes paths
// that were re-added by later commits — callers intersect
// against the live tree to flag that case.
DeletedFilesInCommitsMatching(messageGrep string) ([]string, error)
}
Repo is the slice of git operations monorel needs. Methods are intentionally narrow: monorel does not implement git itself, just the handful of commands a release flow performs.
Implementations:
- Exec (default) — shells out to the `git` CLI in a working directory. The CLI is already on every CI runner and dev box; we don't pull in go-git's 50k-LOC partial reimplementation just for these few commands.
- Fake (in-memory) — for unit tests of higher layers.
All methods return wrapped errors that include the underlying git stderr output when shelling out fails.