Merge branch 'mg/tags/gitrpc_cleanup' of _OKE5H2PQKOUfzFFDuD4FA/default/CODE/gitness (#154)

This commit is contained in:
Marko Gacesa 2023-06-21 11:19:17 +00:00 committed by Harness
commit 306cae9db2

View File

@ -26,41 +26,19 @@ const (
// GetAnnotatedTag returns the tag for a specific tag sha. // GetAnnotatedTag returns the tag for a specific tag sha.
func (g Adapter) GetAnnotatedTag(ctx context.Context, repoPath string, sha string) (*types.Tag, error) { func (g Adapter) GetAnnotatedTag(ctx context.Context, repoPath string, sha string) (*types.Tag, error) {
giteaRepo, err := gitea.OpenRepository(ctx, repoPath) tags, err := giteaGetAnnotatedTags(ctx, repoPath, []string{sha})
if err != nil { if err != nil || len(tags) == 0 {
return nil, err
}
defer giteaRepo.Close()
tag, err := giteaGetAnnotatedTag(giteaRepo, sha)
if err != nil {
return nil, processGiteaErrorf(err, "failed to get annotated tag with sha '%s'", sha) return nil, processGiteaErrorf(err, "failed to get annotated tag with sha '%s'", sha)
} }
return tag, nil return &tags[0], nil
} }
// GetAnnotatedTags returns the tags for a specific list of tag sha. // GetAnnotatedTags returns the tags for a specific list of tag sha.
func (g Adapter) GetAnnotatedTags(ctx context.Context, repoPath string, shas []string) ([]types.Tag, error) { func (g Adapter) GetAnnotatedTags(ctx context.Context, repoPath string, shas []string) ([]types.Tag, error) {
giteaRepo, err := gitea.OpenRepository(ctx, repoPath) return giteaGetAnnotatedTags(ctx, repoPath, shas)
if err != nil {
return nil, err
}
defer giteaRepo.Close()
tags := make([]types.Tag, len(shas))
for i, sha := range shas {
var tag *types.Tag
tag, err = giteaGetAnnotatedTag(giteaRepo, sha)
if err != nil {
return nil, processGiteaErrorf(err, "failed to get annotated tag with sha '%s'", sha)
}
tags[i] = *tag
}
return tags, nil
} }
func (g Adapter) CreateAnnotatedTag( func (g Adapter) CreateAnnotatedTag(
ctx context.Context, ctx context.Context,
repoPath string, repoPath string,
@ -80,85 +58,90 @@ func (g Adapter) CreateAnnotatedTag(
// giteaGetAnnotatedTag is a custom implementation to retrieve an annotated tag from a sha. // giteaGetAnnotatedTag is a custom implementation to retrieve an annotated tag from a sha.
// The code is following parts of the gitea implementation. // The code is following parts of the gitea implementation.
// func giteaGetAnnotatedTags(ctx context.Context, repoPath string, shas []string) ([]types.Tag, error) {
// IMPORTANT: This is required as all gitea implementations of form get*Tag
// are having huge performance issues (with 2,500 tags it took seconds per single tag!)
func giteaGetAnnotatedTag(giteaRepo *gitea.Repository, sha string) (*types.Tag, error) {
// The tag is an annotated tag with a message. // The tag is an annotated tag with a message.
writer, reader, cancel := giteaRepo.CatFileBatch(giteaRepo.Ctx) writer, reader, cancel := gitea.CatFileBatch(ctx, repoPath)
defer cancel() defer func() {
if _, err := writer.Write([]byte(sha + "\n")); err != nil { cancel()
return nil, err _ = writer.Close()
} }()
tagSha, typ, size, err := gitea.ReadBatchLine(reader)
if err != nil { tags := make([]types.Tag, len(shas))
if errors.Is(err, io.EOF) || gitea.IsErrNotExist(err) {
return nil, fmt.Errorf("tag with sha %s does not exist", sha) for i, sha := range shas {
if _, err := writer.Write([]byte(sha + "\n")); err != nil {
return nil, err
} }
return nil, err tagSha, typ, size, err := gitea.ReadBatchLine(reader)
} if err != nil {
if typ != string(types.GitObjectTypeTag) { if errors.Is(err, io.EOF) || gitea.IsErrNotExist(err) {
return nil, fmt.Errorf("git object is of type '%s', expected tag", typ) return nil, fmt.Errorf("tag with sha %s does not exist", sha)
}
return nil, err
}
if typ != string(types.GitObjectTypeTag) {
return nil, fmt.Errorf("git object is of type '%s', expected tag", typ)
}
// read the remaining rawData
rawData, err := io.ReadAll(io.LimitReader(reader, size))
if err != nil {
return nil, err
}
_, err = reader.Discard(1)
if err != nil {
return nil, err
}
tag, err := parseTagDataFromCatFile(rawData)
if err != nil {
return nil, fmt.Errorf("failed to parse tag '%s': %w", sha, err)
}
// fill in the sha
tag.Sha = string(tagSha)
tags[i] = tag
} }
// read the remaining rawData return tags, nil
rawData, err := io.ReadAll(io.LimitReader(reader, size))
if err != nil {
return nil, err
}
_, err = reader.Discard(1)
if err != nil {
return nil, err
}
tag, err := parseTagDataFromCatFile(rawData)
if err != nil {
return nil, fmt.Errorf("failed to parse tag '%s': %w", sha, err)
}
// fill in the sha
tag.Sha = string(tagSha)
return tag, nil
} }
// parseTagDataFromCatFile parses a tag from a cat-file output. // parseTagDataFromCatFile parses a tag from a cat-file output.
func parseTagDataFromCatFile(data []byte) (*types.Tag, error) { func parseTagDataFromCatFile(data []byte) (tag types.Tag, err error) {
tag := &types.Tag{}
p := 0 p := 0
var err error
// parse object Id // parse object Id
tag.TargetSha, p, err = giteaParseCatFileLine(data, p, "object") tag.TargetSha, p, err = giteaParseCatFileLine(data, p, "object")
if err != nil { if err != nil {
return nil, err return
} }
// parse object type // parse object type
rawType, p, err := giteaParseCatFileLine(data, p, "type") rawType, p, err := giteaParseCatFileLine(data, p, "type")
if err != nil { if err != nil {
return nil, err return
} }
tag.TargetType, err = types.ParseGitObjectType(rawType) tag.TargetType, err = types.ParseGitObjectType(rawType)
if err != nil { if err != nil {
return nil, err return
} }
// parse tag name // parse tag name
tag.Name, p, err = giteaParseCatFileLine(data, p, "tag") tag.Name, p, err = giteaParseCatFileLine(data, p, "tag")
if err != nil { if err != nil {
return nil, err return
} }
// parse tagger // parse tagger
rawTaggerInfo, p, err := giteaParseCatFileLine(data, p, "tagger") rawTaggerInfo, p, err := giteaParseCatFileLine(data, p, "tagger")
if err != nil { if err != nil {
return nil, err return
} }
tag.Tagger, err = parseSignatureFromCatFileLine(rawTaggerInfo) tag.Tagger, err = parseSignatureFromCatFileLine(rawTaggerInfo)
if err != nil { if err != nil {
return nil, err return
} }
// remainder is message and gpg (remove leading and tailing new lines) // remainder is message and gpg (remove leading and tailing new lines)