this repo has no description
1package reporesolver 2 3import ( 4 "fmt" 5 "log" 6 "net/http" 7 "path" 8 "regexp" 9 "strings" 10 11 "github.com/bluesky-social/indigo/atproto/identity" 12 "github.com/go-chi/chi/v5" 13 "tangled.org/core/appview/config" 14 "tangled.org/core/appview/db" 15 "tangled.org/core/appview/models" 16 "tangled.org/core/appview/oauth" 17 "tangled.org/core/appview/pages/repoinfo" 18 "tangled.org/core/rbac" 19) 20 21type ResolvedRepo struct { 22 models.Repo 23 OwnerId identity.Identity 24 CurrentDir string 25 Ref string 26 27 rr *RepoResolver 28} 29 30type RepoResolver struct { 31 config *config.Config 32 enforcer *rbac.Enforcer 33 execer db.Execer 34} 35 36func New(config *config.Config, enforcer *rbac.Enforcer, execer db.Execer) *RepoResolver { 37 return &RepoResolver{config: config, enforcer: enforcer, execer: execer} 38} 39 40// NOTE: this... should not even be here. the entire package will be removed in future refactor 41func GetBaseRepoPath(r *http.Request, repo *models.Repo) string { 42 var ( 43 user = chi.URLParam(r, "user") 44 name = chi.URLParam(r, "repo") 45 ) 46 if user == "" || name == "" { 47 return repo.DidSlashRepo() 48 } 49 return path.Join(user, name) 50} 51 52func (rr *RepoResolver) Resolve(r *http.Request) (*ResolvedRepo, error) { 53 repo, ok := r.Context().Value("repo").(*models.Repo) 54 if !ok { 55 log.Println("malformed middleware: `repo` not exist in context") 56 return nil, fmt.Errorf("malformed middleware") 57 } 58 id, ok := r.Context().Value("resolvedId").(identity.Identity) 59 if !ok { 60 log.Println("malformed middleware") 61 return nil, fmt.Errorf("malformed middleware") 62 } 63 64 currentDir := path.Dir(extractPathAfterRef(r.URL.EscapedPath())) 65 ref := chi.URLParam(r, "ref") 66 67 return &ResolvedRepo{ 68 Repo: *repo, 69 OwnerId: id, 70 CurrentDir: currentDir, 71 Ref: ref, 72 73 rr: rr, 74 }, nil 75} 76 77// this function is a bit weird since it now returns RepoInfo from an entirely different 78// package. we should refactor this or get rid of RepoInfo entirely. 79func (f *ResolvedRepo) RepoInfo(user *oauth.User) repoinfo.RepoInfo { 80 repoAt := f.RepoAt() 81 isStarred := false 82 if user != nil { 83 isStarred = db.GetStarStatus(f.rr.execer, user.Did, repoAt) 84 } 85 86 stats := f.RepoStats 87 if stats == nil { 88 starCount, err := db.GetStarCount(f.rr.execer, repoAt) 89 if err != nil { 90 log.Println("failed to get star count for ", repoAt) 91 } 92 issueCount, err := db.GetIssueCount(f.rr.execer, repoAt) 93 if err != nil { 94 log.Println("failed to get issue count for ", repoAt) 95 } 96 pullCount, err := db.GetPullCount(f.rr.execer, repoAt) 97 if err != nil { 98 log.Println("failed to get pull count for ", repoAt) 99 } 100 stats = &models.RepoStats{ 101 StarCount: starCount, 102 IssueCount: issueCount, 103 PullCount: pullCount, 104 } 105 } 106 107 sourceRepo, err := db.GetRepoSourceRepo(f.rr.execer, repoAt) 108 if err != nil { 109 log.Println("failed to get repo by at uri", err) 110 } 111 112 repoInfo := repoinfo.RepoInfo{ 113 // this is basically a models.Repo 114 OwnerDid: f.OwnerId.DID.String(), 115 OwnerHandle: f.OwnerId.Handle.String(), 116 Name: f.Name, 117 Rkey: f.Rkey, 118 Description: f.Description, 119 Website: f.Website, 120 Topics: f.Topics, 121 Knot: f.Knot, 122 Spindle: f.Spindle, 123 Stats: *stats, 124 125 // fork repo upstream 126 Source: sourceRepo, 127 128 CurrentDir: f.CurrentDir, 129 Ref: f.Ref, 130 131 // info related to the session 132 IsStarred: isStarred, 133 Roles: f.RolesInRepo(user), 134 } 135 136 return repoInfo 137} 138 139func (f *ResolvedRepo) RolesInRepo(u *oauth.User) repoinfo.RolesInRepo { 140 if u != nil { 141 r := f.rr.enforcer.GetPermissionsInRepo(u.Did, f.Knot, f.DidSlashRepo()) 142 return repoinfo.RolesInRepo{Roles: r} 143 } else { 144 return repoinfo.RolesInRepo{} 145 } 146} 147 148// extractPathAfterRef gets the actual repository path 149// after the ref. for example: 150// 151// /@icyphox.sh/foorepo/blob/main/abc/xyz/ => abc/xyz/ 152func extractPathAfterRef(fullPath string) string { 153 fullPath = strings.TrimPrefix(fullPath, "/") 154 155 // match blob/, tree/, or raw/ followed by any ref and then a slash 156 // 157 // captures everything after the final slash 158 pattern := `(?:blob|tree|raw)/[^/]+/(.*)$` 159 160 re := regexp.MustCompile(pattern) 161 matches := re.FindStringSubmatch(fullPath) 162 163 if len(matches) > 1 { 164 return matches[1] 165 } 166 167 return "" 168}