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.

Turn the code tab into an editor-style file browser

a464f8927bfb3edcf170694f120dc9b3f68320da · Keenan Nemetz · 15d ago · parent f09ef39e

Turn the code tab into an editor-style file browser

- Add a persistent nested file tree with HTMX file and folder swaps, active
  rows, expanded ancestors, and deep-link support.
- Share one page header across every repository tab: title and summary on the
  left, tab actions grouped on the right.
- Make the repository name the first tab and show visibility with a lock or
  globe icon derived from the ACL.
- Open markdown as syntax-highlighted source by default, with an explicit
  full-width preview toggle.
- Point the branch breadcrumb at the Code overview instead of a second root
  directory listing.
- Move contributor-branch CI approval from the code browser to the Runs tab.
- Extend UI tests for the file tree, fragments, repo visibility, markdown
  source/preview, shared headers, and the moved CI control.

server/auth_test.go +6−2

@@ -433,7 +433,7 @@ jobs:
433 433 }
434 434
435 435 contribSess, contribCookie := f.browserSession(t, contrib.ID)
436 resp, body := f.browserGet(t, "/r/"+f.repo+"/code", contribCookie)
436 resp, body := f.browserGet(t, "/r/"+f.repo+"/runs", contribCookie)
437 437 if resp.StatusCode != http.StatusOK || !strings.Contains(body, "waiting for a maintainer") {
438 438 t.Fatalf("contributor branch status: status=%d body=%s", resp.StatusCode, body)
439 439 }
@@ -445,10 +445,14 @@ jobs:
445 445 }
446 446
447 447 ownerSess, ownerCookie := f.browserSession(t, f.ownerID)
448 resp, body = f.browserGet(t, "/r/"+f.repo+"/code", ownerCookie)
448 resp, body = f.browserGet(t, "/r/"+f.repo+"/runs", ownerCookie)
449 449 if resp.StatusCode != http.StatusOK || !strings.Contains(body, "Allow CI for this tip") {
450 450 t.Fatalf("maintainer CI control missing: status=%d body=%s", resp.StatusCode, body)
451 451 }
452 resp, codePage := f.browserGet(t, "/r/"+f.repo+"/code", ownerCookie)
453 if resp.StatusCode != http.StatusOK || strings.Contains(codePage, "Allow CI for this tip") {
454 t.Fatalf("contributor CI control should not be in the code browser: status=%d body=%s", resp.StatusCode, codePage)
455 }
452 456 resp, body = f.browserPost(t, "/r/"+f.repo+"/ci/allow", ownerCookie, url.Values{
453 457 "csrf": {ownerSess.CSRF}, "ref": {"refs/heads/" + ref},
454 458 })