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.

Phase 5: LFS objects, over SSH for writes and the proxy for reads

64ac5071a173e4e9ce8bc8d7170f9b0411bee52a · Keenan Nemetz · 17d 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/lfs/pointer_real_test.go +30

@@ -0,0 +1,30 @@
1 package lfs
2
3 import "testing"
4
5 // TestParsePointerFromARealClient pins the exact bytes git-lfs writes. An earlier
6 // version of this parser accepted a first line without the `version ` key and the
7 // hook silently stopped recognising pointers — the whole gate went quiet, and only
8 // the end-to-end test noticed.
9 func TestParsePointerFromARealClient(t *testing.T) {
10 text := "version https://git-lfs.github.com/spec/v1\n" +
11 "oid sha256:6c82914b2d961ffcbbe375c41515e962207893b7207bfd293d37e5cf58bb752b\n" +
12 "size 30\n"
13 if len(text) != 127 {
14 t.Fatalf("fixture is %d bytes; the client writes a 127-byte pointer for these fields", len(text))
15 }
16 p, ok := ParsePointer([]byte(text))
17 if !ok {
18 t.Fatalf("did not parse the bytes a client actually writes:\n%s", text)
19 }
20 if p.OID != "6c82914b2d961ffcbbe375c41515e962207893b7207bfd293d37e5cf58bb752b" || p.Size != 30 {
21 t.Fatalf("parsed %+v", p)
22 }
23 // A url with no `version` key is a filter line, not a pointer.
24 bare := "https://git-lfs.github.com/spec/v1\n" +
25 "oid sha256:6c82914b2d961ffcbbe375c41515e962207893b7207bfd293d37e5cf58bb752b\n" +
26 "size 30\n"
27 if _, ok := ParsePointer([]byte(bare)); ok {
28 t.Fatal("a bare url on the first line was accepted as a pointer")
29 }
30 }