refactor how commits are created, as well as how reference following is done
--- type: change message: |- refactor how commits are created, as well as how reference following is done In light of the upcoming combine commit feature, it will be necessary to have more fine-grained control over how commits are created and stored. This change attempts to address that, by adding a CommitBare method, which the Commit method then uses. CommitBare merely creates and stores a commit, without updating HEAD. Since Commit now has to figure out the parent commit of the HEAD, and deal with the case of HEAD not being set (a new repo, or an orphan branch), the logic for reference traversal had to be refactored some as well. change_hash: AKwHmb4T5APrl3EL7Ox27ABGWrjqjlOGvBD1cOycgPcN credentials: - type: pgp_signature pub_key_id: 95C46FA6A41148AC body: iQIzBAABAgAdFiEEJ6tQKp6olvZKJ0lwlcRvpqQRSKwFAl53+qwACgkQlcRvpqQRSKzXuQ/9HBnrwB3zYSsLsQrNTlZ6MW5DaH/y1pypba6eD57fC6Tl3ipuDvTLrjiRMdPkS8LFvPOkT8FUFRZH7farBZBZGRnoAL88ELPB/h5Ip7FaUu+syfuTsHnBvWPs2hPN/sEhceIy+io3P03vIKSYCPMAhhigkWhoZZa+SJNQyTTJ/WzbGmuopCYhe3/4JDfpLNIvfOzJb40jVXqmqZ4Lf82uqf9DIh8LjNRhhOBeVFOVyQ4FOHh6a/T7D4qNSMPi/RRFg9VSXlNV5tp2ykdQdzyS6vdBBxV5j8pz8DyTDZYxlqkHyb5Blkl4vcndoJOYjyacVqVuXMgvjf0a8cmuhDEmC1vRDepx4jKZQwKyl1HQ9X0+KodMAxrx671+m7Zga9OcyCdNdyaH+Tl2W4c6apaEv2lcx5DalSLW2uoDbo5B4uutBOFrL12ML2tnnyF93tRSZkcNibo69/88qjFjaYEAjOhupgNtrbU+92Dsj/8UGYKFQgfx7DSHGXhs8fzphzPvZifWoiGV49iXvOauNlUzolX3h4bmxcXAnl/+tC4F1a19TGl7TG7HAC8kajXAf01pSD+WxJGMN+gerOYHOCrlQVx+sWhQBh22yfsaAJXPLl4R/2bUKqSTXjHHp3/WTqK4HdRRN/L728YhOxBCy6Ue0CjAZKpi+cQWQUUxpCKQiXs= account: mediocregopher
This commit is contained in:
parent
a47404b4a7
commit
1c2bc11fc3
@ -25,8 +25,8 @@ func cmdVerify(ctx context.Context, cmd *dcmd.Cmd) {
|
|||||||
|
|
||||||
var branchName plumbing.ReferenceName
|
var branchName plumbing.ReferenceName
|
||||||
if *branch == "" {
|
if *branch == "" {
|
||||||
if branchName, err = repo.CheckedOutBranch(); err != nil {
|
if branchName, err = repo.ReferenceToBranchName(plumbing.HEAD); err != nil {
|
||||||
return nil, fmt.Errorf("could not determined currently checked out branch: %w", err)
|
return nil, fmt.Errorf("determining branch at HEAD: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
branchName = plumbing.NewBranchReferenceName(*branch)
|
branchName = plumbing.NewBranchReferenceName(*branch)
|
||||||
|
134
commit.go
134
commit.go
@ -6,7 +6,6 @@ import (
|
|||||||
"dehub/fs"
|
"dehub/fs"
|
||||||
"dehub/sigcred"
|
"dehub/sigcred"
|
||||||
"dehub/typeobj"
|
"dehub/typeobj"
|
||||||
"encoding"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -177,34 +176,93 @@ func (r *Repo) AccreditCommit(commit Commit, sigInt sigcred.SignifierInterface)
|
|||||||
return commit, nil
|
return commit, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit uses the given TextMarshaler to create a git commit object (with the
|
// CommitBareParams are the parameters to the CommitBare method. All are
|
||||||
// specified accountID as the author) and commits it to the current HEAD,
|
// required, unless otherwise noted.
|
||||||
// returning the hash of the commit.
|
type CommitBareParams struct {
|
||||||
func (r *Repo) Commit(m encoding.TextMarshaler, accountID string) (GitCommit, error) {
|
Commit Commit
|
||||||
msgB, err := m.MarshalText()
|
AccountID string // used as the author
|
||||||
|
ParentHash plumbing.Hash // can be zero if the commit has no parents (Q_Q)
|
||||||
|
GitTree *object.Tree
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitBare constructs a git commit object and and stores it, returning the
|
||||||
|
// resulting GitCommit. This method does not interact with HEAD at all.
|
||||||
|
func (r *Repo) CommitBare(params CommitBareParams) (GitCommit, error) {
|
||||||
|
msgB, err := params.Commit.MarshalText()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return GitCommit{}, fmt.Errorf("encoding %T to message string: %v", m, err)
|
return GitCommit{}, fmt.Errorf("encoding %T to message string: %w",
|
||||||
|
params.Commit, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
w, err := r.GitRepo.Worktree()
|
author := object.Signature{
|
||||||
if err != nil {
|
Name: params.AccountID,
|
||||||
return GitCommit{}, fmt.Errorf("getting git worktree: %w", err)
|
When: time.Now(),
|
||||||
}
|
}
|
||||||
h, err := w.Commit(string(msgB), &git.CommitOptions{
|
commit := &object.Commit{
|
||||||
Author: &object.Signature{
|
Author: author,
|
||||||
Name: accountID,
|
Committer: author,
|
||||||
When: time.Now(),
|
Message: string(msgB),
|
||||||
},
|
TreeHash: params.GitTree.Hash,
|
||||||
|
}
|
||||||
|
if params.ParentHash != plumbing.ZeroHash {
|
||||||
|
commit.ParentHashes = []plumbing.Hash{params.ParentHash}
|
||||||
|
}
|
||||||
|
|
||||||
|
commitObj := r.GitRepo.Storer.NewEncodedObject()
|
||||||
|
if err := commit.Encode(commitObj); err != nil {
|
||||||
|
return GitCommit{}, fmt.Errorf("encoding commit object: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
commitHash, err := r.GitRepo.Storer.SetEncodedObject(commitObj)
|
||||||
|
if err != nil {
|
||||||
|
return GitCommit{}, fmt.Errorf("setting encoded object: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.GetGitCommit(commitHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit uses the given Commit to create a git commit object (with the
|
||||||
|
// specified accountID as the author) and commits it to the current HEAD,
|
||||||
|
// returning the full GitCommit.
|
||||||
|
func (r *Repo) Commit(commit Commit, accountID string) (GitCommit, error) {
|
||||||
|
headRef, err := r.TraverseReferenceChain(plumbing.HEAD, func(ref *plumbing.Reference) bool {
|
||||||
|
return ref.Type() == plumbing.HashReference
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return GitCommit{}, fmt.Errorf("committing to git worktree: %w", err)
|
return GitCommit{}, fmt.Errorf("resolving HEAD to a hash reference: %w", err)
|
||||||
|
}
|
||||||
|
headRefName := headRef.Name()
|
||||||
|
|
||||||
|
headHash, err := r.ReferenceToHash(headRefName)
|
||||||
|
if err != nil {
|
||||||
|
return GitCommit{}, fmt.Errorf("resolving ref %q (HEAD): %w", headRefName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
gc, err := r.GetGitCommit(h)
|
// TODO this is also used in the same way in NewCommitChange. It might make
|
||||||
|
// sense to refactor this logic out, it might not be needed in fs at all.
|
||||||
|
_, stagedTree, err := fs.FromStagedChangesTree(r.GitRepo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return GitCommit{}, fmt.Errorf("retrieving fresh commit %q back from git: %w", h, err)
|
return GitCommit{}, fmt.Errorf("getting staged changes: %w", err)
|
||||||
}
|
}
|
||||||
return gc, nil
|
|
||||||
|
gitCommit, err := r.CommitBare(CommitBareParams{
|
||||||
|
Commit: commit,
|
||||||
|
AccountID: accountID,
|
||||||
|
ParentHash: headHash,
|
||||||
|
GitTree: stagedTree,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return GitCommit{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// now set the branch to this new commit
|
||||||
|
newHeadRef := plumbing.NewHashReference(headRefName, gitCommit.GitCommit.Hash)
|
||||||
|
if err := r.GitRepo.Storer.SetReference(newHeadRef); err != nil {
|
||||||
|
return GitCommit{}, fmt.Errorf("setting reference %q to new commit hash %q: %w",
|
||||||
|
headRefName, gitCommit.GitCommit.Hash, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return gitCommit, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasStagedChanges returns true if there are file changes which have been
|
// HasStagedChanges returns true if there are file changes which have been
|
||||||
@ -308,20 +366,32 @@ func (r *Repo) VerifyCommits(branch plumbing.ReferenceName, gitCommits []GitComm
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parentTree returns the tree of the parent commit of the given commit. If the
|
||||||
|
// given commit has no parents then a bare tree is returned.
|
||||||
|
func (r *Repo) parentTree(commitObj *object.Commit) (*object.Tree, error) {
|
||||||
|
switch commitObj.NumParents() {
|
||||||
|
case 0:
|
||||||
|
return new(object.Tree), nil
|
||||||
|
case 1:
|
||||||
|
if parentCommitObj, err := commitObj.Parent(0); err != nil {
|
||||||
|
return nil, fmt.Errorf("getting parent commit %q: %w",
|
||||||
|
commitObj.ParentHashes[0], err)
|
||||||
|
} else if parentTree, err := r.GitRepo.TreeObject(parentCommitObj.TreeHash); err != nil {
|
||||||
|
return nil, fmt.Errorf("getting parent tree object %q: %w",
|
||||||
|
parentCommitObj.TreeHash, err)
|
||||||
|
} else {
|
||||||
|
return parentTree, nil
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, errors.New("commit has multiple parents")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if parentTree is nil then it will be inferred.
|
// if parentTree is nil then it will be inferred.
|
||||||
func (r *Repo) verifyCommit(branch plumbing.ReferenceName, gitCommit GitCommit, parentTree *object.Tree) error {
|
func (r *Repo) verifyCommit(branch plumbing.ReferenceName, gitCommit GitCommit, parentTree *object.Tree) error {
|
||||||
isRoot := gitCommit.Root()
|
parentTree, err := r.parentTree(gitCommit.GitCommit)
|
||||||
|
if err != nil {
|
||||||
if parentTree == nil {
|
return fmt.Errorf("retrieving parent tree of commit: %w", err)
|
||||||
if isRoot {
|
|
||||||
parentTree = new(object.Tree)
|
|
||||||
} else if parentCommit, err := gitCommit.GitCommit.Parent(0); err != nil {
|
|
||||||
return fmt.Errorf("getting parent commit %q: %w",
|
|
||||||
gitCommit.GitCommit.ParentHashes[0], err)
|
|
||||||
} else if parentTree, err = r.GitRepo.TreeObject(parentCommit.TreeHash); err != nil {
|
|
||||||
return fmt.Errorf("getting parent tree object %q: %w",
|
|
||||||
parentCommit.TreeHash, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vctx := verificationCtx{
|
vctx := verificationCtx{
|
||||||
@ -331,7 +401,7 @@ func (r *Repo) verifyCommit(branch plumbing.ReferenceName, gitCommit GitCommit,
|
|||||||
}
|
}
|
||||||
|
|
||||||
var sigFS fs.FS
|
var sigFS fs.FS
|
||||||
if isRoot {
|
if gitCommit.Root() {
|
||||||
sigFS = fs.FromTree(vctx.commitTree)
|
sigFS = fs.FromTree(vctx.commitTree)
|
||||||
} else {
|
} else {
|
||||||
sigFS = fs.FromTree(vctx.parentTree)
|
sigFS = fs.FromTree(vctx.parentTree)
|
||||||
|
@ -22,7 +22,7 @@ var _ CommitInterface = CommitChange{}
|
|||||||
// returned Commit will _not_ be filled in.
|
// returned Commit will _not_ be filled in.
|
||||||
func (r *Repo) NewCommitChange(msg string) (Commit, error) {
|
func (r *Repo) NewCommitChange(msg string) (Commit, error) {
|
||||||
headTree := new(object.Tree)
|
headTree := new(object.Tree)
|
||||||
if head, err := r.GetGitHead(); err != nil && !errors.Is(err, ErrNoHead) {
|
if head, err := r.GetGitHead(); err != nil && !errors.Is(err, ErrHeadIsZero) {
|
||||||
return Commit{}, fmt.Errorf("getting HEAD commit: %w", err)
|
return Commit{}, fmt.Errorf("getting HEAD commit: %w", err)
|
||||||
} else if err == nil {
|
} else if err == nil {
|
||||||
headTree = head.GitTree
|
headTree = head.GitTree
|
||||||
|
94
repo.go
94
repo.go
@ -93,8 +93,8 @@ func InitMemRepo() *Repo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Repo) init() error {
|
func (r *Repo) init() error {
|
||||||
h := plumbing.NewSymbolicReference(plumbing.HEAD, MainRefName)
|
headRef := plumbing.NewSymbolicReference(plumbing.HEAD, MainRefName)
|
||||||
if err := r.GitRepo.Storer.SetReference(h); err != nil {
|
if err := r.GitRepo.Storer.SetReference(headRef); err != nil {
|
||||||
return fmt.Errorf("setting HEAD reference to %q: %w", MainRefName, err)
|
return fmt.Errorf("setting HEAD reference to %q: %w", MainRefName, err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -108,40 +108,70 @@ func (r *Repo) billyFilesystem() (billy.Filesystem, error) {
|
|||||||
return w.Filesystem, nil
|
return w.Filesystem, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckedOutBranch returns the name of the currently checked out branch.
|
var errTraverseRefNoMatch = errors.New("failed to find reference matching given predicate")
|
||||||
func (r *Repo) CheckedOutBranch() (plumbing.ReferenceName, error) {
|
|
||||||
// Head() can't be used for this, because it doesn't handle the case of a
|
|
||||||
// newly initialized repo very well.
|
|
||||||
ogRef, err := r.GitRepo.Storer.Reference(plumbing.HEAD)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("de-referencing HEAD (is it a bare repo?): %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ref := ogRef
|
// TraverseReferenceChain resolves a chain of references, calling the given
|
||||||
|
// predicate on each one, and returning the first one for which the predicate
|
||||||
|
// returns true. This method will return an error if it reaches the end of the
|
||||||
|
// chain and the predicate still has not returned true.
|
||||||
|
//
|
||||||
|
// If a reference name is encountered which does not actually exist, then it is
|
||||||
|
// assumed to be a hash reference to the zero hash.
|
||||||
|
func (r *Repo) TraverseReferenceChain(refName plumbing.ReferenceName, pred func(*plumbing.Reference) bool) (*plumbing.Reference, error) {
|
||||||
|
// TODO infinite loop checking
|
||||||
for {
|
for {
|
||||||
if ref.Type() != plumbing.SymbolicReference {
|
ref, err := r.GitRepo.Storer.Reference(refName)
|
||||||
break
|
if errors.Is(err, plumbing.ErrReferenceNotFound) {
|
||||||
|
ref = plumbing.NewHashReference(refName, plumbing.ZeroHash)
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, fmt.Errorf("resolving reference %q: %w", refName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
target := ref.Target()
|
if pred(ref) {
|
||||||
if target.IsBranch() {
|
return ref, nil
|
||||||
return target, nil
|
} else if ref.Type() != plumbing.SymbolicReference {
|
||||||
}
|
return nil, errTraverseRefNoMatch
|
||||||
|
|
||||||
ref, err = r.GitRepo.Storer.Reference(target)
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
refName = ref.Target()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return "", fmt.Errorf("could not de-reference HEAD to a branch: %w", err)
|
// ReferenceToBranchName traverses a chain of references looking for a branch
|
||||||
|
// reference, and returns that name, or returns an error if no branch reference
|
||||||
|
// is part of the chain.
|
||||||
|
func (r *Repo) ReferenceToBranchName(refName plumbing.ReferenceName) (plumbing.ReferenceName, error) {
|
||||||
|
ref, err := r.TraverseReferenceChain(refName, func(ref *plumbing.Reference) bool {
|
||||||
|
return ref.Target().IsBranch()
|
||||||
|
})
|
||||||
|
if errors.Is(err, errTraverseRefNoMatch) {
|
||||||
|
return "", errors.New("no branch in reference chain")
|
||||||
|
} else if err != nil {
|
||||||
|
return "", fmt.Errorf("traversing reference chain: %w", err)
|
||||||
|
}
|
||||||
|
return ref.Target(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReferenceToHash fully resolves a reference to a hash. If a reference cannot
|
||||||
|
// be resolved then plumbing.ZeroHash is returned.
|
||||||
|
func (r *Repo) ReferenceToHash(refName plumbing.ReferenceName) (plumbing.Hash, error) {
|
||||||
|
ref, err := r.TraverseReferenceChain(refName, func(ref *plumbing.Reference) bool {
|
||||||
|
return ref.Type() == plumbing.HashReference
|
||||||
|
})
|
||||||
|
if errors.Is(err, errTraverseRefNoMatch) {
|
||||||
|
return plumbing.ZeroHash, errors.New("no hash in reference chain (is this even possible???)")
|
||||||
|
} else if errors.Is(err, plumbing.ErrReferenceNotFound) {
|
||||||
|
return plumbing.ZeroHash, nil
|
||||||
|
} else if err != nil {
|
||||||
|
return plumbing.ZeroHash, fmt.Errorf("traversing reference chain: %w", err)
|
||||||
|
}
|
||||||
|
return ref.Hash(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// headFS returns an FS based on the HEAD commit, or if there is no HEAD commit
|
// headFS returns an FS based on the HEAD commit, or if there is no HEAD commit
|
||||||
// (it's an empty repo) an FS based on the raw filesystem.
|
// (it's an empty repo) an FS based on the raw filesystem.
|
||||||
func (r *Repo) headFS() (fs.FS, error) {
|
func (r *Repo) headFS() (fs.FS, error) {
|
||||||
head, err := r.GetGitHead()
|
head, err := r.GetGitHead()
|
||||||
if errors.Is(err, ErrNoHead) {
|
if errors.Is(err, ErrHeadIsZero) {
|
||||||
bfs, err := r.billyFilesystem()
|
bfs, err := r.billyFilesystem()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("getting underlying filesystem: %w", err)
|
return nil, fmt.Errorf("getting underlying filesystem: %w", err)
|
||||||
@ -205,20 +235,20 @@ func (r *Repo) GetGitRevision(rev plumbing.Revision) (GitCommit, error) {
|
|||||||
return gc, nil
|
return gc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrNoHead is returns from GetGitHead if there is no HEAD reference defined in
|
// ErrHeadIsZero is used to indicate that HEAD resolves to the zero hash. An
|
||||||
// the repo. This can happen if the repo has no commits
|
// example of when this can happen is if the repo was just initialized and has
|
||||||
var ErrNoHead = errors.New("HEAD reference not found")
|
// no commits, or if an orphan branch is checked out.
|
||||||
|
var ErrHeadIsZero = errors.New("HEAD resolves to the zero hash")
|
||||||
|
|
||||||
// GetGitHead returns the GitCommit which is currently referenced by HEAD.
|
// GetGitHead returns the GitCommit which is currently referenced by HEAD.
|
||||||
// This method may return ErrNoHead if the repo has no commits.
|
// This method may return ErrHeadIsZero if HEAD resolves to the zero hash.
|
||||||
func (r *Repo) GetGitHead() (GitCommit, error) {
|
func (r *Repo) GetGitHead() (GitCommit, error) {
|
||||||
head, err := r.GitRepo.Head()
|
headHash, err := r.ReferenceToHash(plumbing.HEAD)
|
||||||
if errors.Is(err, plumbing.ErrReferenceNotFound) {
|
if err != nil {
|
||||||
return GitCommit{}, ErrNoHead
|
|
||||||
} else if err != nil {
|
|
||||||
return GitCommit{}, fmt.Errorf("resolving HEAD: %w", err)
|
return GitCommit{}, fmt.Errorf("resolving HEAD: %w", err)
|
||||||
|
} else if headHash == plumbing.ZeroHash {
|
||||||
|
return GitCommit{}, ErrHeadIsZero
|
||||||
}
|
}
|
||||||
headHash := head.Hash()
|
|
||||||
|
|
||||||
gc, err := r.GetGitCommit(headHash)
|
gc, err := r.GetGitCommit(headHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -162,7 +162,7 @@ func (h *harness) tryCommit(
|
|||||||
h.t.Fatalf("failed to commit ChangeCommit: %v", err)
|
h.t.Fatalf("failed to commit ChangeCommit: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
branch, err := h.repo.CheckedOutBranch()
|
branch, err := h.repo.ReferenceToBranchName(plumbing.HEAD)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.t.Fatalf("determining checked out branch: %v", err)
|
h.t.Fatalf("determining checked out branch: %v", err)
|
||||||
}
|
}
|
||||||
@ -177,7 +177,7 @@ func (h *harness) tryCommit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if gitCommit.GitCommit.NumParents() == 0 {
|
if gitCommit.GitCommit.NumParents() == 0 {
|
||||||
h.t.Fatalf("unverifiable commit %q has no parents, but it should", gitCommit.GitCommit.NumParents())
|
h.t.Fatalf("unverifiable commit %q has no parents, but it should", gitCommit.GitCommit.Hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
h.reset(gitCommit.GitCommit.ParentHashes[0], git.HardReset)
|
h.reset(gitCommit.GitCommit.ParentHashes[0], git.HardReset)
|
||||||
@ -289,7 +289,7 @@ func TestThisRepoStillVerifies(t *testing.T) {
|
|||||||
headGitCommit.GitCommit.Hash, err)
|
headGitCommit.GitCommit.Hash, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkedOutBranch, err := repo.CheckedOutBranch()
|
checkedOutBranch, err := repo.ReferenceToBranchName(plumbing.HEAD)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error determining checked out branch: %v", err)
|
t.Fatalf("error determining checked out branch: %v", err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user