vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
Let the browser edit issue and change details
a4e7a99a9ecf697586abdb884351a722fc25a864 · Keenan Nemetz · 5d ago · parent de84c32b
Let the browser edit issue and change details An issue's title and description could only be corrected with the CLI, and a change request's prose could not be corrected at all after it was opened. Add an edit page for each, offered to the author and to a maintainer. A change edit writes through a new metadata writer so the record is still validated, and neither edit touches the discussion, labels, or review state.
metadata/request_write.go +37
| @@ -151,6 +151,43 @@ func GetRequest(g *git.Repo, id string) (*Request, error) { | |||
| 151 | 151 | return req, nil | |
| 152 | 152 | } | |
| 153 | 153 | ||
| 154 | // SetRequestDetails replaces the title and description of a request. The prose is | ||
| 155 | // not what an approval names — that is the base and head — so correcting it does | ||
| 156 | // not start the review over, and it stays possible after the request is closed or | ||
| 157 | // merged, when a record with a typo is still worth fixing. The writer validates the | ||
| 158 | // whole record, so an edit cannot leave a request the reader would refuse. | ||
| 159 | func SetRequestDetails(g *git.Repo, id, title, body, actor string) (*Request, error) { | ||
| 160 | title = strings.TrimSpace(title) | ||
| 161 | var out *Request | ||
| 162 | base := fmt.Sprintf("%s/%s/", RequestsDir, id) | ||
| 163 | _, err := git.CommitFiles(g, Ref, func(files map[string][]byte) error { | ||
| 164 | r, err := loadFrom(files, id) | ||
| 165 | if err != nil { | ||
| 166 | return err | ||
| 167 | } | ||
| 168 | if r.Title == title && r.Description == body { | ||
| 169 | out = r | ||
| 170 | return ErrNoChange | ||
| 171 | } | ||
| 172 | r.Title = title | ||
| 173 | r.Description = body | ||
| 174 | if err := validateRequestForWrite(r); err != nil { | ||
| 175 | return err | ||
| 176 | } | ||
| 177 | raw, err := renderRequest(r) | ||
| 178 | if err != nil { | ||
| 179 | return err | ||
| 180 | } | ||
| 181 | files[base+requestName] = raw | ||
| 182 | out = r | ||
| 183 | return nil | ||
| 184 | }, fmt.Sprintf("request: update %s", id), actor) | ||
| 185 | if errors.Is(err, ErrNoChange) { | ||
| 186 | return out, nil | ||
| 187 | } | ||
| 188 | return out, err | ||
| 189 | } | ||
| 190 | |||
| 154 | 191 | // SetRequestHead repoints an open request at a commit and, optionally, at the | |
| 155 | 192 | // branch it should follow. A non-empty headRef makes the request follow that | |
| 156 | 193 | // branch, so the next push moves the head again; an empty one pins it to head. | |