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.
Refuse a protected-ref pattern that can never match
93c7cae8ebb7d6d853dca476851e2bd0cbe10079 · Keenan Nemetz · 18h ago · parent 2c988ecd
Refuse a protected-ref pattern that can never match acl protect stored any string: refs/head/main read like a protected branch in acl show while the hook compared it against refs/heads/main and matched nothing, so approvals and required checks were off on the branch everything lands on. Validate the pattern in forge/access, where the rule is stored, and call it from both acl protect add|set and the repository settings form. Only the two shapes IsProtected understands are accepted, exact ref and one trailing wildcard, the ref part must be a name git could store, and a singular category is named as the typo it is.
server/admin_test.go +17
| @@ -185,6 +185,23 @@ func TestRemoteAdminManagesAccountsAndRepos(t *testing.T) { | |||
| 185 | 185 | t.Fatalf("runners = %q", got) | |
| 186 | 186 | } | |
| 187 | 187 | ||
| 188 | // The remote surface applies the same rule as the local one: a pattern the | ||
| 189 | // hook can never match is refused and nothing is stored. | ||
| 190 | out, errOut, err = f.adminSSH(f.keyPath, nil, "acl", "protect", "add", "remote-demo", "refs/head/main") | ||
| 191 | if err == nil { | ||
| 192 | t.Fatalf("the remote admin stored a pattern that cannot match:\n%s", out) | ||
| 193 | } | ||
| 194 | if !strings.Contains(errOut, "refs/heads/main") { | ||
| 195 | t.Fatalf("the remote refusal does not name the fix:\n%s", errOut) | ||
| 196 | } | ||
| 197 | if fresh, err := f.srv.Repos.Open("remote-demo"); err != nil { | ||
| 198 | t.Fatal(err) | ||
| 199 | } else if acl, err := fresh.ACL(); err != nil { | ||
| 200 | t.Fatal(err) | ||
| 201 | } else if got := strings.Join(acl.Protected, ","); got != "refs/heads/main" { | ||
| 202 | t.Fatalf("the remote refusal changed the list: %q", got) | ||
| 203 | } | ||
| 204 | |||
| 188 | 205 | out, errOut, err = f.adminSSH(f.keyPath, nil, "repo", "rename", "remote-demo", "renamed-demo") | |
| 189 | 206 | if err != nil { | |
| 190 | 207 | t.Fatalf("repo rename: %v\nstdout: %s\nstderr: %s", err, out, errOut) | |