Context and cancellation¶
Every network-touching operation takes a context.Context as its first
argument. Clone, in-memory clone, push, and the pull that CreateBranch
performs all run against a remote, and a remote can hang. Without a context
there is no way to bound how long a clone against an unresponsive server blocks.
On a ThreadSafeRepo that is worse than a stall,
because the mutex is held for the operation's full duration, so one hung clone
wedges every other method behind it. The context is the cancellation handle that
fixes both.
The thin-veneer stance¶
The role interfaces traffic in go-git's own concrete types: *git.Repository,
*git.Worktree, *object.File, plumbing.ReferenceName, *git.PushOptions,
and so on. That is deliberate. This package is a thin veneer over go-git: it
adds binding, role decomposition, forge-aware auth, and concurrency safety, but
it does not try to hide go-git behind an abstraction of its own. Threading a
context through the network methods keeps faith with that stance. It wires each
call to the …Context form go-git already provides (CloneContext,
PlainCloneContext, PushContext, PullContext) rather than inventing a
cancellation mechanism.
Which methods take a context¶
The network-touching methods of the Opener, Committer, and Brancher roles:
Open(ctx, repoType, location, branch, opts...)
OpenLocal(ctx, location) // branch parameter removed, see below
OpenInMemory(ctx, location, branch, opts...)
Clone(ctx, uri, targetPath, opts...)
Commit(ctx, message, opts)
Push(ctx, opts)
CreateBranch(ctx, branchName)
Commit and OpenLocal do no network I/O, but they belong to roles whose other
methods do, so they take the context too for a uniform role surface; they ignore
it.
Migration (pre-1.0 breaking change)¶
This is an API-breaking signature change. The module is pre-1.0, so it ships as a minor bump. To migrate:
- Add a context as the first argument to
Open,OpenLocal,OpenInMemory,Clone,Commit,Push, andCreateBranch. Pass the request/operation context you already have, orcontext.Background()at a top-level entry point. - Drop the
branchargument fromOpenLocal. It was silently unused on the open path.OpenLocal(ctx, location)opens an existing repository, and only when the path is genuinely not a repository (git.ErrRepositoryNotExists) does it initialise a fresh one onmain. To initialise on a specific branch, useInitLocal(location, branch), which is the purpose-built init entry point.
OpenLocal no longer clobbers on a non-fatal open error¶
Previously OpenLocal fell into initialise-a-new-repository on any
git.PlainOpen failure: a corrupt repository, a permission error, anything. So a
transient fault on a real project directory got an empty repository initialised
over it, destroying the evidence of the original problem. It now initialises
only for git.ErrRepositoryNotExists and returns every other open error
verbatim (wrapped as failed to open git repository at <path>). If you relied on
the old init-on-any-error behaviour, call InitLocal explicitly.
Since v0.3.0 one case inside git.ErrRepositoryNotExists is carved back out. A
.git file naming a git directory that has gone (a pruned linked worktree, a
moved --separate-git-dir checkout, a submodule whose superproject was
re-cloned) returns
ErrMissingGitDir
and writes nothing, because that directory holds real work rather than being
empty.