Documentation
¶
Overview ¶
Package gitops wraps the git command-line tool with the operations gitten needs: clone and fetch, transparent backup (stash refs + patch files), worktree management, and working-tree status/lock inspection.
Index ¶
- Constants
- Variables
- func AddWorktree(ctx context.Context, source, dest, branch, base string, opts CloneOptions) error
- func AheadBehind(ctx context.Context, repoPath, ref string) (ahead, behind int, err error)
- func ApplyBackup(ctx context.Context, repoPath string, b BackupInfo) error
- func ArchiveClone(ctx context.Context, repoPath, dir, name string) (string, error)
- func BatchEnv() []string
- func BranchExists(ctx context.Context, repoPath, branch string) bool
- func CheckIdle(ctx context.Context, repoPath string, operations bool) error
- func Clone(ctx context.Context, url, destPath string, opts CloneOptions) error
- func CloneFromSource(ctx context.Context, source, dest, upstream, branch, base string, shared bool, ...) error
- func Commit(ctx context.Context, repoPath, message string, addUntracked bool) (committed bool, err error)
- func CopyID(ctx context.Context, repoPath string) (string, error)
- func DefaultBase(ctx context.Context, source string) string
- func DeleteArchive(path string) error
- func FastForward(ctx context.Context, repoPath string) (updated bool, skipped string, err error)
- func Fetch(ctx context.Context, repoPath, sshKeyPath string) error
- func Git(ctx context.Context, repoPath string, args ...string) (string, error)
- func GitExitCode(ctx context.Context, repoPath string, args ...string) int
- func GitOutput(ctx context.Context, repoPath string, args ...string) ([]byte, error)
- func GitWithSSHKey(ctx context.Context, repoPath, sshKeyPath string, args ...string) (string, error)
- func HasGitDir(path string) bool
- func IsBareRepo(ctx context.Context, repoPath string) bool
- func IsLocked(ctx context.Context, repoPath string) (bool, string)
- func IsPartial(ctx context.Context, path string) bool
- func IsStaging(name string) bool
- func LinkedWorktrees(ctx context.Context, repoPath string) ([]string, error)
- func LocalConfig(ctx context.Context, repoPath string) (map[string]string, error)
- func LockRepo(ctx context.Context, repoPath string, exclusive bool, wait time.Duration) (release func(), err error)
- func Mirror(ctx context.Context, url, path string, opts MirrorOptions) (created bool, err error)
- func ParseRemoteURL(ctx context.Context, repoPath string) (*repourl.Identity, error)
- func Pull(ctx context.Context, repoPath, sshKeyPath string, ffOnly, rebase bool) (string, error)
- func Push(ctx context.Context, repoPath, sshKeyPath string, setUpstream bool) (string, error)
- func PushOffsite(ctx context.Context, repoPath string, latest *Latest, o Offsite, ...) (OffsiteRecord, OffsitePlan, error)
- func ReadCopyID(ctx context.Context, repoPath string) string
- func RefreshFromSource(ctx context.Context, copyPath, source string) error
- func RemoveClone(ctx context.Context, repoPath, archiveDir, name string, opts RemoveOptions) (string, error)
- func RemoveWorktree(ctx context.Context, source, path, archiveDir, name string, opts RemoveOptions) (string, error)
- func RepointSource(ctx context.Context, copyPath, from, to string) error
- func ResolveBase(ctx context.Context, repo, base string) (string, error)
- func RestoreArchive(ctx context.Context, path, dest, base string) error
- func RestoreBackupInto(ctx context.Context, repoPath string, b BackupInfo, into string) error
- func SetLocalConfig(ctx context.Context, repoPath, key, value string) error
- func SetOriginURL(ctx context.Context, repoPath, url string) error
- func Source(ctx context.Context, path string) string
- func Submodules(ctx context.Context, repoPath string) ([]string, error)
- func TestSign(ctx context.Context, settings map[string]string) error
- func UnsetLocalConfig(ctx context.Context, repoPath, key string) error
- func Upstream(ctx context.Context, repoPath string) string
- func WorktreeAdd(ctx context.Context, repoPath, worktreePath, branch, baseRef string) error
- func WorktreeMove(ctx context.Context, repoPath, from, to string) error
- func WorktreePrune(ctx context.Context, repoPath string) error
- func WorktreeRemove(ctx context.Context, repoPath, worktreePath string, force bool) error
- func WorktreeRepair(ctx context.Context, repoPath string) error
- type ArchiveMeta
- type BackupConfig
- type BackupInfo
- type BackupMeta
- type BackupOption
- type BackupOutcome
- type BackupResult
- type CloneOptions
- type GitDirs
- type Latest
- type MirrorOptions
- type Offsite
- type OffsitePlan
- type OffsiteRecord
- type RemoveOptions
- type RepoStatus
- type Retention
- type Shape
- type SkippedFile
- type Snapshot
- type SnapshotLimits
- type SubmoduleBackup
- type SubmoduleError
- type UniqueWork
- type WorktreeInfo
Constants ¶
const LFSFetchExclude = "lfs.fetchexclude"
LFSFetchExclude is the git config key that, set to "*", keeps Git LFS from downloading any content.
const RewrittenPrefix = "refs/gitten-rewritten/"
RewrittenPrefix holds the old tips of refs a mirror's remote rewrote. It is outside refs/gitten/, which a remote may hold refs of its own under.
const SourceRemote = "gitten"
SourceRemote is a workspace clone's remote for the repo's own clone, its source, whose branches it fetches as gitten/<branch>.
Variables ¶
var ErrBusy = errors.New("git is busy in it")
ErrBusy reports a repository a git command is working in: it holds one of the repository's locks, or a rebase, merge, cherry-pick or revert is under way. Archiving or deleting it then could catch it half-changed.
var ErrHasWorktrees = errors.New("it has linked worktrees")
ErrHasWorktrees reports a clone with linked worktrees: deleting it would delete their branches and history, and leave their work unreadable.
var ErrLocked = errors.New("repo locked")
ErrLocked indicates an operation was skipped because a git lock file (e.g. .git/index.lock) was present, signalling another git process is active on the repo. It is transient, not a failure.
var ErrNoBackup = errors.New("no backup found")
ErrNoBackup reports that a working copy has no backup, or none by that ID.
var ErrNotAMirror = errors.New("it isn't a mirror (remote.origin.mirror is unset)")
ErrNotAMirror reports something at a mirror's path that isn't a mirror, which is left alone.
var ErrPartialSource = errors.New("the repo's clone is partial (clone.filter); only worktree copies can be made from it")
ErrPartialSource reports a source made with a partial clone filter: a copy can't fetch through it the objects it lacks.
var ErrRepoGone = errors.New("the repo is gone")
ErrRepoGone reports a repository that isn't there to lock: never cloned, or deleted or moved away while its lock was waited for.
var ErrRepoInUse = errors.New("another gitten command is using the repo")
ErrRepoInUse reports a repository whose lock another gitten command holds: one deleting, archiving or moving it, or making a copy of it.
Functions ¶
func AddWorktree ¶
func AddWorktree(ctx context.Context, source, dest, branch, base string, opts CloneOptions) error
AddWorktree adds a linked worktree of the repo at source at dest, on branch: the existing local branch, origin's branch when only origin has it, else a new branch at base (see ResolveBase). It checks out what opts.Shape asks for; opts' key, filter and depth clone its submodules. A worktree whose submodules can't all be checked out stays, and a *SubmoduleError says so.
func AheadBehind ¶
AheadBehind reports how many commits HEAD is ahead of and behind ref (typically an upstream such as "origin/main").
func ApplyBackup ¶
func ApplyBackup(ctx context.Context, repoPath string, b BackupInfo) error
ApplyBackup restores backup b onto the working copy at repoPath, which the caller has checked is safe to change. A snapshot ref is applied with `git stash apply --index`, which restores the staged and unstaged changes and the untracked files and stops rather than overwrite an existing untracked file; if HEAD has moved since the backup, git merges and reports any conflict. Without a ref the patch backup is applied instead.
func ArchiveClone ¶
ArchiveClone moves the whole clone at repoPath into dir, as dir/<id>, with a JSON description beside it at dir/<id>.json, and returns its new path, or "" when it is already gone from disk. Moving loses nothing, so a clone whose work can't be inspected -- or that holds a nested repository a bundle can't -- is moved all the same. A clone with linked worktrees on disk is left in place: moving it would cut them off from their history. With a *pathutil.MovedError the clone is archived at the returned path, and what failed came after it was moved there.
func BatchEnv ¶
func BatchEnv() []string
BatchEnv is the environment that keeps git and its helpers from prompting, for other programs gitten runs unattended.
func BranchExists ¶
BranchExists reports whether a local branch exists in the repo.
func CheckIdle ¶
CheckIdle returns an error wrapping ErrBusy when git is busy in the repository at repoPath or in one of its checked-out submodules. A lock a crashed git command left behind counts too: only a person can tell it is stale. Without operations, in-progress rebases and the like are allowed: moving a whole clone keeps them.
func Clone ¶
func Clone(ctx context.Context, url, destPath string, opts CloneOptions) error
Clone clones url into destPath, creating parent directories, and checks out what opts.Shape asks for. See staged for how destPath is protected. A clone whose submodules can't all be checked out stays at destPath, and a *SubmoduleError says so.
func CloneFromSource ¶
func CloneFromSource(ctx context.Context, source, dest, upstream, branch, base string, shared bool, opts CloneOptions) error
CloneFromSource makes a clone at dest of the repo whose clone is at source, on branch, with origin set to upstream. Its objects come from source: hardlinked (copied across filesystems), or with shared borrowed through git's alternates, in which case git gc in source is stopped from pruning objects the copy may need. branch is checked out tracking origin's when origin has it, else made at base (see ResolveBase). The clone is staged, as Clone's are.
func Commit ¶
func Commit(ctx context.Context, repoPath, message string, addUntracked bool) (committed bool, err error)
Commit stages changes and commits them. With addUntracked it stages untracked files too (git add -A); otherwise only tracked modifications (git add -u). It returns committed=false when there was nothing to commit.
func CopyID ¶
CopyID returns the ID of the working copy at repoPath, creating one on first use. Clones and linked worktrees of one repository each get their own, so their backups never mix, and the ID moves with the copy because it lives in the copy's git directory.
func DefaultBase ¶
DefaultBase names the branch a repo's work is compared with when no base ref is configured: origin's default branch, else the upstream of source's checked-out branch -- for a workspace copy, source is the repo it was made from. "" when neither is known.
func DeleteArchive ¶
DeleteArchive deletes the archive at path: its bundle or archived clone, its description, its LFS objects and its submodules' archives. What is already gone is skipped. Only files of the archive's own name, beside it, are deleted, whatever its description says, and a directory only when its description names it as the archived clone: a path recorded wrongly can't take someone's working copy with it.
func FastForward ¶
FastForward brings the checked-out branch of the clone at repoPath up to its upstream, as git merge --ff-only does, when nothing can be lost: the branch is behind and not ahead, no tracked file has changes, and git is not busy in it. Untracked and ignored files stay where they are: git refuses rather than overwrite one (--no-overwrite-ignore, as by default it would overwrite an ignored file the upstream starts tracking). A clone it leaves behind its upstream gets a reason in skipped; one that is up to date, detached or without an upstream has nothing to do.
func Fetch ¶
Fetch fetches all remotes with pruning and tags using the given SSH key. It returns ErrLocked (without fetching) if the repo has an active git lock.
func Git ¶
Git executes a git command in the given repo directory and returns stdout with surrounding whitespace trimmed. Use GitOutput when the bytes matter.
func GitExitCode ¶
GitExitCode runs a git command and returns just the exit code.
func GitOutput ¶
GitOutput executes a git command in the given repo directory and returns stdout unchanged. Patches need this: trimming drops the final newline and leaves a patch git refuses to apply.
func GitWithSSHKey ¶
func GitWithSSHKey(ctx context.Context, repoPath, sshKeyPath string, args ...string) (string, error)
GitWithSSHKey executes a git command with a custom SSH key.
func IsBareRepo ¶
IsBareRepo checks if the repo at repoPath is a bare repository.
func IsLocked ¶
IsLocked reports whether any git lock file is present, resolving the repo's real git directories first so it is correct for linked worktrees. The returned string is the lock file's name (e.g. "index.lock").
func IsPartial ¶
IsPartial reports whether the repo at path was made with a partial clone filter: it has a promisor remote, which lends it the objects it lacks.
func IsStaging ¶
IsStaging reports whether a directory name is a clone in progress, which scans for repositories skip.
func LinkedWorktrees ¶
LinkedWorktrees lists the paths of the repo's linked worktrees that are on disk; the main worktree isn't one.
func LocalConfig ¶
LocalConfig returns the repository's own git config (not global or system), keyed by git's lower-case names such as core.sshcommand and remote.origin.url. For a key set more than once the last value wins, as it does for git.
func LockRepo ¶
func LockRepo(ctx context.Context, repoPath string, exclusive bool, wait time.Duration) (release func(), err error)
LockRepo takes gitten's lock on the repository at repoPath, waiting up to wait: exclusive to delete, archive or move it, shared to make a copy of it. A copy holds the shared lock until it is recorded in state, so a command holding the exclusive lock sees every copy in state and no copy is begun from the repository while it goes. The lock is a file in the repository's git dir, so it moves with the repository and is deleted with it. Call release once done.
func Mirror ¶
Mirror makes or updates the mirror of url at path: a bare repository with every ref the remote has (git clone --mirror), made in a staging directory like any clone. An existing mirror gets url as its origin, then fetches every ref, never pruning, whatever git's config says: a branch deleted upstream stays in the mirror. One moved follows the remote, and when the move rewrote history its old tip is kept (see KeepRewritten). It reports whether it made the mirror.
func ParseRemoteURL ¶
ParseRemoteURL parses a repo's origin remote URL into identity components.
func Pull ¶
Pull updates the current branch. rebase uses --rebase; otherwise ffOnly restricts to a fast-forward (the safe default for group operations).
func Push ¶
Push pushes the current branch. setUpstream publishes it as origin/<branch> and records the upstream.
func PushOffsite ¶
func PushOffsite(ctx context.Context, repoPath string, latest *Latest, o Offsite, last OffsiteRecord) (OffsiteRecord, OffsitePlan, error)
PushOffsite carries out the plan for the copy at repoPath and returns the new record. A part that fails keeps that part's old record, so it is retried next run.
func ReadCopyID ¶
ReadCopyID returns the copy's ID without creating one; "" if it has none.
func RefreshFromSource ¶
RefreshFromSource updates the copy's view of origin from its source without the network: whatever the source last fetched.
func RemoveClone ¶
func RemoveClone(ctx context.Context, repoPath, archiveDir, name string, opts RemoveOptions) (string, error)
RemoveClone deletes the clone at repoPath. Unless opts.Discard is set it first archives the clone's unique work into archiveDir; if that work cannot be inspected or archived the clone is left in place and an error is returned. A clone with linked worktrees on disk, or that git is busy in, is always left in place, discard or not. A clone already gone from disk counts as removed. It returns the archive path, or "" when there was nothing to save.
func RemoveWorktree ¶
func RemoveWorktree(ctx context.Context, source, path, archiveDir, name string, opts RemoveOptions) (string, error)
RemoveWorktree removes the linked worktree at path from source. Unless opts.Discard is set it first archives what removal would lose (the working tree, index and detached-HEAD commits); branches stay in source, its base. On an inspection or archive failure, or while git is busy in it, the worktree is left in place. The worktree's backup refs go with it.
func RepointSource ¶
RepointSource points the copy at copyPath at its source's new path to: its gitten remote, and the alternates it borrows objects through.
func ResolveBase ¶
ResolveBase returns the commit new branches in repo start from: base, or origin's branch of that name; with base empty, origin's default branch, or HEAD when origin has none.
func RestoreArchive ¶
RestoreArchive makes dest a clone holding what the archive at path -- its bundle or its description -- saved: branches, tags and other refs, stashes, HEAD, and the index, working tree and untracked files it had, with its Git LFS objects and its submodules' archives in their places. A complete bundle restores on its own. Any other archive is restored into a clone of base -- by default the one it records -- or of its origin remote when the base is gone. dest must not exist, or be an empty directory. The clone is built beside dest and published as clones are, so a failed restore leaves nothing there, and whatever appears at dest meanwhile is kept.
func RestoreBackupInto ¶
RestoreBackupInto clones the copy at repoPath into the empty or missing directory into, checks out the backup's base commit there and restores the backup on top, leaving the original working copy untouched.
func SetLocalConfig ¶
SetLocalConfig sets key to value in the repository's own git config.
func SetOriginURL ¶
SetOriginURL points the origin remote at url.
func Source ¶
Source returns the path of the repo the copy at path was made from: the main worktree of a linked worktree, the gitten remote of a workspace clone; "" when it is neither.
func Submodules ¶
Submodules lists the paths of the repository's checked-out submodules, nested ones included, relative to it.
func TestSign ¶
TestSign makes a throwaway signed commit with settings (git config keys and values) in a temporary repository, with no terminal, as an agent would. It returns why signing failed, or nil if it works unattended.
func UnsetLocalConfig ¶
UnsetLocalConfig removes key from the repository's own git config.
func Upstream ¶
Upstream returns the configured upstream of the current branch (e.g. "origin/main"), or "" if none is set.
func WorktreeAdd ¶
WorktreeAdd creates a new worktree of repoPath at worktreePath.
If branch is non-empty: an existing branch is checked out, otherwise a new branch is created at baseRef (or current HEAD when baseRef is empty). With an empty branch the worktree is checked out detached at baseRef/HEAD.
func WorktreeMove ¶
WorktreeMove moves the linked worktree at from to to.
func WorktreePrune ¶
WorktreePrune prunes stale worktree administrative entries.
func WorktreeRemove ¶
WorktreeRemove removes a worktree. force discards a dirty or locked worktree.
Types ¶
type ArchiveMeta ¶
type ArchiveMeta struct {
Source string `json:"source"`
Remotes map[string]string `json:"remotes,omitempty"`
Branch string `json:"branch,omitempty"`
// Head is the commit HEAD was at; "" on an unborn branch.
Head string `json:"head,omitempty"`
Work string `json:"work"`
Created time.Time `json:"created"`
// Bundle is the repository's own bundle; "" when only its submodules
// had work to save.
Bundle string `json:"bundle,omitempty"`
// Complete marks a bundle holding all of the repository's history, so it
// restores with nothing else. Otherwise the bundle holds only what Base
// lacks, and restores into a clone of Base or of the repository's remote.
Complete bool `json:"complete,omitempty"`
Base string `json:"base,omitempty"`
// Repo is the tracked repo the archived clone was, or was a copy of: a
// deletion of that repo finds the archives leaning on it by Repo or Base.
Repo string `json:"repo,omitempty"`
Restore string `json:"restore,omitempty"`
// Submodules maps each submodule with work saved to its own archive.
Submodules map[string]string `json:"submodules,omitempty"`
// LFS holds the clone's Git LFS objects, which a bundle carries only
// pointers to; copy them into the restored repo's .git/lfs/objects.
LFS string `json:"lfs,omitempty"`
// Clone is where the whole clone was moved, for an archive that kept
// all of it rather than a bundle of its unique work.
Clone string `json:"clone,omitempty"`
}
ArchiveMeta describes an archive bundle and is written beside it as JSON.
func ReadArchive ¶
func ReadArchive(path string) (ArchiveMeta, string, error)
ReadArchive returns the description of the archive at path -- a bundle, an archived clone or its description -- and the archive's ID: its file name without extension.
type BackupConfig ¶
type BackupConfig struct {
Strategy string // "stash-ref", "patch" or "both"
Limits SnapshotLimits
Retention Retention
PatchDir string
Now func() time.Time
}
BackupConfig holds backup-related settings.
func NewBackupConfig ¶
func NewBackupConfig(opts ...BackupOption) BackupConfig
NewBackupConfig creates a BackupConfig with defaults and optional overrides.
type BackupInfo ¶
type BackupInfo struct {
ID string
CopyID string
Ref string // "" if there is no snapshot ref
Commit string // the snapshot ref's commit
PatchDir string // "" if there is no patch backup
Meta *BackupMeta
// Submodules are the submodules' backups that go with this one, by path.
Submodules map[string]SubmoduleBackup
// contains filtered or unexported fields
}
BackupInfo is one backup of a working copy: a snapshot ref in the repo, a patch backup directory, or both.
func FindBackup ¶
func FindBackup(ctx context.Context, repoPath, patchRoot, id string) (BackupInfo, error)
FindBackup returns the backup of the copy at repoPath with the given ID, or its newest backup when id is "" or "latest".
func ListBackups ¶
func ListBackups(ctx context.Context, repoPath, patchRoot string) ([]BackupInfo, error)
ListBackups returns the backups of the working copy at repoPath, oldest first: its own, plus patch backups left by earlier copies at the same path, such as a clone that was deleted and cloned again.
func (BackupInfo) RestoreCommands ¶
func (b BackupInfo) RestoreCommands() []string
RestoreCommands returns the shell commands that restore b by hand from inside the working copy, onto a clean tree.
func (BackupInfo) Snapshot ¶
func (b BackupInfo) Snapshot() string
Snapshot is the commit holding the backed-up state: the snapshot ref's, or the one a patch backup recorded.
func (BackupInfo) Submodule ¶
func (b BackupInfo) Submodule(ctx context.Context, repoPath, path string) (sub BackupInfo, ok bool, err error)
Submodule is the backup of the submodule at path, relative to repoPath, that goes with b. ok is false when b names none: the submodule was clean.
type BackupMeta ¶
type BackupMeta struct {
ID string `json:"id"`
CopyID string `json:"copy_id"`
Path string `json:"path"`
Created time.Time `json:"created"`
Snapshot string `json:"snapshot"`
Base string `json:"base,omitempty"`
Branch string `json:"branch"`
IndexUnmerged bool `json:"index_unmerged,omitempty"`
Skipped []SkippedFile `json:"skipped,omitempty"`
// Submodules are the submodules' backups that go with this one, by path.
Submodules map[string]SubmoduleBackup `json:"submodules,omitempty"`
}
BackupMeta is a patch backup's metadata.json.
type BackupOption ¶
type BackupOption func(*BackupConfig)
BackupOption is a functional option for BackupConfig.
func WithClock ¶
func WithClock(now func() time.Time) BackupOption
WithClock sets the clock that names and ages backups.
func WithIncludeUntracked ¶
func WithIncludeUntracked(b bool) BackupOption
WithIncludeUntracked controls whether untracked files are backed up.
func WithPatchDir ¶
func WithPatchDir(d string) BackupOption
WithPatchDir sets the directory where patch-strategy backups are written.
func WithRetention ¶
func WithRetention(r Retention) BackupOption
WithRetention sets which backups of a working copy are kept.
func WithStrategy ¶
func WithStrategy(s string) BackupOption
WithStrategy sets the backup strategy ("stash-ref", "patch", or "both").
func WithUntrackedLimits ¶
func WithUntrackedLimits(maxFile, maxTotal int64) BackupOption
WithUntrackedLimits caps the size of one untracked file and of all of them together; 0 means no limit.
type BackupOutcome ¶
type BackupOutcome int
BackupOutcome is what a backup run did.
const ( BackupClean BackupOutcome = iota // nothing uncommitted, nothing saved BackupUnchanged // identical to the latest backup, which still stands BackupSaved // a new backup was written )
func (BackupOutcome) String ¶
func (o BackupOutcome) String() string
type BackupResult ¶
type BackupResult struct {
Outcome BackupOutcome
ID string // backup holding the current state; "" when clean
CopyID string
Snapshot string // commit of the backed-up state; "" when clean
Ref string // snapshot ref; "" if the strategy keeps none or it failed
PatchDir string // patch backup directory; "" if the strategy keeps none or it failed
Skipped []SkippedFile
IndexUnmerged bool
// Submodules holds, by path, the backups of the checked-out submodules
// that had uncommitted work.
Submodules map[string]*BackupResult
}
BackupResult reports a backup run.
func Backup ¶
func Backup(ctx context.Context, repoPath string, cfg BackupConfig) (*BackupResult, error)
Backup saves the uncommitted state of the working copy at repoPath: staged and unstaged changes and untracked files within cfg.Limits. It never touches the working tree, the index, index.lock, branches or the stash.
Each checked-out submodule with uncommitted work is backed up the same way, as a working copy of its own -- its own copy ID, refs and patch folder -- and the parent's backup records which of the submodules' backups go with it, so restoring it restores theirs.
An unchanged state is not saved again. Old backups are pruned by cfg.Retention, and only after a new one is complete. Every requested part that fails is reported in the error; the result still describes what was saved.
func (*BackupResult) Dirty ¶
func (r *BackupResult) Dirty() bool
Dirty reports whether the working copy had anything to back up.
type CloneOptions ¶
type CloneOptions struct {
// SSHKey is the key to clone with -- submodules too; "" uses the default
// SSH configuration.
SSHKey string
// Filter is a partial clone filter, such as blob:none; "" clones every
// object. Submodules are cloned with it too.
Filter string
// Depth limits history to that many commits on every branch; 0 is all.
// Submodules are cloned with it too.
Depth int
// Shape is how much of the repository a checkout holds.
Shape
}
CloneOptions shape a clone, and the checkouts made from it.
type GitDirs ¶
GitDirs holds a repo's resolved git directories. For a normal repo (or the main worktree) GitDir and CommonDir are both <repo>/.git. For a LINKED worktree -- where .git is a file, not a directory -- GitDir is the per-worktree dir (HEAD, index, MERGE_HEAD, rebase state, index.lock) and CommonDir is the shared dir (config, packed-refs, refs/stash and their locks).
func ResolveGitDirs ¶
ResolveGitDirs resolves a repo's per-worktree and common git directories so lock and in-progress-operation checks are correct for linked worktrees (where .git is a file pointing at .git/worktrees/<name>). When .git is a real directory -- the common case -- it is both dirs and no git process is spawned; only linked worktrees pay for the rev-parse calls. Falls back to <repo>/.git.
type Latest ¶
type Latest struct {
Snapshot string // the backup's commit; "" when the copy is clean
BackupID string
}
Latest is a copy's uncommitted state as its latest backup holds it.
type MirrorOptions ¶
type MirrorOptions struct {
// SSHKey is the key to fetch with over SSH; "" for ssh's own choice.
SSHKey string
// LFS also fetches all the repository's Git LFS content.
LFS bool
// KeepRewritten is how long the old tip of a ref the remote rewrote --
// moved to a commit that doesn't descend from it, as a force-push does --
// is kept, under refs/gitten-rewritten/<time>/; 0 keeps none.
KeepRewritten time.Duration
// Now is when an update is made; nil for time.Now.
Now func() time.Time
}
MirrorOptions are how a mirror is made and kept.
type Offsite ¶
type Offsite struct {
Remote string // a remote name or URL
Namespace string // hidden ref prefix the copy owns, e.g. refs/gitten/<machine>/<copy>
WIP string // "ref", "branch" or "off"
Branch string // the copy's visible WIP branch, for WIP "branch"
Unpushed string // "push", "bundle" or "off"
Bundle string // the bundle file, for Unpushed "bundle"
Keep time.Duration // pushed WIP refs older than this are deleted; the current one stays
SSHKey string
Now func() time.Time
}
Offsite is what of one working copy goes to a remote, and where. Every ref it writes is the copy's own: under Namespace, or the copy's visible WIP Branch, so a force-push never touches anyone else's refs.
type OffsitePlan ¶
type OffsitePlan struct {
// Push are refspecs: "+<commit>:<ref>" writes a ref, ":<ref>" deletes one.
Push []string
// Bundle is the branches the bundle must hold; nil leaves it as it is,
// empty removes it.
Bundle map[string]string
Next OffsiteRecord
}
OffsitePlan is what one push does.
func PlanOffsite ¶
func PlanOffsite(ctx context.Context, repoPath string, latest *Latest, o Offsite, last OffsiteRecord) (OffsitePlan, error)
PlanOffsite works out what to push for the copy at repoPath, given what the last push left. latest is the copy's state from this run's backup; nil when no backup ran or it failed, which leaves the WIP refs as they are.
func (OffsitePlan) Empty ¶
func (p OffsitePlan) Empty() bool
Empty reports whether the plan changes nothing.
type OffsiteRecord ¶
type OffsiteRecord struct {
Remote string
Namespace string
WIP []string // backup IDs at <Namespace>/wip/<id>
Branch string // the commit at the visible WIP branch
Heads map[string]string // branch -> commit at <Namespace>/heads/<branch>
Bundled map[string]string // branch -> commit in the bundle
}
OffsiteRecord is what pushes left offsite; the next push starts from it.
func (OffsiteRecord) Empty ¶
func (r OffsiteRecord) Empty() bool
Empty reports whether the record holds nothing pushed or bundled: nothing a later push would have to clean up.
type RemoveOptions ¶
type RemoveOptions struct {
// Discard deletes the clone without saving anything.
Discard bool
// Base is a repository that keeps the history the clone shares with its
// remotes: the repo a workspace copy was made from. The bundle then holds
// only what the base lacks. Without one it holds the clone's whole
// history, so it restores with nothing else: once the clone is gone, its
// upstream may be the only other copy, and may be gone too.
Base string
// KeepHistory archives the clone's whole history even when it has no
// unique work, for archives that lean on it.
KeepHistory bool
// Repo is the tracked repo the clone is, or is a copy of, recorded in its
// archive.
Repo string
}
RemoveOptions says how RemoveClone saves a clone's work before deleting it.
type RepoStatus ¶
type RepoStatus struct {
CurrentBranch string
HasStaged bool
HasUnstaged bool
HasUntracked bool
InRebase bool
InMerge bool
InCherryPick bool
}
RepoStatus describes the working tree state of a repo.
func GetStatus ¶
func GetStatus(ctx context.Context, repoPath string) (*RepoStatus, error)
GetStatus returns the current status of a repo's working tree.
func (*RepoStatus) StatusString ¶
func (rs *RepoStatus) StatusString() string
StatusString returns a summary status string for state tracking.
type Retention ¶
type Retention struct {
KeepAll time.Duration // keep every backup younger than this
KeepDaily time.Duration // keep the newest backup of each UTC day younger than this
Max int // then keep at most this many, newest first; 0 means no cap
}
Retention decides which of a working copy's backups to keep.
type Shape ¶
type Shape struct {
// Sparse lists the only directories checked out, in cone mode: the files
// at the top level, and directly in each listed directory's parents,
// come too. Empty checks out everything.
Sparse []string
// Submodules checks out the submodules within the checkout -- in its
// sparse cone, when it has one -- recursively.
Submodules bool
// SkipLFS leaves Git LFS files as pointers: their content is never
// downloaded, in this checkout or later ones.
SkipLFS bool
}
Shape is how much of a repository a new checkout holds beyond its history: which directories, whether its submodules are checked out, and whether Git LFS content is downloaded.
type SkippedFile ¶
SkippedFile is an untracked path a snapshot left out, and why.
type Snapshot ¶
type Snapshot struct {
Commit string
Base string // "" on an unborn branch
Index string
Untracked string // "" when no untracked files were captured
// IndexUnmerged is set when the index held unresolved conflicts. The index
// commit then records the base tree; the conflicted files' working copies
// are still in Commit.
IndexUnmerged bool
// Skipped lists untracked paths left out of the snapshot.
Skipped []SkippedFile
}
Snapshot is a working copy's state stored as commits in the layout `git stash` uses, so `git stash apply --index <Commit>` restores it exactly. Commit holds the tracked files of the working tree; its parents are the base commit (HEAD when taken), the index commit and, when untracked files were captured, a commit of those. On an unborn branch there is no base and the index commit is the first parent.
Snapshot commits carry a fixed identity and the base commit's date, so the same state always produces the same Commit ID.
func TakeSnapshot ¶
TakeSnapshot captures the index, the working tree and, within limits, the untracked files of the working copy at repoPath. Ignored files are never captured.
Every tree is built in a temporary index, so the repository's own index and index.lock are never touched: it works while an agent's git command holds the lock, and it changes no file, index entry, stash or ref. Commits are never signed.
type SnapshotLimits ¶
type SnapshotLimits struct {
Untracked bool // capture untracked files at all
MaxFileBytes int64 // skip larger untracked files; 0 means no limit
MaxTotalBytes int64 // stop adding untracked files past this total; 0 means no limit
}
SnapshotLimits bounds the untracked files a snapshot hashes into the repository's object store.
type SubmoduleBackup ¶
SubmoduleBackup names the backup of one submodule that goes with its parent's: the submodule's own copy ID and backup ID.
type SubmoduleError ¶
SubmoduleError reports a checkout made in full whose submodules couldn't all be checked out. The checkout stays where it is.
func (*SubmoduleError) Error ¶
func (e *SubmoduleError) Error() string
func (*SubmoduleError) Unwrap ¶
func (e *SubmoduleError) Unwrap() error
type UniqueWork ¶
type UniqueWork struct {
Changed int // tracked files with staged or unstaged changes
Untracked int // untracked files; ignored files don't count
Stashes int // stash entries
UnpushedCommits int // commits on local branches or HEAD that no remote-tracking ref reaches
DetachedCommits int // commits reachable only from a detached HEAD
// OtherRefCommits counts commits that only tags or other refs of the
// repository's own reach: no branch, HEAD, stash or remote does.
OtherRefCommits int
InProgress string // "rebase", "merge", "cherry-pick" or "revert" when one is under way
// Submodules holds, by path, the unique work of each checked-out
// submodule that has some. A submodule's repository goes with the copy
// that checked it out, so all of it is lost.
Submodules map[string]UniqueWork
}
UniqueWork is local work in a repository that exists nowhere else, so deleting the repository would lose it.
func InspectUniqueWork ¶
func InspectUniqueWork(ctx context.Context, repoPath string) (UniqueWork, error)
InspectUniqueWork reports the unique work in the repository at repoPath and in its checked-out submodules. Any git failure is returned as an error: a caller deciding whether to delete must treat "could not tell" as unsafe.
func (UniqueWork) LostWithClone ¶
func (u UniqueWork) LostWithClone() bool
LostWithClone reports whether deleting a whole clone would lose work.
func (UniqueWork) LostWithWorktree ¶
func (u UniqueWork) LostWithWorktree() bool
LostWithWorktree reports whether removing a linked worktree would lose work. Its branches, tags and stashes live in the shared repository and survive; its working tree, index, submodules and commits reachable only from a detached HEAD don't.
func (UniqueWork) String ¶
func (u UniqueWork) String() string
type WorktreeInfo ¶
type WorktreeInfo struct {
Path string
Head string
Branch string // short branch name; empty if detached/bare
Bare bool
Detached bool
}
WorktreeInfo describes one entry from `git worktree list --porcelain`.
func WorktreeList ¶
func WorktreeList(ctx context.Context, repoPath string) ([]WorktreeInfo, error)
WorktreeList returns the worktrees attached to repoPath (including the main one).