A vibe coded tangled fork which supports pijul.
at master 146 lines 3.5 kB view raw
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) FullName() string { 23 return path.Join(r.owner(), r.Name) 24} 25 26func (r RepoInfo) ownerWithoutAt() string { 27 if r.OwnerHandle != "" { 28 return r.OwnerHandle 29 } else { 30 return userutil.FlattenDid(r.OwnerDid) 31 } 32} 33 34func (r RepoInfo) FullNameWithoutAt() string { 35 return path.Join(r.ownerWithoutAt(), r.Name) 36} 37 38func (r RepoInfo) GetTabs() [][]string { 39 tabs := [][]string{ 40 {"overview", "/", "square-chart-gantt"}, 41 } 42 43 if r.IsPijul() { 44 tabs = append(tabs, []string{"changes", "/changes", "logs"}) 45 tabs = append(tabs, []string{"discussions", "/discussions", "message-square"}) 46 } else { 47 tabs = append(tabs, []string{"issues", "/issues", "circle-dot"}) 48 tabs = append(tabs, []string{"pulls", "/pulls", "git-pull-request"}) 49 } 50 51 tabs = append(tabs, []string{"pipelines", "/pipelines", "layers-2"}) 52 53 if r.Roles.SettingsAllowed() { 54 tabs = append(tabs, []string{"settings", "/settings", "cog"}) 55 } 56 57 return tabs 58} 59 60func (r RepoInfo) RepoAt() syntax.ATURI { 61 return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", r.OwnerDid, tangled.RepoNSID, r.Rkey)) 62} 63 64type RepoInfo struct { 65 Name string 66 Rkey string 67 OwnerDid string 68 OwnerHandle string 69 Description string 70 Website string 71 Topics []string 72 Knot string 73 Spindle string 74 Vcs string // "git" or "pijul" 75 IsStarred bool 76 Stats models.RepoStats 77 Roles RolesInRepo 78 Source *models.Repo 79 Ref string 80 CurrentDir string 81} 82 83func (r RepoInfo) IsGit() bool { 84 return r.Vcs == "" || r.Vcs == "git" 85} 86 87func (r RepoInfo) IsPijul() bool { 88 return r.Vcs == "pijul" 89} 90 91// each tab on a repo could have some metadata: 92// 93// issues -> number of open issues etc. 94// settings -> a warning icon to setup branch protection? idk 95// 96// we gather these bits of info here, because go templates 97// are difficult to program in 98func (r RepoInfo) TabMetadata() map[string]any { 99 meta := make(map[string]any) 100 101 if r.IsPijul() { 102 // Pijul repos use discussions 103 meta["discussions"] = r.Stats.DiscussionCount.Open 104 } else { 105 // Git repos use separate issues and pulls 106 meta["issues"] = r.Stats.IssueCount.Open 107 meta["pulls"] = r.Stats.PullCount.Open 108 } 109 110 return meta 111} 112 113type RolesInRepo struct { 114 Roles []string 115} 116 117func (r RolesInRepo) SettingsAllowed() bool { 118 return slices.Contains(r.Roles, "repo:settings") 119} 120 121func (r RolesInRepo) CollaboratorInviteAllowed() bool { 122 return slices.Contains(r.Roles, "repo:invite") 123} 124 125func (r RolesInRepo) RepoDeleteAllowed() bool { 126 return slices.Contains(r.Roles, "repo:delete") 127} 128 129func (r RolesInRepo) IsOwner() bool { 130 return slices.Contains(r.Roles, "repo:owner") 131} 132 133func (r RolesInRepo) IsCollaborator() bool { 134 return slices.Contains(r.Roles, "repo:collaborator") 135} 136 137func (r RolesInRepo) IsPushAllowed() bool { 138 return slices.Contains(r.Roles, "repo:push") 139} 140 141// CanManageRepo returns true if the user has any role that grants management 142// access (owner, collaborator, or push). Used for actions like closing/merging 143// discussions, removing patches, etc. 144func (r RolesInRepo) CanManageRepo() bool { 145 return r.IsOwner() || r.IsCollaborator() || r.IsPushAllowed() 146}