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/requests.go +15−6

@@ -114,18 +114,23 @@ func (w *Web) RequestView(rw http.ResponseWriter, r *http.Request) {
114 114 }
115 115
116 116 // The diff is computed from git on every view: it is cheap for one branch and
117 // always matches what the approver is being asked to approve.
118 var changed []string
117 // always matches what the approver is being asked to approve. Three-dot range:
118 // a review is about what the branch adds since it diverged, not about every
119 // commit main gained meanwhile.
120 var files []diffFile
121 truncated := false
119 122 alreadyMerged := false
120 123 if req.Head != "" {
121 if files, err := m.Git().DiffNameStatus(req.Base, req.Head); err == nil {
122 changed = files
124 if patch, cut, err := m.Git().Diff(req.Base+"..."+req.Head, "", diffCap); err == nil {
125 files = parseDiff(patch)
126 truncated = cut
123 127 }
124 128 // An empty diff means one of two very different things, so say which.
125 129 if in, err := m.Git().IsAncestor(req.Head, req.Base); err == nil && in {
126 130 alreadyMerged = true
127 131 }
128 132 }
133 added, removed := diffSummary(files)
129 134 w.render(rw, "request", struct {
130 135 Page
131 136 Name string
@@ -133,8 +138,12 @@ func (w *Web) RequestView(rw http.ResponseWriter, r *http.Request) {
133 138 Description template.HTML
134 139 Approvals []requestApproval
135 140 Checks []checkRow
136 Changed []string
141 Files []diffFile
142 Added int
143 Removed int
144 Truncated bool
137 145 AlreadyMerged bool
138 146 }{Page: w.base(m.Name + " · " + req.Title), Name: m.Name, Request: req,
139 Description: w.renderMarkdown(m.Name, req.Description), Approvals: approvals, Checks: checks, Changed: changed, AlreadyMerged: alreadyMerged}, 0)
147 Description: w.renderMarkdown(m.Name, req.Description), Approvals: approvals, Checks: checks,
148 Files: files, Added: added, Removed: removed, Truncated: truncated, AlreadyMerged: alreadyMerged}, 0)
140 149 }