Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Phase 7 slice 1: review on the web, so approving does not start with a clone

78912785b00227cffe3f8fb26b057cd60159a6b4 · Keenan Nemetz · 18d ago · parent 9bea7f11

Phase 7 slice 1: review on the web, so approving does not start with a clone

Phase 7 is re-scoped: signing is deferred (the SSH handshake already establishes
who pushed, and there is no third-party verifier here), and the phase is now about
the experience of using the forge.

- GET /r/<repo>/commit/<sha>: a commit's metadata and the patch it introduced,
  per-file hunks with line numbers; the commit list links to it
- change requests show the same diff, computed three-dot: a review is what the
  branch adds since it diverged, not every commit main gained meanwhile
- diffs are capped at 512 KiB and labelled when cut, binary files are named
  rather than faked, and every line is escaped (a <script> line is a test)
- the repository README renders on its home page and markdown blobs render as
  markdown, through the sanitiser issues already use

internal/web/templates.go +56−7

@@ -46,6 +46,18 @@ select{background:var(--card);color:var(--fg);border:1px solid var(--line);borde
46 46 .md blockquote{margin:.6rem 0;padding-left:.8rem;border-left:3px solid var(--line);color:var(--muted)}
47 47 .md ul,.md ol{padding-left:1.4rem}
48 48 .md table{width:auto}
49 .diff{border:1px solid var(--line);border-radius:8px;margin:1rem 0;overflow:hidden}
50 .diff h3{margin:0;padding:.55rem .8rem;background:var(--card);border-bottom:1px solid var(--line);font-size:.9rem;font-weight:600}
51 .diff table{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.82rem;border-collapse:collapse}
52 .diff td{border:0;padding:0 .5rem;white-space:pre-wrap;word-break:break-word;vertical-align:top}
53 .diff td.ln{width:3.5rem;text-align:right;color:var(--muted);user-select:none;border-right:1px solid var(--line)}
54 .diff td.code{padding-left:.75rem}
55 .diff tr.add{background:rgba(46,160,67,.12)}
56 .diff tr.add td.ln{color:#3fb950}
57 .diff tr.del{background:rgba(248,81,73,.10)}
58 .diff tr.del td.ln{color:var(--bad)}
59 .diff tr.hunk td{color:var(--muted);background:var(--card);padding:.25rem .5rem;font-size:.78rem}
60 .diff .binary{padding:.7rem .8rem;color:var(--muted);font-size:.85rem}
49 61 </style>
50 62 </head>
51 63 <body>
@@ -107,6 +119,7 @@ select{background:var(--card);color:var(--fg);border:1px solid var(--line);borde
107 119 <h1>{{.Name}}</h1>
108 120 {{if .Description}}<p class="muted">{{.Description}}</p>{{end}}
109 121 {{if .Site}}<p class="muted">Site: <a href="{{.Site}}">{{.Site}}</a></p>{{end}}
122 {{if .Readme}}<div class="md readme">{{.Readme}}</div>{{end}}
110 123
111 124 <div class="row">
112 125 <div>
@@ -159,8 +172,8 @@ select{background:var(--card);color:var(--fg);border:1px solid var(--line);borde
159 172 <table>
160 173 {{range .Commits}}
161 174 <tr>
162 <td><span class="sha">{{short .SHA}}</span></td>
163 <td>{{.Subject}}</td>
175 <td><a class="sha" href="/r/{{$.Name}}/commit/{{.SHA}}">{{short .SHA}}</a></td>
176 <td><a href="/r/{{$.Name}}/commit/{{.SHA}}">{{.Subject}}</a></td>
164 177 <td class="muted">{{.Author}}</td>
165 178 <td class="muted">{{since .When}}</td>
166 179 </tr>
@@ -193,6 +206,41 @@ select{background:var(--card);color:var(--fg);border:1px solid var(--line);borde
193 206 {{template "footer" .}}
194 207 {{end}}
195 208
209 {{define "diff"}}
210 <p class="muted">{{len .Files}} file(s) changed{{if .Added}} · <span class="adds">+{{.Added}}</span>{{end}}{{if .Removed}} · <span class="dels">−{{.Removed}}</span>{{end}}{{if .Truncated}} · showing the first 512 KiB{{end}}</p>
211 {{range .Files}}
212 <div class="diff">
213 <h3>{{if and .OldPath (ne .OldPath .NewPath)}}{{.OldPath}} → {{end}}{{.Label}}{{if .Binary}} <span class="muted">binary</span>{{end}}</h3>
214 {{if .Binary}}
215 <p class="binary">Binary file: no line diff to show. Use <code>git show</code> to inspect it.</p>
216 {{end}}
217 {{if .Hunks}}
218 <table>
219 {{range .Hunks}}
220 <tr class="hunk"><td colspan="3">{{.Header}}</td></tr>
221 {{range .Lines}}
222 <tr class="{{.Kind}}">
223 <td class="ln">{{if .OldNo}}{{.OldNo}}{{end}}</td>
224 <td class="ln">{{if .NewNo}}{{.NewNo}}{{end}}</td>
225 <td class="code">{{.Text}}</td>
226 </tr>
227 {{end}}
228 {{end}}
229 </table>
230 {{end}}
231 </div>
232 {{end}}
233 {{end}}
234
235 {{define "commit"}}
236 {{template "header" .}}
237 <h1>{{.Commit.Subject}}</h1>
238 <p class="muted"><span class="sha">{{.Commit.SHA}}</span> · {{.Commit.Author}} · {{since .Commit.When}}</p>
239 {{if .Body}}<pre>{{.Body}}</pre>{{end}}
240 {{template "diff" .}}
241 {{template "footer" .}}
242 {{end}}
243
196 244 {{define "blob"}}
197 245 {{template "header" .}}
198 246 <h1><a href="/r/{{.Name}}">{{.Name}}</a></h1>
@@ -205,7 +253,8 @@ select{background:var(--card);color:var(--fg);border:1px solid var(--line);borde
205 253 <p class="muted">Binary file, {{.Size}} bytes. <a href="/r/{{.Name}}/raw/{{esc .Ref}}/{{.Path}}">Download it</a>.</p>
206 254 {{else}}
207 255 {{if .Truncated}}<p class="muted">Showing the first 1 MiB.</p>{{end}}
208 <pre>{{.Content}}</pre>
256 {{if .Markdown}}<div class="md">{{.Markdown}}</div>
257 {{else}}<pre>{{.Content}}</pre>{{end}}
209 258 {{end}}
210 259 {{template "footer" .}}
211 260 {{end}}
@@ -275,8 +324,8 @@ select{background:var(--card);color:var(--fg);border:1px solid var(--line);borde
275 324 <table>
276 325 {{range .Backlinks}}
277 326 <tr>
278 <td><span class="sha">{{short .SHA}}</span></td>
279 <td>{{.Subject}}</td>
327 <td><a class="sha" href="/r/{{$.Name}}/commit/{{.SHA}}">{{short .SHA}}</a></td>
328 <td><a href="/r/{{$.Name}}/commit/{{.SHA}}">{{.Subject}}</a></td>
280 329 <td class="muted">{{.Author}}</td>
281 330 <td class="muted">{{since .When}}</td>
282 331 </tr>
@@ -371,8 +420,8 @@ commit to land, plus <code>approvals/&lt;user&gt;.json</code> from each approver
371 420 <h2>What would land</h2>
372 421 {{if .AlreadyMerged}}
373 422 <p class="muted">Already merged into {{.Request.Base}}.</p>
374 {{else if .Changed}}
375 <ul class="files">{{range .Changed}}<li class="sha">{{.}}</li>{{end}}</ul>
423 {{else if .Files}}
424 {{template "diff" .}}
376 425 {{else}}
377 426 <p class="muted">No changes, or the head is not reachable from this repository yet.</p>
378 427 {{end}}