aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--options.go6
-rw-r--r--worktree.go23
-rw-r--r--worktree_commit.go2
-rw-r--r--worktree_test.go35
4 files changed, 49 insertions, 17 deletions
diff --git a/options.go b/options.go
index 8902b7e..e748b91 100644
--- a/options.go
+++ b/options.go
@@ -324,9 +324,9 @@ var (
// CheckoutOptions describes how a checkout operation should be performed.
type CheckoutOptions struct {
- // Hash is the hash of the commit to be checked out. If used, HEAD will be
- // in detached mode. If Create is not used, Branch and Hash are mutually
- // exclusive.
+ // Hash is the hash of a commit or tag to be checked out. If used, HEAD
+ // will be in detached mode. If Create is not used, Branch and Hash are
+ // mutually exclusive.
Hash plumbing.Hash
// Branch to be checked out, if Branch and Hash are empty is set to `master`.
Branch plumbing.ReferenceName
diff --git a/worktree.go b/worktree.go
index ad525c1..4dfe036 100644
--- a/worktree.go
+++ b/worktree.go
@@ -227,20 +227,17 @@ func (w *Worktree) createBranch(opts *CheckoutOptions) error {
}
func (w *Worktree) getCommitFromCheckoutOptions(opts *CheckoutOptions) (plumbing.Hash, error) {
- if !opts.Hash.IsZero() {
- return opts.Hash, nil
- }
-
- b, err := w.r.Reference(opts.Branch, true)
- if err != nil {
- return plumbing.ZeroHash, err
- }
+ hash := opts.Hash
+ if hash.IsZero() {
+ b, err := w.r.Reference(opts.Branch, true)
+ if err != nil {
+ return plumbing.ZeroHash, err
+ }
- if !b.Name().IsTag() {
- return b.Hash(), nil
+ hash = b.Hash()
}
- o, err := w.r.Object(plumbing.AnyObject, b.Hash())
+ o, err := w.r.Object(plumbing.AnyObject, hash)
if err != nil {
return plumbing.ZeroHash, err
}
@@ -248,7 +245,7 @@ func (w *Worktree) getCommitFromCheckoutOptions(opts *CheckoutOptions) (plumbing
switch o := o.(type) {
case *object.Tag:
if o.TargetType != plumbing.CommitObject {
- return plumbing.ZeroHash, fmt.Errorf("unsupported tag object target %q", o.TargetType)
+ return plumbing.ZeroHash, fmt.Errorf("%w: tag target %q", object.ErrUnsupportedObject, o.TargetType)
}
return o.Target, nil
@@ -256,7 +253,7 @@ func (w *Worktree) getCommitFromCheckoutOptions(opts *CheckoutOptions) (plumbing
return o.Hash, nil
}
- return plumbing.ZeroHash, fmt.Errorf("unsupported tag target %q", o.Type())
+ return plumbing.ZeroHash, fmt.Errorf("%w: %q", object.ErrUnsupportedObject, o.Type())
}
func (w *Worktree) setHEADToCommit(commit plumbing.Hash) error {
diff --git a/worktree_commit.go b/worktree_commit.go
index eaa21c3..4d811f3 100644
--- a/worktree_commit.go
+++ b/worktree_commit.go
@@ -263,4 +263,4 @@ func (h *buildTreeHelper) copyTreeToStorageRecursive(parent string, t *object.Tr
return hash, nil
}
return h.s.SetEncodedObject(o)
-} \ No newline at end of file
+}
diff --git a/worktree_test.go b/worktree_test.go
index 50ff189..5759ec4 100644
--- a/worktree_test.go
+++ b/worktree_test.go
@@ -886,6 +886,41 @@ func (s *WorktreeSuite) TestCheckoutTag(c *C) {
c.Assert(head.Name().String(), Equals, "HEAD")
}
+func (s *WorktreeSuite) TestCheckoutTagHash(c *C) {
+ f := fixtures.ByTag("tags").One()
+ r := s.NewRepositoryWithEmptyWorktree(f)
+ w, err := r.Worktree()
+ c.Assert(err, IsNil)
+
+ for _, hash := range []string{
+ "b742a2a9fa0afcfa9a6fad080980fbc26b007c69", // annotated tag
+ "ad7897c0fb8e7d9a9ba41fa66072cf06095a6cfc", // commit tag
+ "f7b877701fbf855b44c0a9e86f3fdce2c298b07f", // lightweight tag
+ } {
+ err = w.Checkout(&CheckoutOptions{
+ Hash: plumbing.NewHash(hash),
+ })
+ c.Assert(err, IsNil)
+ head, err := w.r.Head()
+ c.Assert(err, IsNil)
+ c.Assert(head.Name().String(), Equals, "HEAD")
+
+ status, err := w.Status()
+ c.Assert(err, IsNil)
+ c.Assert(status.IsClean(), Equals, true)
+ }
+
+ for _, hash := range []string{
+ "fe6cb94756faa81e5ed9240f9191b833db5f40ae", // blob tag
+ "152175bf7e5580299fa1f0ba41ef6474cc043b70", // tree tag
+ } {
+ err = w.Checkout(&CheckoutOptions{
+ Hash: plumbing.NewHash(hash),
+ })
+ c.Assert(err, NotNil)
+ }
+}
+
func (s *WorktreeSuite) TestCheckoutBisect(c *C) {
if testing.Short() {
c.Skip("skipping test in short mode.")