Documentation
¶
Overview ¶
Package git — the error-code range owned by this domain (ADR 0005 §Registry).
Package git — the sentinels every implementation of this domain returns.
Package git is the version-control contract: what "the set a branch changed" is, and what a resolution of it reports.
The domain is deliberately thin. It names a CHANGED SET — the files, line ranges and directories a branch touched relative to its merge-base — and the outcome of computing one. It does not model repositories, commits, refs or history: the SDK has exactly one implementation, which shells out to the git binary (framework/internal/service/git), and a contract broader than that would describe nothing real.
There is **no registry**. A registry's key would be a VCS name, and resolving one from a config string would let a typo silently swap the implementation with every call still succeeding — the same argument ADR 0052 makes for lock.
Package git — the LineRangeValue value type: an inclusive run of changed lines.
Index ¶
Constants ¶
const CodeCommandFailed errs.Code = 0x00_02_21_02 // 0.2.33.2
CodeCommandFailed identifies a version-control command that exited non-zero. The stderr tail travels in Private, never in Public.
const CodePathAbsent errs.Code = 0x00_02_21_03 // 0.2.33.3
CodePathAbsent identifies a path that does not exist at the requested commit, which is distinct from a path that exists and is empty.
const CodeRepositoryUnresolved errs.Code = 0x00_02_21_01 // 0.2.33.1
CodeRepositoryUnresolved identifies a path that is not inside a repository the implementation can read, or a repository probe that failed outright.
Variables ¶
var ( // RepositoryUnresolved is returned when a path is not inside a readable // repository, or when the probe that would have told us failed. RepositoryUnresolved = errs.Static(CodeRepositoryUnresolved, "REPOSITORY_UNRESOLVED", "the path is not inside a readable repository", "core/git: the repository probe failed or the path lies outside any repository", 0, 0) // CommandFailed is returned when a version-control command exits non-zero. // The command line and its stderr are attached as Private: they can name // branches, paths and remotes, none of which belongs on a wire-safe surface. CommandFailed = errs.Static(CodeCommandFailed, "COMMAND_FAILED", "the version-control command failed", "core/git: the version-control command exited non-zero", 0, 0) // PathAbsent is returned when a path does not exist at the requested commit. // It is deliberately distinct from a successful read of an empty file: a // caller reconstructing history has to tell "deleted" from "emptied". PathAbsent = errs.Static(CodePathAbsent, "PATH_ABSENT", "the path does not exist at that commit", "core/git: the requested path is absent from the requested commit's tree", 0, 0) )
Functions ¶
This section is empty.
Types ¶
type ChangedSet ¶
type ChangedSet interface {
// ContainsLine reports whether line on absFile falls inside a changed hunk.
// Lines are 1-based and the bounds are inclusive.
ContainsLine(absFile string, line int) bool
// ContainsFile reports whether absFile appears anywhere in the diff,
// including as the old side of a rename or a deletion.
ContainsFile(absFile string) bool
// ContainsDir reports whether absDir directly encloses any touched file.
// It is not recursive: a parent of a touched directory is not itself
// touched.
ContainsDir(absDir string) bool
// IsEmpty reports whether nothing at all was touched — a clean branch, or
// one whose every change the caller's own filter excluded.
IsEmpty() bool
}
ChangedSet reports what a branch changed, at the three granularities a caller can ask about. It is FROZEN at four methods.
Every path argument is absolute. Implementations normalise through filepath.Clean before comparing, so a caller need not — but Clean is LEXICAL and resolves no symbolic link, so two spellings of one file do not match each other. There is exactly one exception, and it exists because it is the one spelling a caller cannot choose: THE ROOT IT NAMED. An implementation whose backend canonicalises that root away still answers for paths spelled through the caller's root, and for paths spelled the backend's way — the two roots a caller actually has in hand. An indirection anywhere else in a queried path is still lexical, and still does not match.
The three Contains methods are not interchangeable and none implies another in the direction a caller might assume: a pure rename or a deletion touches a FILE and its DIRECTORY while contributing no line range at all, so ContainsFile can be true where ContainsLine is false for every line of it. That is the point — a check that only looks at lines silently ignores a deleted file.
type LineRangeValue ¶
type LineRangeValue struct {
// Start is the first changed line, inclusive and 1-based.
Start int
// End is the last changed line, inclusive.
End int
}
LineRangeValue is an inclusive, 1-based range of source lines taken from a diff hunk's "+"-side, i.e. post-edit line numbers.
A whole-file change — a new or untracked file — is represented by a range starting at 1 and ending at a synthetic upper bound, so a membership test matches any line without the parser needing to know the file's true length.
func (LineRangeValue) Contains ¶
func (r LineRangeValue) Contains(line int) bool
Contains reports whether line falls inside the range. Both bounds are inclusive, which is what makes a single-line hunk (Start == End) match.
type ResolutionValue ¶
type ResolutionValue struct {
// Set is what the branch changed, or nil when FullFallback is true.
Set ChangedSet
// BaseRef is the default-branch ref the comparison used, e.g. "origin/main".
// Empty when degraded.
BaseRef string
// BaseSHA is the merge-base commit between BaseRef and HEAD. Empty when
// degraded.
BaseSHA string
// HeadSHA is the commit HEAD resolved to. Empty when degraded.
HeadSHA string
// FullFallback reports that no trustworthy changed set could be computed and
// the caller must fall back to considering everything in scope.
FullFallback bool
// Reason is the human-readable cause of the fallback, meant to be surfaced
// rather than swallowed. Empty when not degraded.
Reason string
}
ResolutionValue is the outcome of resolving what a branch changed.
It has exactly two readable shapes and the zero value is neither, which is deliberate: a ResolutionValue nobody produced carries a nil Set AND FullFallback false, a combination no constructor mints, so a caller that forgot to check reads "nothing changed" from no code path that ever ran. Check Degraded first.
- Resolved: Set is non-nil and BaseRef / BaseSHA / HeadSHA name the comparison that produced it.
- Degraded: FullFallback is true and Reason says why. Set is nil. The caller must treat EVERYTHING as in scope.
The degraded shape is the whole reason this is a value rather than (ChangedSet, error). A resolver that cannot be trusted must never answer with an empty set: "nothing changed" and "I could not tell what changed" are opposite instructions, and conflating them is how a review silently passes on a branch it never looked at.
func (*ResolutionValue) Degraded ¶
func (r *ResolutionValue) Degraded() bool
Degraded reports whether the resolution failed to produce a trustworthy set and the caller must treat everything as in scope.
It is the predicate callers want, and it reads from FullFallback rather than from a nil Set so the two can never disagree.
The receiver is a pointer because the value is 88 bytes — four strings, an interface and a bool — and copying all of it to read one bool is what KTN-VAR-BIGSTRUCT exists to catch. Assign the resolution to a variable and call it on that; the chained form Resolve(...).Degraded() does not compile, which is a fair trade for not copying 88 bytes per query.