vcs

package
v0.0.0-...-c77a77e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package vcs implements Vesper's operations on git repositories: commits made on the server, reads, diffs, history, and landing without locks.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalid wraps every error caused by a bad request rather than a server fault.
	ErrInvalid = errors.New("invalid request")
	// ErrNotFound means the repo, revision, path or object doesn't exist.
	ErrNotFound = git.ErrNotFound
	// ErrExists means a repo with that name already exists.
	ErrExists = errors.New("already exists")
)
View Source
var ErrNothingChanged = errors.New("nothing changed")

ErrNothingChanged means a commit would not change its parent's tree.

View Source
var ErrTooManyAttempts = errors.New("the branch kept moving; try again")

ErrTooManyAttempts means upstream kept moving while landing.

Functions

This section is empty.

Types

type Change

type Change struct {
	Path   string   `json:"path"`
	Delete bool     `json:"delete,omitempty"`
	Mode   git.Mode `json:"mode,omitempty"`
	Blob   *git.ID  `json:"blob,omitempty"`
}

Change is one path's change relative to a commit's first parent.

type CommitRequest

type CommitRequest struct {
	Parents []git.ID
	Changes []Change
	// Author is "Name <email>".
	Author  string
	Message string
	// Time is seconds since the epoch; zero means now.
	Time int64
	// AllowEmpty permits a single-parent commit that changes nothing.
	AllowEmpty bool
}

CommitRequest describes a new commit as changes to its first parent.

type ConflictError

type ConflictError struct {
	Branch string   `json:"branch"`
	Tip    git.ID   `json:"tip"`
	Paths  []string `json:"paths"`
}

ConflictError means a commit can't be rebased onto the branch: the same lines changed differently on both sides.

func (*ConflictError) Error

func (e *ConflictError) Error() string

type DiffEntry

type DiffEntry struct {
	Path string         `json:"path"`
	Old  *git.TreeEntry `json:"old,omitempty"`
	New  *git.TreeEntry `json:"new,omitempty"`
}

DiffEntry is one file that differs between two trees. Old or New is nil when the file was added or removed.

type Host

type Host struct {
	// contains filtered or unexported fields
}

Host is a directory of repositories, each a bare git repo at repos/<name>.git.

func OpenHost

func OpenHost(dir string, logger *slog.Logger) (*Host, error)

OpenHost opens or creates a data directory.

func (*Host) Close

func (h *Host) Close()

Close stops every repository's background git process.

func (*Host) Create

func (h *Host) Create(ctx context.Context, name, upstream string) (*Repo, error)

Create makes a repository. With an upstream, it mirrors that remote and lands by pushing to it; without one, it stands alone.

func (*Host) FetchEvery

func (h *Host) FetchEvery(ctx context.Context, interval time.Duration)

FetchEvery keeps every mirror close to its upstream until ctx ends. Landing doesn't depend on it, since a push from a stale mirror is refused and retried.

func (*Host) List

func (h *Host) List() ([]RepoInfo, error)

List returns every repository.

func (*Host) Repo

func (h *Host) Repo(name string) (*Repo, error)

Repo returns an existing repository.

type LandResult

type LandResult struct {
	// ID is the commit now on the branch: the original, or a rebased copy.
	ID      git.ID `json:"id"`
	Rebased bool   `json:"rebased"`
	// AlreadyLanded means the branch already had every change.
	AlreadyLanded bool `json:"alreadyLanded"`
	// Attempts counts publishes, more than one when upstream moved meanwhile.
	Attempts int `json:"attempts"`
	// Batch is how many landings were published together with this one.
	Batch int `json:"batch"`
}

LandResult reports where a commit ended up.

type LogEntry

type LogEntry struct {
	ID     git.ID
	Commit *git.Commit
}

LogEntry is one commit in a log.

type Repo

type Repo struct {
	Name string
	// Upstream is the remote this repo mirrors and lands to, or "" if it stands alone.
	Upstream string
	// contains filtered or unexported fields
}

Repo is one repository.

func (*Repo) Branches

func (r *Repo) Branches(ctx context.Context) (map[string]git.ID, error)

Branches lists the repo's branches. For a mirror, these are upstream's as of the last fetch.

func (*Repo) Changes

func (r *Repo) Changes(c *git.Commit) ([]Change, error)

Changes lists what a commit changed relative to its first parent.

func (*Repo) Commit

func (r *Repo) Commit(ctx context.Context, req CommitRequest) (git.ID, error)

Commit validates the changes, writes the new trees and the commit, and returns its id. Only directories on changed paths are rewritten.

func (*Repo) Diff

func (r *Repo) Diff(from, to git.ID) ([]DiffEntry, error)

Diff lists the files that differ between two trees. Subtrees with the same id are skipped without being read.

func (*Repo) Fetch

func (r *Repo) Fetch(ctx context.Context) error

Fetch updates the mirror from upstream. Standalone repos have nothing to fetch.

func (*Repo) GetCommit

func (r *Repo) GetCommit(id git.ID) (*git.Commit, error)

Commit returns a commit by id.

func (*Repo) Git

func (r *Repo) Git() *git.Repo

Git exposes the underlying repository, for reading objects.

func (*Repo) Land

func (r *Repo) Land(ctx context.Context, branch string, id git.ID) (*LandResult, error)

Land puts a commit on a branch. Nobody holds a lock while working: landing happens on the server. If the branch's tip is the commit's parent, it is a fast-forward. Otherwise git merges the commit's changes onto the tip, line by line, and only genuinely conflicting edits are refused.

Landings that arrive together are published together, in order, with one push (or one ref update). Pushing is the compare-and-swap: if upstream moved, the push is refused, and the batch is fetched, rebased and pushed again.

func (*Repo) ListDir

func (r *Repo) ListDir(root git.ID, path string) ([]git.TreeEntry, error)

ListDir returns the entries of the directory at path.

func (*Repo) Log

func (r *Repo) Log(ctx context.Context, start git.ID, limit int, path string) ([]LogEntry, error)

Log walks first parents from start, newest first. With a path, only commits that changed that file or directory are returned; that check compares one tree entry per commit, so it costs the path's depth, not the commit's size.

func (*Repo) Lookup

func (r *Repo) Lookup(root git.ID, path string) (git.TreeEntry, error)

Lookup finds the entry at path below a root tree. The empty path is the root.

func (*Repo) ReadFile

func (r *Repo) ReadFile(root git.ID, path string) ([]byte, git.TreeEntry, error)

ReadFile returns the contents and entry of the file at path.

func (*Repo) Resolve

func (r *Repo) Resolve(ctx context.Context, rev string) (git.ID, error)

Resolve turns a revision (branch, full or short id, with ~N or ^N) into a commit id.

func (*Repo) SetBranch

func (r *Repo) SetBranch(ctx context.Context, name string, oldID, newID git.ID) error

SetBranch moves a branch by compare-and-swap; a zero old creates it and a zero new deletes it. Mirrors only change through land, which pushes upstream.

func (*Repo) Walk

func (r *Repo) Walk(root git.ID, fn func(path string, entry git.TreeEntry) error) error

Walk calls fn for every file below a tree, in path order.

type RepoInfo

type RepoInfo struct {
	Name     string `json:"name"`
	Upstream string `json:"upstream,omitempty"`
}

RepoInfo describes a repository.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL