+20
appview/pages/pages.go
+20
appview/pages/pages.go
···
185
185
func (p *Pages) RepoTree(w io.Writer, params RepoTreeParams) error {
186
186
return p.execute("repo/tree", w, params)
187
187
}
188
+
189
+
type RepoBranchesParams struct {
190
+
LoggedInUser *auth.User
191
+
RepoInfo RepoInfo
192
+
types.RepoBranchesResponse
193
+
}
194
+
195
+
func (p *Pages) RepoBranches(w io.Writer, params RepoBranchesParams) error {
196
+
return p.execute("repo/branches", w, params)
197
+
}
198
+
199
+
type RepoTagsParams struct {
200
+
LoggedInUser *auth.User
201
+
RepoInfo RepoInfo
202
+
types.RepoTagsResponse
203
+
}
204
+
205
+
func (p *Pages) RepoTags(w io.Writer, params RepoTagsParams) error {
206
+
return p.execute("repo/tags", w, params)
207
+
}
+18
appview/pages/templates/repo/branches.html
+18
appview/pages/templates/repo/branches.html
···
1
+
{{ define "title" }}
2
+
branches | {{ .RepoInfo.OwnerWithAt }} /
3
+
{{ .RepoInfo.Name }}
4
+
{{ end }}
5
+
6
+
{{ define "content" }}
7
+
{{ $name := .RepoInfo.Name }}
8
+
<h3>branches</h3>
9
+
<div class="refs">
10
+
{{ range .Branches }}
11
+
<div>
12
+
<strong>{{ .Name }}</strong>
13
+
<a href="/{{ $name }}/tree/{{ .Name }}/">browse</a>
14
+
<a href="/{{ $name }}/log/{{ .Name }}">log</a>
15
+
</div>
16
+
{{ end }}
17
+
</div>
18
+
{{ end }}
+6
-8
appview/pages/templates/repo/empty.html
+6
-8
appview/pages/templates/repo/empty.html
···
1
-
<html>
2
-
{{ template "layouts/head" . }}
1
+
{{ define "title" }}{{ .RepoInfo.OwnerWithAt }} / {{ .RepoInfo.Name }}{{ end }}
3
2
4
-
<body>
5
-
<main></main>
6
-
<p>This is an empty Git repository. Push some commits here.</p>
7
-
</main>
8
-
</body>
9
-
</html>
3
+
{{ define "content" }}
4
+
<main>
5
+
<p>This is an empty Git repository. Push some commits here.</p>
6
+
</main>
7
+
{{ end }}
-38
appview/pages/templates/repo/refs.html
-38
appview/pages/templates/repo/refs.html
···
1
-
<html>
2
-
{{ template "layouts/head" . }}
3
-
4
-
{{ template "layouts/repo-header" . }}
5
-
<body>
6
-
{{ template "layouts/nav" . }}
7
-
<main>
8
-
{{ $name := .name }}
9
-
<h3>branches</h3>
10
-
<div class="refs">
11
-
{{ range .branches }}
12
-
<div>
13
-
<strong>{{ .Name.Short }}</strong>
14
-
<a href="/{{ $name }}/tree/{{ .Name.Short }}/">browse</a>
15
-
<a href="/{{ $name }}/log/{{ .Name.Short }}">log</a>
16
-
<a href="/{{ $name }}/archive/{{ .Name.Short }}.tar.gz">tar.gz</a>
17
-
</div>
18
-
{{ end }}
19
-
</div>
20
-
{{ if .tags }}
21
-
<h3>tags</h3>
22
-
<div class="refs">
23
-
{{ range .tags }}
24
-
<div>
25
-
<strong>{{ .Name }}</strong>
26
-
<a href="/{{ $name }}/tree/{{ .Name }}/">browse</a>
27
-
<a href="/{{ $name }}/log/{{ .Name }}">log</a>
28
-
<a href="/{{ $name }}/archive/{{ .Name }}.tar.gz">tar.gz</a>
29
-
{{ if .Message }}
30
-
<pre>{{ .Message }}</pre>
31
-
</div>
32
-
{{ end }}
33
-
{{ end }}
34
-
</div>
35
-
{{ end }}
36
-
</main>
37
-
</body>
38
-
</html>
+76
appview/state/repo.go
+76
appview/state/repo.go
···
175
175
return
176
176
}
177
177
178
+
func (s *State) RepoTags(w http.ResponseWriter, r *http.Request) {
179
+
repoName, knot, id, err := repoKnotAndId(r)
180
+
if err != nil {
181
+
log.Println("failed to get repo and knot", err)
182
+
return
183
+
}
184
+
185
+
resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s/tags", knot, id.DID.String(), repoName))
186
+
if err != nil {
187
+
log.Println("failed to reach knotserver", err)
188
+
return
189
+
}
190
+
191
+
body, err := io.ReadAll(resp.Body)
192
+
if err != nil {
193
+
log.Fatalf("Error reading response body: %v", err)
194
+
return
195
+
}
196
+
197
+
var result types.RepoTagsResponse
198
+
err = json.Unmarshal(body, &result)
199
+
if err != nil {
200
+
log.Println("failed to parse response:", err)
201
+
return
202
+
}
203
+
204
+
s.pages.RepoTags(w, pages.RepoTagsParams{
205
+
LoggedInUser: s.auth.GetUser(r),
206
+
RepoInfo: pages.RepoInfo{
207
+
OwnerDid: id.DID.String(),
208
+
OwnerHandle: id.Handle.String(),
209
+
Name: repoName,
210
+
},
211
+
RepoTagsResponse: result,
212
+
})
213
+
return
214
+
}
215
+
216
+
func (s *State) RepoBranches(w http.ResponseWriter, r *http.Request) {
217
+
repoName, knot, id, err := repoKnotAndId(r)
218
+
if err != nil {
219
+
log.Println("failed to get repo and knot", err)
220
+
return
221
+
}
222
+
223
+
resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s/branches", knot, id.DID.String(), repoName))
224
+
if err != nil {
225
+
log.Println("failed to reach knotserver", err)
226
+
return
227
+
}
228
+
229
+
body, err := io.ReadAll(resp.Body)
230
+
if err != nil {
231
+
log.Fatalf("Error reading response body: %v", err)
232
+
return
233
+
}
234
+
235
+
var result types.RepoBranchesResponse
236
+
err = json.Unmarshal(body, &result)
237
+
if err != nil {
238
+
log.Println("failed to parse response:", err)
239
+
return
240
+
}
241
+
242
+
s.pages.RepoBranches(w, pages.RepoBranchesParams{
243
+
LoggedInUser: s.auth.GetUser(r),
244
+
RepoInfo: pages.RepoInfo{
245
+
OwnerDid: id.DID.String(),
246
+
OwnerHandle: id.Handle.String(),
247
+
Name: repoName,
248
+
},
249
+
RepoBranchesResponse: result,
250
+
})
251
+
return
252
+
}
253
+
178
254
func repoKnotAndId(r *http.Request) (string, string, identity.Identity, error) {
179
255
repoName := chi.URLParam(r, "repo")
180
256
knot, ok := r.Context().Value("knot").(string)
+2
appview/state/state.go
+2
appview/state/state.go
+8
knotserver/git/git.go
+8
knotserver/git/git.go
+2
-1
knotserver/handler.go
+2
-1
knotserver/handler.go
+43
-7
knotserver/routes.go
+43
-7
knotserver/routes.go
···
316
316
return
317
317
}
318
318
319
-
func (h *Handle) Refs(w http.ResponseWriter, r *http.Request) {
319
+
func (h *Handle) Tags(w http.ResponseWriter, r *http.Request) {
320
320
path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
321
321
l := h.l.With("handler", "Refs")
322
322
···
329
329
tags, err := gr.Tags()
330
330
if err != nil {
331
331
// Non-fatal, we *should* have at least one branch to show.
332
-
l.Error("getting tags", "error", err.Error())
332
+
l.Warn("getting tags", "error", err.Error())
333
+
}
334
+
335
+
rtags := []*types.TagReference{}
336
+
for _, tag := range tags {
337
+
tr := types.TagReference{
338
+
Ref: types.Reference{
339
+
Name: tag.Name(),
340
+
Hash: tag.Hash().String(),
341
+
},
342
+
Tag: tag.TagObject(),
343
+
}
344
+
rtags = append(rtags, &tr)
345
+
}
346
+
347
+
resp := types.RepoTagsResponse{
348
+
Tags: rtags,
349
+
}
350
+
351
+
writeJSON(w, resp)
352
+
return
353
+
}
354
+
355
+
func (h *Handle) Branches(w http.ResponseWriter, r *http.Request) {
356
+
path := filepath.Join(h.c.Repo.ScanPath, didPath(r))
357
+
l := h.l.With("handler", "Branches")
358
+
359
+
gr, err := git.Open(path, "")
360
+
if err != nil {
361
+
notFound(w)
362
+
return
333
363
}
334
364
335
365
branches, err := gr.Branches()
···
339
369
return
340
370
}
341
371
342
-
data := make(map[string]interface{})
372
+
bs := []types.Branch{}
373
+
for _, branch := range branches {
374
+
b := types.Branch{}
375
+
b.Hash = branch.Hash().String()
376
+
b.Name = branch.Name().Short()
377
+
bs = append(bs, b)
378
+
}
343
379
344
-
data["branches"] = branches
345
-
data["tags"] = tags
346
-
data["desc"] = getDescription(path)
380
+
resp := types.RepoBranchesResponse{
381
+
Branches: bs,
382
+
}
347
383
348
-
writeJSON(w, data)
384
+
writeJSON(w, resp)
349
385
return
350
386
}
351
387
+23
types/repo.go
+23
types/repo.go
···
36
36
DotDot string `json:"dotdot,omitempty"`
37
37
Files []NiceTree `json:"files,omitempty"`
38
38
}
39
+
40
+
type TagReference struct {
41
+
Ref Reference `json:"ref,omitempty"`
42
+
Tag *object.Tag `json:"tag,omitempty"`
43
+
Message string `json:"message,omitempty"`
44
+
}
45
+
46
+
type Reference struct {
47
+
Name string `json:"name"`
48
+
Hash string `json:"hash"`
49
+
}
50
+
51
+
type Branch struct {
52
+
Reference `json:"reference"`
53
+
}
54
+
55
+
type RepoTagsResponse struct {
56
+
Tags []*TagReference `json:"tags,omitempty"`
57
+
}
58
+
59
+
type RepoBranchesResponse struct {
60
+
Branches []Branch `json:"branches,omitempty"`
61
+
}