Skip to content

Commit b32e3d6

Browse files
committed
Check arity with git hook params when using MFA
1 parent 6e5f268 commit b32e3d6

File tree

6 files changed

+55
-18
lines changed

6 files changed

+55
-18
lines changed

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ Main features are:
1717
* Executable files
1818
* Elixir modules
1919
* **No limits**: Any git hook is and will be supported out of the box,
20-
you can [check here the git hooks list](https://git-scm.com/docs/githooks) available.
20+
you can [check here the git hooks list](https://git-scm.com/docs/githooks)
21+
available.
2122

2223
## Table of Contents
2324

@@ -172,10 +173,9 @@ them as you please.
172173
It is also possible to use Elixir modules to execute actions for a given git
173174
hook.
174175

175-
It is recommended the module implement the behaviour `GitHooks` first and then
176-
add your config as a
176+
Just add in your config the
177177
[MFA](https://hexdocs.pm/elixir/typespecs.html#built-in-types) (`{module,
178-
function, arity}`):
178+
function, arity}`) definition:
179179

180180
```elixir
181181
config :git_hooks,
@@ -189,8 +189,9 @@ config :git_hooks,
189189
]
190190
```
191191

192-
To see which arguments a git hook receives, [check the git
193-
documentation](https://git-scm.com/docs/githooks).
192+
To check how many args you function should expect [check the git
193+
documentation](https://git-scm.com/docs/githooks) to know which parameters are
194+
being sent on each hook.
194195

195196
## Removing a hook
196197

config/config.exs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ use Mix.Config
33
config :git_hooks,
44
auto_install: false,
55
hooks: [
6+
#prepare_commit_msg: [
7+
#verbose: true,
8+
#tasks: [
9+
#{MyApp.GitHooks.PrepareCommitMsg, :execute, 4}
10+
#]
11+
#],
612
commit_msg: [
713
verbose: true,
814
tasks: [

lib/git_hooks.ex

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,6 @@ defmodule GitHooks do
33

44
alias Mix.Tasks.GitHooks.Install
55

6-
@doc """
7-
Receives the git hook name and the list of the hook arguments.
8-
9-
To see how which arguments a git hook has, [check the git
10-
documentation](https://git-scm.com/docs/githooks).
11-
"""
12-
@callback execute(atom, list) :: any
13-
146
if Application.get_env(:git_hooks, :auto_install, true) do
157
Install.run(["--quiet"])
168
end

lib/mix/tasks/git_hooks/run.ex

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,18 +144,28 @@ defmodule Mix.Tasks.GitHooks.Run do
144144
error_exit()
145145
end
146146

147-
defp run_task({module, function, _arity}, git_hook_type, git_hook_args) when is_atom(module) do
148-
Kernel.apply(module, function, [git_hook_type | git_hook_args])
147+
defp run_task({module, function, arity}, git_hook_type, git_hook_args) when is_atom(module) do
148+
expected_arity = length(git_hook_args)
149+
150+
if arity != expected_arity do
151+
raise """
152+
Invalid #{module}.#{function} arity for #{git_hook_type}, expected #{expected_arity} but got #{
153+
arity
154+
}. Check the Git hooks documentation to fix the expected parameters.
155+
"""
156+
end
157+
158+
Kernel.apply(module, function, git_hook_args)
149159
end
150160

151161
defp run_task(command, git_hook_type, git_hook_args) when is_binary(command) do
152162
run_task({:cmd, command, []}, git_hook_type, git_hook_args)
153163
end
154164

155165
defp run_task(task, git_hook_type, _git_hook_args) do
156-
raise("""
166+
raise """
157167
Invalid task #{inspect(task)} for hook #{inspect(git_hook_type)}", only String, {:file, ""} or {:cmd, ""} are supported.
158-
""")
168+
"""
159169
end
160170

161171
@spec get_atom_from_arg(String.t()) :: atom | no_return

test/mix/tasks/git_hooks/run_test.exs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,29 @@ defmodule Mix.Tasks.RunTest do
2727
end) =~ "test command"
2828
end
2929

30+
test "when it is a MFA then the module function it called" do
31+
put_git_hook_config(:pre_commit,
32+
tasks: [{GitHooks.TestSupport.MFATest, :execute, 0}],
33+
verbose: true
34+
)
35+
36+
assert Run.run(["pre-commit"]) == :ok
37+
end
38+
39+
test "when the arity of the MFA is not the same as the git hook raises an error" do
40+
put_git_hook_config(:pre_commit,
41+
tasks: [{GitHooks.TestSupport.MFATest, :execute, 5}],
42+
verbose: true
43+
)
44+
45+
expect_error_message =
46+
"Invalid Elixir.GitHooks.TestSupport.MFATest.execute arity for pre_commit, expected 0 but got 5. Check the Git hooks documentation to fix the expected parameters.\n"
47+
48+
assert_raise RuntimeError, expect_error_message, fn ->
49+
Run.run(["pre-commit"])
50+
end
51+
end
52+
3053
test "when it is a string then the command it's executed" do
3154
put_git_hook_config(:pre_commit, tasks: ["echo 'test string command'"], verbose: true)
3255

test/support/mfa_test.ex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
defmodule GitHooks.TestSupport.MFATest do
2+
def execute() do
3+
:ok
4+
end
5+
end

0 commit comments

Comments
 (0)