Skip to main content

Odb

Struct Odb 

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

A loose-object database rooted at a given objects/ directory.

§Examples

use grit_lib::objects::{ObjectKind, odb::Odb};
use std::path::Path;

let dir = tempfile::tempdir()?;
let objects = dir.path().join("objects");
std::fs::create_dir_all(&objects)?;
let odb = Odb::new(&objects);
let oid = odb.write(ObjectKind::Blob, b"hello")?;
let obj = odb.read(&oid)?;
assert_eq!(obj.data, b"hello");

Implementations§

Source§

impl Odb

Source

pub fn uses_files_primary(&self) -> bool

Whether the primary backend is the default on-disk super::store::FilesSource.

Source

pub fn files_objects_dir(&self) -> Option<&Path>

objects/ path when the primary is files-backed; None for custom primaries.

Source

pub fn primary_writable(&self) -> Result<Arc<dyn WritableObjectStore>>

Primary writable backend (files source or custom store).

§Errors

Propagates failures while opening the lazy files source.

Source

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

In-process garbage collection for the files-backed object directory.

Custom primaries return Error::UnsupportedObjectStore.

§Errors

Propagates object-store or I/O failures during maintenance.

Source

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

Write objects/info/commit-graph from reachable commits (files primary only).

Writes nothing and deletes any existing graph in a repository that rewrites parent lists (shallow, info/grafts, or replace refs unless core.useReplaceRefs=false), as crate::maintenance::write_commit_graph does.

§Errors

Returns Error::UnsupportedObjectStore for custom primaries, or errors from graph generation or I/O.

Source

pub fn with_resolved_work_tree(self, work_tree: Option<PathBuf>) -> Self

Attach a resolved work tree after OdbBuilder::build.

Source§

impl Odb

Source

pub fn read_commit(&self, oid: &ObjectId) -> Result<CommitData>

Read oid and parse it as a commit.

Annotated tags are not followed; peel first with Self::peel_to_commit when the id may name a tag.

§Parameters
  • oid: the commit to read.
§Returns

The owned, parsed commit headers and message.

§Errors
Source

pub fn commit_tree(&self, oid: &ObjectId) -> Result<ObjectId>

The root tree of the commit oid.

Only the commit headers are decoded; the author, committer and message are not copied.

§Parameters
  • oid: the commit whose tree to return.
§Errors

Same as Self::read_commit.

Source§

impl Odb

Source

pub fn peel_tags(&self, oid: ObjectId) -> Result<(ObjectId, ObjectKind)>

Follow annotated tags starting at oid until reaching an object that is not a tag.

A non-tag oid is returned unchanged. Only tag objects are fully read, and only their object header is parsed (other headers and the message may be absent or not UTF-8); the final object’s kind comes from Self::read_info, so peeling to a large blob or tree does not inflate it.

§Parameters
  • oid: the object to start from, usually a ref tip.
§Returns

The id and kind of the first non-tag object in the chain.

§Errors
  • Error::ObjectNotFound when oid or any object the chain names is missing.
  • Error::CorruptObject when a tag has no valid object header, or the chain names a tag it already passed through. Chains of any length are followed; content-addressed ids make a cycle impossible in a real repository, but a pluggable store can serve one.
  • Any other error Self::read / Self::read_info reports for the objects read.
Source

pub fn peel_to_commit(&self, oid: ObjectId) -> Result<Option<ObjectId>>

Peel oid through annotated tags to a commit.

§Parameters
  • oid: a commit, or an annotated tag (possibly nested) naming one.
§Returns

Some(commit) when the chain ends at a commit, None when it ends at a tree or blob.

§Errors

Same as Self::peel_tags: missing objects, unparsable tags and overlong chains are errors rather than None, so callers can tell “not a commit” from “broken repository”.

Source§

impl Odb

Source

pub fn new(objects_dir: &Path) -> Self

Create an Odb pointing at the given objects/ directory.

The directory does not need to exist yet; it will be created on the first write operation. Does not read GIT_ALTERNATE_OBJECT_DIRECTORIES; use Self::env_alternate_dirs_from_var and Self::with_env_alternate_dirs (or open via crate::repo::Repository, which resolves env alternates lazily on first use).

Source

pub fn with_work_tree(objects_dir: &Path, work_tree: &Path) -> Self

