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  }