1package git
2
3import (
4 "fmt"
5 "strconv"
6 "strings"
7 "time"
8
9 "github.com/go-git/go-git/v5/plumbing"
10 "github.com/go-git/go-git/v5/plumbing/object"
11)
12
13func (g *GitRepo) Tags() ([]object.Tag, error) {
14 fields := []string{
15 "refname:short",
16 "objectname",
17 "objecttype",
18 "*objectname",
19 "*objecttype",
20 "taggername",
21 "taggeremail",
22 "taggerdate:unix",
23 "contents",
24 }
25
26 var outFormat strings.Builder
27 outFormat.WriteString("--format=")
28 for i, f := range fields {
29 if i != 0 {
30 outFormat.WriteString(fieldSeparator)
31 }
32 outFormat.WriteString(fmt.Sprintf("%%(%s)", f))
33 }
34 outFormat.WriteString("")
35 outFormat.WriteString(recordSeparator)
36
37 output, err := g.forEachRef(outFormat.String(), "--sort=-creatordate", "refs/tags")
38 if err != nil {
39 return nil, fmt.Errorf("failed to get tags: %w", err)
40 }
41
42 records := strings.Split(strings.TrimSpace(string(output)), recordSeparator)
43 if len(records) == 1 && records[0] == "" {
44 return nil, nil
45 }
46
47 tags := make([]object.Tag, 0, len(records))
48
49 for _, line := range records {
50 parts := strings.SplitN(strings.TrimSpace(line), fieldSeparator, len(fields))
51 if len(parts) < 6 {
52 continue
53 }
54
55 tagName := parts[0]
56 objectHash := parts[1]
57 objectType := parts[2]
58 targetHash := parts[3] // dereferenced object hash (empty for lightweight tags)
59 // targetType := parts[4] // dereferenced object type (empty for lightweight tags)
60 taggerName := parts[5]
61 taggerEmail := parts[6]
62 taggerDate := parts[7]
63 message := parts[8]
64
65 // parse creation time
66 var createdAt time.Time
67 if unix, err := strconv.ParseInt(taggerDate, 10, 64); err == nil {
68 createdAt = time.Unix(unix, 0)
69 }
70
71 // parse object type
72 typ, err := plumbing.ParseObjectType(objectType)
73 if err != nil {
74 return nil, err
75 }
76
77 // strip email separators
78 taggerEmail = strings.TrimSuffix(strings.TrimPrefix(taggerEmail, "<"), ">")
79
80 tag := object.Tag{
81 Hash: plumbing.NewHash(objectHash),
82 Name: tagName,
83 Tagger: object.Signature{
84 Name: taggerName,
85 Email: taggerEmail,
86 When: createdAt,
87 },
88 Message: message,
89 TargetType: typ,
90 Target: plumbing.NewHash(targetHash),
91 }
92
93 tags = append(tags, tag)
94 }
95
96 return tags, nil
97}