Create an Odb with a work tree for resolving relative alternate paths.

Does not read GIT_ALTERNATE_OBJECT_DIRECTORIES; pass env-derived paths with Self::with_env_alternate_dirs (see Self::env_alternate_dirs_from_var).

Source

pub fn env_alternate_dirs_from_var( env: &Environment, resolve_base: Option<&Path>, ) -> Vec<PathBuf>

Parse GIT_ALTERNATE_OBJECT_DIRECTORIES once for Self::with_env_alternate_dirs.

Relative entries are resolved against resolve_base (typically the work tree root).

Source

pub fn with_env_alternate_dirs(self, dirs: Vec<PathBuf>) -> Self

Attach env-derived alternate object directories (see Self::env_alternate_dirs_from_var).

Source

pub fn invalidate_alternates_cache(&self)

Drop the cached info/alternates chain so the next lookup re-reads the file.

Source

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

Reload info/alternates from disk into this Odb’s cache (used after external writes).

§Errors

Propagates failures from reading the alternates chain (I/O or malformed info/alternates).

Source

pub fn append_file_alternate(&self, alternate_objects_dir: &Path) -> Result<()>

Append alternate_objects_dir to objects/info/alternates (deduped) and refresh the cache.

§Errors

Error::Io when the alternates file cannot be read or written.

Source

pub fn append_alternate_objects_line( objects_dir: &Path, alternate_objects_dir: &Path, ) -> Result<()>

Append one absolute objects directory line to objects/info/alternates (deduped).

Does not update any in-memory cache; pair with Self::refresh_file_alternates_from_disk on the relevant Odb when the same process keeps using it.

Source

pub fn enable_mem_overlay(&self)

Enable the in-memory write overlay (Git’s tmp-objdir): subsequent Self::write/ Self::write_local calls keep objects only in memory, and Self::read consults that overlay before the on-disk store. Used by merge-tree --quiet so a full merge can run without persisting any new loose objects.

Source

pub fn disable_mem_overlay(&self)

Disable the in-memory write overlay, discarding any objects accumulated in it.

Source

pub fn primary(&self) -> Result<Arc<FilesSource>>

Primary on-disk object source for this repository’s objects/ directory.

§Errors

Propagates failures while opening pack, MIDX, or loose backends.

Source

pub fn sources(&self) -> Result<Arc<CompositeStore>>

Alternate object directories (info/alternates, env, submodules) as one composite store.

§Errors

Propagates failures while opening any alternate files source.

Source

pub fn register_submodule_object_directories_from_index( &self, work_tree: &Path, index: &Index, )

Register <submodule-git-dir>/objects for every stage-0 gitlink in index that has a checkout under work_tree, so reads can resolve submodule commits stored only in the nested repository (matches Git’s odb_add_submodule_source_by_path / register_all_submodule_sources).

Source

pub fn with_config_git_dir(self, git_dir: PathBuf) -> Self

Attach a git directory so Self::read can honor core.multiPackIndex when resolving packed objects.

Source

pub fn hash_algo(&self) -> HashAlgo

The repository’s object hash algorithm, detected from extensions.objectformat and cached for the lifetime of this Odb.

The git directory is taken from the attached config_git_dir when set, otherwise inferred as the parent of the objects/ directory. Defaults to HashAlgo::Sha1 when no config can be read.

Source

pub fn big_file_threshold(&self) -> Result<u64>

core.bigFileThreshold (ConfigSet::big_file_threshold), cached for the lifetime of this Odb.

Objects of at least this size are written by Self::write_stream into their own pack, and worktree files of at least this size that need no clean conversion are hashed and stored as a stream instead of being read into memory.

§Errors

Returns errors from loading the config cascade or from an invalid threshold value.

Source

pub fn pack_store(&self) -> Result<&Arc<PackStore>>

Pack/MIDX read cache shared by this handle and its Clones.

Source

pub fn largest_pack_index_path(&self) -> Result<Option<PathBuf>>

Path to the largest pack index in the primary objects/pack/ directory (by entry count).

Used when writing a reachability bitmap for an all-into-one repack. Returns Ok(None) when no pack index exists.

§Errors

Returns Error::InvalidRef when the store is not files-backed.

Source

pub fn invalidate_packs(&self)

Drop cached pack listings, parsed indexes, pack bytes, delta bases, and MIDX layers.

