+25
-3
appview/pages/pages.go
+25
-3
appview/pages/pages.go
···
127
127
return p.execute("user/profile", w, params)
128
128
}
129
129
130
+
type RepoInfo struct {
131
+
Name string
132
+
OwnerDid string
133
+
OwnerHandle string
134
+
}
135
+
136
+
func (r RepoInfo) OwnerWithAt() string {
137
+
if r.OwnerHandle != "" {
138
+
return fmt.Sprintf("@%s", r.OwnerHandle)
139
+
} else {
140
+
return r.OwnerDid
141
+
}
142
+
}
143
+
130
144
type RepoIndexParams struct {
131
145
LoggedInUser *auth.User
132
-
Name string
133
-
UserDid string
134
-
UserHandle string
146
+
RepoInfo RepoInfo
135
147
types.RepoIndexResponse
136
148
}
137
149
138
150
func (p *Pages) RepoIndexPage(w io.Writer, params RepoIndexParams) error {
139
151
return p.execute("repo/index", w, params)
140
152
}
153
+
154
+
type RepoLogParams struct {
155
+
LoggedInUser *auth.User
156
+
RepoInfo RepoInfo
157
+
types.RepoLogResponse
158
+
}
159
+
160
+
func (p *Pages) RepoLog(w io.Writer, params RepoLogParams) error {
161
+
return p.execute("repo/log", w, params)
162
+
}
+4
-10
appview/pages/templates/repo/index.html
+4
-10
appview/pages/templates/repo/index.html
···
1
-
{{define "title"}} {{ or .UserHandle .UserDid }} / {{ .Name }} {{end}}
1
+
{{define "title"}} {{ .RepoInfo.OwnerWithAt }} / {{ .RepoInfo.Name }} {{end}}
2
2
3
3
{{define "content"}}
4
-
{{- $id := "" -}}
5
-
{{- if .UserHandle -}}
6
-
{{- $id = printf "@%s" .UserHandle -}}
7
-
{{- else -}}
8
-
{{- $id = .UserDid -}}
9
-
{{- end -}}
10
4
11
5
<h1>
12
-
{{ $id }} / {{ .Name }}
6
+
{{ .RepoInfo.OwnerWithAt }} / {{ .RepoInfo.Name }}
13
7
</h1>
14
8
<main>
15
9
<div class="log">
16
10
{{ range .Commits }}
17
11
<div>
18
-
<div><a href="/{{ $id }}/{{ $.Name }}/commit/{{ .Hash.String }}" class="commit-hash">{{ slice .Hash.String 0 8 }}</a></div>
12
+
<div><a href="/{{ $.RepoInfo.OwnerWithAt }}/{{ $.RepoInfo.Name }}/commit/{{ .Hash.String }}" class="commit-hash">{{ slice .Hash.String 0 8 }}</a></div>
19
13
<pre>{{ .Message }}</pre>
20
14
</div>
21
15
<div class="commit-info">
···
33
27
<div class="clone-url">
34
28
<strong>clone</strong>
35
29
<pre>
36
-
git clone https://tangled.sh/{{ $id }}/{{ .Name }}
30
+
git clone https://tangled.sh/{{ .RepoInfo.OwnerWithAt }}/{{ .RepoInfo.Name }}
37
31
</pre>
38
32
</div>
39
33
</main>
+9
-10
appview/pages/templates/repo/log.html
+9
-10
appview/pages/templates/repo/log.html
···
1
-
<html>
2
-
{{ template "layouts/head" . }}
1
+
{{define "title"}} log | {{ .RepoInfo.OwnerWithAt }} / {{ .RepoInfo.Name }} {{end}}
3
2
4
-
{{ template "layouts/repo-header" . }}
5
-
<body>
6
-
{{ template "layouts/nav" . }}
3
+
{{define "content"}}
4
+
5
+
<h1>
6
+
log | {{ .RepoInfo.OwnerWithAt }} / {{ .RepoInfo.Name }}
7
+
</h1>
7
8
<main>
8
-
{{ $repo := .name }}
9
9
<div class="log">
10
-
{{ range .commits }}
10
+
{{ range .Commits }}
11
11
<div>
12
-
<div><a href="/{{ $repo }}/commit/{{ .Hash.String }}" class="commit-hash">{{ slice .Hash.String 0 8 }}</a></div>
12
+
<div><a href="/{{ $.RepoInfo.OwnerWithAt }}/{{ $.RepoInfo.Name }}/commit/{{ .Hash.String }}" class="commit-hash">{{ slice .Hash.String 0 8 }}</a></div>
13
13
<pre>{{ .Message }}</pre>
14
14
</div>
15
15
<div class="commit-info">
···
19
19
{{ end }}
20
20
</div>
21
21
</main>
22
-
</body>
23
-
</html>
22
+
{{end}}
+64
-20
appview/state/repo.go
+64
-20
appview/state/repo.go
···
14
14
)
15
15
16
16
func (s *State) RepoIndex(w http.ResponseWriter, r *http.Request) {
17
-
ctx := r.Context()
18
-
repoName := chi.URLParam(r, "repo")
19
-
20
-
knot, ok := ctx.Value("knot").(string)
21
-
if !ok {
22
-
log.Println("malformed middleware")
23
-
w.WriteHeader(http.StatusInternalServerError)
24
-
return
25
-
}
26
-
27
-
id, ok := ctx.Value("resolvedId").(identity.Identity)
28
-
if !ok {
29
-
log.Println("malformed middleware")
30
-
w.WriteHeader(http.StatusInternalServerError)
17
+
repoName, knot, id, err := repoKnotAndId(r)
18
+
if err != nil {
19
+
log.Println("failed to get repo and knot", err)
31
20
return
32
21
}
33
22
···
38
27
}
39
28
defer resp.Body.Close()
40
29
41
-
// Read the response body
42
30
body, err := io.ReadAll(resp.Body)
43
31
if err != nil {
44
32
log.Fatalf("Error reading response body: %v", err)
···
54
42
55
43
log.Println(resp.Status, result)
56
44
57
-
user := s.auth.GetUser(r)
58
45
s.pages.RepoIndexPage(w, pages.RepoIndexParams{
59
-
LoggedInUser: user,
60
-
UserDid: id.DID.String(),
61
-
UserHandle: id.Handle.String(),
62
-
Name: repoName,
46
+
LoggedInUser: s.auth.GetUser(r),
47
+
RepoInfo: pages.RepoInfo{
48
+
OwnerDid: id.DID.String(),
49
+
OwnerHandle: id.Handle.String(),
50
+
Name: repoName,
51
+
},
63
52
RepoIndexResponse: result,
64
53
})
65
54
66
55
return
67
56
}
57
+
58
+
func (s *State) RepoLog(w http.ResponseWriter, r *http.Request) {
59
+
repoName, knot, id, err := repoKnotAndId(r)
60
+
if err != nil {
61
+
log.Println("failed to get repo and knot", err)
62
+
return
63
+
}
64
+
65
+
ref := chi.URLParam(r, "ref")
66
+
resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s/log/%s", knot, id.DID.String(), repoName, ref))
67
+
if err != nil {
68
+
log.Println("failed to reach knotserver", err)
69
+
return
70
+
}
71
+
72
+
body, err := io.ReadAll(resp.Body)
73
+
if err != nil {
74
+
log.Fatalf("Error reading response body: %v", err)
75
+
return
76
+
}
77
+
78
+
var result types.RepoLogResponse
79
+
err = json.Unmarshal(body, &result)
80
+
if err != nil {
81
+
log.Println("failed to parse json response", err)
82
+
return
83
+
}
84
+
85
+
s.pages.RepoLog(w, pages.RepoLogParams{
86
+
LoggedInUser: s.auth.GetUser(r),
87
+
RepoInfo: pages.RepoInfo{
88
+
OwnerDid: id.DID.String(),
89
+
OwnerHandle: id.Handle.String(),
90
+
Name: repoName,
91
+
},
92
+
RepoLogResponse: result,
93
+
})
94
+
return
95
+
}
96
+
97
+
func repoKnotAndId(r *http.Request) (string, string, identity.Identity, error) {
98
+
repoName := chi.URLParam(r, "repo")
99
+
knot, ok := r.Context().Value("knot").(string)
100
+
if !ok {
101
+
log.Println("malformed middleware")
102
+
return "", "", identity.Identity{}, fmt.Errorf("malformed middleware")
103
+
}
104
+
id, ok := r.Context().Value("resolvedId").(identity.Identity)
105
+
if !ok {
106
+
log.Println("malformed middleware")
107
+
return "", "", identity.Identity{}, fmt.Errorf("malformed middleware")
108
+
}
109
+
110
+
return repoName, knot, id, nil
111
+
}
-14
appview/state/signer.go
-14
appview/state/signer.go
···
113
113
114
114
return s.client.Do(req)
115
115
}
116
-
117
-
func (s *SignedClient) RepoIndex(did, repo string) (*http.Response, error) {
118
-
const (
119
-
Method = "GET"
120
-
)
121
-
endpoint := fmt.Sprint("/%s/%s", did, repo)
122
-
123
-
req, err := s.newRequest(Method, endpoint, nil)
124
-
if err != nil {
125
-
return nil, err
126
-
}
127
-
128
-
return s.client.Do(req)
129
-
}
+3
appview/state/state.go
+3
appview/state/state.go
···
601
601
r.Get("/", s.ProfilePage)
602
602
r.With(ResolveRepoKnot(s)).Route("/{repo}", func(r chi.Router) {
603
603
r.Get("/", s.RepoIndex)
604
+
r.Get("/log/{ref}", s.RepoLog)
605
+
604
606
// These routes get proxied to the knot
605
607
r.Get("/info/refs", s.InfoRefs)
606
608
r.Post("/git-upload-pack", s.UploadPack)
609
+
607
610
})
608
611
})
609
612
+10
-9
knotserver/routes.go
+10
-9
knotserver/routes.go
···
266
266
commits = commits[start:end]
267
267
}
268
268
269
-
data := make(map[string]interface{})
270
-
data["commits"] = commits
271
-
data["ref"] = ref
272
-
data["desc"] = getDescription(path)
273
-
data["log"] = true
274
-
data["total"] = total
275
-
data["page"] = page
276
-
data["per_page"] = pageSize
269
+
resp := types.RepoLogResponse{
270
+
Commits: commits,
271
+
Ref: ref,
272
+
Description: getDescription(path),
273
+
Log: true,
274
+
Total: total,
275
+
Page: page,
276
+
PerPage: pageSize,
277
+
}
277
278
278
-
writeJSON(w, data)
279
+
writeJSON(w, resp)
279
280
return
280
281
}
281
282
+10
types/repo.go
+10
types/repo.go
···
13
13
Commits []*object.Commit `json:"commits,omitempty"`
14
14
Description string `json:"description,omitempty"`
15
15
}
16
+
17
+
type RepoLogResponse struct {
18
+
Commits []*object.Commit `json:"commits,omitempty"`
19
+
Ref string `json:"ref,omitempty"`
20
+
Description string `json:"description,omitempty"`
21
+
Log bool `json:"log,omitempty"`
22
+
Total int `json:"total,omitempty"`
23
+
Page int `json:"page,omitempty"`
24
+
PerPage int `json:"per_page,omitempty"`
25
+
}