# `Git.Hooks`
[🔗](https://github.com/joshrotenberg/git_wrapper_ex/blob/main/lib/git/hooks.ex#L1)

Helpers for reading, writing, and managing git hooks.

Operates on the `.git/hooks/` directory of a repository. These functions
don't map to a single git subcommand but instead provide convenient access
to hook files.

All functions accept an optional keyword list with `:config` for specifying
the repository via a `Git.Config` struct.

# `disable`

```elixir
@spec disable(
  String.t(),
  keyword()
) :: {:ok, String.t()} | {:error, :not_found | :invalid_hook | term()}
```

Removes the executable bit from a hook (`chmod -x`).

## Options

  * `:config` - a `Git.Config` struct (default: `Git.Config.new()`)

Returns `{:ok, path}` or `{:error, :not_found}`.
Returns `{:error, :invalid_hook}` if the hook name is not valid.

# `enable`

```elixir
@spec enable(
  String.t(),
  keyword()
) :: {:ok, String.t()} | {:error, :not_found | :invalid_hook | term()}
```

Makes a hook executable (`chmod +x`).

## Options

  * `:config` - a `Git.Config` struct (default: `Git.Config.new()`)

Returns `{:ok, path}` or `{:error, :not_found}`.
Returns `{:error, :invalid_hook}` if the hook name is not valid.

# `enabled?`

```elixir
@spec enabled?(
  String.t(),
  keyword()
) :: {:ok, boolean()} | {:error, :invalid_hook | term()}
```

Checks whether a hook file exists and is executable.

## Options

  * `:config` - a `Git.Config` struct (default: `Git.Config.new()`)

Returns `{:ok, boolean()}`.
Returns `{:error, :invalid_hook}` if the hook name is not valid.

# `exists?`

```elixir
@spec exists?(
  String.t(),
  keyword()
) :: {:ok, boolean()} | {:error, :invalid_hook | term()}
```

Checks whether a hook file exists.

## Options

  * `:config` - a `Git.Config` struct (default: `Git.Config.new()`)

Returns `{:ok, boolean()}`.
Returns `{:error, :invalid_hook}` if the hook name is not valid.

# `list`

```elixir
@spec list(keyword()) ::
  {:ok, [%{name: String.t(), enabled: boolean(), path: String.t()}]}
  | {:error, term()}
```

Lists installed hooks in the repository.

Returns a list of maps with `:name`, `:enabled`, and `:path` keys.
A hook is considered enabled if it has the executable bit set.
Only files matching valid hook names are included (`.sample` files are skipped).

## Options

  * `:config` - a `Git.Config` struct (default: `Git.Config.new()`)

## Examples

    {:ok, hooks} = Git.Hooks.list()
    # => [%{name: "pre-commit", enabled: true, path: "/repo/.git/hooks/pre-commit"}]

# `read`

```elixir
@spec read(
  String.t(),
  keyword()
) :: {:ok, String.t()} | {:error, :not_found | :invalid_hook | term()}
```

Reads the content of a hook file.

## Options

  * `:config` - a `Git.Config` struct (default: `Git.Config.new()`)

Returns `{:ok, content}` or `{:error, :not_found}`.
Returns `{:error, :invalid_hook}` if the hook name is not valid.

# `remove`

```elixir
@spec remove(
  String.t(),
  keyword()
) :: :ok | {:error, :not_found | :invalid_hook | term()}
```

Deletes a hook file.

## Options

  * `:config` - a `Git.Config` struct (default: `Git.Config.new()`)

Returns `:ok` or `{:error, :not_found}`.
Returns `{:error, :invalid_hook}` if the hook name is not valid.

# `valid_hooks`

```elixir
@spec valid_hooks() :: [String.t()]
```

Returns the list of valid git hook names.

# `write`

```elixir
@spec write(String.t(), String.t(), keyword()) ::
  {:ok, String.t()} | {:error, :invalid_hook | term()}
```

Writes a hook file.

By default the file is made executable. Pass `executable: false` to skip
setting the executable bit.

## Options

  * `:config` - a `Git.Config` struct (default: `Git.Config.new()`)
  * `:executable` - whether to chmod +x the file (default: `true`)

Returns `{:ok, path}` or `{:error, reason}`.
Returns `{:error, :invalid_hook}` if the hook name is not valid.

---

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