defmodule GitHoox do
@moduledoc """
Git hooks in pure Elixir. Configurable file globs, per-hook options,
built-in support for `mix format`, Credo, ExUnit, and Dialyzer.
## Quickstart
mix git_hoox.install
Add hooks in `.git_hoox.exs`:
%{
hooks: [
pre_commit: [
{GitHoox.Hooks.Format, []},
{GitHoox.Hooks.Credo, []}
]
]
}
See `GitHoox.Hook` for writing custom hooks.
"""
@typedoc "Git lifecycle stage. See `git help hooks`."
@type stage ::
:pre_commit
| :prepare_commit_msg
| :commit_msg
| :post_commit
| :pre_rebase
| :post_checkout
| :post_merge
| :pre_push
@typedoc "Glob pattern matched against repo-relative paths."
@type glob :: String.t()
@typedoc "Repo-relative file path."
@type path :: String.t()
@typedoc "Hook entry in config: `{Module, keyword_opts}`."
@type hook_entry :: {module(), keyword()}
@typedoc "Loaded and validated config."
@type config :: %{
hooks: keyword(),
parallel: boolean(),
fail_fast: boolean(),
skip_env: String.t()
}
@typedoc "Result of a single hook invocation."
@type hook_result ::
:ok
| {:ok, modified :: [path()]}
| :skip
| {:error, term()}
@doc """
Execute all hooks configured for `stage`.
`args` are the positional arguments the git shim received (e.g. the
commit message file path for `commit_msg`). `stdin` is the raw input
passed to the shim, only meaningful for `pre_push`.
"""
@spec run(stage(), [String.t()], String.t() | nil) ::
:ok | {:error, [{module(), term()}]}
def run(stage, args \\ [], stdin \\ nil),
do: GitHoox.Runner.run(stage, args, stdin)
end