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) {