+28
appview/pages/pages.go
+28
appview/pages/pages.go
···
857
return p.executePlain("repo/pulls/fragments/pullNewComment", w, params)
858
}
859
860
+
type RepoCompareParams struct {
861
+
LoggedInUser *oauth.User
862
+
RepoInfo repoinfo.RepoInfo
863
+
Forks []db.Repo
864
+
Branches []types.Branch
865
+
Tags []*types.TagReference
866
+
867
+
Active string
868
+
}
869
+
870
+
func (p *Pages) RepoCompare(w io.Writer, params RepoCompareParams) error {
871
+
params.Active = "overview"
872
+
return p.executeRepo("repo/compare/new", w, params)
873
+
}
874
+
875
+
type RepoCompareDiffParams struct {
876
+
LoggedInUser *oauth.User
877
+
RepoInfo repoinfo.RepoInfo
878
+
FormatPatch types.RepoFormatPatchResponse
879
+
880
+
Active string
881
+
}
882
+
883
+
func (p *Pages) RepoCompareDiff(w io.Writer, params RepoCompareDiffParams) error {
884
+
params.Active = "overview"
885
+
return p.executeRepo("repo/compare/new", w, params)
886
+
}
887
+
888
func (p *Pages) Static() http.Handler {
889
if p.dev {
890
return http.StripPrefix("/static/", http.FileServer(http.Dir("appview/pages/static")))
+74
appview/pages/templates/repo/compare/new.html
+74
appview/pages/templates/repo/compare/new.html
···
···
1
+
{{ define "title" }}new comparison{{ end }}
2
+
3
+
{{ define "repoContent" }}
4
+
<h2 class="font-bold text-sm mb-4 uppercase dark:text-white">
5
+
Compare changes
6
+
</h2>
7
+
<p>Choose any two refs to compare.</p>
8
+
9
+
<div class="flex items-center gap-2 py-4">
10
+
<div>
11
+
base:
12
+
<select
13
+
class="p-1 border max-w-32 border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700"
14
+
>
15
+
<optgroup
16
+
label="branches ({{ len .Branches }})"
17
+
class="bold text-sm"
18
+
>
19
+
{{ range .Branches }}
20
+
<option
21
+
value="{{ .Reference.Name }}"
22
+
class="py-1"
23
+
{{ if .IsDefault }}
24
+
selected
25
+
{{ end }}
26
+
>
27
+
{{ .Reference.Name }}
28
+
</option>
29
+
{{ end }}
30
+
</optgroup>
31
+
<optgroup label="tags ({{ len .Tags }})" class="bold text-sm">
32
+
{{ range .Tags }}
33
+
<option value="{{ .Reference.Name }}" class="py-1">
34
+
{{ .Reference.Name }}
35
+
</option>
36
+
{{ else }}
37
+
<option class="py-1" disabled>no tags found</option>
38
+
{{ end }}
39
+
</optgroup>
40
+
</select>
41
+
</div>
42
+
{{ i "arrow-left" "w-4 h-4" }}
43
+
<div>
44
+
compare:
45
+
<select
46
+
class="p-1 border max-w-32 border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700"
47
+
>
48
+
<optgroup
49
+
label="branches ({{ len .Branches }})"
50
+
class="bold text-sm"
51
+
>
52
+
{{ range .Branches }}
53
+
<option value="{{ .Reference.Name }}" class="py-1">
54
+
{{ .Reference.Name }}
55
+
</option>
56
+
{{ end }}
57
+
</optgroup>
58
+
<optgroup label="tags ({{ len .Tags }})" class="bold text-sm">
59
+
{{ range .Tags }}
60
+
<option value="{{ .Reference.Name }}" class="py-1">
61
+
{{ .Reference.Name }}
62
+
</option>
63
+
{{ else }}
64
+
<option class="py-1" disabled>no tags found</option>
65
+
{{ end }}
66
+
</optgroup>
67
+
</select>
68
+
</div>
69
+
</div>
70
+
{{ end }}
71
+
72
+
{{ define "repoAfter" }}
73
+
<div id="compare-diff"></div>
74
+
{{ end }}
+84
appview/state/repo.go
+84
appview/state/repo.go
···
2054
return
2055
}
2056
}
2057
+
2058
+
func (s *State) RepoCompare(w http.ResponseWriter, r *http.Request) {
2059
+
user := s.oauth.GetUser(r)
2060
+
f, err := s.fullyResolvedRepo(r)
2061
+
if err != nil {
2062
+
log.Println("failed to get repo and knot", err)
2063
+
return
2064
+
}
2065
+
2066
+
us, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev)
2067
+
if err != nil {
2068
+
log.Printf("failed to create unsigned client for %s", f.Knot)
2069
+
s.pages.Error503(w)
2070
+
return
2071
+
}
2072
+
2073
+
branches, err := us.Branches(f.OwnerDid(), f.RepoName)
2074
+
if err != nil {
2075
+
s.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
2076
+
log.Println("failed to reach knotserver", err)
2077
+
return
2078
+
}
2079
+
2080
+
tags, err := us.Tags(f.OwnerDid(), f.RepoName)
2081
+
if err != nil {
2082
+
s.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
2083
+
log.Println("failed to reach knotserver", err)
2084
+
return
2085
+
}
2086
+
2087
+
forks, err := db.GetForksByDid(s.db, user.Did)
2088
+
if err != nil {
2089
+
s.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
2090
+
log.Println("failed to get forks", err)
2091
+
return
2092
+
}
2093
+
2094
+
s.pages.RepoCompare(w, pages.RepoCompareParams{
2095
+
LoggedInUser: user,
2096
+
RepoInfo: f.RepoInfo(s, user),
2097
+
Forks: forks,
2098
+
Branches: branches.Branches,
2099
+
Tags: tags.Tags,
2100
+
})
2101
+
}
2102
+
2103
+
func (s *State) RepoCompareDiff(w http.ResponseWriter, r *http.Request) {
2104
+
f, err := s.fullyResolvedRepo(r)
2105
+
if err != nil {
2106
+
log.Println("failed to get repo and knot", err)
2107
+
return
2108
+
}
2109
+
user := s.oauth.GetUser(r)
2110
+
2111
+
rest := chi.URLParam(r, "*") // master...feature/xyz
2112
+
parts := strings.SplitN(rest, "...", 2)
2113
+
if len(parts) != 2 {
2114
+
s.pages.Notice(w, "compare-error", "Invalid ref format.")
2115
+
return
2116
+
}
2117
+
2118
+
ref1 := parts[0]
2119
+
ref2 := parts[1]
2120
+
2121
+
us, err := knotclient.NewUnsignedClient(f.Knot, s.config.Core.Dev)
2122
+
if err != nil {
2123
+
s.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
2124
+
log.Println("failed to reach knotserver", err)
2125
+
return
2126
+
}
2127
+
2128
+
formatPatch, err := us.Compare(f.OwnerDid(), f.RepoName, ref1, ref2)
2129
+
if err != nil {
2130
+
s.pages.Notice(w, "compare-error", "Failed to produce comparison. Try again later.")
2131
+
log.Println("failed to compare", err)
2132
+
return
2133
+
}
2134
+
2135
+
s.pages.RepoCompareDiff(w, pages.RepoCompareDiffParams{
2136
+
LoggedInUser: user,
2137
+
RepoInfo: f.RepoInfo(s, user),
2138
+
FormatPatch: *formatPatch,
2139
+
})
2140
+
}
+11
appview/state/router.go
+11
appview/state/router.go
···
118
})
119
})
120
121
+
r.Route("/compare", func(r chi.Router) {
122
+
r.Get("/", s.RepoCompare)
123
+
124
+
// we have to wildcard here since we want to support GitHub's compare syntax
125
+
// /compare/{ref1}...{ref2}
126
+
// for example:
127
+
// /compare/master...some/feature
128
+
// /compare/master...example.com:another/feature <- this is a fork
129
+
r.Get("/*", s.RepoCompareDiff)
130
+
})
131
+
132
r.Route("/pulls", func(r chi.Router) {
133
r.Get("/", s.RepoPulls)
134
r.With(middleware.AuthMiddleware(s.oauth)).Route("/new", func(r chi.Router) {