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.
Store changes under changes/<ulid>/change.md
b492b557f5cc5633b3dcb21fdbb5e2ad98d0bc16 · Keenan Nemetz · 3d ago · parent 9bce3723
Store changes under changes/<ulid>/change.md The web, the CLI, and the docs call these items changes; only the metadata tree still said requests. Rename the directory and the record file so the format and the product use one word. The tree is a contract, so this is a format change rather than a display change: the top-level layout stays closed, and a request path no longer validates. An existing repository is migrated by rewriting its vole branch, which is an audited admin force-push; the index rebuilds from the new tip and the #N aliases keep their ULIDs because the rewrite preserves commit order. Refs #202 (01M6S3JC3Y2KA6EFJK6APX7A1T).
server/web_test.go +8−8
| @@ -85,7 +85,7 @@ func TestRequestPageShowsWhatWouldLand(t *testing.T) { | |||
| 85 | 85 | ||
| 86 | 86 | meta := f.newMetaRepo(t) | |
| 87 | 87 | if err := meta.apply(map[string]string{ | |
| 88 | "requests/" + reqID + "/request.md": requestFile("main", head, "keenan", "why this change\n"), | ||
| 88 | "changes/" + reqID + "/change.md": requestFile("main", head, "keenan", "why this change\n"), | ||
| 89 | 89 | }, "request"); err != nil { | |
| 90 | 90 | t.Fatalf("request push: %v", err) | |
| 91 | 91 | } | |
| @@ -156,7 +156,7 @@ func TestMergedRequestStillShowsWhatLanded(t *testing.T) { | |||
| 156 | 156 | ||
| 157 | 157 | meta := f.newMetaRepo(t) | |
| 158 | 158 | if err := meta.apply(map[string]string{ | |
| 159 | "requests/" + reqID + "/request.md": requestFile("main", head, "keenan", "why this change\n"), | ||
| 159 | "changes/" + reqID + "/change.md": requestFile("main", head, "keenan", "why this change\n"), | ||
| 160 | 160 | }, "request"); err != nil { | |
| 161 | 161 | t.Fatalf("request push: %v", err) | |
| 162 | 162 | } | |
| @@ -167,7 +167,7 @@ func TestMergedRequestStillShowsWhatLanded(t *testing.T) { | |||
| 167 | 167 | // The landing names where the branch started from, in the same commit that says | |
| 168 | 168 | // it landed. | |
| 169 | 169 | record, _, err := runGit(t, filepath.Join(f.cfg.ReposDir(), f.repo+".git"), | |
| 170 | "show", "refs/heads/vole:requests/"+reqID+"/request.md") | ||
| 170 | "show", "refs/heads/vole:changes/"+reqID+"/change.md") | ||
| 171 | 171 | if err != nil { | |
| 172 | 172 | t.Fatalf("read the record: %v", err) | |
| 173 | 173 | } | |
| @@ -231,7 +231,7 @@ func TestRequestRecordsTheBranchItCameFrom(t *testing.T) { | |||
| 231 | 231 | t.Fatalf("change new: %v\n%s", err, errs) | |
| 232 | 232 | } | |
| 233 | 233 | id := strings.Fields(out)[0] | |
| 234 | recordPath := "refs/heads/vole:requests/" + id + "/request.md" | ||
| 234 | recordPath := "refs/heads/vole:changes/" + id + "/change.md" | ||
| 235 | 235 | record, _, err := runGit(t, filepath.Join(f.cfg.ReposDir(), f.repo+".git"), "show", recordPath) | |
| 236 | 236 | if err != nil { | |
| 237 | 237 | t.Fatalf("read the request: %v", err) | |
| @@ -281,7 +281,7 @@ func TestRequestRecordsTheBranchItCameFrom(t *testing.T) { | |||
| 281 | 281 | t.Fatalf("the fixup did not create a new tip") | |
| 282 | 282 | } | |
| 283 | 283 | record, _, err = runGit(t, filepath.Join(f.cfg.ReposDir(), f.repo+".git"), | |
| 284 | "show", "refs/heads/vole:requests/"+id+"/request.md") | ||
| 284 | "show", "refs/heads/vole:changes/"+id+"/change.md") | ||
| 285 | 285 | if err != nil { | |
| 286 | 286 | t.Fatalf("read the followed request: %v", err) | |
| 287 | 287 | } | |
| @@ -312,7 +312,7 @@ func TestRequestRecordsTheBranchItCameFrom(t *testing.T) { | |||
| 312 | 312 | } | |
| 313 | 313 | commitID := strings.Fields(out)[0] | |
| 314 | 314 | record, _, err = runGit(t, filepath.Join(f.cfg.ReposDir(), f.repo+".git"), | |
| 315 | "show", "refs/heads/vole:requests/"+commitID+"/request.md") | ||
| 315 | "show", "refs/heads/vole:changes/"+commitID+"/change.md") | ||
| 316 | 316 | if err != nil { | |
| 317 | 317 | t.Fatalf("read the commit request: %v", err) | |
| 318 | 318 | } | |
| @@ -504,8 +504,8 @@ func TestChangeListFiltersMergedRequests(t *testing.T) { | |||
| 504 | 504 | ) | |
| 505 | 505 | meta := f.newMetaRepo(t) | |
| 506 | 506 | if err := meta.apply(map[string]string{ | |
| 507 | "requests/" + openID + "/request.md": requestFileTitled("Still open", "main", head, "keenan", "open body\n"), | ||
| 508 | "requests/" + mergedID + "/request.md": requestFileTitled("Already landed", "main", head, "keenan", "merged body\n"), | ||
| 507 | "changes/" + openID + "/change.md": requestFileTitled("Still open", "main", head, "keenan", "open body\n"), | ||
| 508 | "changes/" + mergedID + "/change.md": requestFileTitled("Already landed", "main", head, "keenan", "merged body\n"), | ||
| 509 | 509 | }, "requests"); err != nil { | |
| 510 | 510 | t.Fatalf("requests push: %v", err) | |
| 511 | 511 | } | |