Exgit.ObjectStore.Disk (exgit v0.1.0)

Copy Markdown View Source

On-disk git object store — reads and writes objects from <root>/objects/ in git's standard layout: loose objects under aa/bbbb... and packed objects via pack-*.{pack,idx}.

Loose-object reads wrap :zlib.uncompress/1 in try/rescue so corrupt or bit-rotted files return {:error, :zlib_error} rather than crashing the caller. Pack lookups use :file.pread/3 with the idx offset so single-object latency is independent of pack size.

Content-addressed SHA verification runs on every loose-object read — see verify_sha/2. Pack reads rely on the pack's own content-addressed lookup via idx; the SHA is verified implicitly at inflate time.

Summary

Types

t()

@type t() :: %Exgit.ObjectStore.Disk{root: Path.t()}

Functions

delete_object(disk, sha)

@spec delete_object(t(), binary()) :: :ok | {:error, :not_found}

get_object(disk, sha)

@spec get_object(t(), binary()) ::
  {:ok, Exgit.Object.t()} | {:error, :not_found | term()}

has_object?(store, sha)

@spec has_object?(t(), binary()) :: boolean()

list_objects(disk)

@spec list_objects(t()) :: [binary()]

new(root)

@spec new(Path.t()) :: t()

object_size(disk, sha)

@spec object_size(t(), binary()) :: {:ok, non_neg_integer()} | {:error, term()}

Uncompressed object size without materializing the object.

For a loose object this reads and inflates only enough compressed bytes to cover the header ("<type> <size>\0") — constant memory AND constant I/O, no matter how large the blob. Packed objects fall back to a full read (the delta chain must be resolved to know the final size), so this is cheap for loose objects and O(object) for packed ones.

put_object(disk, object)

@spec put_object(t(), Exgit.Object.t()) :: {:ok, binary()} | {:error, term()}