Skip to main content

VaultRepo

Struct VaultRepo 

Source
pub struct VaultRepo { /* private fields */ }
Expand description

A handle to the git repository backing a vault.

Implementations§

Source§

impl VaultRepo

Source

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.

Source

pub fn commit_with_retry<F>( &self, refname: &str, build: F, ) -> Result<Option<Oid>, Error>
where F: FnMut(Option<Oid>) -> Result<Option<Oid>, Error>,

Advance refname with optimistic retry (default retry budget). See Self::commit_with_retry_n.

Source

pub fn commit_with_retry_n<F>( &self, refname: &str, max_retries: u32, build: F, ) -> Result<Option<Oid>, Error>
where F: FnMut(Option<Oid>) -> 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

Source

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

Source

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.

Source

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.

Source

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.

Source

pub fn abandon_fanout_by_info(&self, info: &FanoutInfo) -> Result<(), Error>

Stateless abandon — cleanup the worktree + wip branch without touching main.

Source

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

Source

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

pub fn resync_to_head(&self, paths: &[String]) -> Result<(), Error>

Re-materialize paths from the current HEAD commit (the resync entry point after a crash/partial materialization). No-op if the branch is unborn (nothing committed yet).

Source§

impl VaultRepo

Source

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.

Source

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

Source

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.

Source

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

pub fn blob_oid_at(&self, tree: Oid, path: &str) -> Result<Option<Oid>, Error>

The blob oid at path in tree, or None if absent. This is the value a changeset reads as its CAS pre-image (GWS.4) and what materialization resolves to working-tree bytes (GWS.5).

Source

pub fn read_blob(&self, oid: Oid) -> Result<Vec<u8>, Error>

Read a blob’s bytes by oid.

Source§

impl VaultRepo

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn is_git_repo(vault_root: &Path) -> bool

Whether vault_root is the root of a git repository.

Source

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.

Source

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).

Source

pub fn head_oid(&self) -> Option<Oid>

The HEAD commit oid, or None when the branch is unborn (no commits).

Source

pub fn is_unborn(&self) -> bool

Whether the current branch is unborn (a fresh repo with no commits).

Source

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.

Source

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

pub fn is_path_ignored(&self, path: &str) -> Result<bool, Error>

turbovault-lri: whether path (repo-root-relative) is excluded by any active .gitignore. Thin wrapper over libgit2’s is_path_ignored. Used by the substrate’s include_ignored policy enforcement.

Source§

impl VaultRepo

Source

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.

Source

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.

Source

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 in b (re-index it).
  • false → path was deleted in b (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.

Source

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§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts 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>

Converts 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)

Converts &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)

Converts &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
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Fruit for T
where T: Send + Downcast,

Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> MaybeSend for T
where T: Send + ?Sized,

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more