···33import (
44 "errors"
55 "fmt"
66- "log"
66+ "log/slog"
77 "net/http"
88 "net/url"
99 "slices"
···3131)
32323333func (rp *Repo) RepoIndex(w http.ResponseWriter, r *http.Request) {
3434+ l := rp.logger.With("handler", "RepoIndex")
3535+3436 ref := chi.URLParam(r, "ref")
3537 ref, _ = url.PathUnescape(ref)
36383739 f, err := rp.repoResolver.Resolve(r)
3840 if err != nil {
3939- log.Println("failed to fully resolve repo", err)
4141+ l.Error("failed to fully resolve repo", "err", err)
4042 return
4143 }
4244···5658 result, err := rp.buildIndexResponse(r.Context(), xrpcc, f, ref)
5759 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
5860 if errors.Is(xrpcerr, xrpcclient.ErrXrpcUnsupported) {
5959- log.Println("failed to call XRPC repo.index", err)
6161+ l.Error("failed to call XRPC repo.index", "err", err)
6062 rp.pages.RepoIndexPage(w, pages.RepoIndexParams{
6163 LoggedInUser: user,
6264 NeedsKnotUpgrade: true,
···6668 }
67696870 rp.pages.Error503(w)
6969- log.Println("failed to build index response", err)
7171+ l.Error("failed to build index response", "err", err)
7072 return
7173 }
7274···119121 emails := uniqueEmails(commitsTrunc)
120122 emailToDidMap, err := db.GetEmailToDid(rp.db, emails, true)
121123 if err != nil {
122122- log.Println("failed to get email to did map", err)
124124+ l.Error("failed to get email to did map", "err", err)
123125 }
124126125127 vc, err := commitverify.GetVerifiedObjectCommits(rp.db, emailToDidMap, commitsTrunc)
126128 if err != nil {
127127- log.Println(err)
129129+ l.Error("failed to GetVerifiedObjectCommits", "err", err)
128130 }
129131130132 // TODO: a bit dirty
131131- languageInfo, err := rp.getLanguageInfo(r.Context(), f, xrpcc, result.Ref, ref == "")
133133+ languageInfo, err := rp.getLanguageInfo(r.Context(), l, f, xrpcc, result.Ref, ref == "")
132134 if err != nil {
133133- log.Printf("failed to compute language percentages: %s", err)
135135+ l.Warn("failed to compute language percentages", "err", err)
134136 // non-fatal
135137 }
136138···140142 }
141143 pipelines, err := getPipelineStatuses(rp.db, repoInfo, shas)
142144 if err != nil {
143143- log.Printf("failed to fetch pipeline statuses: %s", err)
145145+ l.Error("failed to fetch pipeline statuses", "err", err)
144146 // non-fatal
145147 }
146148···162164163165func (rp *Repo) getLanguageInfo(
164166 ctx context.Context,
167167+ l *slog.Logger,
165168 f *reporesolver.ResolvedRepo,
166169 xrpcc *indigoxrpc.Client,
167170 currentRef string,
···180183 ls, err := tangled.RepoLanguages(ctx, xrpcc, currentRef, repo)
181184 if err != nil {
182185 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
183183- log.Println("failed to call XRPC repo.languages", xrpcerr)
186186+ l.Error("failed to call XRPC repo.languages", "err", xrpcerr)
184187 return nil, xrpcerr
185188 }
186189 return nil, err
···210213 err = db.UpdateRepoLanguages(tx, f.RepoAt(), currentRef, langs)
211214 if err != nil {
212215 // non-fatal
213213- log.Println("failed to cache lang results", err)
216216+ l.Error("failed to cache lang results", "err", err)
214217 }
215218216219 err = tx.Commit()
+1-1
appview/repo/ogcard/card.go
···46464747// DefaultSize returns the default size for a card
4848func DefaultSize() (int, int) {
4949- return 1200, 630
4949+ return 1200, 600
5050}
51515252// NewCard creates a new card with the given dimensions in pixels
+28-54
appview/repo/opengraph.go
···3535 // Split content horizontally: main content (80%) and avatar area (20%)
3636 mainContent, avatarArea := contentCard.Split(true, 80)
37373838- // Use main content area for both repo name and description to allow dynamic wrapping.
3939- mainContent.SetMargin(10)
3838+ // Split main content: 50% for name/description, 50% for spacing
3939+ topSection, _ := mainContent.Split(false, 50)
4040+4141+ // Split top section: 40% for repo name, 60% for description
4242+ repoNameCard, descriptionCard := topSection.Split(false, 50)
40434444+ // Draw repo name with owner in regular and repo name in bold
4545+ repoNameCard.SetMargin(10)
4146 var ownerHandle string
4247 owner, err := rp.idResolver.ResolveIdent(context.Background(), repo.Did)
4348 if err != nil {
···4651 ownerHandle = "@" + owner.Handle.String()
4752 }
48534949- bounds := mainContent.Img.Bounds()
5050- startX := bounds.Min.X + mainContent.Margin
5151- startY := bounds.Min.Y + mainContent.Margin
5454+ // Draw repo name with wrapping support
5555+ repoNameCard.SetMargin(10)
5656+ bounds := repoNameCard.Img.Bounds()
5757+ startX := bounds.Min.X + repoNameCard.Margin
5858+ startY := bounds.Min.Y + repoNameCard.Margin
5259 currentX := startX
5353- currentY := startY
5454- lineHeight := 64 // Font size 54 + padding
5560 textColor := color.RGBA{88, 96, 105, 255}
56615757- // Draw owner handle
5858- ownerWidth, err := mainContent.DrawTextAtWithWidth(ownerHandle, currentX, currentY, textColor, 54, ogcard.Top, ogcard.Left)
6262+ // Draw owner handle in gray
6363+ ownerWidth, err := repoNameCard.DrawTextAtWithWidth(ownerHandle, currentX, startY, textColor, 54, ogcard.Top, ogcard.Left)
5964 if err != nil {
6065 return nil, err
6166 }
6267 currentX += ownerWidth
63686469 // Draw separator
6565- sepWidth, err := mainContent.DrawTextAtWithWidth(" / ", currentX, currentY, textColor, 54, ogcard.Top, ogcard.Left)
7070+ sepWidth, err := repoNameCard.DrawTextAtWithWidth(" / ", currentX, startY, textColor, 54, ogcard.Top, ogcard.Left)
6671 if err != nil {
6772 return nil, err
6873 }
6974 currentX += sepWidth
70757171- words := strings.Fields(repo.Name)
7272- spaceWidth, _ := mainContent.DrawTextAtWithWidth(" ", -1000, -1000, color.Black, 54, ogcard.Top, ogcard.Left)
7373- if spaceWidth == 0 {
7474- spaceWidth = 15
7676+ // Draw repo name in bold
7777+ _, err = repoNameCard.DrawBoldText(repo.Name, currentX, startY, color.Black, 54, ogcard.Top, ogcard.Left)
7878+ if err != nil {
7979+ return nil, err
7580 }
76817777- for _, word := range words {
7878- // estimate bold width by measuring regular width and adding a multiplier
7979- regularWidth, _ := mainContent.DrawTextAtWithWidth(word, -1000, -1000, color.Black, 54, ogcard.Top, ogcard.Left)
8080- estimatedBoldWidth := int(float64(regularWidth) * 1.15) // Heuristic for bold text
8181-8282- if currentX+estimatedBoldWidth > (bounds.Max.X - mainContent.Margin) {
8383- currentX = startX
8484- currentY += lineHeight
8585- }
8686-8787- _, err := mainContent.DrawBoldText(word, currentX, currentY, color.Black, 54, ogcard.Top, ogcard.Left)
8888- if err != nil {
8989- return nil, err
9090- }
9191- currentX += estimatedBoldWidth + spaceWidth
8282+ // Draw description (DrawText handles multi-line wrapping automatically)
8383+ descriptionCard.SetMargin(10)
8484+ description := repo.Description
8585+ if len(description) > 70 {
8686+ description = description[:70] + "…"
9287 }
93889494- // update Y position for the description
9595- currentY += lineHeight
9696-9797- // draw description
9898- if currentY < bounds.Max.Y-mainContent.Margin {
9999- totalHeight := float64(bounds.Dy())
100100- repoNameHeight := float64(currentY - bounds.Min.Y)
101101-102102- if totalHeight > 0 && repoNameHeight < totalHeight {
103103- repoNamePercent := (repoNameHeight / totalHeight) * 100
104104- if repoNamePercent < 95 { // Ensure there's space left for description
105105- _, descriptionCard := mainContent.Split(false, int(repoNamePercent))
106106- descriptionCard.SetMargin(8)
107107-108108- description := repo.Description
109109- if len(description) > 70 {
110110- description = description[:70] + "…"
111111- }
112112-113113- _, err = descriptionCard.DrawText(description, color.RGBA{88, 96, 105, 255}, 36, ogcard.Top, ogcard.Left)
114114- if err != nil {
115115- log.Printf("failed to draw description: %v", err)
116116- }
117117- }
118118- }
8989+ _, err = descriptionCard.DrawText(description, color.RGBA{88, 96, 105, 255}, 36, ogcard.Top, ogcard.Left)
9090+ if err != nil {
9191+ log.Printf("failed to draw description: %v", err)
9292+ return nil, err
11993 }
1209412195 // Draw avatar circle on the right side
+130-92
appview/repo/repo.go
···77 "errors"
88 "fmt"
99 "io"
1010- "log"
1110 "log/slog"
1211 "net/http"
1312 "net/url"
···9089}
91909291func (rp *Repo) DownloadArchive(w http.ResponseWriter, r *http.Request) {
9292+ l := rp.logger.With("handler", "DownloadArchive")
9393+9394 ref := chi.URLParam(r, "ref")
9495 ref, _ = url.PathUnescape(ref)
95969697 f, err := rp.repoResolver.Resolve(r)
9798 if err != nil {
9898- log.Println("failed to get repo and knot", err)
9999+ l.Error("failed to get repo and knot", "err", err)
99100 return
100101 }
101102···111112 repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
112113 archiveBytes, err := tangled.RepoArchive(r.Context(), xrpcc, "tar.gz", "", ref, repo)
113114 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
114114- log.Println("failed to call XRPC repo.archive", xrpcerr)
115115+ l.Error("failed to call XRPC repo.archive", "err", xrpcerr)
115116 rp.pages.Error503(w)
116117 return
117118 }
···128129}
129130130131func (rp *Repo) RepoLog(w http.ResponseWriter, r *http.Request) {
132132+ l := rp.logger.With("handler", "RepoLog")
133133+131134 f, err := rp.repoResolver.Resolve(r)
132135 if err != nil {
133133- log.Println("failed to fully resolve repo", err)
136136+ l.Error("failed to fully resolve repo", "err", err)
134137 return
135138 }
136139···165168 repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
166169 xrpcBytes, err := tangled.RepoLog(r.Context(), xrpcc, cursor, limit, "", ref, repo)
167170 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
168168- log.Println("failed to call XRPC repo.log", xrpcerr)
171171+ l.Error("failed to call XRPC repo.log", "err", xrpcerr)
169172 rp.pages.Error503(w)
170173 return
171174 }
172175173176 var xrpcResp types.RepoLogResponse
174177 if err := json.Unmarshal(xrpcBytes, &xrpcResp); err != nil {
175175- log.Println("failed to decode XRPC response", err)
178178+ l.Error("failed to decode XRPC response", "err", err)
176179 rp.pages.Error503(w)
177180 return
178181 }
179182180183 tagBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo)
181184 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
182182- log.Println("failed to call XRPC repo.tags", xrpcerr)
185185+ l.Error("failed to call XRPC repo.tags", "err", xrpcerr)
183186 rp.pages.Error503(w)
184187 return
185188 }
···196199197200 branchBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
198201 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
199199- log.Println("failed to call XRPC repo.branches", xrpcerr)
202202+ l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
200203 rp.pages.Error503(w)
201204 return
202205 }
···214217215218 emailToDidMap, err := db.GetEmailToDid(rp.db, uniqueEmails(xrpcResp.Commits), true)
216219 if err != nil {
217217- log.Println("failed to fetch email to did mapping", err)
220220+ l.Error("failed to fetch email to did mapping", "err", err)
218221 }
219222220223 vc, err := commitverify.GetVerifiedObjectCommits(rp.db, emailToDidMap, xrpcResp.Commits)
221224 if err != nil {
222222- log.Println(err)
225225+ l.Error("failed to GetVerifiedObjectCommits", "err", err)
223226 }
224227225228 repoInfo := f.RepoInfo(user)
···230233 }
231234 pipelines, err := getPipelineStatuses(rp.db, repoInfo, shas)
232235 if err != nil {
233233- log.Println(err)
236236+ l.Error("failed to getPipelineStatuses", "err", err)
234237 // non-fatal
235238 }
236239···246249}
247250248251func (rp *Repo) RepoDescriptionEdit(w http.ResponseWriter, r *http.Request) {
252252+ l := rp.logger.With("handler", "RepoDescriptionEdit")
253253+249254 f, err := rp.repoResolver.Resolve(r)
250255 if err != nil {
251251- log.Println("failed to get repo and knot", err)
256256+ l.Error("failed to get repo and knot", "err", err)
252257 w.WriteHeader(http.StatusBadRequest)
253258 return
254259 }
···260265}
261266262267func (rp *Repo) RepoDescription(w http.ResponseWriter, r *http.Request) {
268268+ l := rp.logger.With("handler", "RepoDescription")
269269+263270 f, err := rp.repoResolver.Resolve(r)
264271 if err != nil {
265265- log.Println("failed to get repo and knot", err)
272272+ l.Error("failed to get repo and knot", "err", err)
266273 w.WriteHeader(http.StatusBadRequest)
267274 return
268275 }
···270277 repoAt := f.RepoAt()
271278 rkey := repoAt.RecordKey().String()
272279 if rkey == "" {
273273- log.Println("invalid aturi for repo", err)
280280+ l.Error("invalid aturi for repo", "err", err)
274281 w.WriteHeader(http.StatusInternalServerError)
275282 return
276283 }
···287294 newDescription := r.FormValue("description")
288295 client, err := rp.oauth.AuthorizedClient(r)
289296 if err != nil {
290290- log.Println("failed to get client")
297297+ l.Error("failed to get client")
291298 rp.pages.Notice(w, "repo-notice", "Failed to update description, try again later.")
292299 return
293300 }
···295302 // optimistic update
296303 err = db.UpdateDescription(rp.db, string(repoAt), newDescription)
297304 if err != nil {
298298- log.Println("failed to perferom update-description query", err)
305305+ l.Error("failed to perform update-description query", "err", err)
299306 rp.pages.Notice(w, "repo-notice", "Failed to update description, try again later.")
300307 return
301308 }
···324331 })
325332326333 if err != nil {
327327- log.Println("failed to perferom update-description query", err)
334334+ l.Error("failed to perferom update-description query", "err", err)
328335 // failed to get record
329336 rp.pages.Notice(w, "repo-notice", "Failed to update description, unable to save to PDS.")
330337 return
···341348}
342349343350func (rp *Repo) RepoCommit(w http.ResponseWriter, r *http.Request) {
351351+ l := rp.logger.With("handler", "RepoCommit")
352352+344353 f, err := rp.repoResolver.Resolve(r)
345354 if err != nil {
346346- log.Println("failed to fully resolve repo", err)
355355+ l.Error("failed to fully resolve repo", "err", err)
347356 return
348357 }
349358 ref := chi.URLParam(r, "ref")
···371380 repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
372381 xrpcBytes, err := tangled.RepoDiff(r.Context(), xrpcc, ref, repo)
373382 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
374374- log.Println("failed to call XRPC repo.diff", xrpcerr)
383383+ l.Error("failed to call XRPC repo.diff", "err", xrpcerr)
375384 rp.pages.Error503(w)
376385 return
377386 }
378387379388 var result types.RepoCommitResponse
380389 if err := json.Unmarshal(xrpcBytes, &result); err != nil {
381381- log.Println("failed to decode XRPC response", err)
390390+ l.Error("failed to decode XRPC response", "err", err)
382391 rp.pages.Error503(w)
383392 return
384393 }
385394386395 emailToDidMap, err := db.GetEmailToDid(rp.db, []string{result.Diff.Commit.Committer.Email, result.Diff.Commit.Author.Email}, true)
387396 if err != nil {
388388- log.Println("failed to get email to did mapping:", err)
397397+ l.Error("failed to get email to did mapping", "err", err)
389398 }
390399391400 vc, err := commitverify.GetVerifiedCommits(rp.db, emailToDidMap, []types.NiceDiff{*result.Diff})
392401 if err != nil {
393393- log.Println(err)
402402+ l.Error("failed to GetVerifiedCommits", "err", err)
394403 }
395404396405 user := rp.oauth.GetUser(r)
397406 repoInfo := f.RepoInfo(user)
398407 pipelines, err := getPipelineStatuses(rp.db, repoInfo, []string{result.Diff.Commit.This})
399408 if err != nil {
400400- log.Println(err)
409409+ l.Error("failed to getPipelineStatuses", "err", err)
401410 // non-fatal
402411 }
403412 var pipeline *models.Pipeline
···417426}
418427419428func (rp *Repo) RepoTree(w http.ResponseWriter, r *http.Request) {
429429+ l := rp.logger.With("handler", "RepoTree")
430430+420431 f, err := rp.repoResolver.Resolve(r)
421432 if err != nil {
422422- log.Println("failed to fully resolve repo", err)
433433+ l.Error("failed to fully resolve repo", "err", err)
423434 return
424435 }
425436···444455 repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
445456 xrpcResp, err := tangled.RepoTree(r.Context(), xrpcc, treePath, ref, repo)
446457 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
447447- log.Println("failed to call XRPC repo.tree", xrpcerr)
458458+ l.Error("failed to call XRPC repo.tree", "err", xrpcerr)
448459 rp.pages.Error503(w)
449460 return
450461 }
···519530}
520531521532func (rp *Repo) RepoTags(w http.ResponseWriter, r *http.Request) {
533533+ l := rp.logger.With("handler", "RepoTags")
534534+522535 f, err := rp.repoResolver.Resolve(r)
523536 if err != nil {
524524- log.Println("failed to get repo and knot", err)
537537+ l.Error("failed to get repo and knot", "err", err)
525538 return
526539 }
527540···537550 repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
538551 xrpcBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo)
539552 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
540540- log.Println("failed to call XRPC repo.tags", xrpcerr)
553553+ l.Error("failed to call XRPC repo.tags", "err", xrpcerr)
541554 rp.pages.Error503(w)
542555 return
543556 }
544557545558 var result types.RepoTagsResponse
546559 if err := json.Unmarshal(xrpcBytes, &result); err != nil {
547547- log.Println("failed to decode XRPC response", err)
560560+ l.Error("failed to decode XRPC response", "err", err)
548561 rp.pages.Error503(w)
549562 return
550563 }
551564552565 artifacts, err := db.GetArtifact(rp.db, db.FilterEq("repo_at", f.RepoAt()))
553566 if err != nil {
554554- log.Println("failed grab artifacts", err)
567567+ l.Error("failed grab artifacts", "err", err)
555568 return
556569 }
557570···588601}
589602590603func (rp *Repo) RepoBranches(w http.ResponseWriter, r *http.Request) {
604604+ l := rp.logger.With("handler", "RepoBranches")
605605+591606 f, err := rp.repoResolver.Resolve(r)
592607 if err != nil {
593593- log.Println("failed to get repo and knot", err)
608608+ l.Error("failed to get repo and knot", "err", err)
594609 return
595610 }
596611···606621 repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
607622 xrpcBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
608623 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
609609- log.Println("failed to call XRPC repo.branches", xrpcerr)
624624+ l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
610625 rp.pages.Error503(w)
611626 return
612627 }
613628614629 var result types.RepoBranchesResponse
615630 if err := json.Unmarshal(xrpcBytes, &result); err != nil {
616616- log.Println("failed to decode XRPC response", err)
631631+ l.Error("failed to decode XRPC response", "err", err)
617632 rp.pages.Error503(w)
618633 return
619634 }
···629644}
630645631646func (rp *Repo) DeleteBranch(w http.ResponseWriter, r *http.Request) {
647647+ l := rp.logger.With("handler", "DeleteBranch")
648648+632649 f, err := rp.repoResolver.Resolve(r)
633650 if err != nil {
634634- log.Println("failed to get repo and knot", err)
651651+ l.Error("failed to get repo and knot", "err", err)
635652 return
636653 }
637654638655 noticeId := "delete-branch-error"
639656 fail := func(msg string, err error) {
640640- log.Println(msg, "err", err)
657657+ l.Error(msg, "err", err)
641658 rp.pages.Notice(w, noticeId, msg)
642659 }
643660···670687 fail(fmt.Sprintf("Failed to delete branch: %s", err), err)
671688 return
672689 }
673673- log.Println("deleted branch from knot", "branch", branch, "repo", f.RepoAt())
690690+ l.Error("deleted branch from knot", "branch", branch, "repo", f.RepoAt())
674691675692 rp.pages.HxRefresh(w)
676693}
677694678695func (rp *Repo) RepoBlob(w http.ResponseWriter, r *http.Request) {
696696+ l := rp.logger.With("handler", "RepoBlob")
697697+679698 f, err := rp.repoResolver.Resolve(r)
680699 if err != nil {
681681- log.Println("failed to get repo and knot", err)
700700+ l.Error("failed to get repo and knot", "err", err)
682701 return
683702 }
684703···700719 repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Repo.Name)
701720 resp, err := tangled.RepoBlob(r.Context(), xrpcc, filePath, false, ref, repo)
702721 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
703703- log.Println("failed to call XRPC repo.blob", xrpcerr)
722722+ l.Error("failed to call XRPC repo.blob", "err", xrpcerr)
704723 rp.pages.Error503(w)
705724 return
706725 }
···800819}
801820802821func (rp *Repo) RepoBlobRaw(w http.ResponseWriter, r *http.Request) {
822822+ l := rp.logger.With("handler", "RepoBlobRaw")
823823+803824 f, err := rp.repoResolver.Resolve(r)
804825 if err != nil {
805805- log.Println("failed to get repo and knot", err)
826826+ l.Error("failed to get repo and knot", err)
806827 w.WriteHeader(http.StatusBadRequest)
807828 return
808829 }
···834855835856 req, err := http.NewRequest("GET", blobURL, nil)
836857 if err != nil {
837837- log.Println("failed to create request", err)
858858+ l.Error("failed to create request", "err", err)
838859 return
839860 }
840861···846867 client := &http.Client{}
847868 resp, err := client.Do(req)
848869 if err != nil {
849849- log.Println("failed to reach knotserver", err)
870870+ l.Error("failed to reach knotserver", "err", err)
850871 rp.pages.Error503(w)
851872 return
852873 }
···859880 }
860881861882 if resp.StatusCode != http.StatusOK {
862862- log.Printf("knotserver returned non-OK status for raw blob %s: %d", blobURL, resp.StatusCode)
883883+ l.Error("knotserver returned non-OK status for raw blob", "url", blobURL, "statuscode", resp.StatusCode)
863884 w.WriteHeader(resp.StatusCode)
864885 _, _ = io.Copy(w, resp.Body)
865886 return
···868889 contentType := resp.Header.Get("Content-Type")
869890 body, err := io.ReadAll(resp.Body)
870891 if err != nil {
871871- log.Printf("error reading response body from knotserver: %v", err)
892892+ l.Error("error reading response body from knotserver", "err", err)
872893 w.WriteHeader(http.StatusInternalServerError)
873894 return
874895 }
···14431464 db.FilterContains("scope", subject.Collection().String()),
14441465 )
14451466 if err != nil {
14461446- log.Println("failed to fetch label defs", err)
14671467+ l.Error("failed to fetch label defs", "err", err)
14471468 return
14481469 }
14491470···1454147514551476 states, err := db.GetLabels(rp.db, db.FilterEq("subject", subject))
14561477 if err != nil {
14571457- log.Println("failed to build label state", err)
14781478+ l.Error("failed to build label state", "err", err)
14581479 return
14591480 }
14601481 state := states[subject]
···14911512 db.FilterContains("scope", subject.Collection().String()),
14921513 )
14931514 if err != nil {
14941494- log.Println("failed to fetch labels", err)
15151515+ l.Error("failed to fetch labels", "err", err)
14951516 return
14961517 }
14971518···1502152315031524 states, err := db.GetLabels(rp.db, db.FilterEq("subject", subject))
15041525 if err != nil {
15051505- log.Println("failed to build label state", err)
15261526+ l.Error("failed to build label state", "err", err)
15061527 return
15071528 }
15081529 state := states[subject]
···1649167016501671func (rp *Repo) DeleteRepo(w http.ResponseWriter, r *http.Request) {
16511672 user := rp.oauth.GetUser(r)
16731673+ l := rp.logger.With("handler", "DeleteRepo")
1652167416531675 noticeId := "operation-error"
16541676 f, err := rp.repoResolver.Resolve(r)
16551677 if err != nil {
16561656- log.Println("failed to get repo and knot", err)
16781678+ l.Error("failed to get repo and knot", "err", err)
16571679 return
16581680 }
1659168116601682 // remove record from pds
16611683 atpClient, err := rp.oauth.AuthorizedClient(r)
16621684 if err != nil {
16631663- log.Println("failed to get authorized client", err)
16851685+ l.Error("failed to get authorized client", "err", err)
16641686 return
16651687 }
16661688 _, err = comatproto.RepoDeleteRecord(r.Context(), atpClient, &comatproto.RepoDeleteRecord_Input{
···16691691 Rkey: f.Rkey,
16701692 })
16711693 if err != nil {
16721672- log.Printf("failed to delete record: %s", err)
16941694+ l.Error("failed to delete record", "err", err)
16731695 rp.pages.Notice(w, noticeId, "Failed to delete repository from PDS.")
16741696 return
16751697 }
16761676- log.Println("removed repo record ", f.RepoAt().String())
16981698+ l.Info("removed repo record", "aturi", f.RepoAt().String())
1677169916781700 client, err := rp.oauth.ServiceClient(
16791701 r,
···16821704 oauth.WithDev(rp.config.Core.Dev),
16831705 )
16841706 if err != nil {
16851685- log.Println("failed to connect to knot server:", err)
17071707+ l.Error("failed to connect to knot server", "err", err)
16861708 return
16871709 }
16881710···16991721 rp.pages.Notice(w, noticeId, err.Error())
17001722 return
17011723 }
17021702- log.Println("deleted repo from knot")
17241724+ l.Info("deleted repo from knot")
1703172517041726 tx, err := rp.db.BeginTx(r.Context(), nil)
17051727 if err != nil {
17061706- log.Println("failed to start tx")
17281728+ l.Error("failed to start tx")
17071729 w.Write(fmt.Append(nil, "failed to add collaborator: ", err))
17081730 return
17091731 }
···17111733 tx.Rollback()
17121734 err = rp.enforcer.E.LoadPolicy()
17131735 if err != nil {
17141714- log.Println("failed to rollback policies")
17361736+ l.Error("failed to rollback policies")
17151737 }
17161738 }()
17171739···17251747 did := c[0]
17261748 rp.enforcer.RemoveCollaborator(did, f.Knot, f.DidSlashRepo())
17271749 }
17281728- log.Println("removed collaborators")
17501750+ l.Info("removed collaborators")
1729175117301752 // remove repo RBAC
17311753 err = rp.enforcer.RemoveRepo(f.OwnerDid(), f.Knot, f.DidSlashRepo())
···17401762 rp.pages.Notice(w, noticeId, "Failed to update appview")
17411763 return
17421764 }
17431743- log.Println("removed repo from db")
17651765+ l.Info("removed repo from db")
1744176617451767 err = tx.Commit()
17461768 if err != nil {
17471747- log.Println("failed to commit changes", err)
17691769+ l.Error("failed to commit changes", "err", err)
17481770 http.Error(w, err.Error(), http.StatusInternalServerError)
17491771 return
17501772 }
1751177317521774 err = rp.enforcer.E.SavePolicy()
17531775 if err != nil {
17541754- log.Println("failed to update ACLs", err)
17761776+ l.Error("failed to update ACLs", "err", err)
17551777 http.Error(w, err.Error(), http.StatusInternalServerError)
17561778 return
17571779 }
···17601782}
1761178317621784func (rp *Repo) SetDefaultBranch(w http.ResponseWriter, r *http.Request) {
17851785+ l := rp.logger.With("handler", "SetDefaultBranch")
17861786+17631787 f, err := rp.repoResolver.Resolve(r)
17641788 if err != nil {
17651765- log.Println("failed to get repo and knot", err)
17891789+ l.Error("failed to get repo and knot", "err", err)
17661790 return
17671791 }
17681792···17801804 oauth.WithDev(rp.config.Core.Dev),
17811805 )
17821806 if err != nil {
17831783- log.Println("failed to connect to knot server:", err)
18071807+ l.Error("failed to connect to knot server", "err", err)
17841808 rp.pages.Notice(w, noticeId, "Failed to connect to knot server.")
17851809 return
17861810 }
···17941818 },
17951819 )
17961820 if err := xrpcclient.HandleXrpcErr(xe); err != nil {
17971797- log.Println("xrpc failed", "err", xe)
18211821+ l.Error("xrpc failed", "err", xe)
17981822 rp.pages.Notice(w, noticeId, err.Error())
17991823 return
18001824 }
···1809183318101834 f, err := rp.repoResolver.Resolve(r)
18111835 if err != nil {
18121812- log.Println("failed to get repo and knot", err)
18361836+ l.Error("failed to get repo and knot", "err", err)
18131837 return
18141838 }
1815183918161840 if f.Spindle == "" {
18171817- log.Println("empty spindle cannot add/rm secret", err)
18411841+ l.Error("empty spindle cannot add/rm secret", "err", err)
18181842 return
18191843 }
18201844···18311855 oauth.WithDev(rp.config.Core.Dev),
18321856 )
18331857 if err != nil {
18341834- log.Println("failed to create spindle client", err)
18581858+ l.Error("failed to create spindle client", "err", err)
18351859 return
18361860 }
18371861···19171941}
1918194219191943func (rp *Repo) generalSettings(w http.ResponseWriter, r *http.Request) {
19441944+ l := rp.logger.With("handler", "generalSettings")
19451945+19201946 f, err := rp.repoResolver.Resolve(r)
19211947 user := rp.oauth.GetUser(r)
19221948···19321958 repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
19331959 xrpcBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
19341960 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
19351935- log.Println("failed to call XRPC repo.branches", xrpcerr)
19611961+ l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
19361962 rp.pages.Error503(w)
19371963 return
19381964 }
1939196519401966 var result types.RepoBranchesResponse
19411967 if err := json.Unmarshal(xrpcBytes, &result); err != nil {
19421942- log.Println("failed to decode XRPC response", err)
19681968+ l.Error("failed to decode XRPC response", "err", err)
19431969 rp.pages.Error503(w)
19441970 return
19451971 }
1946197219471973 defaultLabels, err := db.GetLabelDefinitions(rp.db, db.FilterIn("at_uri", models.DefaultLabelDefs()))
19481974 if err != nil {
19491949- log.Println("failed to fetch labels", err)
19751975+ l.Error("failed to fetch labels", "err", err)
19501976 rp.pages.Error503(w)
19511977 return
19521978 }
1953197919541980 labels, err := db.GetLabelDefinitions(rp.db, db.FilterIn("at_uri", f.Repo.Labels))
19551981 if err != nil {
19561956- log.Println("failed to fetch labels", err)
19821982+ l.Error("failed to fetch labels", "err", err)
19571983 rp.pages.Error503(w)
19581984 return
19591985 }
···20012027}
2002202820032029func (rp *Repo) accessSettings(w http.ResponseWriter, r *http.Request) {
20302030+ l := rp.logger.With("handler", "accessSettings")
20312031+20042032 f, err := rp.repoResolver.Resolve(r)
20052033 user := rp.oauth.GetUser(r)
2006203420072035 repoCollaborators, err := f.Collaborators(r.Context())
20082036 if err != nil {
20092009- log.Println("failed to get collaborators", err)
20372037+ l.Error("failed to get collaborators", "err", err)
20102038 }
2011203920122040 rp.pages.RepoAccessSettings(w, pages.RepoAccessSettingsParams{
···20192047}
2020204820212049func (rp *Repo) pipelineSettings(w http.ResponseWriter, r *http.Request) {
20502050+ l := rp.logger.With("handler", "pipelineSettings")
20512051+20222052 f, err := rp.repoResolver.Resolve(r)
20232053 user := rp.oauth.GetUser(r)
2024205420252055 // all spindles that the repo owner is a member of
20262056 spindles, err := rp.enforcer.GetSpindlesForUser(f.OwnerDid())
20272057 if err != nil {
20282028- log.Println("failed to fetch spindles", err)
20582058+ l.Error("failed to fetch spindles", "err", err)
20292059 return
20302060 }
20312061···20382068 oauth.WithExp(60),
20392069 oauth.WithDev(rp.config.Core.Dev),
20402070 ); err != nil {
20412041- log.Println("failed to create spindle client", err)
20712071+ l.Error("failed to create spindle client", "err", err)
20422072 } else if resp, err := tangled.RepoListSecrets(r.Context(), spindleClient, f.RepoAt().String()); err != nil {
20432043- log.Println("failed to fetch secrets", err)
20732073+ l.Error("failed to fetch secrets", "err", err)
20442074 } else {
20452075 secrets = resp.Secrets
20462076 }
···20802110}
2081211120822112func (rp *Repo) SyncRepoFork(w http.ResponseWriter, r *http.Request) {
21132113+ l := rp.logger.With("handler", "SyncRepoFork")
21142114+20832115 ref := chi.URLParam(r, "ref")
20842116 ref, _ = url.PathUnescape(ref)
2085211720862118 user := rp.oauth.GetUser(r)
20872119 f, err := rp.repoResolver.Resolve(r)
20882120 if err != nil {
20892089- log.Printf("failed to resolve source repo: %v", err)
21212121+ l.Error("failed to resolve source repo", "err", err)
20902122 return
20912123 }
20922124···21302162}
2131216321322164func (rp *Repo) ForkRepo(w http.ResponseWriter, r *http.Request) {
21652165+ l := rp.logger.With("handler", "ForkRepo")
21662166+21332167 user := rp.oauth.GetUser(r)
21342168 f, err := rp.repoResolver.Resolve(r)
21352169 if err != nil {
21362136- log.Printf("failed to resolve source repo: %v", err)
21702170+ l.Error("failed to resolve source repo", "err", err)
21372171 return
21382172 }
21392173···21842218 )
21852219 if err != nil {
21862220 if !errors.Is(err, sql.ErrNoRows) {
21872187- log.Println("error fetching existing repo from db", "err", err)
22212221+ l.Error("error fetching existing repo from db", "err", err)
21882222 rp.pages.Notice(w, "repo", "Failed to fork this repository. Try again later.")
21892223 return
21902224 }
···2299233323002334 err = db.AddRepo(tx, repo)
23012335 if err != nil {
23022302- log.Println(err)
23362336+ l.Error("failed to AddRepo", "err", err)
23032337 rp.pages.Notice(w, "repo", "Failed to save repository information.")
23042338 return
23052339 }
···23082342 p, _ := securejoin.SecureJoin(user.Did, forkName)
23092343 err = rp.enforcer.AddRepo(user.Did, targetKnot, p)
23102344 if err != nil {
23112311- log.Println(err)
23452345+ l.Error("failed to add ACLs", "err", err)
23122346 rp.pages.Notice(w, "repo", "Failed to set up repository permissions.")
23132347 return
23142348 }
2315234923162350 err = tx.Commit()
23172351 if err != nil {
23182318- log.Println("failed to commit changes", err)
23522352+ l.Error("failed to commit changes", "err", err)
23192353 http.Error(w, err.Error(), http.StatusInternalServerError)
23202354 return
23212355 }
2322235623232357 err = rp.enforcer.E.SavePolicy()
23242358 if err != nil {
23252325- log.Println("failed to update ACLs", err)
23592359+ l.Error("failed to update ACLs", "err", err)
23262360 http.Error(w, err.Error(), http.StatusInternalServerError)
23272361 return
23282362 }
···23582392}
2359239323602394func (rp *Repo) RepoCompareNew(w http.ResponseWriter, r *http.Request) {
23952395+ l := rp.logger.With("handler", "RepoCompareNew")
23962396+23612397 user := rp.oauth.GetUser(r)
23622398 f, err := rp.repoResolver.Resolve(r)
23632399 if err != nil {
23642364- log.Println("failed to get repo and knot", err)
24002400+ l.Error("failed to get repo and knot", "err", err)
23652401 return
23662402 }
23672403···23772413 repo := fmt.Sprintf("%s/%s", f.OwnerDid(), f.Name)
23782414 branchBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
23792415 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
23802380- log.Println("failed to call XRPC repo.branches", xrpcerr)
24162416+ l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
23812417 rp.pages.Error503(w)
23822418 return
23832419 }
2384242023852421 var branchResult types.RepoBranchesResponse
23862422 if err := json.Unmarshal(branchBytes, &branchResult); err != nil {
23872387- log.Println("failed to decode XRPC branches response", err)
24232423+ l.Error("failed to decode XRPC branches response", "err", err)
23882424 rp.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
23892425 return
23902426 }
···2414245024152451 tagBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo)
24162452 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
24172417- log.Println("failed to call XRPC repo.tags", xrpcerr)
24532453+ l.Error("failed to call XRPC repo.tags", "err", xrpcerr)
24182454 rp.pages.Error503(w)
24192455 return
24202456 }
2421245724222458 var tags types.RepoTagsResponse
24232459 if err := json.Unmarshal(tagBytes, &tags); err != nil {
24242424- log.Println("failed to decode XRPC tags response", err)
24602460+ l.Error("failed to decode XRPC tags response", "err", err)
24252461 rp.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
24262462 return
24272463 }
···24392475}
2440247624412477func (rp *Repo) RepoCompare(w http.ResponseWriter, r *http.Request) {
24782478+ l := rp.logger.With("handler", "RepoCompare")
24792479+24422480 user := rp.oauth.GetUser(r)
24432481 f, err := rp.repoResolver.Resolve(r)
24442482 if err != nil {
24452445- log.Println("failed to get repo and knot", err)
24832483+ l.Error("failed to get repo and knot", "err", err)
24462484 return
24472485 }
24482486···24692507 head, _ = url.PathUnescape(head)
2470250824712509 if base == "" || head == "" {
24722472- log.Printf("invalid comparison")
25102510+ l.Error("invalid comparison")
24732511 rp.pages.Error404(w)
24742512 return
24752513 }
···2487252524882526 branchBytes, err := tangled.RepoBranches(r.Context(), xrpcc, "", 0, repo)
24892527 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
24902490- log.Println("failed to call XRPC repo.branches", xrpcerr)
25282528+ l.Error("failed to call XRPC repo.branches", "err", xrpcerr)
24912529 rp.pages.Error503(w)
24922530 return
24932531 }
2494253224952533 var branches types.RepoBranchesResponse
24962534 if err := json.Unmarshal(branchBytes, &branches); err != nil {
24972497- log.Println("failed to decode XRPC branches response", err)
25352535+ l.Error("failed to decode XRPC branches response", "err", err)
24982536 rp.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
24992537 return
25002538 }
2501253925022540 tagBytes, err := tangled.RepoTags(r.Context(), xrpcc, "", 0, repo)
25032541 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
25042504- log.Println("failed to call XRPC repo.tags", xrpcerr)
25422542+ l.Error("failed to call XRPC repo.tags", "err", xrpcerr)
25052543 rp.pages.Error503(w)
25062544 return
25072545 }
2508254625092547 var tags types.RepoTagsResponse
25102548 if err := json.Unmarshal(tagBytes, &tags); err != nil {
25112511- log.Println("failed to decode XRPC tags response", err)
25492549+ l.Error("failed to decode XRPC tags response", "err", err)
25122550 rp.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
25132551 return
25142552 }
2515255325162554 compareBytes, err := tangled.RepoCompare(r.Context(), xrpcc, repo, base, head)
25172555 if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil {
25182518- log.Println("failed to call XRPC repo.compare", xrpcerr)
25562556+ l.Error("failed to call XRPC repo.compare", "err", xrpcerr)
25192557 rp.pages.Error503(w)
25202558 return
25212559 }
2522256025232561 var formatPatch types.RepoFormatPatchResponse
25242562 if err := json.Unmarshal(compareBytes, &formatPatch); err != nil {
25252525- log.Println("failed to decode XRPC compare response", err)
25632563+ l.Error("failed to decode XRPC compare response", "err", err)
25262564 rp.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
25272565 return
25282566 }