Monorepo for Tangled tangled.org

appview: pages/markup: resolve relative links in markdown

authored by anirudh.fi and committed by Tangled 04e2bc40 8eba71c6

Changed files
+106 -78
appview
+2 -1
appview/pages/funcmap.go
··· 143 return v.Slice(start, end).Interface() 144 }, 145 "markdown": func(text string) template.HTML { 146 - return template.HTML(markup.RenderMarkdown(text)) 147 }, 148 "isNil": func(t any) bool { 149 // returns false for other "zero" values
··· 143 return v.Slice(start, end).Interface() 144 }, 145 "markdown": func(text string) template.HTML { 146 + rctx := &markup.RenderContext{} 147 + return template.HTML(rctx.RenderMarkdown(text)) 148 }, 149 "isNil": func(t any) bool { 150 // returns false for other "zero" values
+4 -11
appview/pages/markup/markdown.go
··· 19 const ( 20 // RendererTypeRepoMarkdown is for repository documentation markdown files 21 RendererTypeRepoMarkdown RendererType = iota 22 - // RendererTypeIssueComment is for issue comments 23 - RendererTypeIssueComment 24 - // RendererTypePullComment is for pull request comments 25 - RendererTypePullComment 26 - // RendererTypeDefault is the default renderer with minimal transformations 27 - RendererTypeDefault 28 ) 29 30 // RenderContext holds the contextual data for rendering markdown. 31 - // It can be initialized empty, and that'll skip any transformations 32 - // and use the default renderer (RendererTypeDefault). 33 type RenderContext struct { 34 Ref string 35 FullRepoName string ··· 73 74 switch a.rctx.RendererType { 75 case RendererTypeRepoMarkdown: 76 - a.rctx.relativeLinkTransformer(n.(*ast.Link)) 77 - case RendererTypeDefault: 78 - a.rctx.relativeLinkTransformer(n.(*ast.Link)) 79 // more types here like RendererTypeIssue/Pull etc. 80 } 81
··· 19 const ( 20 // RendererTypeRepoMarkdown is for repository documentation markdown files 21 RendererTypeRepoMarkdown RendererType = iota 22 ) 23 24 // RenderContext holds the contextual data for rendering markdown. 25 + // It can be initialized empty, and that'll skip any transformations. 26 type RenderContext struct { 27 Ref string 28 FullRepoName string ··· 66 67 switch a.rctx.RendererType { 68 case RendererTypeRepoMarkdown: 69 + if v, ok := n.(*ast.Link); ok { 70 + a.rctx.relativeLinkTransformer(v) 71 + } 72 // more types here like RendererTypeIssue/Pull etc. 73 } 74
+13 -2
appview/pages/pages.go
··· 366 Roles RolesInRepo 367 Source *db.Repo 368 SourceHandle string 369 DisableFork bool 370 } 371 ··· 478 return p.executeRepo("repo/empty", w, params) 479 } 480 481 if params.ReadmeFileName != "" { 482 var htmlString string 483 ext := filepath.Ext(params.ReadmeFileName) 484 switch ext { 485 case ".md", ".markdown", ".mdown", ".mkdn", ".mkd": 486 - htmlString = markup.RenderMarkdown(params.Readme) 487 params.Raw = false 488 params.HTMLReadme = template.HTML(bluemonday.UGCPolicy().Sanitize(htmlString)) 489 default: ··· 601 if params.ShowRendered { 602 switch markup.GetFormat(params.Path) { 603 case markup.FormatMarkdown: 604 - params.RenderedContents = template.HTML(markup.RenderMarkdown(params.Contents)) 605 } 606 } 607
··· 366 Roles RolesInRepo 367 Source *db.Repo 368 SourceHandle string 369 + Ref string 370 DisableFork bool 371 } 372 ··· 479 return p.executeRepo("repo/empty", w, params) 480 } 481 482 + rctx := markup.RenderContext{ 483 + Ref: params.RepoInfo.Ref, 484 + FullRepoName: params.RepoInfo.FullName(), 485 + } 486 + 487 if params.ReadmeFileName != "" { 488 var htmlString string 489 ext := filepath.Ext(params.ReadmeFileName) 490 switch ext { 491 case ".md", ".markdown", ".mdown", ".mkdn", ".mkd": 492 + htmlString = rctx.RenderMarkdown(params.Readme) 493 params.Raw = false 494 params.HTMLReadme = template.HTML(bluemonday.UGCPolicy().Sanitize(htmlString)) 495 default: ··· 607 if params.ShowRendered { 608 switch markup.GetFormat(params.Path) { 609 case markup.FormatMarkdown: 610 + rctx := markup.RenderContext{ 611 + Ref: params.RepoInfo.Ref, 612 + FullRepoName: params.RepoInfo.FullName(), 613 + RendererType: markup.RendererTypeRepoMarkdown, 614 + } 615 + params.RenderedContents = template.HTML(rctx.RenderMarkdown(params.Contents)) 616 } 617 } 618
+2 -2
appview/state/middleware.go
··· 61 http.Error(w, "Forbiden", http.StatusUnauthorized) 62 return 63 } 64 - f, err := fullyResolvedRepo(r) 65 if err != nil { 66 http.Error(w, "malformed url", http.StatusBadRequest) 67 return ··· 148 func ResolvePull(s *State) middleware.Middleware { 149 return func(next http.Handler) http.Handler { 150 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 151 - f, err := fullyResolvedRepo(r) 152 if err != nil { 153 log.Println("failed to fully resolve repo", err) 154 http.Error(w, "invalid repo url", http.StatusNotFound)
··· 61 http.Error(w, "Forbiden", http.StatusUnauthorized) 62 return 63 } 64 + f, err := s.fullyResolvedRepo(r) 65 if err != nil { 66 http.Error(w, "malformed url", http.StatusBadRequest) 67 return ··· 148 func ResolvePull(s *State) middleware.Middleware { 149 return func(next http.Handler) http.Handler { 150 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 151 + f, err := s.fullyResolvedRepo(r) 152 if err != nil { 153 log.Println("failed to fully resolve repo", err) 154 http.Error(w, "invalid repo url", http.StatusNotFound)
+19 -19
appview/state/pull.go
··· 30 switch r.Method { 31 case http.MethodGet: 32 user := s.auth.GetUser(r) 33 - f, err := fullyResolvedRepo(r) 34 if err != nil { 35 log.Println("failed to get repo and knot", err) 36 return ··· 74 75 func (s *State) RepoSinglePull(w http.ResponseWriter, r *http.Request) { 76 user := s.auth.GetUser(r) 77 - f, err := fullyResolvedRepo(r) 78 if err != nil { 79 log.Println("failed to get repo and knot", err) 80 return ··· 251 252 func (s *State) RepoPullPatch(w http.ResponseWriter, r *http.Request) { 253 user := s.auth.GetUser(r) 254 - f, err := fullyResolvedRepo(r) 255 if err != nil { 256 log.Println("failed to get repo and knot", err) 257 return ··· 300 func (s *State) RepoPullInterdiff(w http.ResponseWriter, r *http.Request) { 301 user := s.auth.GetUser(r) 302 303 - f, err := fullyResolvedRepo(r) 304 if err != nil { 305 log.Println("failed to get repo and knot", err) 306 return ··· 408 state = db.PullMerged 409 } 410 411 - f, err := fullyResolvedRepo(r) 412 if err != nil { 413 log.Println("failed to get repo and knot", err) 414 return ··· 462 463 func (s *State) PullComment(w http.ResponseWriter, r *http.Request) { 464 user := s.auth.GetUser(r) 465 - f, err := fullyResolvedRepo(r) 466 if err != nil { 467 log.Println("failed to get repo and knot", err) 468 return ··· 569 570 func (s *State) NewPull(w http.ResponseWriter, r *http.Request) { 571 user := s.auth.GetUser(r) 572 - f, err := fullyResolvedRepo(r) 573 if err != nil { 574 log.Println("failed to get repo and knot", err) 575 return ··· 904 } 905 906 func (s *State) ValidatePatch(w http.ResponseWriter, r *http.Request) { 907 - _, err := fullyResolvedRepo(r) 908 if err != nil { 909 log.Println("failed to get repo and knot", err) 910 return ··· 930 931 func (s *State) PatchUploadFragment(w http.ResponseWriter, r *http.Request) { 932 user := s.auth.GetUser(r) 933 - f, err := fullyResolvedRepo(r) 934 if err != nil { 935 log.Println("failed to get repo and knot", err) 936 return ··· 943 944 func (s *State) CompareBranchesFragment(w http.ResponseWriter, r *http.Request) { 945 user := s.auth.GetUser(r) 946 - f, err := fullyResolvedRepo(r) 947 if err != nil { 948 log.Println("failed to get repo and knot", err) 949 return ··· 983 984 func (s *State) CompareForksFragment(w http.ResponseWriter, r *http.Request) { 985 user := s.auth.GetUser(r) 986 - f, err := fullyResolvedRepo(r) 987 if err != nil { 988 log.Println("failed to get repo and knot", err) 989 return ··· 1004 func (s *State) CompareForksBranchesFragment(w http.ResponseWriter, r *http.Request) { 1005 user := s.auth.GetUser(r) 1006 1007 - f, err := fullyResolvedRepo(r) 1008 if err != nil { 1009 log.Println("failed to get repo and knot", err) 1010 return ··· 1082 1083 func (s *State) ResubmitPull(w http.ResponseWriter, r *http.Request) { 1084 user := s.auth.GetUser(r) 1085 - f, err := fullyResolvedRepo(r) 1086 if err != nil { 1087 log.Println("failed to get repo and knot", err) 1088 return ··· 1126 return 1127 } 1128 1129 - f, err := fullyResolvedRepo(r) 1130 if err != nil { 1131 log.Println("failed to get repo and knot", err) 1132 return ··· 1209 return 1210 } 1211 1212 - f, err := fullyResolvedRepo(r) 1213 if err != nil { 1214 log.Println("failed to get repo and knot", err) 1215 return ··· 1322 return 1323 } 1324 1325 - f, err := fullyResolvedRepo(r) 1326 if err != nil { 1327 log.Println("failed to get repo and knot", err) 1328 return ··· 1470 } 1471 1472 func (s *State) MergePull(w http.ResponseWriter, r *http.Request) { 1473 - f, err := fullyResolvedRepo(r) 1474 if err != nil { 1475 log.Println("failed to resolve repo:", err) 1476 s.pages.Notice(w, "pull-merge-error", "Failed to merge pull request. Try again later.") ··· 1535 func (s *State) ClosePull(w http.ResponseWriter, r *http.Request) { 1536 user := s.auth.GetUser(r) 1537 1538 - f, err := fullyResolvedRepo(r) 1539 if err != nil { 1540 log.Println("malformed middleware") 1541 return ··· 1589 func (s *State) ReopenPull(w http.ResponseWriter, r *http.Request) { 1590 user := s.auth.GetUser(r) 1591 1592 - f, err := fullyResolvedRepo(r) 1593 if err != nil { 1594 log.Println("failed to resolve repo", err) 1595 s.pages.Notice(w, "pull-reopen", "Failed to reopen pull.")
··· 30 switch r.Method { 31 case http.MethodGet: 32 user := s.auth.GetUser(r) 33 + f, err := s.fullyResolvedRepo(r) 34 if err != nil { 35 log.Println("failed to get repo and knot", err) 36 return ··· 74 75 func (s *State) RepoSinglePull(w http.ResponseWriter, r *http.Request) { 76 user := s.auth.GetUser(r) 77 + f, err := s.fullyResolvedRepo(r) 78 if err != nil { 79 log.Println("failed to get repo and knot", err) 80 return ··· 251 252 func (s *State) RepoPullPatch(w http.ResponseWriter, r *http.Request) { 253 user := s.auth.GetUser(r) 254 + f, err := s.fullyResolvedRepo(r) 255 if err != nil { 256 log.Println("failed to get repo and knot", err) 257 return ··· 300 func (s *State) RepoPullInterdiff(w http.ResponseWriter, r *http.Request) { 301 user := s.auth.GetUser(r) 302 303 + f, err := s.fullyResolvedRepo(r) 304 if err != nil { 305 log.Println("failed to get repo and knot", err) 306 return ··· 408 state = db.PullMerged 409 } 410 411 + f, err := s.fullyResolvedRepo(r) 412 if err != nil { 413 log.Println("failed to get repo and knot", err) 414 return ··· 462 463 func (s *State) PullComment(w http.ResponseWriter, r *http.Request) { 464 user := s.auth.GetUser(r) 465 + f, err := s.fullyResolvedRepo(r) 466 if err != nil { 467 log.Println("failed to get repo and knot", err) 468 return ··· 569 570 func (s *State) NewPull(w http.ResponseWriter, r *http.Request) { 571 user := s.auth.GetUser(r) 572 + f, err := s.fullyResolvedRepo(r) 573 if err != nil { 574 log.Println("failed to get repo and knot", err) 575 return ··· 904 } 905 906 func (s *State) ValidatePatch(w http.ResponseWriter, r *http.Request) { 907 + _, err := s.fullyResolvedRepo(r) 908 if err != nil { 909 log.Println("failed to get repo and knot", err) 910 return ··· 930 931 func (s *State) PatchUploadFragment(w http.ResponseWriter, r *http.Request) { 932 user := s.auth.GetUser(r) 933 + f, err := s.fullyResolvedRepo(r) 934 if err != nil { 935 log.Println("failed to get repo and knot", err) 936 return ··· 943 944 func (s *State) CompareBranchesFragment(w http.ResponseWriter, r *http.Request) { 945 user := s.auth.GetUser(r) 946 + f, err := s.fullyResolvedRepo(r) 947 if err != nil { 948 log.Println("failed to get repo and knot", err) 949 return ··· 983 984 func (s *State) CompareForksFragment(w http.ResponseWriter, r *http.Request) { 985 user := s.auth.GetUser(r) 986 + f, err := s.fullyResolvedRepo(r) 987 if err != nil { 988 log.Println("failed to get repo and knot", err) 989 return ··· 1004 func (s *State) CompareForksBranchesFragment(w http.ResponseWriter, r *http.Request) { 1005 user := s.auth.GetUser(r) 1006 1007 + f, err := s.fullyResolvedRepo(r) 1008 if err != nil { 1009 log.Println("failed to get repo and knot", err) 1010 return ··· 1082 1083 func (s *State) ResubmitPull(w http.ResponseWriter, r *http.Request) { 1084 user := s.auth.GetUser(r) 1085 + f, err := s.fullyResolvedRepo(r) 1086 if err != nil { 1087 log.Println("failed to get repo and knot", err) 1088 return ··· 1126 return 1127 } 1128 1129 + f, err := s.fullyResolvedRepo(r) 1130 if err != nil { 1131 log.Println("failed to get repo and knot", err) 1132 return ··· 1209 return 1210 } 1211 1212 + f, err := s.fullyResolvedRepo(r) 1213 if err != nil { 1214 log.Println("failed to get repo and knot", err) 1215 return ··· 1322 return 1323 } 1324 1325 + f, err := s.fullyResolvedRepo(r) 1326 if err != nil { 1327 log.Println("failed to get repo and knot", err) 1328 return ··· 1470 } 1471 1472 func (s *State) MergePull(w http.ResponseWriter, r *http.Request) { 1473 + f, err := s.fullyResolvedRepo(r) 1474 if err != nil { 1475 log.Println("failed to resolve repo:", err) 1476 s.pages.Notice(w, "pull-merge-error", "Failed to merge pull request. Try again later.") ··· 1535 func (s *State) ClosePull(w http.ResponseWriter, r *http.Request) { 1536 user := s.auth.GetUser(r) 1537 1538 + f, err := s.fullyResolvedRepo(r) 1539 if err != nil { 1540 log.Println("malformed middleware") 1541 return ··· 1589 func (s *State) ReopenPull(w http.ResponseWriter, r *http.Request) { 1590 user := s.auth.GetUser(r) 1591 1592 + f, err := s.fullyResolvedRepo(r) 1593 if err != nil { 1594 log.Println("failed to resolve repo", err) 1595 s.pages.Notice(w, "pull-reopen", "Failed to reopen pull.")
+35 -40
appview/state/repo.go
··· 37 38 func (s *State) RepoIndex(w http.ResponseWriter, r *http.Request) { 39 ref := chi.URLParam(r, "ref") 40 - f, err := fullyResolvedRepo(r) 41 if err != nil { 42 log.Println("failed to fully resolve repo", err) 43 return ··· 129 } 130 131 func (s *State) RepoLog(w http.ResponseWriter, r *http.Request) { 132 - f, err := fullyResolvedRepo(r) 133 if err != nil { 134 log.Println("failed to fully resolve repo", err) 135 return ··· 210 } 211 212 func (s *State) RepoDescriptionEdit(w http.ResponseWriter, r *http.Request) { 213 - f, err := fullyResolvedRepo(r) 214 if err != nil { 215 log.Println("failed to get repo and knot", err) 216 w.WriteHeader(http.StatusBadRequest) ··· 225 } 226 227 func (s *State) RepoDescription(w http.ResponseWriter, r *http.Request) { 228 - f, err := fullyResolvedRepo(r) 229 if err != nil { 230 log.Println("failed to get repo and knot", err) 231 w.WriteHeader(http.StatusBadRequest) ··· 304 } 305 306 func (s *State) RepoCommit(w http.ResponseWriter, r *http.Request) { 307 - f, err := fullyResolvedRepo(r) 308 if err != nil { 309 log.Println("failed to fully resolve repo", err) 310 return ··· 350 } 351 352 func (s *State) RepoTree(w http.ResponseWriter, r *http.Request) { 353 - f, err := fullyResolvedRepo(r) 354 if err != nil { 355 log.Println("failed to fully resolve repo", err) 356 return ··· 378 err = json.Unmarshal(body, &result) 379 if err != nil { 380 log.Println("failed to parse response:", err) 381 return 382 } 383 ··· 406 } 407 408 func (s *State) RepoTags(w http.ResponseWriter, r *http.Request) { 409 - f, err := fullyResolvedRepo(r) 410 if err != nil { 411 log.Println("failed to get repo and knot", err) 412 return ··· 447 } 448 449 func (s *State) RepoBranches(w http.ResponseWriter, r *http.Request) { 450 - f, err := fullyResolvedRepo(r) 451 if err != nil { 452 log.Println("failed to get repo and knot", err) 453 return ··· 502 } 503 504 func (s *State) RepoBlob(w http.ResponseWriter, r *http.Request) { 505 - f, err := fullyResolvedRepo(r) 506 if err != nil { 507 log.Println("failed to get repo and knot", err) 508 return ··· 562 } 563 564 func (s *State) RepoBlobRaw(w http.ResponseWriter, r *http.Request) { 565 - f, err := fullyResolvedRepo(r) 566 if err != nil { 567 log.Println("failed to get repo and knot", err) 568 return ··· 606 } 607 608 func (s *State) AddCollaborator(w http.ResponseWriter, r *http.Request) { 609 - f, err := fullyResolvedRepo(r) 610 if err != nil { 611 log.Println("failed to get repo and knot", err) 612 return ··· 697 func (s *State) DeleteRepo(w http.ResponseWriter, r *http.Request) { 698 user := s.auth.GetUser(r) 699 700 - f, err := fullyResolvedRepo(r) 701 if err != nil { 702 log.Println("failed to get repo and knot", err) 703 return ··· 801 } 802 803 func (s *State) SetDefaultBranch(w http.ResponseWriter, r *http.Request) { 804 - f, err := fullyResolvedRepo(r) 805 if err != nil { 806 log.Println("failed to get repo and knot", err) 807 return ··· 840 } 841 842 func (s *State) RepoSettings(w http.ResponseWriter, r *http.Request) { 843 - f, err := fullyResolvedRepo(r) 844 if err != nil { 845 log.Println("failed to get repo and knot", err) 846 return ··· 891 } 892 } 893 894 - resp, err = us.DefaultBranch(f.OwnerDid(), f.RepoName) 895 if err != nil { 896 log.Println("failed to reach knotserver", err) 897 } else { 898 - defer resp.Body.Close() 899 - 900 - body, err := io.ReadAll(resp.Body) 901 - if err != nil { 902 - log.Printf("Error reading response body: %v", err) 903 - } else { 904 - var result types.RepoDefaultBranchResponse 905 - err = json.Unmarshal(body, &result) 906 - if err != nil { 907 - log.Println("failed to parse response:", err) 908 - } else { 909 - defaultBranch = result.Branch 910 - } 911 - } 912 } 913 } 914 - 915 s.pages.RepoSettings(w, pages.RepoSettingsParams{ 916 LoggedInUser: user, 917 RepoInfo: f.RepoInfo(s, user), ··· 930 RepoAt syntax.ATURI 931 Description string 932 CreatedAt string 933 } 934 935 func (f *FullyResolvedRepo) OwnerDid() string { ··· 1082 Name: f.RepoName, 1083 RepoAt: f.RepoAt, 1084 Description: f.Description, 1085 IsStarred: isStarred, 1086 Knot: knot, 1087 Roles: RolesInRepo(s, u, f), ··· 1103 1104 func (s *State) RepoSingleIssue(w http.ResponseWriter, r *http.Request) { 1105 user := s.auth.GetUser(r) 1106 - f, err := fullyResolvedRepo(r) 1107 if err != nil { 1108 log.Println("failed to get repo and knot", err) 1109 return ··· 1157 1158 func (s *State) CloseIssue(w http.ResponseWriter, r *http.Request) { 1159 user := s.auth.GetUser(r) 1160 - f, err := fullyResolvedRepo(r) 1161 if err != nil { 1162 log.Println("failed to get repo and knot", err) 1163 return ··· 1229 1230 func (s *State) ReopenIssue(w http.ResponseWriter, r *http.Request) { 1231 user := s.auth.GetUser(r) 1232 - f, err := fullyResolvedRepo(r) 1233 if err != nil { 1234 log.Println("failed to get repo and knot", err) 1235 return ··· 1277 1278 func (s *State) NewIssueComment(w http.ResponseWriter, r *http.Request) { 1279 user := s.auth.GetUser(r) 1280 - f, err := fullyResolvedRepo(r) 1281 if err != nil { 1282 log.Println("failed to get repo and knot", err) 1283 return ··· 1356 1357 func (s *State) IssueComment(w http.ResponseWriter, r *http.Request) { 1358 user := s.auth.GetUser(r) 1359 - f, err := fullyResolvedRepo(r) 1360 if err != nil { 1361 log.Println("failed to get repo and knot", err) 1362 return ··· 1415 1416 func (s *State) EditIssueComment(w http.ResponseWriter, r *http.Request) { 1417 user := s.auth.GetUser(r) 1418 - f, err := fullyResolvedRepo(r) 1419 if err != nil { 1420 log.Println("failed to get repo and knot", err) 1421 return ··· 1540 1541 func (s *State) DeleteIssueComment(w http.ResponseWriter, r *http.Request) { 1542 user := s.auth.GetUser(r) 1543 - f, err := fullyResolvedRepo(r) 1544 if err != nil { 1545 log.Println("failed to get repo and knot", err) 1546 return ··· 1645 } 1646 1647 user := s.auth.GetUser(r) 1648 - f, err := fullyResolvedRepo(r) 1649 if err != nil { 1650 log.Println("failed to get repo and knot", err) 1651 return ··· 1686 func (s *State) NewIssue(w http.ResponseWriter, r *http.Request) { 1687 user := s.auth.GetUser(r) 1688 1689 - f, err := fullyResolvedRepo(r) 1690 if err != nil { 1691 log.Println("failed to get repo and knot", err) 1692 return ··· 1768 1769 func (s *State) ForkRepo(w http.ResponseWriter, r *http.Request) { 1770 user := s.auth.GetUser(r) 1771 - f, err := fullyResolvedRepo(r) 1772 if err != nil { 1773 log.Printf("failed to resolve source repo: %v", err) 1774 return
··· 37 38 func (s *State) RepoIndex(w http.ResponseWriter, r *http.Request) { 39 ref := chi.URLParam(r, "ref") 40 + f, err := s.fullyResolvedRepo(r) 41 if err != nil { 42 log.Println("failed to fully resolve repo", err) 43 return ··· 129 } 130 131 func (s *State) RepoLog(w http.ResponseWriter, r *http.Request) { 132 + f, err := s.fullyResolvedRepo(r) 133 if err != nil { 134 log.Println("failed to fully resolve repo", err) 135 return ··· 210 } 211 212 func (s *State) RepoDescriptionEdit(w http.ResponseWriter, r *http.Request) { 213 + f, err := s.fullyResolvedRepo(r) 214 if err != nil { 215 log.Println("failed to get repo and knot", err) 216 w.WriteHeader(http.StatusBadRequest) ··· 225 } 226 227 func (s *State) RepoDescription(w http.ResponseWriter, r *http.Request) { 228 + f, err := s.fullyResolvedRepo(r) 229 if err != nil { 230 log.Println("failed to get repo and knot", err) 231 w.WriteHeader(http.StatusBadRequest) ··· 304 } 305 306 func (s *State) RepoCommit(w http.ResponseWriter, r *http.Request) { 307 + f, err := s.fullyResolvedRepo(r) 308 if err != nil { 309 log.Println("failed to fully resolve repo", err) 310 return ··· 350 } 351 352 func (s *State) RepoTree(w http.ResponseWriter, r *http.Request) { 353 + f, err := s.fullyResolvedRepo(r) 354 if err != nil { 355 log.Println("failed to fully resolve repo", err) 356 return ··· 378 err = json.Unmarshal(body, &result) 379 if err != nil { 380 log.Println("failed to parse response:", err) 381 + return 382 + } 383 + 384 + // redirects tree paths trying to access a blob; in this case the result.Files is unpopulated, 385 + // so we can safely redirect to the "parent" (which is the same file). 386 + if len(result.Files) == 0 && result.Parent == treePath { 387 + http.Redirect(w, r, fmt.Sprintf("/%s/blob/%s/%s", f.OwnerSlashRepo(), ref, result.Parent), http.StatusFound) 388 return 389 } 390 ··· 413 } 414 415 func (s *State) RepoTags(w http.ResponseWriter, r *http.Request) { 416 + f, err := s.fullyResolvedRepo(r) 417 if err != nil { 418 log.Println("failed to get repo and knot", err) 419 return ··· 454 } 455 456 func (s *State) RepoBranches(w http.ResponseWriter, r *http.Request) { 457 + f, err := s.fullyResolvedRepo(r) 458 if err != nil { 459 log.Println("failed to get repo and knot", err) 460 return ··· 509 } 510 511 func (s *State) RepoBlob(w http.ResponseWriter, r *http.Request) { 512 + f, err := s.fullyResolvedRepo(r) 513 if err != nil { 514 log.Println("failed to get repo and knot", err) 515 return ··· 569 } 570 571 func (s *State) RepoBlobRaw(w http.ResponseWriter, r *http.Request) { 572 + f, err := s.fullyResolvedRepo(r) 573 if err != nil { 574 log.Println("failed to get repo and knot", err) 575 return ··· 613 } 614 615 func (s *State) AddCollaborator(w http.ResponseWriter, r *http.Request) { 616 + f, err := s.fullyResolvedRepo(r) 617 if err != nil { 618 log.Println("failed to get repo and knot", err) 619 return ··· 704 func (s *State) DeleteRepo(w http.ResponseWriter, r *http.Request) { 705 user := s.auth.GetUser(r) 706 707 + f, err := s.fullyResolvedRepo(r) 708 if err != nil { 709 log.Println("failed to get repo and knot", err) 710 return ··· 808 } 809 810 func (s *State) SetDefaultBranch(w http.ResponseWriter, r *http.Request) { 811 + f, err := s.fullyResolvedRepo(r) 812 if err != nil { 813 log.Println("failed to get repo and knot", err) 814 return ··· 847 } 848 849 func (s *State) RepoSettings(w http.ResponseWriter, r *http.Request) { 850 + f, err := s.fullyResolvedRepo(r) 851 if err != nil { 852 log.Println("failed to get repo and knot", err) 853 return ··· 898 } 899 } 900 901 + defaultBranchResp, err := us.DefaultBranch(f.OwnerDid(), f.RepoName) 902 if err != nil { 903 log.Println("failed to reach knotserver", err) 904 } else { 905 + defaultBranch = defaultBranchResp.Branch 906 } 907 } 908 s.pages.RepoSettings(w, pages.RepoSettingsParams{ 909 LoggedInUser: user, 910 RepoInfo: f.RepoInfo(s, user), ··· 923 RepoAt syntax.ATURI 924 Description string 925 CreatedAt string 926 + Ref string 927 } 928 929 func (f *FullyResolvedRepo) OwnerDid() string { ··· 1076 Name: f.RepoName, 1077 RepoAt: f.RepoAt, 1078 Description: f.Description, 1079 + Ref: f.Ref, 1080 IsStarred: isStarred, 1081 Knot: knot, 1082 Roles: RolesInRepo(s, u, f), ··· 1098 1099 func (s *State) RepoSingleIssue(w http.ResponseWriter, r *http.Request) { 1100 user := s.auth.GetUser(r) 1101 + f, err := s.fullyResolvedRepo(r) 1102 if err != nil { 1103 log.Println("failed to get repo and knot", err) 1104 return ··· 1152 1153 func (s *State) CloseIssue(w http.ResponseWriter, r *http.Request) { 1154 user := s.auth.GetUser(r) 1155 + f, err := s.fullyResolvedRepo(r) 1156 if err != nil { 1157 log.Println("failed to get repo and knot", err) 1158 return ··· 1224 1225 func (s *State) ReopenIssue(w http.ResponseWriter, r *http.Request) { 1226 user := s.auth.GetUser(r) 1227 + f, err := s.fullyResolvedRepo(r) 1228 if err != nil { 1229 log.Println("failed to get repo and knot", err) 1230 return ··· 1272 1273 func (s *State) NewIssueComment(w http.ResponseWriter, r *http.Request) { 1274 user := s.auth.GetUser(r) 1275 + f, err := s.fullyResolvedRepo(r) 1276 if err != nil { 1277 log.Println("failed to get repo and knot", err) 1278 return ··· 1351 1352 func (s *State) IssueComment(w http.ResponseWriter, r *http.Request) { 1353 user := s.auth.GetUser(r) 1354 + f, err := s.fullyResolvedRepo(r) 1355 if err != nil { 1356 log.Println("failed to get repo and knot", err) 1357 return ··· 1410 1411 func (s *State) EditIssueComment(w http.ResponseWriter, r *http.Request) { 1412 user := s.auth.GetUser(r) 1413 + f, err := s.fullyResolvedRepo(r) 1414 if err != nil { 1415 log.Println("failed to get repo and knot", err) 1416 return ··· 1535 1536 func (s *State) DeleteIssueComment(w http.ResponseWriter, r *http.Request) { 1537 user := s.auth.GetUser(r) 1538 + f, err := s.fullyResolvedRepo(r) 1539 if err != nil { 1540 log.Println("failed to get repo and knot", err) 1541 return ··· 1640 } 1641 1642 user := s.auth.GetUser(r) 1643 + f, err := s.fullyResolvedRepo(r) 1644 if err != nil { 1645 log.Println("failed to get repo and knot", err) 1646 return ··· 1681 func (s *State) NewIssue(w http.ResponseWriter, r *http.Request) { 1682 user := s.auth.GetUser(r) 1683 1684 + f, err := s.fullyResolvedRepo(r) 1685 if err != nil { 1686 log.Println("failed to get repo and knot", err) 1687 return ··· 1763 1764 func (s *State) ForkRepo(w http.ResponseWriter, r *http.Request) { 1765 user := s.auth.GetUser(r) 1766 + f, err := s.fullyResolvedRepo(r) 1767 if err != nil { 1768 log.Printf("failed to resolve source repo: %v", err) 1769 return
+18 -1
appview/state/repo_util.go
··· 17 "tangled.sh/tangled.sh/core/appview/pages" 18 ) 19 20 - func fullyResolvedRepo(r *http.Request) (*FullyResolvedRepo, error) { 21 repoName := chi.URLParam(r, "repo") 22 knot, ok := r.Context().Value("knot").(string) 23 if !ok { ··· 42 return nil, fmt.Errorf("malformed middleware") 43 } 44 45 // pass through values from the middleware 46 description, ok := r.Context().Value("repoDescription").(string) 47 addedAt, ok := r.Context().Value("repoAddedAt").(string) ··· 53 RepoAt: parsedRepoAt, 54 Description: description, 55 CreatedAt: addedAt, 56 }, nil 57 } 58
··· 17 "tangled.sh/tangled.sh/core/appview/pages" 18 ) 19 20 + func (s *State) fullyResolvedRepo(r *http.Request) (*FullyResolvedRepo, error) { 21 repoName := chi.URLParam(r, "repo") 22 knot, ok := r.Context().Value("knot").(string) 23 if !ok { ··· 42 return nil, fmt.Errorf("malformed middleware") 43 } 44 45 + ref := chi.URLParam(r, "ref") 46 + 47 + if ref == "" { 48 + us, err := NewUnsignedClient(knot, s.config.Dev) 49 + if err != nil { 50 + return nil, err 51 + } 52 + 53 + defaultBranch, err := us.DefaultBranch(id.DID.String(), repoName) 54 + if err != nil { 55 + return nil, err 56 + } 57 + 58 + ref = defaultBranch.Branch 59 + } 60 + 61 // pass through values from the middleware 62 description, ok := r.Context().Value("repoDescription").(string) 63 addedAt, ok := r.Context().Value("repoAddedAt").(string) ··· 69 RepoAt: parsedRepoAt, 70 Description: description, 71 CreatedAt: addedAt, 72 + Ref: ref, 73 }, nil 74 } 75
+13 -2
appview/state/signer.go
··· 380 return us.client.Do(req) 381 } 382 383 - func (us *UnsignedClient) DefaultBranch(ownerDid, repoName string) (*http.Response, error) { 384 const ( 385 Method = "GET" 386 ) ··· 392 return nil, err 393 } 394 395 - return us.client.Do(req) 396 } 397 398 func (us *UnsignedClient) Capabilities() (*types.Capabilities, error) {
··· 380 return us.client.Do(req) 381 } 382 383 + func (us *UnsignedClient) DefaultBranch(ownerDid, repoName string) (*types.RepoDefaultBranchResponse, error) { 384 const ( 385 Method = "GET" 386 ) ··· 392 return nil, err 393 } 394 395 + resp, err := us.client.Do(req) 396 + if err != nil { 397 + return nil, err 398 + } 399 + defer resp.Body.Close() 400 + 401 + var defaultBranch types.RepoDefaultBranchResponse 402 + if err := json.NewDecoder(resp.Body).Decode(&defaultBranch); err != nil { 403 + return nil, err 404 + } 405 + 406 + return &defaultBranch, nil 407 } 408 409 func (us *UnsignedClient) Capabilities() (*types.Capabilities, error) {