appview: directly inherit Repo on ResolvedRepo #392

merged
opened by boltless.me targeting master from boltless.me/core: ref/inherit-repo
  • reduce duplicated codes
  • possibly remove/refactor ResolvedRepo in future
  • allow accessing db.Repo after it is resolved
Changed files
+59 -100
appview
db
issues
middleware
repo
reporesolver
state
+19 -19
appview/issues/issues.go
··· 73 73 return 74 74 } 75 75 76 - issue, comments, err := db.GetIssueWithComments(rp.db, f.RepoAt, issueIdInt) 76 + issue, comments, err := db.GetIssueWithComments(rp.db, f.RepoAt(), issueIdInt) 77 77 if err != nil { 78 78 log.Println("failed to get issue and comments", err) 79 79 rp.pages.Notice(w, "issues", "Failed to load issue. Try again later.") ··· 127 127 return 128 128 } 129 129 130 - issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt) 130 + issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt) 131 131 if err != nil { 132 132 log.Println("failed to get issue", err) 133 133 rp.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.") ··· 171 171 return 172 172 } 173 173 174 - err = db.CloseIssue(rp.db, f.RepoAt, issueIdInt) 174 + err = db.CloseIssue(rp.db, f.RepoAt(), issueIdInt) 175 175 if err != nil { 176 176 log.Println("failed to close issue", err) 177 177 rp.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.") ··· 203 203 return 204 204 } 205 205 206 - issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt) 206 + issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt) 207 207 if err != nil { 208 208 log.Println("failed to get issue", err) 209 209 rp.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.") ··· 220 220 isIssueOwner := user.Did == issue.OwnerDid 221 221 222 222 if isCollaborator || isIssueOwner { 223 - err := db.ReopenIssue(rp.db, f.RepoAt, issueIdInt) 223 + err := db.ReopenIssue(rp.db, f.RepoAt(), issueIdInt) 224 224 if err != nil { 225 225 log.Println("failed to reopen issue", err) 226 226 rp.pages.Notice(w, "issue-action", "Failed to reopen issue. Try again later.") ··· 264 264 265 265 err := db.NewIssueComment(rp.db, &db.Comment{ 266 266 OwnerDid: user.Did, 267 - RepoAt: f.RepoAt, 267 + RepoAt: f.RepoAt(), 268 268 Issue: issueIdInt, 269 269 CommentId: commentId, 270 270 Body: body, ··· 279 279 createdAt := time.Now().Format(time.RFC3339) 280 280 commentIdInt64 := int64(commentId) 281 281 ownerDid := user.Did 282 - issueAt, err := db.GetIssueAt(rp.db, f.RepoAt, issueIdInt) 282 + issueAt, err := db.GetIssueAt(rp.db, f.RepoAt(), issueIdInt) 283 283 if err != nil { 284 284 log.Println("failed to get issue at", err) 285 285 rp.pages.Notice(w, "issue-comment", "Failed to create comment.") 286 286 return 287 287 } 288 288 289 - atUri := f.RepoAt.String() 289 + atUri := f.RepoAt().String() 290 290 client, err := rp.oauth.AuthorizedClient(r) 291 291 if err != nil { 292 292 log.Println("failed to get authorized client", err) ··· 343 343 return 344 344 } 345 345 346 - issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt) 346 + issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt) 347 347 if err != nil { 348 348 log.Println("failed to get issue", err) 349 349 rp.pages.Notice(w, "issues", "Failed to load issue. Try again later.") 350 350 return 351 351 } 352 352 353 - comment, err := db.GetComment(rp.db, f.RepoAt, issueIdInt, commentIdInt) 353 + comment, err := db.GetComment(rp.db, f.RepoAt(), issueIdInt, commentIdInt) 354 354 if err != nil { 355 355 http.Error(w, "bad comment id", http.StatusBadRequest) 356 356 return ··· 388 388 return 389 389 } 390 390 391 - issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt) 391 + issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt) 392 392 if err != nil { 393 393 log.Println("failed to get issue", err) 394 394 rp.pages.Notice(w, "issues", "Failed to load issue. Try again later.") 395 395 return 396 396 } 397 397 398 - comment, err := db.GetComment(rp.db, f.RepoAt, issueIdInt, commentIdInt) 398 + comment, err := db.GetComment(rp.db, f.RepoAt(), issueIdInt, commentIdInt) 399 399 if err != nil { 400 400 http.Error(w, "bad comment id", http.StatusBadRequest) 401 401 return ··· 506 506 return 507 507 } 508 508 509 - issue, err := db.GetIssue(rp.db, f.RepoAt, issueIdInt) 509 + issue, err := db.GetIssue(rp.db, f.RepoAt(), issueIdInt) 510 510 if err != nil { 511 511 log.Println("failed to get issue", err) 512 512 rp.pages.Notice(w, "issues", "Failed to load issue. Try again later.") ··· 521 521 return 522 522 } 523 523 524 - comment, err := db.GetComment(rp.db, f.RepoAt, issueIdInt, commentIdInt) 524 + comment, err := db.GetComment(rp.db, f.RepoAt(), issueIdInt, commentIdInt) 525 525 if err != nil { 526 526 http.Error(w, "bad comment id", http.StatusBadRequest) 527 527 return ··· 539 539 540 540 // optimistic deletion 541 541 deleted := time.Now() 542 - err = db.DeleteComment(rp.db, f.RepoAt, issueIdInt, commentIdInt) 542 + err = db.DeleteComment(rp.db, f.RepoAt(), issueIdInt, commentIdInt) 543 543 if err != nil { 544 544 log.Println("failed to delete comment") 545 545 rp.pages.Notice(w, fmt.Sprintf("comment-%s-status", commentId), "failed to delete comment") ··· 603 603 return 604 604 } 605 605 606 - issues, err := db.GetIssues(rp.db, f.RepoAt, isOpen, page) 606 + issues, err := db.GetIssues(rp.db, f.RepoAt(), isOpen, page) 607 607 if err != nil { 608 608 log.Println("failed to get issues", err) 609 609 rp.pages.Notice(w, "issues", "Failed to load issues. Try again later.") ··· 650 650 } 651 651 652 652 issue := &db.Issue{ 653 - RepoAt: f.RepoAt, 653 + RepoAt: f.RepoAt(), 654 654 Title: title, 655 655 Body: body, 656 656 OwnerDid: user.Did, ··· 668 668 rp.pages.Notice(w, "issues", "Failed to create issue.") 669 669 return 670 670 } 671 - atUri := f.RepoAt.String() 671 + atUri := f.RepoAt().String() 672 672 resp, err := client.RepoPutRecord(r.Context(), &comatproto.RepoPutRecord_Input{ 673 673 Collection: tangled.RepoIssueNSID, 674 674 Repo: user.Did, ··· 689 689 return 690 690 } 691 691 692 - err = db.SetIssueAt(rp.db, f.RepoAt, issue.IssueId, resp.Uri) 692 + err = db.SetIssueAt(rp.db, f.RepoAt(), issue.IssueId, resp.Uri) 693 693 if err != nil { 694 694 log.Println("failed to set issue at", err) 695 695 rp.pages.Notice(w, "issues", "Failed to create issue.")
+3 -8
appview/middleware/middleware.go
··· 8 8 "slices" 9 9 "strconv" 10 10 "strings" 11 - "time" 12 11 13 12 "github.com/bluesky-social/indigo/atproto/identity" 14 13 "github.com/go-chi/chi/v5" ··· 214 213 return 215 214 } 216 215 217 - ctx := context.WithValue(req.Context(), "knot", repo.Knot) 218 - ctx = context.WithValue(ctx, "repoAt", repo.AtUri) 219 - ctx = context.WithValue(ctx, "repoDescription", repo.Description) 220 - ctx = context.WithValue(ctx, "repoSpindle", repo.Spindle) 221 - ctx = context.WithValue(ctx, "repoAddedAt", repo.Created.Format(time.RFC3339)) 216 + ctx := context.WithValue(req.Context(), "repo", repo) 222 217 next.ServeHTTP(w, req.WithContext(ctx)) 223 218 }) 224 219 } ··· 243 238 return 244 239 } 245 240 246 - pr, err := db.GetPull(mw.db, f.RepoAt, prIdInt) 241 + pr, err := db.GetPull(mw.db, f.RepoAt(), prIdInt) 247 242 if err != nil { 248 243 log.Println("failed to get pull and comments", err) 249 244 return ··· 284 279 return 285 280 } 286 281 287 - fullName := f.OwnerHandle() + "/" + f.RepoName 282 + fullName := f.OwnerHandle() + "/" + f.Name 288 283 289 284 if r.Header.Get("User-Agent") == "Go-http-client/1.1" { 290 285 if r.URL.Query().Get("go-get") == "1" {
+6 -6
appview/repo/artifact.go
··· 76 76 Artifact: uploadBlobResp.Blob, 77 77 CreatedAt: createdAt.Format(time.RFC3339), 78 78 Name: handler.Filename, 79 - Repo: f.RepoAt.String(), 79 + Repo: f.RepoAt().String(), 80 80 Tag: tag.Tag.Hash[:], 81 81 }, 82 82 }, ··· 100 100 artifact := db.Artifact{ 101 101 Did: user.Did, 102 102 Rkey: rkey, 103 - RepoAt: f.RepoAt, 103 + RepoAt: f.RepoAt(), 104 104 Tag: tag.Tag.Hash, 105 105 CreatedAt: createdAt, 106 106 BlobCid: cid.Cid(uploadBlobResp.Blob.Ref), ··· 155 155 156 156 artifacts, err := db.GetArtifact( 157 157 rp.db, 158 - db.FilterEq("repo_at", f.RepoAt), 158 + db.FilterEq("repo_at", f.RepoAt()), 159 159 db.FilterEq("tag", tag.Tag.Hash[:]), 160 160 db.FilterEq("name", filename), 161 161 ) ··· 197 197 198 198 artifacts, err := db.GetArtifact( 199 199 rp.db, 200 - db.FilterEq("repo_at", f.RepoAt), 200 + db.FilterEq("repo_at", f.RepoAt()), 201 201 db.FilterEq("tag", tag[:]), 202 202 db.FilterEq("name", filename), 203 203 ) ··· 239 239 defer tx.Rollback() 240 240 241 241 err = db.DeleteArtifact(tx, 242 - db.FilterEq("repo_at", f.RepoAt), 242 + db.FilterEq("repo_at", f.RepoAt()), 243 243 db.FilterEq("tag", artifact.Tag[:]), 244 244 db.FilterEq("name", filename), 245 245 ) ··· 270 270 return nil, err 271 271 } 272 272 273 - result, err := us.Tags(f.OwnerDid(), f.RepoName) 273 + result, err := us.Tags(f.OwnerDid(), f.Name) 274 274 if err != nil { 275 275 log.Println("failed to reach knotserver", err) 276 276 return nil, err
+5 -5
appview/repo/index.go
··· 37 37 return 38 38 } 39 39 40 - result, err := us.Index(f.OwnerDid(), f.RepoName, ref) 40 + result, err := us.Index(f.OwnerDid(), f.Name, ref) 41 41 if err != nil { 42 42 rp.pages.Error503(w) 43 43 log.Println("failed to reach knotserver", err) ··· 166 166 // first attempt to fetch from db 167 167 langs, err := db.GetRepoLanguages( 168 168 rp.db, 169 - db.FilterEq("repo_at", f.RepoAt), 169 + db.FilterEq("repo_at", f.RepoAt()), 170 170 db.FilterEq("ref", f.Ref), 171 171 ) 172 172 173 173 if err != nil || langs == nil { 174 174 // non-fatal, fetch langs from ks 175 - ls, err := signedClient.RepoLanguages(f.OwnerDid(), f.RepoName, f.Ref) 175 + ls, err := signedClient.RepoLanguages(f.OwnerDid(), f.Name, f.Ref) 176 176 if err != nil { 177 177 return nil, err 178 178 } ··· 182 182 183 183 for l, s := range ls.Languages { 184 184 langs = append(langs, db.RepoLanguage{ 185 - RepoAt: f.RepoAt, 185 + RepoAt: f.RepoAt(), 186 186 Ref: f.Ref, 187 187 IsDefaultRef: isDefaultRef, 188 188 Language: l, ··· 279 279 hiddenRef := fmt.Sprintf("hidden/%s/%s", f.Ref, f.Ref) 280 280 281 281 var status types.AncestorCheckResponse 282 - forkSyncableResp, err := signedClient.RepoForkAheadBehind(user.Did, string(f.RepoAt), repoInfo.Name, f.Ref, hiddenRef) 282 + forkSyncableResp, err := signedClient.RepoForkAheadBehind(user.Did, string(f.RepoAt()), repoInfo.Name, f.Ref, hiddenRef) 283 283 if err != nil { 284 284 log.Printf("failed to check if fork is ahead/behind: %s", err) 285 285 return nil, err
+25 -58
appview/reporesolver/resolver.go
··· 12 12 "strings" 13 13 14 14 "github.com/bluesky-social/indigo/atproto/identity" 15 - "github.com/bluesky-social/indigo/atproto/syntax" 16 15 securejoin "github.com/cyphar/filepath-securejoin" 17 16 "github.com/go-chi/chi/v5" 18 17 "tangled.sh/tangled.sh/core/appview/config" ··· 26 25 ) 27 26 28 27 type ResolvedRepo struct { 29 - Knot string 28 + db.Repo 30 29 OwnerId identity.Identity 31 - RepoName string 32 - RepoAt syntax.ATURI 33 - Description string 34 - Spindle string 35 - CreatedAt string 36 30 Ref string 37 31 CurrentDir string 38 32 ··· 51 45 } 52 46 53 47 func (rr *RepoResolver) Resolve(r *http.Request) (*ResolvedRepo, error) { 54 - repoName := chi.URLParam(r, "repo") 55 - knot, ok := r.Context().Value("knot").(string) 48 + repo, ok := r.Context().Value("repo").(*db.Repo) 56 49 if !ok { 57 - log.Println("malformed middleware") 50 + log.Println("malformed middleware: `repo` not exist in context") 58 51 return nil, fmt.Errorf("malformed middleware") 59 52 } 60 53 id, ok := r.Context().Value("resolvedId").(identity.Identity) ··· 63 56 return nil, fmt.Errorf("malformed middleware") 64 57 } 65 58 66 - repoAt, ok := r.Context().Value("repoAt").(string) 67 - if !ok { 68 - log.Println("malformed middleware") 69 - return nil, fmt.Errorf("malformed middleware") 70 - } 71 - 72 - parsedRepoAt, err := syntax.ParseATURI(repoAt) 73 - if err != nil { 74 - log.Println("malformed repo at-uri") 75 - return nil, fmt.Errorf("malformed middleware") 76 - } 77 - 78 59 ref := chi.URLParam(r, "ref") 79 60 80 61 if ref == "" { 81 - us, err := knotclient.NewUnsignedClient(knot, rr.config.Core.Dev) 62 + us, err := knotclient.NewUnsignedClient(repo.Knot, rr.config.Core.Dev) 82 63 if err != nil { 83 64 return nil, err 84 65 } 85 66 86 - defaultBranch, err := us.DefaultBranch(id.DID.String(), repoName) 67 + defaultBranch, err := us.DefaultBranch(id.DID.String(), repo.Name) 87 68 if err != nil { 88 69 return nil, err 89 70 } ··· 93 74 94 75 currentDir := path.Dir(extractPathAfterRef(r.URL.EscapedPath(), ref)) 95 76 96 - // pass through values from the middleware 97 - description, ok := r.Context().Value("repoDescription").(string) 98 - addedAt, ok := r.Context().Value("repoAddedAt").(string) 99 - spindle, ok := r.Context().Value("repoSpindle").(string) 100 - 101 77 return &ResolvedRepo{ 102 - Knot: knot, 103 - OwnerId: id, 104 - RepoName: repoName, 105 - RepoAt: parsedRepoAt, 106 - Description: description, 107 - CreatedAt: addedAt, 108 - Ref: ref, 109 - CurrentDir: currentDir, 110 - Spindle: spindle, 78 + Repo: *repo, 79 + OwnerId: id, 80 + Ref: ref, 81 + CurrentDir: currentDir, 111 82 112 83 rr: rr, 113 84 }, nil ··· 126 97 127 98 var p string 128 99 if handle != "" && !handle.IsInvalidHandle() { 129 - p, _ = securejoin.SecureJoin(fmt.Sprintf("@%s", handle), f.RepoName) 100 + p, _ = securejoin.SecureJoin(fmt.Sprintf("@%s", handle), f.Name) 130 101 } else { 131 - p, _ = securejoin.SecureJoin(f.OwnerDid(), f.RepoName) 102 + p, _ = securejoin.SecureJoin(f.OwnerDid(), f.Name) 132 103 } 133 104 134 105 return p 135 106 } 136 107 137 - func (f *ResolvedRepo) DidSlashRepo() string { 138 - p, _ := securejoin.SecureJoin(f.OwnerDid(), f.RepoName) 139 - return p 140 - } 141 - 142 108 func (f *ResolvedRepo) Collaborators(ctx context.Context) ([]pages.Collaborator, error) { 143 109 repoCollaborators, err := f.rr.enforcer.E.GetImplicitUsersForResourceByDomain(f.DidSlashRepo(), f.Knot) 144 110 if err != nil { ··· 187 153 // this function is a bit weird since it now returns RepoInfo from an entirely different 188 154 // package. we should refactor this or get rid of RepoInfo entirely. 189 155 func (f *ResolvedRepo) RepoInfo(user *oauth.User) repoinfo.RepoInfo { 156 + repoAt := f.RepoAt() 190 157 isStarred := false 191 158 if user != nil { 192 - isStarred = db.GetStarStatus(f.rr.execer, user.Did, syntax.ATURI(f.RepoAt)) 159 + isStarred = db.GetStarStatus(f.rr.execer, user.Did, repoAt) 193 160 } 194 161 195 - starCount, err := db.GetStarCount(f.rr.execer, f.RepoAt) 162 + starCount, err := db.GetStarCount(f.rr.execer, repoAt) 196 163 if err != nil { 197 - log.Println("failed to get star count for ", f.RepoAt) 164 + log.Println("failed to get star count for ", repoAt) 198 165 } 199 - issueCount, err := db.GetIssueCount(f.rr.execer, f.RepoAt) 166 + issueCount, err := db.GetIssueCount(f.rr.execer, repoAt) 200 167 if err != nil { 201 - log.Println("failed to get issue count for ", f.RepoAt) 168 + log.Println("failed to get issue count for ", repoAt) 202 169 } 203 - pullCount, err := db.GetPullCount(f.rr.execer, f.RepoAt) 170 + pullCount, err := db.GetPullCount(f.rr.execer, repoAt) 204 171 if err != nil { 205 - log.Println("failed to get issue count for ", f.RepoAt) 172 + log.Println("failed to get issue count for ", repoAt) 206 173 } 207 - source, err := db.GetRepoSource(f.rr.execer, f.RepoAt) 174 + source, err := db.GetRepoSource(f.rr.execer, repoAt) 208 175 if errors.Is(err, sql.ErrNoRows) { 209 176 source = "" 210 177 } else if err != nil { 211 - log.Println("failed to get repo source for ", f.RepoAt, err) 178 + log.Println("failed to get repo source for ", repoAt, err) 212 179 } 213 180 214 181 var sourceRepo *db.Repo ··· 233 200 if err != nil { 234 201 log.Printf("failed to create unsigned client for %s: %v", knot, err) 235 202 } else { 236 - result, err := us.Branches(f.OwnerDid(), f.RepoName) 203 + result, err := us.Branches(f.OwnerDid(), f.Name) 237 204 if err != nil { 238 - log.Printf("failed to get branches for %s/%s: %v", f.OwnerDid(), f.RepoName, err) 205 + log.Printf("failed to get branches for %s/%s: %v", f.OwnerDid(), f.Name, err) 239 206 } 240 207 241 208 if len(result.Branches) == 0 { ··· 246 213 repoInfo := repoinfo.RepoInfo{ 247 214 OwnerDid: f.OwnerDid(), 248 215 OwnerHandle: f.OwnerHandle(), 249 - Name: f.RepoName, 250 - RepoAt: f.RepoAt, 216 + Name: f.Name, 217 + RepoAt: repoAt, 251 218 Description: f.Description, 252 219 Ref: f.Ref, 253 220 IsStarred: isStarred,
-1
appview/state/state.go
··· 381 381 // continue 382 382 } 383 383 384 - repo.AtUri = atresp.Uri 385 384 err = db.AddRepo(tx, repo) 386 385 if err != nil { 387 386 log.Println(err)
+1 -3
appview/db/star.go
··· 196 196 r.name, 197 197 r.knot, 198 198 r.rkey, 199 - r.created, 200 - r.at_uri 199 + r.created 201 200 from stars s 202 201 join repos r on s.repo_at = r.at_uri 203 202 `) ··· 222 221 &repo.Knot, 223 222 &repo.Rkey, 224 223 &repoCreatedAt, 225 - &repo.AtUri, 226 224 ); err != nil { 227 225 return nil, err 228 226 }