Documentation
¶
Index ¶
- Variables
- func IsObjectID(sha string) bool
- func ValidateClaimKey(ctx context.Context, key string) error
- type ClaimOrigin
- type ClaimRef
- type ClaimRefRequest
- type CoalesceConfig
- type ConflictResolver
- type Git
- type GitOption
- type GitOptions
- type RebaseConflictError
- type RemoteRef
- type RemoteURL
- type SSHKeyPath
- type Side
- type Status
- type VaultAPIMergeClient
- type VaultAPIMergeResult
Constants ¶
This section is empty.
Variables ¶
var ErrConflictResolutionFailed = stderrors.New("conflict resolution failed")
ErrConflictResolutionFailed is returned by Pull when the ConflictResolver returns an error. The merge is aborted before returning so the repo is left in a clean state. Callers detect this via errors.Is(err, ErrConflictResolutionFailed).
var ErrFileExists = stderrors.New("file already exists")
ErrFileExists is returned when a create-only write targets a path that is already occupied. Callers distinguish "already there" (a benign no-op for idempotent publishers) from a genuine write failure via errors.Is.
var ErrInvalidPath = stderrors.New("invalid path")
ErrInvalidPath is returned when the requested path fails validation.
var ErrInvalidRefName = stderrors.New("invalid claim ref name")
ErrInvalidRefName is returned when a claim key or expected sha is not a safe, well-formed ref name.
var ErrMissingFrontmatter = stderrors.New("missing frontmatter")
ErrMissingFrontmatter is returned when an overwrite of an existing task file would replace it with content that has no frontmatter block. The existing file is left untouched. Callers detect this via errors.Is.
var ErrNoRemote = stderrors.New("no origin remote configured")
ErrNoRemote is returned when a claim ref operation needs the origin but the repository has no remote configured.
var ErrNotFound = stderrors.New("file not found")
ErrNotFound is returned when a requested file does not exist in the repository.
var ErrRefConflict = stderrors.New("claim ref conflict")
ErrRefConflict is returned when the origin's compare-and-swap rejects a claim ref write because another writer won the race.
var ErrRepoUnrecoverable = stderrors.New("repo state unrecoverable")
ErrRepoUnrecoverable is returned by Pull when the repository is in a state that cannot be automatically healed (e.g., git rebase --abort fails, or refs/remotes/origin/HEAD is missing for detached-HEAD recovery). Callers detect this via errors.Is(err, ErrRepoUnrecoverable).
Functions ¶
func IsObjectID ¶ added in v0.33.0
IsObjectID reports whether sha is a full-length lowercase hex object id (40 hex for SHA-1, 64 hex for SHA-256).
Types ¶
type ClaimOrigin ¶ added in v0.33.0
type ClaimOrigin interface {
ListRefs(ctx context.Context, pattern string) ([]RemoteRef, error)
FetchCommits(ctx context.Context, shas []string) error
ReadCommitMessage(ctx context.Context, sha string) ([]byte, error)
}
ClaimOrigin abstracts the origin-contacting git operations used by claim-ref listing. The production implementation is gitOrigin; tests inject a fake.
type ClaimRef ¶ added in v0.33.0
type ClaimRef struct {
Ref string `json:"ref"`
SHA string `json:"sha"`
Cluster string `json:"cluster"`
TaskID string `json:"task_id"`
LeaseUntil string `json:"lease_until"`
}
ClaimRef is one claim ref as read live from the origin. The JSON field set is the HTTP response contract: exactly these five keys, never a nonce.
type ClaimRefRequest ¶ added in v0.33.0
type ClaimRefRequest struct {
ExpectedSHA string `json:"expected_sha"`
Cluster string `json:"cluster"`
TaskID string `json:"task_id"`
LeaseUntil string `json:"lease_until"`
}
ClaimRefRequest is the create/renew request. ExpectedSHA empty means the ref must not exist.
type CoalesceConfig ¶ added in v0.34.0
CoalesceConfig controls write coalescing. Enabled=false restores the synchronous write-commit-push path used before coalescing existed.
type ConflictResolver ¶ added in v0.20.0
ConflictResolver is called by the puller when git merge produces unresolvable conflicts. Resolve receives the list of conflicted file paths as reported by git merge output. It must stage each path (git add) before returning nil so the puller can commit the merge. On error the puller runs git merge --abort and returns ErrConflictResolutionFailed.
func NewMarkerResolver ¶ added in v0.20.0
func NewMarkerResolver(repoPath string) ConflictResolver
NewMarkerResolver returns a ConflictResolver that preserves git's standard conflict markers. It stages each conflicted file as-is: the <<<<<<< / ======= / >>>>>>> markers written by git's three-way merge are left intact in the committed file. The next human or agent edit resolves them naturally.
func NewVaultAPIMergeResolver ¶ added in v0.35.0
func NewVaultAPIMergeResolver( repoPath string, client VaultAPIMergeClient, fallback ConflictResolver, m metrics.Metrics, ) ConflictResolver
NewVaultAPIMergeResolver returns a ConflictResolver that hands each conflicted path to vault-api and stages whatever the merge wrote.
It exists because git-rest is the only process that sees a divergence: the pull runs here, and the three sides exist only while the merge is open, as index stages 1/2/3. vault-api owns the merge itself — the per-key frontmatter rules — and writes the result through git-rest's own write API, so this resolver's job is to supply the sides and then stage the outcome.
fallback is invoked per path whenever vault-api cannot resolve: it is unreachable, it answers a quarantine (a body both sides edited differently carries no content to stage), or it returns any other failure. The fallback keeps the pre-existing YAML-merge behaviour, so enabling this path can only add resolutions, never remove one.
func NewYAMLMergeResolver ¶ added in v0.21.0
func NewYAMLMergeResolver(repoPath string, m metrics.Metrics) ConflictResolver
NewYAMLMergeResolver returns a ConflictResolver that deep-merges YAML frontmatter in conflicted markdown files. For each conflicted path it:
- Reads the working-tree file (still containing git's three-way merge markers).
- Extracts the "ours" and "theirs" sides of each conflict region.
- Parses the YAML frontmatter on both sides; deep-merges keys (theirs wins on overlap).
- Combines bodies per the rules in the spec (theirs if non-empty, else ours; both differ → "ours\n\ntheirs").
- Writes the merged file back and runs `git add -- <path>`.
On any failure (YAML parse error, missing frontmatter delimiter pair on either side, disk write failure, git add failure) it increments the corresponding failure-category counter, emits a Warningf log line naming the path, and returns ErrConflictResolutionFailed. The caller (the puller) runs `git merge --abort` and surfaces the sentinel.
type Git ¶
type Git interface {
WriteFile(ctx context.Context, path string, content []byte) error
// WriteFileIfAbsent writes content to path only when no file exists there
// yet. It returns ErrFileExists (via errors.Is) when path is occupied, and
// performs no repository modification in that case.
WriteFileIfAbsent(ctx context.Context, path string, content []byte) error
DeleteFile(ctx context.Context, path string) error
ReadFile(ctx context.Context, path string) ([]byte, error)
ListFiles(ctx context.Context, pattern string) ([]string, error)
Pull(ctx context.Context) error
Status(ctx context.Context) (Status, error)
Clone(ctx context.Context, remoteURL RemoteURL) error
ConfigureUser(ctx context.Context, name string, email string) error
ConfigurePackMemory(ctx context.Context) error
// ConfigureClaimMirror configures the clone's origin fetch to carry the claim
// namespace into refs/claim-mirror/* and enables remote.origin.prune. It is
// idempotent and must never abort startup on failure.
ConfigureClaimMirror(ctx context.Context) error
Init(ctx context.Context) error
// ListClaimRefs returns the claim refs under refs/<prefix>. A fresh local
// claim mirror answers without touching the network; a stale, absent,
// unconfigured or object-missing mirror falls back to the live origin path.
// The response contract is identical on both paths.
ListClaimRefs(ctx context.Context, prefix string) ([]ClaimRef, error)
// PutClaimRef creates or renews refs/<key> with the origin's compare-and-swap.
// It returns the new commit sha. A lease mismatch returns ErrRefConflict.
PutClaimRef(ctx context.Context, key string, request ClaimRefRequest) (string, error)
// DeleteClaimRef deletes refs/<key> with the origin's compare-and-swap.
// A lease mismatch or an absent ref returns ErrRefConflict.
DeleteClaimRef(ctx context.Context, key string, expectedSHA string) error
// FlushPending commits and pushes the pending write set. A no-op when the set is empty.
FlushPending(ctx context.Context) error
// FlushPendingIfDue flushes only when the pending set is non-empty and either
// the trailing delay or the max-delay has elapsed.
FlushPendingIfDue(ctx context.Context) error
// RecoverPendingWrites commits and pushes paths left staged in the index by a
// crash, before the HTTP server starts serving. A no-op when nothing is staged.
RecoverPendingWrites(ctx context.Context) error
}
Git abstracts all git shell operations on a local repository.
func New ¶
func New( repoPath string, m metrics.Metrics, currentDateTimeGetter libtime.CurrentDateTimeGetter, sshKeyPath SSHKeyPath, resolver ConflictResolver, options ...GitOption, ) Git
New returns a Git implementation backed by the system git binary for the given repository path.
type GitOption ¶ added in v0.34.0
type GitOption func(*GitOptions)
GitOption modifies GitOptions.
func WithClaimMirrorPullInterval ¶ added in v0.36.1
WithClaimMirrorPullInterval sets the pull interval the claim-mirror staleness bound is derived from.
func WithCoalesce ¶ added in v0.34.0
func WithCoalesce(config CoalesceConfig) GitOption
WithCoalesce sets the write-coalescing configuration.
type GitOptions ¶ added in v0.34.0
type GitOptions struct {
Coalesce CoalesceConfig
// ClaimMirrorPullInterval is the configured pull interval. The claim-mirror
// staleness bound is derived from it (twice the interval, floor 60 s).
// Zero uses the floor.
ClaimMirrorPullInterval libtime.Duration
}
GitOptions holds optional configuration for New.
type RebaseConflictError ¶ added in v0.19.2
type RebaseConflictError struct {
Path string // conflicted file path, from "CONFLICT (content): Merge conflict in <path>"
}
RebaseConflictError is returned by Pull when git rebase encounters a content conflict. The repo is left in its conflicted state for human inspection. git rebase --abort is NEVER invoked automatically.
func (*RebaseConflictError) Error ¶ added in v0.19.2
func (e *RebaseConflictError) Error() string
type RemoteURL ¶ added in v0.9.0
type RemoteURL string
RemoteURL is the URL of a remote git repository.
type SSHKeyPath ¶ added in v0.8.0
type SSHKeyPath string
SSHKeyPath is the path to an SSH private key used for git operations.
type Side ¶ added in v0.35.0
Side is one side of a diverged file as vault-api's merge endpoint expects it: the file's content at that revision plus the revision's committer time, which the merge uses to break ties between two edits to the same frontmatter key.
type Status ¶
type Status struct {
// Clean is true when the working tree has no uncommitted changes.
Clean bool
// NoPushPending is true when there are no commits ahead of the remote.
NoPushPending bool
}
Status represents the current state of the git working tree.
type VaultAPIMergeClient ¶ added in v0.35.0
type VaultAPIMergeClient interface {
Merge(ctx context.Context, path string, base, ours, theirs Side) (VaultAPIMergeResult, error)
}
VaultAPIMergeClient resolves a diverged file through vault-api's POST /api/v1/merge. It exists as an interface so the resolver can be tested without an HTTP server.
func NewHTTPVaultAPIMergeClient ¶ added in v0.35.0
func NewHTTPVaultAPIMergeClient(baseURL, secret string) VaultAPIMergeClient
NewHTTPVaultAPIMergeClient returns a VaultAPIMergeClient that posts to baseURL's /api/v1/merge with the shared gateway secret.
type VaultAPIMergeResult ¶ added in v0.35.0
type VaultAPIMergeResult struct {
Result string `json:"result"`
Reason string `json:"reason"`
// Content carries the merged bytes. The resolver asks vault-api not to apply
// the merge, because this process is mid-pull holding the repository mutex:
// a write back through git-rest's own API waits on the lock the pull holds,
// and the request never returns.
Content string `json:"content"`
}
VaultAPIMergeResult reports what the merge decided. Result is "merged" or "quarantined"; Reason names why a quarantine happened.