github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/git/repo_tag_gogit.go (about) 1 // Copyright 2023 The GitBundle Inc. All rights reserved. 2 // Copyright 2017 The Gitea Authors. All rights reserved. 3 // Use of this source code is governed by a MIT-style 4 // license that can be found in the LICENSE file. 5 6 // Copyright 2015 The Gogs Authors. All rights reserved. 7 8 //go:build gogit 9 10 package git 11 12 import ( 13 "strings" 14 15 "github.com/gitbundle/modules/log" 16 17 "github.com/go-git/go-git/v5/plumbing" 18 ) 19 20 // IsTagExist returns true if given tag exists in the repository. 21 func (repo *Repository) IsTagExist(name string) bool { 22 _, err := repo.gogitRepo.Reference(plumbing.ReferenceName(TagPrefix+name), true) 23 return err == nil 24 } 25 26 // GetTags returns all tags of the repository. 27 // returning at most limit tags, or all if limit is 0. 28 func (repo *Repository) GetTags(skip, limit int) ([]string, error) { 29 var tagNames []string 30 31 tags, err := repo.gogitRepo.Tags() 32 if err != nil { 33 return nil, err 34 } 35 36 _ = tags.ForEach(func(tag *plumbing.Reference) error { 37 tagNames = append(tagNames, strings.TrimPrefix(tag.Name().String(), TagPrefix)) 38 return nil 39 }) 40 41 // Reverse order 42 for i := 0; i < len(tagNames)/2; i++ { 43 j := len(tagNames) - i - 1 44 tagNames[i], tagNames[j] = tagNames[j], tagNames[i] 45 } 46 47 // since we have to reverse order we can paginate only afterwards 48 if len(tagNames) < skip { 49 tagNames = []string{} 50 } else { 51 tagNames = tagNames[skip:] 52 } 53 if limit != 0 && len(tagNames) > limit { 54 tagNames = tagNames[:limit] 55 } 56 57 return tagNames, nil 58 } 59 60 // GetTagType gets the type of the tag, either commit (simple) or tag (annotated) 61 func (repo *Repository) GetTagType(id SHA1) (string, error) { 62 // Get tag type 63 obj, err := repo.gogitRepo.Object(plumbing.AnyObject, id) 64 if err != nil { 65 if err == plumbing.ErrReferenceNotFound { 66 return "", &ErrNotExist{ID: id.String()} 67 } 68 return "", err 69 } 70 71 return obj.Type().String(), nil 72 } 73 74 func (repo *Repository) getTag(tagID SHA1, name string) (*Tag, error) { 75 t, ok := repo.tagCache.Get(tagID.String()) 76 if ok { 77 log.Debug("Hit cache: %s", tagID) 78 tagClone := *t.(*Tag) 79 tagClone.Name = name // This is necessary because lightweight tags may have same id 80 return &tagClone, nil 81 } 82 83 tp, err := repo.GetTagType(tagID) 84 if err != nil { 85 return nil, err 86 } 87 88 // Get the commit ID and tag ID (may be different for annotated tag) for the returned tag object 89 commitIDStr, err := repo.GetTagCommitID(name) 90 if err != nil { 91 // every tag should have a commit ID so return all errors 92 return nil, err 93 } 94 commitID, err := NewIDFromString(commitIDStr) 95 if err != nil { 96 return nil, err 97 } 98 99 // If type is "commit, the tag is a lightweight tag 100 if ObjectType(tp) == ObjectCommit { 101 commit, err := repo.GetCommit(commitIDStr) 102 if err != nil { 103 return nil, err 104 } 105 tag := &Tag{ 106 Name: name, 107 ID: tagID, 108 Object: commitID, 109 Type: tp, 110 Tagger: commit.Committer, 111 Message: commit.Message(), 112 } 113 114 repo.tagCache.Set(tagID.String(), tag) 115 return tag, nil 116 } 117 118 gogitTag, err := repo.gogitRepo.TagObject(tagID) 119 if err != nil { 120 if err == plumbing.ErrReferenceNotFound { 121 return nil, &ErrNotExist{ID: tagID.String()} 122 } 123 124 return nil, err 125 } 126 127 tag := &Tag{ 128 Name: name, 129 ID: tagID, 130 Object: gogitTag.Target, 131 Type: tp, 132 Tagger: &gogitTag.Tagger, 133 Message: gogitTag.Message, 134 } 135 136 repo.tagCache.Set(tagID.String(), tag) 137 return tag, nil 138 }