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