Browse code

Add implementation

Robert Cranston authored on 14/04/2020 01:01:12
Showing 2 changed files

... ...
@@ -2,7 +2,37 @@
2 2
 
3 3
 Manage multiple [Git hooks][githooks] with ease.
4 4
 
5
+Git doesn't allow you to use multiple scripts as hooks for a single action out
6
+of the box. `git-multihook` is meant to be placed in the Git [hooks path][]
7
+(which is [`$GIT_DIR`][]`/hooks` by default, but can be changed to a
8
+centralized location with e.g. `git config --global core.hooksPath
9
+'~/.githooks'`) and be the symlink target of (multiple) standard [Git
10
+hooks][githooks] in that directory. When the hook is run it delegates to,
11
+potentially multiple, (executable) scripts in subdirectories with names on the
12
+form `${hook}.d`.
13
+
14
+For example, splitting the [`pre-commit.sample`][] that comes bundled with Git
15
+into two scripts would look something like this:
16
+
17
+```
18
+.git/hooks
19
+├── git-multihook
20
+├── pre-commit -> git-multihook
21
+└── pre-commit.d
22
+    ├── nonascii
23
+    └── diffcheck
24
+```
25
+
26
+Note that hooks have different interfaces (with regards to standard
27
+in/out/error, return values, etc) and `git-multihook` only makes a general best
28
+effort to accomodate these (specifically, it copies standard in to all the
29
+scripts if it is not a terminal, simply lets standard out/error through, and
30
+returns with the first error code that is non-zero).
31
+
5 32
 [githooks]: https://git-scm.com/docs/githooks
33
+[hooks path]: https://git-scm.com/docs/git-config#Documentation/git-config.txt-corehooksPath
34
+[`$GIT_DIR`]: https://www.git-scm.com/docs/git#Documentation/git.txt-codeGITDIRcode
35
+[`pre-commit.sample`]: https://github.com/git/git/blob/master/templates/hooks--pre-commit.sample
6 36
 
7 37
 ## License
8 38
 
9 39
new file mode 100755
... ...
@@ -0,0 +1,24 @@
1
+#!/bin/sh
2
+set -euC
3
+
4
+# Variables.
5
+prog="$(basename "$0")"
6
+dir="$(dirname "$0")"
7
+
8
+# Delegate to executable files in `*.d` directory.
9
+if ! [ -t 1 ]
10
+then
11
+    stdin="$(cat)"
12
+fi
13
+for file in "$dir/${prog}.d/"*
14
+do
15
+    if [ -x "$file" ]
16
+    then
17
+        if ! [ -t 1 ]
18
+        then
19
+            printf "%s\n" "$stdin" | "$file" "$@" || exit "$?"
20
+        else
21
+            "$file" "$@" || exit "$?"
22
+        fi
23
+    fi
24
+done