Conversation
This commit adds the ability to serve an immutable, shallow checkout of a git repository at a specific commit over NFS. It includes some minimal git metadata so that the git CLI can run read-only commands much like any other shallow checkout. Callers acquire a checkout before mounting /repos/<repo>/<commit> and release it after the guest stops. Concurrent guests share an export until its last lease is released. The checkout is read-only, including its synthetic Git metadata. The index assumes tracked files are unchanged, so this view is not suitable as the backing filesystem for a writable overlay. The backing storage is a bare git repo on disk per configured repository. This is preferred over packing all git repos into the same git storage that the existing gitstore uses for 2 main reasons; firstly the methods required of each store are fairly specialised to their use case, and secondly, I wanted to avoid moving into "interesting" territory for git storage. A store per repo keeps repository data separate for isolation and keeps us on the happy path for the kinds of use cases that git storage is generally well optimised for. Git repository NFS handles are stable SHA-256 hashes of the repository name, commit, and path. Their reverse mappings are kept in memory until the checkout's last lease is released. Unlike the go mod implementation, these mappings are not reconstructed on a cache miss: after release or restart, an old handle remains stale until the checkout is acquired and the path's mapping is registered again. This keeps checkout state bounded by active leases without coupling file identity to a lease's lifetime. The nfsexports package implements a multiplexer to allow us to serve multiple exports on the same NFS server, keeping compatibility with clients that rely on rpcbind. It carves out a namespace for the existing go mod NFS handles (64 bytes long), and a schema for adding other namespaces alongside the new git repo handle namespace. Signed-off-by: Tom Proctor <tomhjp@users.noreply.github.com>
tomhjp
force-pushed
the
tomhjp/git-repo-checkouts
branch
from
September 11, 2026 14:42
b727e44 to
c4d83b0
Compare
Member
|
an NFSv3 filehandle is 64 bytes (we conventional treat it as two 32 byte sections) but a git hash is only 20 bytes. I feel like we have plenty of space to play some encoding games on mapping e.g. "7th entry of tree XXXXXX" in the handle, so then we can just do a git lookup of tree object XXXXX and find the 7th entry to get back to the hash of the file, etc? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This commit adds the ability to serve an immutable, shallow checkout of a git repository at a specific commit over NFS. It includes some minimal git metadata so that the git CLI can run read-only commands much like any other shallow checkout.
Callers acquire a checkout before mounting /repos// and release it after the guest stops. Concurrent guests share an export until its last lease is released. The checkout is read-only, including its synthetic Git metadata. The index assumes tracked files are unchanged, so this view is not suitable as the backing filesystem for a writable overlay.
The backing storage is a bare git repo on disk per configured repository. This is preferred over packing all git repos into the same git storage that the existing gitstore uses for 2 main reasons; firstly the methods required of each store are fairly specialised to their use case, and secondly, I wanted to avoid moving into "interesting" territory for git storage. A store per repo keeps repository data separate for isolation and keeps us on the happy path for the kinds of use cases that git storage is generally well optimised for.
Git repository NFS handles are stable SHA-256 hashes of the repository name, commit, and path. Their reverse mappings are kept in memory until the checkout's last lease is released. Unlike the go mod implementation, these mappings are not reconstructed on a cache miss: after release or restart, an old handle remains stale until the checkout is acquired and the path's mapping is registered again. This keeps checkout state bounded by active leases without coupling file identity to a lease's lifetime.
The nfsexports package implements a multiplexer to allow us to serve multiple exports on the same NFS server, keeping compatibility with clients that rely on rpcbind. It carves out a namespace for the existing go mod NFS handles (64 bytes long), and a schema for adding other namespaces alongside the new git repo handle namespace.