1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
|
diff --git a/internal/handler/log.go b/internal/handler/log.go
new file mode 100644
index 0000000000000000000000000000000000000000..b78e2014fb26f05fc714ca3120d5847e28827caf
--- /dev/null
+++ b/internal/handler/log.go
@@ -0,0 +1,42 @@
+package handler
+
+import (
+ "net/url"
+ "time"
+
+ "git.sr.ht/~mpldr/gogit/internal/conman"
+ "git.sr.ht/~mpldr/gogit/internal/handler/templates"
+ "git.sr.ht/~mpldr/gogit/internal/types"
+ "github.com/go-git/go-git/v5"
+ "github.com/valyala/fasthttp"
+)
+
+func logHandler(repo *types.Repo) fasthttp.RequestHandler {
+ return func(ctx *fasthttp.RequestCtx) {
+ settings := &git.LogOptions{
+ All: true,
+ Order: git.LogOrderCommitterTime,
+ }
+
+ if ctx.QueryArgs().Peek("before") != nil {
+ before := repo.Commit(string(ctx.QueryArgs().Peek("before")))
+ if before != nil {
+ timestampBefore := before.Committer.When.Add(-1 * time.Millisecond)
+ settings.Until = ×tampBefore
+ }
+ }
+
+ history := repo.Log(settings)
+
+ u, _ := url.Parse(ctx.URI().String())
+ data := &templates.LogData{
+ Commits: history,
+ URL: u,
+ }
+
+ log := conman.GetLogger(ctx)
+ log.Debug("rendering log", "repo", repo.Name)
+ ctx.SetContentType("text/html; charset=utf-8")
+ templates.Log(data)(ctx)
+ }
+}
diff --git a/internal/handler/repo.go b/internal/handler/repo.go
index 16f49ce131fa683b57168ca0582fc453b948ebe3..216445ed19d73642491c5fd433b44df5591974cf 100644
--- a/internal/handler/repo.go
+++ b/internal/handler/repo.go
@@ -17,6 +17,8 @@ operation = strings.SplitN(strings.TrimPrefix(operation, "/"), "/", 2)[0]
switch operation {
case "":
templates.Overview(repo)(ctx)
+ case "log":
+ logHandler(repo)(ctx)
case "commit":
commitHandler(repo)(ctx)
default:
diff --git a/internal/handler/templates/functions.go b/internal/handler/templates/functions.go
index a79b21ec4b7fa5e2500c6deeed6dd36b9be67653..42add36876d35ba8edbee87257ddca233b2425d7 100644
--- a/internal/handler/templates/functions.go
+++ b/internal/handler/templates/functions.go
@@ -3,6 +3,7 @@
import (
"bytes"
"html/template"
+ "net/url"
"sort"
"strings"
@@ -14,11 +15,12 @@ "github.com/alecthomas/chroma/styles"
)
var functions = template.FuncMap{
- "toCategoryMap": toCategoryMap,
- "commitTitle": commitTitle,
- "trimTitle": trimTitle,
- "shorten": shorten,
- "colorize": colorize,
+ "toCategoryMap": toCategoryMap,
+ "commitTitle": commitTitle,
+ "trimTitle": trimTitle,
+ "shorten": shorten,
+ "colorize": colorize,
+ "addQueryParameter": addQueryParameter,
}
type ReposByCategory struct {
@@ -87,3 +89,10 @@ buf.WriteString("</style>")
_ = formatter.Format(&buf, style, iterator)
return template.HTML(buf.String())
}
+
+func addQueryParameter(key, value string, url *url.URL) *url.URL {
+ q := url.Query()
+ q.Set(key, value)
+ url.RawQuery = q.Encode()
+ return url
+}
diff --git a/internal/handler/templates/log.go b/internal/handler/templates/log.go
new file mode 100644
index 0000000000000000000000000000000000000000..48b6572e40509705abf61fb3787f9388bd5a20ab
--- /dev/null
+++ b/internal/handler/templates/log.go
@@ -0,0 +1,27 @@
+package templates
+
+import (
+ "html/template"
+ "log/slog"
+ "net/url"
+
+ "git.sr.ht/~mpldr/gogit/internal/types"
+ "github.com/valyala/fasthttp"
+)
+
+var logTmpl *template.Template
+
+func Log(data *LogData) fasthttp.RequestHandler {
+ return func(ctx *fasthttp.RequestCtx) {
+ ctx.SetContentType("text/html; charset=utf-8")
+ err := logTmpl.Execute(ctx, data)
+ if err != nil {
+ slog.Error("failed to execute template", "template", "log", "error", err)
+ }
+ }
+}
+
+type LogData struct {
+ Commits []*types.Commit
+ URL *url.URL
+}
diff --git a/internal/handler/templates/parse.go b/internal/handler/templates/parse.go
index f52ee0fff9122b3c80e5df399b0f07bb9024fb01..e20e75a1eeafe7d312ff5e15760c7caa439ce300 100644
--- a/internal/handler/templates/parse.go
+++ b/internal/handler/templates/parse.go
@@ -39,4 +39,5 @@ var templateMapping = map[string]**template.Template{
"index": &indexTmpl,
"overview": &overviewTmpl,
"commit": &commitTmpl,
+ "log": &logTmpl,
}
diff --git a/internal/types/repo.go b/internal/types/repo.go
index b03cb16576b7654feae881a5b8a0d9a8e1c52aee..2e67222cf8a0db1fdb5a20d47aa9c971b342d71e 100644
--- a/internal/types/repo.go
+++ b/internal/types/repo.go
@@ -122,3 +122,21 @@ return nil
}
return NewCommit(commit, r)
}
+
+func (r *Repo) Log(opts *git.LogOptions) []*Commit {
+ commits, err := r.repo.Log(opts)
+ if err != nil {
+ return nil
+ }
+
+ var results []*Commit
+ for i := 0; i < 20; i++ {
+ commit, err := commits.Next()
+ if err != nil {
+ break
+ }
+ results = append(results, NewCommit(commit, r))
+ }
+
+ return results
+}
diff --git a/themes/i-am-too-lazy-to-make-a-theme/log.html b/themes/i-am-too-lazy-to-make-a-theme/log.html
new file mode 100644
index 0000000000000000000000000000000000000000..ef3122929e39af237ff6c7b97940d82ea4bc01a2
--- /dev/null
+++ b/themes/i-am-too-lazy-to-make-a-theme/log.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Log</title>
+ </head>
+ <body>
+ <h1 class="title">
+ Log
+ </h1>
+ {{$before := ""}}
+ {{if not .Commits}}No commits to show{{end}}
+ {{range .Commits}}
+ <h3><a href="../commit/{{.Hash}}">{{.Message | commitTitle}}</a></h3>
+ <p>
+ by <code>{{.Author.Name}} <{{.Author.Email}}></code> ({{.Author.When.Format "2006-01-02 15:04:05"}})
+ {{$before = .Hash.String}}
+ </p>
+ {{end}}
+ {{if .Commits}}
+ <a href="{{(.URL | addQueryParameter "before" $before).String}}">Earlier →</a>
+ {{end}}
+ </body>
+</html>
|