# `Exgit.Repository`
[🔗](https://github.com/ivarvong/exgit/blob/v0.1.0/lib/exgit/repository.ex#L1)

A git repository value.

Carries an object store, a ref store, optional on-disk path and
config, and a `:mode` that distinguishes eager-fully-populated
repositories from lazy ones.

## `:mode`

The `:mode` field is part of the public API. It has two values:

  * `:eager` — every reachable object is locally available. Streaming
    FS operations (`FS.walk/2`, `FS.grep/4`) can iterate without
    triggering network fetches or producing silent empty results.

  * `:lazy` — backed by an `ObjectStore.Promisor`; some objects are
    fetched on demand from the transport. Streaming FS operations
    would either blow up (unbounded fetches mid-stream) or silently
    skip missing objects, so they **raise** `ArgumentError`. Strict
    FS operations (`FS.read_path/3`, `FS.ls/3`, `FS.stat/3`,
    `FS.write_path/4`) work because they fetch as needed and return
    `{:ok, result, repo}` for cache threading.

Convert a `:lazy` repo to `:eager` via `materialize/2`.

`:mode` defaults to `:eager` when constructing via `new/3` without
an explicit `:mode` opt, so existing callers are unaffected.

# `memory_report`

```elixir
@type memory_report() :: %{
  object_count: non_neg_integer() | :unknown,
  cache_bytes: non_neg_integer() | :unknown,
  commit_count: non_neg_integer() | :unknown,
  tree_count: non_neg_integer() | :unknown,
  blob_count: non_neg_integer() | :unknown,
  tag_count: non_neg_integer() | :unknown,
  max_cache_bytes: non_neg_integer() | :infinity,
  mode: mode(),
  backend: module()
}
```

Structured memory usage report for a repository.

* `:object_count` — total distinct objects in the cache
* `:cache_bytes` — compressed bytes stored (what
  `:max_cache_bytes` bounds)
* `:commit_count`, `:tree_count`, `:blob_count`, `:tag_count` —
  count of each object kind
* `:max_cache_bytes` — configured cap (`:infinity` if unbounded)
* `:mode` — repo mode (`:eager` or `:lazy`)
* `:backend` — the object-store module

Counts and `:cache_bytes` are `:unknown` for backends that can't
be introspected (`Disk`, user-defined stores).

# `mode`

```elixir
@type mode() :: :eager | :lazy
```

# `t`

```elixir
@type t() :: %Exgit.Repository{
  config: Exgit.Config.t() | nil,
  mode: mode(),
  object_store: term(),
  path: Path.t() | nil,
  ref_store: term()
}
```

# `materialize`

```elixir
@spec materialize(t(), String.t() | binary()) :: {:ok, t()} | {:error, term()}
```

Convert a `:lazy` (Promisor-backed) repo into an `:eager`
(Memory-backed) one, fetching every reachable object from
`reference` through the Promisor's transport first.

After materialization, the repo can be freely passed to streaming
operations (`FS.walk/2`, `FS.grep/4`) without any special setup —
the `:mode` is flipped to `:eager` as part of the same call.

On a repo that is already `:eager`, materialize returns the repo
unchanged.

# `memory_report`

```elixir
@spec memory_report(t()) :: memory_report()
```

Returns a structured memory-usage report for `repo`.

Designed for operational monitoring — agent hosts can poll this
between operations to track peak memory, detect unexpected
cache growth, and alert when a configured cap is approached.

Returns consistent shape across all object-store backends
(`Memory`, `Disk`, `Promisor`, `SharedPromisor`); counts and
`:cache_bytes` for backends without per-type bookkeeping (like
`Disk`) are `:unknown`. All keys are always present.

## Examples

    iex> {:ok, repo} = Exgit.clone(url, lazy: true)
    iex> {:ok, repo} = Exgit.FS.prefetch(repo, "HEAD", blobs: true)
    iex> Exgit.Repository.memory_report(repo)
    %{
      object_count: 17_500,
      cache_bytes: 4_213_780,
      commit_count: 0,
      tree_count: 8_290,
      blob_count: 9_210,
      tag_count: 0,
      max_cache_bytes: :infinity,
      mode: :lazy,
      backend: Exgit.ObjectStore.Promisor
    }

## Use in an agent

    repo
    |> Exgit.Repository.memory_report()
    |> log_to_your_observability_stack()

# `new`

```elixir
@spec new(term(), term(), keyword()) :: t()
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
