vole
Clone
Read only, no credentials:
https://rodent.software/vole.git
Write over SSH with a registered key:
git clone ssh://git@rodent.software:2222/vole.git
A free and open-source forge that lives in your Git repo.
Phase 5: LFS objects, over SSH for writes and the proxy for reads
64ac5071a173e4e9ce8bc8d7170f9b0411bee52a · Keenan Nemetz · 18d ago · parent 35eaeccf
Phase 5: LFS objects, over SSH for writes and the proxy for reads Large files leave the git object database and land in one content-addressed store per instance. Reads are anonymous like clone; writes ride the SSH key that already authenticates the push, so no token exists anywhere. - internal/lfs: sha256-addressed store that verifies content and size before an object becomes visible; parser for the pointer format a client writes - HTTP: POST .../info/lfs/objects/batch for downloads, GET .../objects/<oid> with the object id as ETag; upload over HTTP is refused and names SSH - SSH: git-lfs-transfer speaking the pure SSH protocol (pkt-line), so `git lfs push` needs nothing but the key at the handshake - pre-receive: a pointer whose object is missing, or whose size disagrees with the stored object, fails the push that introduced it; a binary over lfs_warn_bytes is accepted with a `git lfs track` suggestion. Checks run before the protected-branch gate, because an admin's approval bypass is about review, not about whether the commit can be checked out - runs: a finished log becomes a content-addressed object in the same write that records the status, served at /r/<repo>/runs/<id>/log - vole gc [--dry-run] [--grace]: marks pointer targets from every ref in every repository plus archived logs, sweeps the rest. Mark-and-sweep rather than reference counts: a counter that is one too low deletes an artifact, a walk over the refs cannot be wrong about what is reachable
internal/hook/hook_test.go +12−7
| @@ -56,15 +56,20 @@ func newFixture(t *testing.T, blob string) *fixture { | |||
| 56 | 56 | ||
| 57 | 57 | func (f *fixture) run(actor, ref string, maxBlob int64) (int, string) { | |
| 58 | 58 | f.t.Helper() | |
| 59 | var out bytes.Buffer | ||
| 60 | code := PreReceive(Config{ | ||
| 61 | RepoDir: f.m.Dir, | ||
| 59 | return f.runWith(Config{ | ||
| 62 | 60 | Actor: actor, | |
| 63 | 61 | MaxBlobBytes: maxBlob, | |
| 64 | In: strings.NewReader(gitx.ZeroSHA + " " + f.head + " " + ref + "\n"), | ||
| 65 | Out: &out, | ||
| 66 | }) | ||
| 67 | return code, out.String() | ||
| 62 | }, ref) | ||
| 63 | } | ||
| 64 | |||
| 65 | // runWith runs pre-receive with a full config, so LFS rules can be exercised. | ||
| 66 | func (f *fixture) runWith(cfg Config, ref string) (int, string) { | ||
| 67 | f.t.Helper() | ||
| 68 | cfg.RepoDir = f.m.Dir | ||
| 69 | var out bytes.Buffer | ||
| 70 | cfg.In = strings.NewReader(gitx.ZeroSHA + " " + f.head + " " + ref + "\n") | ||
| 71 | cfg.Out = &out | ||
| 72 | return PreReceive(cfg), out.String() | ||
| 68 | 73 | } | |
| 69 | 74 | ||
| 70 | 75 | func (f *fixture) setACL(mut func(*acl.ACL)) { | |