# `Minga.Git.Buffer`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga/git/buffer.ex#L1)

Per-buffer GenServer that tracks git diff state.

Caches the HEAD version of the file on startup, then recomputes an
in-memory diff (via `Minga.Core.Diff`) whenever the buffer content
changes. This design means buffer edits never spawn git processes;
only buffer open and git index invalidation do.

One `Git.Buffer` exists per file-backed buffer in a git repository.
Managed under `Minga.Buffer.Supervisor`.

# `diff_summary`

```elixir
@type diff_summary() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}
```

Diff summary counts: {added, modified, deleted}.

# `modeline_info`

```elixir
@type modeline_info() :: {branch :: String.t() | nil, diff_summary()}
```

Pre-computed data for the modeline: branch name and diff summary.

# `start_opt`

```elixir
@type start_opt() ::
  {:git_root, String.t()}
  | {:file_path, String.t()}
  | {:initial_content, String.t()}
```

Options for starting a git buffer.

# `state`

```elixir
@type state() :: %{
  git_root: String.t(),
  relative_path: String.t(),
  base_lines: [String.t()],
  hunks: [Minga.Core.Diff.hunk()],
  signs: %{required(non_neg_integer()) =&gt; Minga.Core.Diff.hunk_type()},
  branch: String.t() | nil
}
```

Internal state.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `git_root`

```elixir
@spec git_root(GenServer.server()) :: String.t()
```

Returns the git root path.

# `hunk_at`

```elixir
@spec hunk_at(GenServer.server(), non_neg_integer()) :: Minga.Core.Diff.hunk() | nil
```

Returns the hunk at a specific buffer line, or nil.

# `hunks`

```elixir
@spec hunks(GenServer.server()) :: [Minga.Core.Diff.hunk()]
```

Returns the list of hunks.

# `invalidate_base`

```elixir
@spec invalidate_base(GenServer.server(), String.t()) :: :ok
```

Re-reads the HEAD version and recomputes the diff.

# `modeline_info`

```elixir
@spec modeline_info(GenServer.server()) :: modeline_info()
```

Returns `{branch, {added, modified, deleted}}` in a single GenServer call.

The branch name is cached on state and refreshed on init and save
(`:invalidate_base`), so this call does zero I/O.

# `relative_path`

```elixir
@spec relative_path(GenServer.server()) :: String.t()
```

Returns the file path relative to git root.

# `signs`

```elixir
@spec signs(GenServer.server()) :: %{
  required(non_neg_integer()) =&gt; Minga.Core.Diff.hunk_type()
}
```

Returns the per-line sign map for the gutter.

# `start_link`

```elixir
@spec start_link([start_opt()]) :: GenServer.on_start()
```

Starts a git buffer for a file in a git repository.

# `summary`

```elixir
@spec summary(GenServer.server()) :: diff_summary()
```

Returns a summary of diff sign counts: `{added, modified, deleted}`.

Counts are derived from the per-line sign map, which is already computed
on every buffer change. This is a cheap GenServer.call (no recomputation).

# `update`

```elixir
@spec update(GenServer.server(), String.t()) :: :ok
```

Recomputes the diff against the cached base content.

---

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