forked from tangled.org/core
Monorepo for Tangled — https://tangled.org
at master 5.7 kB view raw
1package repo 2 3import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "net/url" 8 "strconv" 9 10 "tangled.org/core/api/tangled" 11 "tangled.org/core/appview/commitverify" 12 "tangled.org/core/appview/db" 13 "tangled.org/core/appview/models" 14 "tangled.org/core/appview/pages" 15 xrpcclient "tangled.org/core/appview/xrpcclient" 16 "tangled.org/core/types" 17 18 indigoxrpc "github.com/bluesky-social/indigo/xrpc" 19 "github.com/go-chi/chi/v5" 20 "github.com/go-git/go-git/v5/plumbing" 21) 22 23func (rp *Repo) Log(w http.ResponseWriter, r *http.Request) { 24 l := rp.logger.With("handler", "RepoLog") 25 26 f, err := rp.repoResolver.Resolve(r) 27 if err != nil { 28 l.Error("failed to fully resolve repo", "err", err) 29 return 30 } 31 32 page := 1 33 if r.URL.Query().Get("page") != "" { 34 page, err = strconv.Atoi(r.URL.Query().Get("page")) 35 if err != nil { 36 page = 1 37 } 38 } 39 40 ref := chi.URLParam(r, "ref") 41 ref, _ = url.PathUnescape(ref) 42 43 scheme := "http" 44 if !rp.config.Core.Dev { 45 scheme = "https" 46 } 47 host := fmt.Sprintf("%s://%s", scheme, f.Knot) 48 xrpcc := &indigoxrpc.Client{ 49 Host: host, 50 } 51 52 limit := int64(60) 53 cursor := "" 54 if page > 1 { 55 // Convert page number to cursor (offset) 56 offset := (page - 1) * int(limit) 57 cursor = strconv.Itoa(offset) 58 } 59 60 repo := fmt.Sprintf("%s/%s", f.Did, f.Name) 61 xrpcBytes, err := tangled.RepoLog(r.Context(), xrpcc, cursor, limit, "", ref, repo) 62 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 63 l.Error("failed to call XRPC repo.log", "err", xrpcerr) 64 rp.pages.Error503(w) 65 return 66 } 67 68 var xrpcResp types.RepoLogResponse 69 if err := json.Unmarshal(xrpcBytes, &xrpcResp); err != nil { 70 l.Error("failed to decode XRPC response", "err", err) 71 rp.pages.Error503(w) 72 return 73 } 74 75 tagBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo) 76 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 77 l.Error("failed to call XRPC repo.tags", "err", xrpcerr) 78 rp.pages.Error503(w) 79 return 80 } 81 82 tagMap := make(map[string][]string) 83 if tagBytes != nil { 84 var tagResp types.RepoTagsResponse 85 if err := json.Unmarshal(tagBytes, &tagResp); err == nil { 86 for _, tag := range tagResp.Tags { 87 hash := tag.Hash 88 if tag.Tag != nil { 89 hash = tag.Tag.Target.String() 90 } 91 tagMap[hash] = append(tagMap[hash], tag.Name) 92 } 93 } 94 } 95 96 branchBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo) 97 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 98 l.Error("failed to call XRPC repo.branches", "err", xrpcerr) 99 rp.pages.Error503(w) 100 return 101 } 102 103 if branchBytes != nil { 104 var branchResp types.RepoBranchesResponse 105 if err := json.Unmarshal(branchBytes, &branchResp); err == nil { 106 for _, branch := range branchResp.Branches { 107 tagMap[branch.Hash] = append(tagMap[branch.Hash], branch.Name) 108 } 109 } 110 } 111 112 user := rp.oauth.GetUser(r) 113 114 emailToDidMap, err := db.GetEmailToDid(rp.db, uniqueEmails(xrpcResp.Commits), true) 115 if err != nil { 116 l.Error("failed to fetch email to did mapping", "err", err) 117 } 118 119 vc, err := commitverify.GetVerifiedCommits(rp.db, emailToDidMap, xrpcResp.Commits) 120 if err != nil { 121 l.Error("failed to GetVerifiedObjectCommits", "err", err) 122 } 123 124 var shas []string 125 for _, c := range xrpcResp.Commits { 126 shas = append(shas, c.Hash.String()) 127 } 128 pipelines, err := getPipelineStatuses(rp.db, f, shas) 129 if err != nil { 130 l.Error("failed to getPipelineStatuses", "err", err) 131 // non-fatal 132 } 133 134 rp.pages.RepoLog(w, pages.RepoLogParams{ 135 LoggedInUser: user, 136 TagMap: tagMap, 137 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 138 RepoLogResponse: xrpcResp, 139 EmailToDid: emailToDidMap, 140 VerifiedCommits: vc, 141 Pipelines: pipelines, 142 }) 143} 144 145func (rp *Repo) Commit(w http.ResponseWriter, r *http.Request) { 146 l := rp.logger.With("handler", "RepoCommit") 147 148 f, err := rp.repoResolver.Resolve(r) 149 if err != nil { 150 l.Error("failed to fully resolve repo", "err", err) 151 return 152 } 153 ref := chi.URLParam(r, "ref") 154 ref, _ = url.PathUnescape(ref) 155 156 var diffOpts types.DiffOpts 157 if d := r.URL.Query().Get("diff"); d == "split" { 158 diffOpts.Split = true 159 } 160 161 if !plumbing.IsHash(ref) { 162 rp.pages.Error404(w) 163 return 164 } 165 166 scheme := "http" 167 if !rp.config.Core.Dev { 168 scheme = "https" 169 } 170 host := fmt.Sprintf("%s://%s", scheme, f.Knot) 171 xrpcc := &indigoxrpc.Client{ 172 Host: host, 173 } 174 175 repo := fmt.Sprintf("%s/%s", f.Did, f.Name) 176 xrpcBytes, err := tangled.RepoDiff(r.Context(), xrpcc, ref, repo) 177 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { 178 l.Error("failed to call XRPC repo.diff", "err", xrpcerr) 179 rp.pages.Error503(w) 180 return 181 } 182 183 var result types.RepoCommitResponse 184 if err := json.Unmarshal(xrpcBytes, &result); err != nil { 185 l.Error("failed to decode XRPC response", "err", err) 186 rp.pages.Error503(w) 187 return 188 } 189 190 emailToDidMap, err := db.GetEmailToDid(rp.db, []string{result.Diff.Commit.Committer.Email, result.Diff.Commit.Author.Email}, true) 191 if err != nil { 192 l.Error("failed to get email to did mapping", "err", err) 193 } 194 195 vc, err := commitverify.GetVerifiedCommits(rp.db, emailToDidMap, []types.Commit{result.Diff.Commit}) 196 if err != nil { 197 l.Error("failed to GetVerifiedCommits", "err", err) 198 } 199 200 user := rp.oauth.GetUser(r) 201 pipelines, err := getPipelineStatuses(rp.db, f, []string{result.Diff.Commit.This}) 202 if err != nil { 203 l.Error("failed to getPipelineStatuses", "err", err) 204 // non-fatal 205 } 206 var pipeline *models.Pipeline 207 if p, ok := pipelines[result.Diff.Commit.This]; ok { 208 pipeline = &p 209 } 210 211 rp.pages.RepoCommit(w, pages.RepoCommitParams{ 212 LoggedInUser: user, 213 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 214 RepoCommitResponse: result, 215 EmailToDid: emailToDidMap, 216 VerifiedCommit: vc, 217 Pipeline: pipeline, 218 DiffOpts: diffOpts, 219 }) 220}