1package repo
2
3import (
4 "context"
5 "crypto/rand"
6 "fmt"
7 "math/big"
8
9 "tangled.sh/tangled.sh/core/appview/db"
10 "tangled.sh/tangled.sh/core/appview/pages/repoinfo"
11
12 "github.com/go-git/go-git/v5/plumbing/object"
13)
14
15func uniqueEmails(commits []*object.Commit) []string {
16 emails := make(map[string]struct{})
17 for _, commit := range commits {
18 if commit.Author.Email != "" {
19 emails[commit.Author.Email] = struct{}{}
20 }
21 if commit.Committer.Email != "" {
22 emails[commit.Committer.Email] = struct{}{}
23 }
24 }
25 var uniqueEmails []string
26 for email := range emails {
27 uniqueEmails = append(uniqueEmails, email)
28 }
29 return uniqueEmails
30}
31
32func balanceIndexItems(commitCount, branchCount, tagCount, fileCount int) (commitsTrunc int, branchesTrunc int, tagsTrunc int) {
33 if commitCount == 0 && tagCount == 0 && branchCount == 0 {
34 return
35 }
36
37 // typically 1 item on right side = 2 files in height
38 availableSpace := fileCount / 2
39
40 // clamp tagcount
41 if tagCount > 0 {
42 tagsTrunc = 1
43 availableSpace -= 1 // an extra subtracted for headers etc.
44 }
45
46 // clamp branchcount
47 if branchCount > 0 {
48 branchesTrunc = min(max(branchCount, 1), 3)
49 availableSpace -= branchesTrunc // an extra subtracted for headers etc.
50 }
51
52 // show
53 if commitCount > 0 {
54 commitsTrunc = max(availableSpace, 3)
55 }
56
57 return
58}
59
60// emailToDidOrHandle takes an emailToDidMap from db.GetEmailToDid
61// and resolves all dids to handles and returns a new map[string]string
62func emailToDidOrHandle(r *Repo, emailToDidMap map[string]string) map[string]string {
63 if emailToDidMap == nil {
64 return nil
65 }
66
67 var dids []string
68 for _, v := range emailToDidMap {
69 dids = append(dids, v)
70 }
71 resolvedIdents := r.idResolver.ResolveIdents(context.Background(), dids)
72
73 didHandleMap := make(map[string]string)
74 for _, identity := range resolvedIdents {
75 if !identity.Handle.IsInvalidHandle() {
76 didHandleMap[identity.DID.String()] = fmt.Sprintf("@%s", identity.Handle.String())
77 } else {
78 didHandleMap[identity.DID.String()] = identity.DID.String()
79 }
80 }
81
82 // Create map of email to didOrHandle for commit display
83 emailToDidOrHandle := make(map[string]string)
84 for email, did := range emailToDidMap {
85 if didOrHandle, ok := didHandleMap[did]; ok {
86 emailToDidOrHandle[email] = didOrHandle
87 }
88 }
89
90 return emailToDidOrHandle
91}
92
93func randomString(n int) string {
94 const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
95 result := make([]byte, n)
96
97 for i := 0; i < n; i++ {
98 n, _ := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))
99 result[i] = letters[n.Int64()]
100 }
101
102 return string(result)
103}
104
105// grab pipelines from DB and munge that into a hashmap with commit sha as key
106//
107// golang is so blessed that it requires 35 lines of imperative code for this
108func (rp *Repo) getPipelineStatuses(
109 repoInfo repoinfo.RepoInfo,
110 shas []string,
111) (map[string]db.Pipeline, error) {
112 m := make(map[string]db.Pipeline)
113
114 if len(shas) == 0 {
115 return m, nil
116 }
117
118 ps, err := db.GetPipelineStatuses(
119 rp.db,
120 db.FilterEq("repo_owner", repoInfo.OwnerDid),
121 db.FilterEq("repo_name", repoInfo.Name),
122 db.FilterEq("knot", repoInfo.Knot),
123 db.FilterIn("sha", shas),
124 )
125 if err != nil {
126 return nil, err
127 }
128
129 for _, p := range ps {
130 m[p.Sha] = p
131 }
132
133 return m, nil
134}