pub struct VaultRepo { /* private fields */ }Expand description
A handle to the git repository backing a vault.
Implementations§
Source§impl VaultRepo
impl VaultRepo
Sourcepub fn cas_ref(
&self,
refname: &str,
expected_old: Option<Oid>,
new: Oid,
) -> Result<(), Error>
pub fn cas_ref( &self, refname: &str, expected_old: Option<Oid>, new: Oid, ) -> Result<(), Error>
Atomically advance refname from expected_old to new, under git’s
ref lock (mirrors update-ref <new> <old>).
expected_old == None means the ref must not yet exist (the
initial-commit case). On any mismatch returns Error::CasConflict with
nothing applied — the ref is untouched.
Sourcepub fn commit_with_retry<F>(
&self,
refname: &str,
build: F,
) -> Result<Option<Oid>, Error>
pub fn commit_with_retry<F>( &self, refname: &str, build: F, ) -> Result<Option<Oid>, Error>
Advance refname with optimistic retry (default retry budget).
See Self::commit_with_retry_n.
Sourcepub fn commit_with_retry_n<F>(
&self,
refname: &str,
max_retries: u32,
build: F,
) -> Result<Option<Oid>, Error>
pub fn commit_with_retry_n<F>( &self, refname: &str, max_retries: u32, build: F, ) -> Result<Option<Oid>, Error>
Advance refname with optimistic retry. build is called with the
current tip (the parent to build on, None if the branch is unborn) and
returns Some(commit) to CAS onto that tip, or None to signal a
no-op — there is nothing to commit (e.g. the resulting tree is
identical to the base), so the ref is left untouched and the method
returns Ok(None). If the CAS loses to a concurrent advance, the tip is
re-read and build is called again on the new tip, up to max_retries
rebuilds.
The builder owns conflict policy: on a rebuild it re-validates its per-file preconditions against the new tip (GWS.4) and may itself return an error to abort (the reconsideration domino) instead of rebuilding.
Source§impl VaultRepo
impl VaultRepo
Sourcepub fn commit_changeset(
&self,
txn: &Changeset,
) -> Result<ChangesetResult, Error>
pub fn commit_changeset( &self, txn: &Changeset, ) -> Result<ChangesetResult, Error>
Apply txn as a single commit (see the module docs for the pipeline).
Aborts with Error::PreconditionFailed if any precondition is stale
(nothing committed, working tree untouched) and with Error::Other for
an empty changeset or duplicate change paths.
Source§impl VaultRepo
impl VaultRepo
Sourcepub fn begin_fanout(
&self,
id: &str,
worktree_path: &Path,
) -> Result<FanoutWorktree<'_>, Error>
pub fn begin_fanout( &self, id: &str, worktree_path: &Path, ) -> Result<FanoutWorktree<'_>, Error>
Open a fan-out scratch worktree (GWS.9). Creates a wip branch
wip/<id> at this repo’s current HEAD commit, then creates a git
worktree at worktree_path (must be OUTSIDE main’s working tree —
git refuses nested worktrees). Returns a FanoutWorktree whose
worktree_repo() is the substrate handle for all txns inside the
fan-out.
Errors if this branch is unborn (no commit to fork from) or detached.
Sourcepub fn open_fanout_worktree(
&self,
id: &str,
worktree_path: &Path,
) -> Result<FanoutInfo, Error>
pub fn open_fanout_worktree( &self, id: &str, worktree_path: &Path, ) -> Result<FanoutInfo, Error>
Stateless variant of Self::begin_fanout — does the same work but
returns a FanoutInfo handle that survives the call boundary
(where FanoutWorktree<'a>’s borrow on &self does not). The MCP
begin_transaction tool uses this so it can return to the agent
between the begin call and the eventual commit_transaction /
abandon_transaction.
Same preconditions: branch must be born + not detached.
Sourcepub fn merge_fanout_back(
&self,
info: &FanoutInfo,
strategy: MergeStrategy,
message: Option<&str>,
) -> Result<MergeBackResult, Error>
pub fn merge_fanout_back( &self, info: &FanoutInfo, strategy: MergeStrategy, message: Option<&str>, ) -> Result<MergeBackResult, Error>
Stateless merge-back. Mirrors FanoutWorktree::commit_fanout but
takes the info handle instead of consuming a borrowed FanoutWorktree.
Holds main’s commit lock for the critical section and ALWAYS attempts
cleanup (worktree + wip branch) — even on merge error.
Sourcepub fn abandon_fanout_by_info(&self, info: &FanoutInfo) -> Result<(), Error>
pub fn abandon_fanout_by_info(&self, info: &FanoutInfo) -> Result<(), Error>
Stateless abandon — cleanup the worktree + wip branch without touching main.
Sourcepub fn list_orphan_fanouts(&self) -> Result<Vec<OrphanFanout>, Error>
pub fn list_orphan_fanouts(&self) -> Result<Vec<OrphanFanout>, Error>
Scan this repo’s registered worktrees for wip-* entries — fanout
artifacts left over from a previous session. Pure read; never mutates.
Caller decides whether to clean each one up (via
Self::abandon_fanout_by_info if they can rebuild the FanoutInfo, or
manually via git worktree remove + git branch -D).
Source§impl VaultRepo
impl VaultRepo
Sourcepub fn materialize(&self, commit: Oid, paths: &[String]) -> Result<(), Error>
pub fn materialize(&self, commit: Oid, paths: &[String]) -> Result<(), Error>
Materialize paths from commit’s tree into the working tree, and sync
the index to that tree. For each path: present in the tree → write its
blob atomically (temp + rename, parent dirs created); absent → remove the
working-tree file if present. Idempotent (safe to re-run as a resync).
Source§impl VaultRepo
impl VaultRepo
Sourcepub fn blob_oid_of(content: &[u8]) -> Result<Oid, Error>
pub fn blob_oid_of(content: &[u8]) -> Result<Oid, Error>
The blob oid of content without writing it to the object DB — the
version token for bytes an agent read from the working tree. Equals the
blob oid that Self::build_tree would store for the same bytes, so a
token computed at read time can be compared directly against a base
tree’s entry at commit time.
Sourcepub fn check_preconditions(
&self,
base_tree: Option<Oid>,
preconditions: &[Precondition],
) -> Result<(), Error>
pub fn check_preconditions( &self, base_tree: Option<Oid>, preconditions: &[Precondition], ) -> Result<(), Error>
Validate every precondition against base_tree (the tree the changeset
is building on; None = an empty/unborn base where nothing exists).
Returns Ok(()) only if all match; the first mismatch aborts with
Error::PreconditionFailed (the whole changeset fails, nothing
applied).
Source§impl VaultRepo
impl VaultRepo
Sourcepub fn build_tree(
&self,
base: Option<Oid>,
changes: &[TreeChange],
) -> Result<Oid, Error>
pub fn build_tree( &self, base: Option<Oid>, changes: &[TreeChange], ) -> Result<Oid, Error>
Build a tree from base (a parent commit’s tree oid, or None for an
empty base) applying changes in an isolated in-memory index. Blobs
and the resulting tree are written to the object DB. The shared
.git/index is never touched. Returns the new tree oid.
Sourcepub fn commit_tree(
&self,
tree: Oid,
parents: &[Oid],
message: &str,
) -> Result<Oid, Error>
pub fn commit_tree( &self, tree: Oid, parents: &[Oid], message: &str, ) -> Result<Oid, Error>
Create a commit object from tree and parents without moving any
ref (this is commit-tree, not commit). The ref advance is a separate
CAS step (GWS.3). Returns the new commit oid.
Source§impl VaultRepo
impl VaultRepo
Sourcepub fn open(vault_root: &Path) -> Result<VaultRepo, Error>
pub fn open(vault_root: &Path) -> Result<VaultRepo, Error>
Open the git repository whose working tree root is vault_root, with a
private commit-lock registry. Use Self::open_with_locks when
multiple handles (e.g. a server managing several worktrees) must share
one registry.
Strict: vault_root must be the repository root (we do not walk parent
directories). Returns Error::NotARepo if there is no repo there.
Sourcepub fn open_with_locks(
vault_root: &Path,
commit_locks: Arc<CommitLocks>,
) -> Result<VaultRepo, Error>
pub fn open_with_locks( vault_root: &Path, commit_locks: Arc<CommitLocks>, ) -> Result<VaultRepo, Error>
Open at vault_root sharing the given commit-lock registry, so handles to
the same worktree serialize their commit critical sections.
Sourcepub fn open_with_locks_and_hook(
vault_root: &Path,
commit_locks: Arc<CommitLocks>,
commit_hook: Arc<dyn Fn(Option<Oid>, Oid) + Sync + Send>,
) -> Result<VaultRepo, Error>
pub fn open_with_locks_and_hook( vault_root: &Path, commit_locks: Arc<CommitLocks>, commit_hook: Arc<dyn Fn(Option<Oid>, Oid) + Sync + Send>, ) -> Result<VaultRepo, Error>
Open the repo with both a shared commit-lock registry AND a post-commit
hook. The hook fires once per successful commit_changeset, inside
the commit lock, after materialization (GWS.14 plumbing).
Multiple VaultRepo handles to the same worktree may install
different hooks; each handle’s hook fires only for changesets
applied through THAT handle. The server-side pattern is to install
the same hook on every cached handle for a given vault.
Sourcepub fn commit_locks(&self) -> Arc<CommitLocks> ⓘ
pub fn commit_locks(&self) -> Arc<CommitLocks> ⓘ
Clone the shared commit-lock registry — handed to a scratch worktree’s
VaultRepo (GWS.9) so all handles to the same repo’s worktrees keep
using one registry.
Sourcepub fn with_commit_lock<R>(
&self,
f: impl FnOnce() -> Result<R, Error>,
) -> Result<R, Error>
pub fn with_commit_lock<R>( &self, f: impl FnOnce() -> Result<R, Error>, ) -> Result<R, Error>
Run f while holding both the in-process mutex and a cross-process
advisory lock for this worktree. The lock spans ref CAS and working-tree
materialization, preventing two TurboVault processes from interleaving
checkout writes after independently successful commits.
Sourcepub fn is_git_repo(vault_root: &Path) -> bool
pub fn is_git_repo(vault_root: &Path) -> bool
Whether vault_root is the root of a git repository.
Sourcepub fn current_branch(&self) -> Option<String>
pub fn current_branch(&self) -> Option<String>
The current branch’s short name (e.g. main).
Returns None when HEAD is detached (points directly at a commit, no
branch). Works for an unborn branch too — the name exists before the
first commit.
Sourcepub fn head_ref(&self) -> Result<String, Error>
pub fn head_ref(&self) -> Result<String, Error>
The full ref name HEAD points at (e.g. refs/heads/main), even when the
branch is unborn. Errors if HEAD is detached (no branch ref).
Sourcepub fn head_oid(&self) -> Option<Oid>
pub fn head_oid(&self) -> Option<Oid>
The HEAD commit oid, or None when the branch is unborn (no commits).
Sourcepub fn is_unborn(&self) -> bool
pub fn is_unborn(&self) -> bool
Whether the current branch is unborn (a fresh repo with no commits).
Sourcepub fn git_commit_first_parent(&self, commit: Oid) -> Result<Option<Oid>, Error>
pub fn git_commit_first_parent(&self, commit: Oid) -> Result<Option<Oid>, Error>
First-parent oid of commit, or None for a root commit (the
initial commit on an unborn branch). Thin libgit2 wrapper exposed
so downstream consumers (the GWS.14 reindex drainer) can resolve a
commit’s parent without taking a direct git2 dep.
Sourcepub fn first_parent_range(
&self,
stop_exclusive: Option<Oid>,
tip: Oid,
) -> Result<Option<Vec<Oid>>, Error>
pub fn first_parent_range( &self, stop_exclusive: Option<Oid>, tip: Oid, ) -> Result<Option<Vec<Oid>>, Error>
First-parent commits in (stop_exclusive, tip], oldest-first.
tlx.5: the out-of-band ref listener uses this to enqueue EVERY commit a
multi-commit jump introduced (e.g. a git pull of N commits) instead of
only the new tip — otherwise the drainer diffs the tip against its first
parent and silently skips the intermediate commits’ changes.
Returns Ok(None) when stop_exclusive is set but is NOT on tip’s
FIRST-PARENT chain — a non-ff move (force-push, branch switch) OR a stop
reachable only through a merge’s second parent has no clean range, so the
caller falls back to best-effort (full coherence needs a restart; the
§8.4 limitation). With stop_exclusive == None, walks the whole
first-parent chain from tip to root.
Source§impl VaultRepo
impl VaultRepo
Sourcepub fn read_at(&self, commit: Oid, path: &str) -> Result<Option<Vec<u8>>, Error>
pub fn read_at(&self, commit: Oid, path: &str) -> Result<Option<Vec<u8>>, Error>
Read a path’s bytes at a specific commit. None if the path is absent
in that commit’s tree. The bytes-level preview for the rollback UI.
Sourcepub fn paths_changed_between(
&self,
a: Oid,
b: Oid,
) -> Result<Vec<String>, Error>
pub fn paths_changed_between( &self, a: Oid, b: Oid, ) -> Result<Vec<String>, Error>
The set of paths whose content differs between commits a and b.
For the rollback flow, pass the commit-to-undo as b and its parent as
a to get exactly the paths to restore.
Sourcepub fn diff_path_statuses(
&self,
a: Option<Oid>,
b: Oid,
) -> Result<Vec<(String, bool)>, Error>
pub fn diff_path_statuses( &self, a: Option<Oid>, b: Oid, ) -> Result<Vec<(String, bool)>, Error>
Per-path change status between two commits, or between the empty tree
and b when a is None (the initial-commit case).
Each entry is (path, present_in_b):
true→ path was added or modified inb(re-index it).false→ path was deleted inb(drop it from derived indexes).
Used by the GWS.14 reindex apply step, which needs to distinguish
“added/modified → parse + add to graph” from “deleted → remove from
graph”. paths_changed_between collapses both into one bag, which
loses the information.
Sourcepub fn build_restore_changeset(
&self,
target_commit: Oid,
paths: &[String],
message: impl Into<String>,
) -> Result<Option<Changeset>, Error>
pub fn build_restore_changeset( &self, target_commit: Oid, paths: &[String], message: impl Into<String>, ) -> Result<Option<Changeset>, Error>
Build a changeset that restores paths to their state at
target_commit, with a precondition on each path’s current blob at
HEAD (so a concurrent write since the restore was requested aborts the
whole thing loudly).
For each path:
- target has it + current has a different version →
update. - target has it + current absent →
create. - target lacks it + current has it →
delete. - target == current → skipped (no-op).
Returns Ok(None) when there is nothing to do (every path is already
at the target state). Errors if the branch is unborn.
Auto Trait Implementations§
impl !RefUnwindSafe for VaultRepo
impl !Sync for VaultRepo
impl !UnwindSafe for VaultRepo
impl Freeze for VaultRepo
impl Send for VaultRepo
impl Unpin for VaultRepo
impl UnsafeUnpin for VaultRepo
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
impl<T> Fruit for T
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
Source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more