Call after in-process repack, garbage collection, or crate::index_pack::install_pack_bytes so the next read rescans objects/pack/. Cloned Odb handles share one PackStore for the primary objects/ directory; alternates have separate stores that are invalidated here as well.

Source

pub fn objects_dir(&self) -> &Path

Return the path to the objects/ directory.

This is always the repository layout path (including for custom primaries that do not store objects on disk). Prefer Self::files_objects_dir when the operation requires a files-backed primary; filesystem maintenance returns Error::UnsupportedObjectStore otherwise.

Source

pub fn config_git_dir(&self) -> Option<&Path>

Return the attached git directory, if one was set with Self::with_config_git_dir.

Used by config- and ref-aware operations (delta islands, on-disk delta reuse) that need the repository root rather than just the object store.

Source

pub fn object_path(&self, oid: &ObjectId) -> PathBuf

Return the filesystem path for a given object ID.

Source

pub fn exists_local(&self, oid: &ObjectId) -> bool

Whether the object exists under this database directory only (loose or local packs).

Unlike Self::exists, this ignores info/alternates and GIT_ALTERNATE_OBJECT_DIRECTORIES. Used for partial-clone bookkeeping where objects reachable via alternates are still treated as “missing” until copied locally.

Objects stored only in promisor packs (sibling .promisor marker next to the .pack) are treated as absent: Git considers them fetchable on demand, and rev-list --missing=print lists them until materialized as loose objects or a non-promisor pack.

The empty tree object is treated as present without a loose file (matches Git).

A failing custom primary store counts as “absent”; decision paths inside the crate use the fallible form, which propagates the backend error.

Source

pub fn exists_stored(&self, oid: &ObjectId) -> bool

Whether oid is stored locally in loose storage or any pack (including promisor).

Unlike Self::exists_local, objects present only in promisor-marked packs count as stored. Does not trigger lazy fetch or consult alternates.

A failing custom primary store counts as “absent”; decision paths inside the crate use the fallible form, which propagates the backend error.

Source

pub fn exists_materialized_local(&self, oid: &ObjectId) -> bool

Whether oid is stored on disk in this repository’s object store (loose or non-promisor pack), without treating the canonical empty tree as virtually present.

Use this when deciding whether a peer already holds an object for incremental local transfer; Self::exists and Self::exists_local treat the empty tree as present even when no object file exists.

A failing custom primary store counts as “absent”.

Source

pub fn contains(&self, oid: &ObjectId) -> Result<bool>

Whether oid is in this database: the primary store, any extra read source (OdbBuilder::push_read_source) or an alternate object directory.

The canonical empty tree is always present. Sources are probed in the same order Self::read uses, and a source that fails stops the probe just as it stops a read, so contains never reports an object that read cannot return.

§Errors

The first source failure (for example an Error::Io from a network- or database-backed store), instead of reporting the object as present or missing.

Source

pub fn exists(&self, oid: &ObjectId) -> bool

Lenient Self::contains: a source that fails is skipped, so a later source can still answer true and an object no healthy source holds counts as absent.

Use only for advisory probes. Where “missing” changes what happens next (what to fetch or send, whether a ref is broken), call Self::contains so a backend outage surfaces as an error rather than as a missing object.

Source

pub fn with_pack_read_context<R>(&self, f: impl FnOnce() -> R) -> R

Run f with pack read caches for this database’s primary objects/ directory.

Use for batch workloads (for example cat-file --batch) so each object read does not reinstall thread-local pack context.

Source

pub fn freshen_object(&self, oid: &ObjectId) -> bool

Touch the loose object file or pack file containing oid, matching Git’s odb_freshen_object (updates mtime so age-based prune keeps recently re-referenced objects).

Returns true if an on-disk object was found and touched.

Source

pub fn read_loose_verify_oid( path: &Path, expected_oid: &ObjectId, ) -> Result<Object>

Read a loose object file at path, verifying the uncompressed payload hashes to expected_oid.

Git stores loose objects under paths derived from the OID; if the file contents hash to a different id (for example after a mistaken mv), this returns Error::LooseHashMismatch.

§Errors
Source

pub fn read(&self, oid: &ObjectId) -> Result<Object>

Read and decompress an object from the loose store.

§Errors
Source

pub fn read_into(&self, oid: &ObjectId, buf: &mut Vec<u8>) -> Result<ObjectKind>

