diff options
Diffstat (limited to 'dot_config')
| -rw-r--r-- | dot_config/git/hooks/_dispatch.sh | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/dot_config/git/hooks/_dispatch.sh b/dot_config/git/hooks/_dispatch.sh index 7dcd89c..0b1135d 100644 --- a/dot_config/git/hooks/_dispatch.sh +++ b/dot_config/git/hooks/_dispatch.sh @@ -1,16 +1,26 @@ #!/bin/sh -# Sourced by every hook in this directory. Runs the per-repo hook of the -# same name from `<repo-top>/.githooks/` if it exists, then returns -# control so the calling user-level hook can do its own work after. +# Sourced by every hook in this directory. Runs the per-repo hook of +# the same name and then returns control so the calling user-level +# hook can do its own work after. # -# Repos opt in by just dropping `.githooks/<hookname>` (executable) in -# the working tree — no per-repo `core.hooksPath` setting, no stubs. -# If the per-repo hook exits non-zero we abort with that status so git -# sees the failure. +# Lookup order (first executable file wins): +# 1. `<git-dir>/hooks-local/<hookname>` — untracked per-clone override, +# lives inside .git/ so it stays personal. Use this when you want +# to replace a tracked .githooks/<name> on a shared repo without +# affecting teammates. Create with e.g.: +# $ mkdir -p "$(git rev-parse --git-dir)/hooks-local" +# $ $EDITOR "$(git rev-parse --git-dir)/hooks-local/pre-commit" +# $ chmod +x "$(git rev-parse --git-dir)/hooks-local/pre-commit" +# 2. `<repo-top>/.githooks/<hookname>` — tracked, the project's +# shared hook. The intended default for opting a repo in. +# +# Either an empty file with exit 0 or no hook at all means "skip the +# project layer entirely"; the user-level hook still runs its own +# global logic afterwards. # # GIT_HOOK_DISPATCHED guards against re-entry: if some legacy repo has # its own `.githooks/<hook>` that ends with `exec "$HOME/.config/..."` -# (the old pattern), we won't dispatch back into it a second time. +# (the old stub pattern), we won't dispatch back into it a second time. # shellcheck shell=sh dispatch_repo_hook() { @@ -19,13 +29,17 @@ dispatch_repo_hook() { [ -n "${GIT_HOOK_DISPATCHED:-}" ] && return 0 + gitdir=$(git rev-parse --git-dir 2>/dev/null) || return 0 root=$(git rev-parse --show-toplevel 2>/dev/null) || return 0 - repo_hook="$root/.githooks/$hookname" - [ -x "$repo_hook" ] || return 0 - GIT_HOOK_DISPATCHED=1 "$repo_hook" "$@" - rc=$? - if [ "$rc" -ne 0 ]; then - exit "$rc" - fi + for candidate in "$gitdir/hooks-local/$hookname" "$root/.githooks/$hookname"; do + if [ -x "$candidate" ]; then + GIT_HOOK_DISPATCHED=1 "$candidate" "$@" + rc=$? + if [ "$rc" -ne 0 ]; then + exit "$rc" + fi + return 0 + fi + done } |
