-33
knotserver/git/git.go
-33
knotserver/git/git.go
···
264
264
return io.ReadAll(reader)
265
265
}
266
266
267
-
func (g *GitRepo) Tags() ([]*TagReference, error) {
268
-
iter, err := g.r.Tags()
269
-
if err != nil {
270
-
return nil, fmt.Errorf("tag objects: %w", err)
271
-
}
272
-
273
-
tags := make([]*TagReference, 0)
274
-
275
-
if err := iter.ForEach(func(ref *plumbing.Reference) error {
276
-
obj, err := g.r.TagObject(ref.Hash())
277
-
switch err {
278
-
case nil:
279
-
tags = append(tags, &TagReference{
280
-
ref: ref,
281
-
tag: obj,
282
-
})
283
-
case plumbing.ErrObjectNotFound:
284
-
tags = append(tags, &TagReference{
285
-
ref: ref,
286
-
})
287
-
default:
288
-
return err
289
-
}
290
-
return nil
291
-
}); err != nil {
292
-
return nil, err
293
-
}
294
-
295
-
tagList := &TagList{r: g.r, refs: tags}
296
-
sort.Sort(tagList)
297
-
return tags, nil
298
-
}
299
-
300
267
func (g *GitRepo) Branches() ([]types.Branch, error) {
301
268
bi, err := g.r.Branches()
302
269
if err != nil {
+99
knotserver/git/tag.go
+99
knotserver/git/tag.go
···
1
+
package git
2
+
3
+
import (
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
+
14
+
func (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
+
}
+19
-11
knotserver/routes.go
+19
-11
knotserver/routes.go
···
96
96
total int
97
97
branches []types.Branch
98
98
files []types.NiceTree
99
-
tags []*git.TagReference
99
+
tags []object.Tag
100
100
)
101
101
102
102
var wg sync.WaitGroup
···
169
169
170
170
rtags := []*types.TagReference{}
171
171
for _, tag := range tags {
172
+
var target *object.Tag
173
+
if tag.Target != plumbing.ZeroHash {
174
+
target = &tag
175
+
}
172
176
tr := types.TagReference{
173
-
Tag: tag.TagObject(),
177
+
Tag: target,
174
178
}
175
179
176
180
tr.Reference = types.Reference{
177
-
Name: tag.Name(),
178
-
Hash: tag.Hash().String(),
181
+
Name: tag.Name,
182
+
Hash: tag.Hash.String(),
179
183
}
180
184
181
-
if tag.Message() != "" {
182
-
tr.Message = tag.Message()
185
+
if tag.Message != "" {
186
+
tr.Message = tag.Message
183
187
}
184
188
185
189
rtags = append(rtags, &tr)
···
488
492
489
493
rtags := []*types.TagReference{}
490
494
for _, tag := range tags {
495
+
var target *object.Tag
496
+
if tag.Target != plumbing.ZeroHash {
497
+
target = &tag
498
+
}
491
499
tr := types.TagReference{
492
-
Tag: tag.TagObject(),
500
+
Tag: target,
493
501
}
494
502
495
503
tr.Reference = types.Reference{
496
-
Name: tag.Name(),
497
-
Hash: tag.Hash().String(),
504
+
Name: tag.Name,
505
+
Hash: tag.Hash.String(),
498
506
}
499
507
500
-
if tag.Message() != "" {
501
-
tr.Message = tag.Message()
508
+
if tag.Message != "" {
509
+
tr.Message = tag.Message
502
510
}
503
511
504
512
rtags = append(rtags, &tr)