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/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)