Skip to main content

FsStore

Struct FsStore 

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

Filesystem-based storage for Heddle objects.

Layout:

.heddle/
  objects/
    blobs/
      ab/
        cdef1234...
    trees/
      ab/
        cdef1234...
    states/
      <change_id>.state
  actions/
    <action_id>.action
  packs/
    <hash>.pack
    <hash>.idx

Implementations§

Source§

impl FsStore

Source

pub fn new(root: impl AsRef<Path>) -> Self

Create a new filesystem store rooted at the given path.

The path should be the .heddle directory.

Source

pub fn with_compression( root: impl AsRef<Path>, compression: CompressionConfig, ) -> Self

Create a new filesystem store with custom compression settings.

Source

pub fn init(&self) -> Result<()>

Initialize the directory structure.

Source

pub fn root(&self) -> &Path

Get the root path.

Source

pub fn compression(&self) -> CompressionConfig

Get the compression configuration.

Source

pub fn set_compression(&mut self, compression: CompressionConfig)

Set the compression configuration.

Source

pub fn loose_object_write_mode(&self) -> LooseObjectWriteMode

Source

pub fn set_loose_object_write_mode(&mut self, mode: LooseObjectWriteMode)

Source

pub fn reload_packs(&self) -> Result<()>

Reload pack files from disk.

Source

pub fn pack_manager(&self) -> &RwLock<PackManager>

Get the pack manager for pack operations.

Source

pub fn clear_recent_object_caches(&self)

Source

pub fn pack_ids(&self) -> Result<Vec<PackObjectId>>

Trait Implementations§

Source§

impl ObjectStore for FsStore

Source§

fn loose_blob_path(&self, hash: &ContentHash) -> Option<PathBuf>

Loose blob path safe for hardlink/clonefile materialization.

Returns Some(path) only when the loose file exists and is stored uncompressed — then the on-disk bytes are byte-identical to the blob’s content, so a hard link materializes the worktree file without an extra copy. Compressed blobs and pack-only blobs fall through to None and the caller writes decompressed bytes the slow way.

Source§

fn promote_to_loose_uncompressed(&self, hash: &ContentHash) -> Result<bool>

Promote a blob to its uncompressed-loose canonical path so loose_blob_path returns Some(path) and hardlink-first materialization fires.

Three cases:

  1. Already loose+uncompressed: peek the header, no-op.
  2. Loose but compressed: read+decompress, atomically rewrite the canonical path with raw bytes.
  3. Pack-only: read out of the pack via get_blob, atomically write to the canonical loose path. Pack copy is left in place — the next prune cycle will discard the loose mirror and a future materialize will re-promote.
Source§

fn get_blob(&self, hash: &ContentHash) -> Result<Option<Blob>>

Source§

fn put_blob(&self, blob: &Blob) -> Result<ContentHash>

Source§

fn put_blob_with_hash( &self, blob: &Blob, hash: ContentHash, ) -> Result<ContentHash>

Source§

fn put_blob_bytes_with_hash( &self, data: &[u8], hash: ContentHash, ) -> Result<ContentHash>

Source§

fn has_blob(&self, hash: &ContentHash) -> Result<bool>

Source§

fn blob_size(&self, hash: &ContentHash) -> Result<Option<u64>>

Return the uncompressed byte length of the blob identified by hash, or Ok(None) when the blob is not in the store. Read more
Source§

fn get_tree(&self, hash: &ContentHash) -> Result<Option<Tree>>

Source§

fn put_tree(&self, tree: &Tree) -> Result<ContentHash>

Source§

fn put_tree_serialized( &self, data: &[u8], hash: ContentHash, ) -> Result<ContentHash>

Source§

fn has_tree(&self, hash: &ContentHash) -> Result<bool>

Source§

fn get_state(&self, id: &ChangeId) -> Result<Option<State>>

Source§

fn put_state(&self, state: &State) -> Result<()>

Source§

fn put_state_serialized(&self, data: &[u8], id: ChangeId) -> Result<()>

Source§

fn has_state(&self, id: &ChangeId) -> Result<bool>

Source§

fn list_states(&self) -> Result<Vec<ChangeId>>

Source§

fn get_action(&self, id: &ActionId) -> Result<Option<Action>>

Source§

fn put_action(&self, action: &mut Action) -> Result<ActionId>

Source§

fn list_actions(&self) -> Result<Vec<ActionId>>

Source§

fn list_blobs(&self) -> Result<Vec<ContentHash>>

Source§

fn list_trees(&self) -> Result<Vec<ContentHash>>

Source§

fn pack_objects(&self, aggressive: bool) -> Result<(u64, u64)>

Source§

fn get_pack_object( &self, id: &PackObjectId, ) -> Result<Option<(ObjectType, Vec<u8>)>>

Source§

fn install_pack( &self, pack_data: &[u8], index_data: &[u8], ) -> Result<Vec<PackObjectId>>

Source§

fn put_blobs_packed(&self, blobs: Vec<(ContentHash, Vec<u8>)>) -> Result<()>

Bulk-write a batch of blobs as a single durable unit. The default implementation falls back to per-blob writes; backends that support packfiles (i.e. FsStore) override this to install one packfile + index — two fsyncs total instead of N. Used by the snapshot hot path so writing 1000 small files takes ~one fsync, not 1000. Read more
Source§

fn install_pack_streaming( &self, pack_path: &Path, index_path: &Path, ) -> Result<()>

Install a pack and its index from on-disk files (typically produced by StreamingPackBuilder). The default impl reads both files fully and delegates to install_pack, so any backend that doesn’t override this still works (at the cost of giving back the bounded-memory promise). Real fs- backed stores override this to rename(2) both files into the pack directory without ever loading them. Read more
Source§

fn prune_loose_objects(&self) -> Result<(u64, u64)>

Source§

fn begin_snapshot_write_batch(&self) -> Result<()>

Source§

fn flush_snapshot_write_batch(&self) -> Result<()>

Source§

fn abort_snapshot_write_batch(&self)

Source§

fn put_action_serialized(&self, data: &[u8], id: ActionId) -> Result<()>

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<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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