Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use full output of git show-ref --tags to get tags for PushUpdateAddTag #19235

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions modules/git/repo_branch_gogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"strings"

"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
)

// IsObjectExist returns true if given reference exists in the repository.
Expand Down Expand Up @@ -82,7 +83,7 @@ func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) {
}

// WalkReferences walks all the references from the repository
func WalkReferences(ctx context.Context, repoPath string, walkfn func(string) error) (int, error) {
func WalkReferences(ctx context.Context, repoPath string, walkfn func(sha1, refname string) error) (int, error) {
repo := RepositoryFromContext(ctx, repoPath)
if repo == nil {
var err error
Expand All @@ -101,9 +102,42 @@ func WalkReferences(ctx context.Context, repoPath string, walkfn func(string) er
defer iter.Close()

err = iter.ForEach(func(ref *plumbing.Reference) error {
err := walkfn(string(ref.Name()))
err := walkfn(ref.Hash().String(), string(ref.Name()))
i++
return err
})
return i, err
}

// WalkReferences walks all the references from the repository
func (repo *Repository) WalkReferences(arg string, skip, limit int, walkfn func(sha1, refname string) error) (int, error) {
zeripath marked this conversation as resolved.
Show resolved Hide resolved
i := 0
var iter storer.ReferenceIter
var err error
if arg == "--tags" {
iter, err = repo.gogitRepo.Tags()
} else {
iter, err = repo.gogitRepo.References()
}
if err != nil {
return i, err
}
defer iter.Close()

err = iter.ForEach(func(ref *plumbing.Reference) error {
if i < skip {
i++
return nil
}
err := walkfn(ref.Hash().String(), string(ref.Name()))
i++
if err != nil {
return err
}
if limit != 0 && i >= skip+limit {
return storer.ErrStop
}
return nil
})
return i, err
}
24 changes: 15 additions & 9 deletions modules/git/repo_branch_nogogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,18 @@ func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) {
}

// WalkReferences walks all the references from the repository
func WalkReferences(ctx context.Context, repoPath string, walkfn func(string) error) (int, error) {
func WalkReferences(ctx context.Context, repoPath string, walkfn func(sha1, refname string) error) (int, error) {
return walkShowRef(ctx, repoPath, "", 0, 0, walkfn)
}

// WalkReferences walks all the references from the repository
func (repo *Repository) WalkReferences(arg string, skip, limit int, walkfn func(sha1, refname string) error) (int, error) {
return walkShowRef(repo.Ctx, repo.Path, arg, skip, limit, walkfn)
}

// callShowRef return refs, if limit = 0 it will not limit
func callShowRef(ctx context.Context, repoPath, prefix, arg string, skip, limit int) (branchNames []string, countAll int, err error) {
countAll, err = walkShowRef(ctx, repoPath, arg, skip, limit, func(branchName string) error {
countAll, err = walkShowRef(ctx, repoPath, arg, skip, limit, func(_, branchName string) error {
branchName = strings.TrimPrefix(branchName, prefix)
branchNames = append(branchNames, branchName)

Expand All @@ -83,7 +88,7 @@ func callShowRef(ctx context.Context, repoPath, prefix, arg string, skip, limit
return
}

func walkShowRef(ctx context.Context, repoPath, arg string, skip, limit int, walkfn func(string) error) (countAll int, err error) {
func walkShowRef(ctx context.Context, repoPath, arg string, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) {
stdoutReader, stdoutWriter := io.Pipe()
defer func() {
_ = stdoutReader.Close()
Expand Down Expand Up @@ -130,11 +135,7 @@ func walkShowRef(ctx context.Context, repoPath, arg string, skip, limit int, wal
for limit == 0 || i < skip+limit {
// The output of show-ref is simply a list:
// <sha> SP <ref> LF
_, err := bufReader.ReadSlice(' ')
for err == bufio.ErrBufferFull {
// This shouldn't happen but we'll tolerate it for the sake of peace
_, err = bufReader.ReadSlice(' ')
}
sha, err := bufReader.ReadString(' ')
if err == io.EOF {
return i, nil
}
Expand All @@ -154,7 +155,12 @@ func walkShowRef(ctx context.Context, repoPath, arg string, skip, limit int, wal
if len(branchName) > 0 {
branchName = branchName[:len(branchName)-1]
}
err = walkfn(branchName)

if len(sha) > 0 {
sha = sha[:len(sha)-1]
}

err = walkfn(sha, branchName)
if err != nil {
return i, err
}
Expand Down
91 changes: 14 additions & 77 deletions modules/git/repo_tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"fmt"
"strings"

"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util"
)

Expand All @@ -34,69 +33,6 @@ func (repo *Repository) CreateAnnotatedTag(name, message, revision string) error
return err
}

func (repo *Repository) getTag(tagID SHA1, name string) (*Tag, error) {
t, ok := repo.tagCache.Get(tagID.String())
if ok {
log.Debug("Hit cache: %s", tagID)
tagClone := *t.(*Tag)
tagClone.Name = name // This is necessary because lightweight tags may have same id
return &tagClone, nil
}

tp, err := repo.GetTagType(tagID)
if err != nil {
return nil, err
}

// Get the commit ID and tag ID (may be different for annotated tag) for the returned tag object
commitIDStr, err := repo.GetTagCommitID(name)
if err != nil {
// every tag should have a commit ID so return all errors
return nil, err
}
commitID, err := NewIDFromString(commitIDStr)
if err != nil {
return nil, err
}

// If type is "commit, the tag is a lightweight tag
if ObjectType(tp) == ObjectCommit {
commit, err := repo.GetCommit(commitIDStr)
if err != nil {
return nil, err
}
tag := &Tag{
Name: name,
ID: tagID,
Object: commitID,
Type: tp,
Tagger: commit.Committer,
Message: commit.Message(),
}

repo.tagCache.Set(tagID.String(), tag)
return tag, nil
}

// The tag is an annotated tag with a message.
data, err := NewCommand(repo.Ctx, "cat-file", "-p", tagID.String()).RunInDirBytes(repo.Path)
if err != nil {
return nil, err
}

tag, err := parseTagData(data)
if err != nil {
return nil, err
}

tag.Name = name
tag.ID = tagID
tag.Type = tp

repo.tagCache.Set(tagID.String(), tag)
return tag, nil
}

// GetTagNameBySHA returns the name of a tag from its tag object SHA or commit SHA
func (repo *Repository) GetTagNameBySHA(sha string) (string, error) {
if len(sha) < 5 {
Expand Down Expand Up @@ -159,6 +95,20 @@ func (repo *Repository) GetTag(name string) (*Tag, error) {
return tag, nil
}

// GetTagWithID returns a Git tag by given name.
zeripath marked this conversation as resolved.
Show resolved Hide resolved
func (repo *Repository) GetTagWithID(idStr, name string) (*Tag, error) {
id, err := NewIDFromString(idStr)
if err != nil {
return nil, err
}

tag, err := repo.getTag(id, name)
if err != nil {
return nil, err
}
return tag, nil
}

// GetTagInfos returns all tag infos of the repository.
func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, int, error) {
// TODO this a slow implementation, makes one git command per tag
Expand Down Expand Up @@ -192,19 +142,6 @@ func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, int, error) {
return tags, tagsTotal, nil
}

// GetTagType gets the type of the tag, either commit (simple) or tag (annotated)
func (repo *Repository) GetTagType(id SHA1) (string, error) {
// Get tag type
stdout, err := NewCommand(repo.Ctx, "cat-file", "-t", id.String()).RunInDir(repo.Path)
if err != nil {
return "", err
}
if len(stdout) == 0 {
return "", ErrNotExist{ID: id.String()}
}
return strings.TrimSpace(stdout), nil
}

// GetAnnotatedTag returns a Git tag by its SHA, must be an annotated tag
func (repo *Repository) GetAnnotatedTag(sha string) (*Tag, error) {
id, err := NewIDFromString(sha)
Expand Down
76 changes: 76 additions & 0 deletions modules/git/repo_tag_gogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package git
import (
"strings"

"code.gitea.io/gitea/modules/log"
"github.com/go-git/go-git/v5/plumbing"
)

Expand Down Expand Up @@ -53,3 +54,78 @@ func (repo *Repository) GetTags(skip, limit int) ([]string, error) {

return tagNames, nil
}

// GetTagType gets the type of the tag, either commit (simple) or tag (annotated)
func (repo *Repository) GetTagType(id SHA1) (string, error) {
// Get tag type
stdout, err := NewCommand(repo.Ctx, "cat-file", "-t", id.String()).RunInDir(repo.Path)
if err != nil {
return "", err
}
if len(stdout) == 0 {
return "", ErrNotExist{ID: id.String()}
}
return strings.TrimSpace(stdout), nil
}

func (repo *Repository) getTag(tagID SHA1, name string) (*Tag, error) {
t, ok := repo.tagCache.Get(tagID.String())
if ok {
log.Debug("Hit cache: %s", tagID)
tagClone := *t.(*Tag)
tagClone.Name = name // This is necessary because lightweight tags may have same id
return &tagClone, nil
}

tp, err := repo.GetTagType(tagID)
if err != nil {
return nil, err
}

// Get the commit ID and tag ID (may be different for annotated tag) for the returned tag object
commitIDStr, err := repo.GetTagCommitID(name)
if err != nil {
// every tag should have a commit ID so return all errors
return nil, err
}
commitID, err := NewIDFromString(commitIDStr)
if err != nil {
return nil, err
}

// If type is "commit, the tag is a lightweight tag
if ObjectType(tp) == ObjectCommit {
commit, err := repo.GetCommit(commitIDStr)
if err != nil {
return nil, err
}
tag := &Tag{
Name: name,
ID: tagID,
Object: commitID,
Type: tp,
Tagger: commit.Committer,
Message: commit.Message(),
}

repo.tagCache.Set(tagID.String(), tag)
return tag, nil
}

gogitTag, err := repo.gogitRepo.TagObject(tagID)
if err != nil {
return nil, err
}

tag := &Tag{
Name: name,
ID: tagID,
Object: gogitTag.Target,
Type: tp,
Tagger: &gogitTag.Tagger,
Message: gogitTag.Message,
}

repo.tagCache.Set(tagID.String(), tag)
return tag, nil
}
Loading