Read and decompress an object into buf, reusing its capacity across calls.

Resolution order matches Self::read. Returns a borrowed view of the payload stored in buf.

§Errors

Same as Self::read.

Source

pub fn read_info(&self, oid: &ObjectId) -> Result<ObjectInfo>

Return the kind and uncompressed size of oid without loading the full object body.

Resolution order matches Self::read: in-memory overlay, multi-pack-index, local packs (MRU order, skipping MIDX-covered indexes when MIDX is enabled), loose objects, a pack directory re-prepare and pack retry, then alternates.

§Errors
Source

pub fn open_stream( &self, oid: &ObjectId, ) -> Result<Option<ObjectStream<'static>>>

Open a stream over oid’s uncompressed payload (overlay, primary, then alternates).

The returned stream owns its payload: it is read whole into memory before returning. Use Self::with_stream to read a large object in bounded memory.

§Errors

Propagates backend failures other than a missing object (Ok(None)).

Source

pub fn with_stream<R>( &self, oid: &ObjectId, f: impl FnOnce(ObjectStream<'_>) -> Result<R>, ) -> Result<Option<R>>

Run f on a stream over oid’s uncompressed payload (overlay, primary, then alternates).

Unlike Self::open_stream the payload is not buffered: loose objects and objects stored whole in a pack are inflated as f reads, so memory stays bounded however large the object is. Objects stored as pack deltas are reconstructed in memory first.

§Parameters
  • oid — the object to stream.
  • f — consumes the stream; its result is returned as Ok(Some(_)).
§Errors

Propagates backend failures other than a missing object (Ok(None), and f is not called), and any error returned by f. A corrupt or truncated object surfaces as an std::io::Error from the stream’s reader.

Source

pub fn for_each_object( &self, f: &mut dyn FnMut(&ObjectId) -> ControlFlow<()>, ) -> Result<()>

Invoke f for every object id reachable from this database until f returns ControlFlow::Break.

§Errors

Propagates enumeration failures from any consulted backend.

Source

pub fn lookup_prefix( &self, prefix: &str, limit: usize, out: &mut Vec<ObjectId>, ) -> Result<()>

Fill out with ids whose hex starts with prefix (deduplicated across overlay, primary, alternates).

§Errors

Returns Error::InvalidObjectId when prefix is not valid hex.

Source

pub fn enumerate_local_loose_objects(&self) -> Result<Vec<(ObjectId, PathBuf)>>

Enumerate loose objects in this database’s primary objects/ directory as (oid, path).

Pack files and alternate object directories are not scanned.

§Errors

Propagates failures while opening the primary files source or walking loose storage.

Source

pub fn hash(&self, kind: ObjectKind, data: &[u8]) -> Result<ObjectId>

Hash raw content of a given kind using this repository’s hash algorithm.

This does not write anything to disk.

§Errors

Returns Error::HashCollision when sha1dc detects a chosen-prefix collision.

Source

pub fn hash_stream( &self, kind: ObjectKind, size: u64, reader: &mut dyn Read, ) -> Result<ObjectId>

Hash size payload bytes of kind read from reader, without storing anything.

Memory use does not depend on size: the payload is read in fixed-size chunks. Exactly size bytes are consumed; anything after them is left unread.

§Errors
Source

pub fn write_stream( &self, kind: ObjectKind, size: u64, reader: &mut dyn Read, options: WriteOptions, ) -> Result<ObjectId>

Store size payload bytes of kind read from reader and return the object id.

Objects smaller than Self::big_file_threshold are read into memory and written like Self::write_with_options. Bigger ones are hashed and deflated in fixed-size chunks straight into a new single-object pack (at the ConfigSet::pack_objects_zlib_level level), as Git does for big files, so memory use does not depend on size. If the object already exists the new pack is discarded and the existing copy is freshened unless options.silent is set.

A custom primary receives the stream through WritableObjectStore::write_stream; while the in-memory overlay is active the object is buffered into the overlay.

Exactly size bytes are consumed from reader.

§Errors
Source

pub fn empty_tree_oid(&self) -> Result<ObjectId>

Object id of the empty tree for this store’s hash algorithm.

Hashes the canonical empty tree payload only; nothing is written to disk.

§Errors

Returns Error::HashCollision when sha1dc detects a chosen-prefix collision.

Source

pub fn is_empty_tree(&self, oid: &ObjectId) -> bool

Whether oid is this repository’s empty tree (virtually present when not on disk).

Source

pub fn write(&self, kind: ObjectKind, data: &[u8]) -> Result<ObjectId>

Write an object to the loose store and return its ObjectId.

If the object already exists it is not overwritten (Git behaviour).

The payload is stored as given, without fsck checks; callers that build tree, commit or tag bytes themselves should go through Objects::write instead.

§Errors
  • Error::Io — could not create the directory or write the file.
  • Error::Zlib — compression failed.
Source

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

Create all 256 loose-object prefix directories (objects/xx/).

Bulk git add-style staging calls this once before parallel loose writes. A no-op for custom primaries, which receive those writes instead of objects/.

§Errors

Returns Error::Io if a directory cannot be created.

Source

pub fn count_loose_objects(&self) -> Result<usize>

Count loose object files under this repository’s objects/ directory.

§Errors

Propagates directory enumeration failures from the loose store walker.

Source

pub fn approximate_object_count(&self) -> Result<usize>

Approximate object count for Git-style automatic core.abbrev sizing.

Sums object counts from cached pack indexes (no per-object scan) plus loose files under this database’s objects/ directory. Matches Git’s ODB_COUNT_OBJECTS_APPROXIMATE well enough for abbreviation heuristics on typical repositories.

§Errors

Propagates pack index listing and loose enumeration failures.

Source

pub fn zlib_compress_loose_store(&self, store_bytes: &[u8]) -> Result<Vec<u8>>

Zlib-compress canonical loose store bytes using the repository’s loose level.

§Errors

Returns Error::Zlib when compression fails.

Source

pub fn write_loose_zlib_prehashed( &self, oid: &ObjectId, zlib_store: &[u8], options: WriteOptions, ) -> Result<ObjectId>

Write a loose object from precomputed id and zlib-compressed store bytes.

The caller must supply bytes that the internal zlib loose reader would expand to valid canonical store form ("<kind> <len>\\0<payload>"). Hashing and compression are skipped; use after parallel batch preparation.

With a custom primary the bytes are inflated and stored through WritableObjectStore::write instead, so staging works on any backend.

§Errors

Same as Self::write; Error::Zlib or Error::CorruptObject when a custom primary receives bytes that do not inflate to a valid object.

Source

pub fn write_with_options( &self, kind: ObjectKind, data: &[u8], options: WriteOptions, ) -> Result<ObjectId>

Like Self::write, with control over freshen behaviour on existing objects.

Source

pub fn write_local(&self, kind: ObjectKind, data: &[u8]) -> Result<ObjectId>

Write an object as a loose file in this object directory only.

Unlike Self::write, this ignores info/alternates and GIT_ALTERNATE_OBJECT_DIRECTORIES: if the object exists only in an alternate store, it is still written here. That matches how Git’s unpack-objects materializes every packed object into the receiving repository even when the same OID is already reachable via alternates (see t5519-push-alternates).

The well-known empty tree is still written when no loose file exists yet, even though Self::exists_local treats it as virtually present.

§Errors

Same as Self::write.

Source

pub fn write_loose_materialize( &self, kind: ObjectKind, data: &[u8], ) -> Result<ObjectId>

Write a loose object file when it is missing, even if Self::exists is true because the object lives only in a pack.

Used when materializing a partial-clone layout: objects must be duplicated as loose files before local packs are removed. Unlike Self::write_local, objects present only in a promisor pack are still written because Self::exists_local treats those as absent.

Source

pub fn write_raw(&self, store_bytes: &[u8]) -> Result<ObjectId>

Write an already-serialized object (header + data) to the loose store.

Useful when the caller has the full store bytes (e.g. from stdin with --literally).

§Errors
Source

pub fn write_raw_local(&self, store_bytes: &[u8]) -> Result<ObjectId>

Like Self::write_raw but only consults this object directory, not alternates.

See Self::write_local.

§Errors

Same as Self::write_raw.

Trait Implementations§

Source§

impl Clone for Odb

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Odb

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for Odb

§

impl !UnwindSafe for Odb

§

impl Freeze for Odb

§

impl Send for Odb

§

impl Sync for Odb

§

impl Unpin for Odb

§

impl UnsafeUnpin for Odb

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.