From df75814bfd115153dd4167b371dc3f47faa49f32 Mon Sep 17 00:00:00 2001 From: Anirudh Oppiliappan Date: Tue, 20 May 2025 21:35:49 +0300 Subject: [PATCH] appview: state: add RepoCompare{,Diff} handlers --- appview/pages/pages.go | 28 +++++++ appview/pages/templates/repo/compare/new.html | 74 ++++++++++++++++ appview/state/repo.go | 84 +++++++++++++++++++ appview/state/router.go | 11 +++ 4 files changed, 197 insertions(+) create mode 100644 appview/pages/templates/repo/compare/new.html diff --git a/appview/pages/pages.go b/appview/pages/pages.go index bfd04c24..9665e37a 100644 --- a/appview/pages/pages.go +++ b/appview/pages/pages.go @@ -857,6 +857,34 @@ func (p *Pages) PullNewCommentFragment(w io.Writer, params PullNewCommentParams) return p.executePlain("repo/pulls/fragments/pullNewComment", w, params) } +type RepoCompareParams struct { + LoggedInUser *oauth.User + RepoInfo repoinfo.RepoInfo + Forks []db.Repo + Branches []types.Branch + Tags []*types.TagReference + + Active string +} + +func (p *Pages) RepoCompare(w io.Writer, params RepoCompareParams) error { + params.Active = "overview" + return p.executeRepo("repo/compare/new", w, params) +} + +type RepoCompareDiffParams struct { + LoggedInUser *oauth.User + RepoInfo repoinfo.RepoInfo + FormatPatch types.RepoFormatPatchResponse + + Active string +} + +func (p *Pages) RepoCompareDiff(w io.Writer, params RepoCompareDiffParams) error { + params.Active = "overview" + return p.executeRepo("repo/compare/new", w, params) +} + func (p *Pages) Static() http.Handler { if p.dev { return http.StripPrefix("/static/", http.FileServer(http.Dir("appview/pages/static"))) diff --git a/appview/pages/templates/repo/compare/new.html b/appview/pages/templates/repo/compare/new.html new file mode 100644 index 00000000..527d115b --- /dev/null +++ b/appview/pages/templates/repo/compare/new.html @@ -0,0 +1,74 @@ +{{ define "title" }}new comparison{{ end }} + +{{ define "repoContent" }} +

+ Compare changes +

+

Choose any two refs to compare.

+ +
+
+ base: + +
+ {{ i "arrow-left" "w-4 h-4" }} +
+ compare: + +
+
+{{ end }} + +{{ define "repoAfter" }} +
+{{ end }} diff --git a/appview/state/repo.go b/appview/state/repo.go index 0c46c3f6..29934842 100644 --- a/appview/state/repo.go +++ b/appview/state/repo.go @@ -2054,3 +2054,87 @@ func (s *State) ForkRepo(w http.ResponseWriter, r *http.Request) { return } } + +func (s *State) RepoCompare(w http.ResponseWriter, r *http.Request) { + user := s.oauth.GetUser(r) + f, err := s.fullyResolvedRepo(r) + if err != nil { + log.Println("failed to get repo and knot", err) + return + } + + us, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev) + if err != nil { + log.Printf("failed to create unsigned client for %s", f.Knot) + s.pages.Error503(w) + return + } + + branches, err := us.Branches(f.OwnerDid(), f.RepoName) + if err != nil { + s.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.") + log.Println("failed to reach knotserver", err) + return + } + + tags, err := us.Tags(f.OwnerDid(), f.RepoName) + if err != nil { + s.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.") + log.Println("failed to reach knotserver", err) + return + } + + forks, err := db.GetForksByDid(s.db, user.Did) + if err != nil { + s.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.") + log.Println("failed to get forks", err) + return + } + + s.pages.RepoCompare(w, pages.RepoCompareParams{ + LoggedInUser: user, + RepoInfo: f.RepoInfo(s, user), + Forks: forks, + Branches: branches.Branches, + Tags: tags.Tags, + }) +} + +func (s *State) RepoCompareDiff(w http.ResponseWriter, r *http.Request) { + f, err := s.fullyResolvedRepo(r) + if err != nil { + log.Println("failed to get repo and knot", err) + return + } + user := s.oauth.GetUser(r) + + rest := chi.URLParam(r, "*") // master...feature/xyz + parts := strings.SplitN(rest, "...", 2) + if len(parts) != 2 { + s.pages.Notice(w, "compare-error", "Invalid ref format.") + return + } + + ref1 := parts[0] + ref2 := parts[1] + + us, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev) + if err != nil { + s.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.") + log.Println("failed to reach knotserver", err) + return + } + + formatPatch, err := us.Compare(f.OwnerDid(), f.RepoName, ref1, ref2) + if err != nil { + s.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.") + log.Println("failed to compare", err) + return + } + + s.pages.RepoCompareDiff(w, pages.RepoCompareDiffParams{ + LoggedInUser: user, + RepoInfo: f.RepoInfo(s, user), + FormatPatch: *formatPatch, + }) +} diff --git a/appview/state/router.go b/appview/state/router.go index 9b680100..cb7930cc 100644 --- a/appview/state/router.go +++ b/appview/state/router.go @@ -118,6 +118,17 @@ func (s *State) UserRouter() http.Handler { }) }) + r.Route("/compare", func(r chi.Router) { + r.Get("/", s.RepoCompare) + + // we have to wildcard here since we want to support GitHub's compare syntax + // /compare/{ref1}...{ref2} + // for example: + // /compare/master...some/feature + // /compare/master...example.com:another/feature <- this is a fork + r.Get("/*", s.RepoCompareDiff) + }) + r.Route("/pulls", func(r chi.Router) { r.Get("/", s.RepoPulls) r.With(middleware.AuthMiddleware(s.oauth)).Route("/new", func(r chi.Router) { -- 2.51.2