Monorepo for Tangled
tangled.org
1package repoinfo
2
3import (
4 "fmt"
5 "path"
6 "slices"
7
8 "github.com/bluesky-social/indigo/atproto/syntax"
9 "tangled.org/core/api/tangled"
10 "tangled.org/core/appview/models"
11 "tangled.org/core/appview/state/userutil"
12)
13
14func (r RepoInfo) owner() string {
15 if r.OwnerHandle != "" {
16 return r.OwnerHandle
17 } else {
18 return r.OwnerDid
19 }
20}
21
22func (r RepoInfo) Slug() string {
23 if r.Name != "" {
24 return r.Name
25 }
26 return r.Rkey
27}
28
29func (r RepoInfo) FullName() string {
30 return path.Join(r.owner(), r.Slug())
31}
32
33func (r RepoInfo) RepoIdentifier() string {
34 if r.RepoDid != "" {
35 return r.RepoDid
36 }
37 return path.Join(r.OwnerDid, r.Name)
38}
39
40func (r RepoInfo) ownerWithoutAt() string {
41 if r.OwnerHandle != "" {
42 return r.OwnerHandle
43 } else {
44 return userutil.FlattenDid(r.OwnerDid)
45 }
46}
47
48func (r RepoInfo) FullNameWithoutAt() string {
49 return path.Join(r.ownerWithoutAt(), r.Slug())
50}
51
52func (r RepoInfo) GetTabs() [][]string {
53 tabs := [][]string{
54 {"overview", "/", "square-chart-gantt"},
55 {"issues", "/issues", "circle-dot"},
56 {"pulls", "/pulls", "git-pull-request"},
57 {"pipelines", "/pipelines", "layers-2"},
58 }
59
60 if r.Roles.SettingsAllowed() {
61 tabs = append(tabs, []string{"settings", "/settings", "cog"})
62 }
63
64 return tabs
65}
66
67func (r RepoInfo) RepoAt() syntax.ATURI {
68 return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", r.OwnerDid, tangled.RepoNSID, r.Rkey))
69}
70
71type RepoInfo struct {
72 Name string
73 Rkey string
74 OwnerDid string
75 OwnerHandle string
76 RepoDid string
77 Description string
78 Website string
79 Topics []string
80 Knot string
81 Spindle string
82 IsStarred bool
83 Stats models.RepoStats
84 Roles RolesInRepo
85 Source *models.Repo
86 Ref string
87 CurrentDir string
88}
89
90// each tab on a repo could have some metadata:
91//
92// issues -> number of open issues etc.
93// settings -> a warning icon to setup branch protection? idk
94//
95// we gather these bits of info here, because go templates
96// are difficult to program in
97func (r RepoInfo) TabMetadata() map[string]any {
98 meta := make(map[string]any)
99
100 meta["pulls"] = r.Stats.PullCount.Open
101 meta["issues"] = r.Stats.IssueCount.Open
102
103 // more stuff?
104
105 return meta
106}
107
108type RolesInRepo struct {
109 Roles []string
110}
111
112func (r RolesInRepo) SettingsAllowed() bool {
113 return slices.Contains(r.Roles, "repo:settings")
114}
115
116func (r RolesInRepo) CollaboratorInviteAllowed() bool {
117 return slices.Contains(r.Roles, "repo:invite")
118}
119
120func (r RolesInRepo) RepoDeleteAllowed() bool {
121 return slices.Contains(r.Roles, "repo:delete")
122}
123
124func (r RolesInRepo) IsOwner() bool {
125 return slices.Contains(r.Roles, "repo:owner")
126}
127
128func (r RolesInRepo) IsCollaborator() bool {
129 return slices.Contains(r.Roles, "repo:collaborator")
130}
131
132func (r RolesInRepo) IsPushAllowed() bool {
133 return slices.Contains(r.Roles, "repo:push")
134}