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 "tangled.sh/tangled.sh/core/types"
13)
14
15func (g *GitRepo) Branches() ([]types.Branch, error) {
16 fields := []string{
17 "refname:short",
18 "objectname",
19 "authorname",
20 "authoremail",
21 "authordate:unix",
22 "committername",
23 "committeremail",
24 "committerdate:unix",
25 "tree",
26 "parent",
27 "contents",
28 }
29
30 var outFormat strings.Builder
31 outFormat.WriteString("--format=")
32 for i, f := range fields {
33 if i != 0 {
34 outFormat.WriteString(fieldSeparator)
35 }
36 outFormat.WriteString(fmt.Sprintf("%%(%s)", f))
37 }
38 outFormat.WriteString("")
39 outFormat.WriteString(recordSeparator)
40
41 output, err := g.forEachRef(outFormat.String(), "refs/heads")
42 if err != nil {
43 return nil, fmt.Errorf("failed to get branches: %w", err)
44 }
45
46 records := strings.Split(strings.TrimSpace(string(output)), recordSeparator)
47 if len(records) == 1 && records[0] == "" {
48 return nil, nil
49 }
50
51 branches := make([]types.Branch, 0, len(records))
52
53 // ignore errors here
54 defaultBranch, _ := g.FindMainBranch()
55
56 for _, line := range records {
57 parts := strings.SplitN(strings.TrimSpace(line), fieldSeparator, len(fields))
58 if len(parts) < 6 {
59 continue
60 }
61
62 branchName := parts[0]
63 commitHash := plumbing.NewHash(parts[1])
64 authorName := parts[2]
65 authorEmail := strings.TrimSuffix(strings.TrimPrefix(parts[3], "<"), ">")
66 authorDate := parts[4]
67 committerName := parts[5]
68 committerEmail := strings.TrimSuffix(strings.TrimPrefix(parts[6], "<"), ">")
69 committerDate := parts[7]
70 treeHash := plumbing.NewHash(parts[8])
71 parentHash := plumbing.NewHash(parts[9])
72 message := parts[10]
73
74 // parse creation time
75 var authoredAt, committedAt time.Time
76 if unix, err := strconv.ParseInt(authorDate, 10, 64); err == nil {
77 authoredAt = time.Unix(unix, 0)
78 }
79 if unix, err := strconv.ParseInt(committerDate, 10, 64); err == nil {
80 committedAt = time.Unix(unix, 0)
81 }
82
83 branch := types.Branch{
84 IsDefault: branchName == defaultBranch,
85 Reference: types.Reference{
86 Name: branchName,
87 Hash: commitHash.String(),
88 },
89 Commit: &object.Commit{
90 Hash: commitHash,
91 Author: object.Signature{
92 Name: authorName,
93 Email: authorEmail,
94 When: authoredAt,
95 },
96 Committer: object.Signature{
97 Name: committerName,
98 Email: committerEmail,
99 When: committedAt,
100 },
101 TreeHash: treeHash,
102 ParentHashes: []plumbing.Hash{parentHash},
103 Message: message,
104 },
105 }
106
107 branches = append(branches, branch)
108 }
109
110 slices.Reverse(branches)
111 return branches, nil
112}