main
install-hooks.sh
Eric Bower
·
2026-05-07
1#!/usr/bin/env bash
2# install-hooks.sh — sync the post-receive hook to all bare repos in a directory.
3#
4# Usage:
5# ./install-hooks.sh /path/to/bare-repos
6# ./install-hooks.sh /path/to/repo1.git /path/to/repo2.git
7# ./install-hooks.sh --force /path/to/bare-repos # overwrite existing hooks
8#
9# The hook is read from hooks/post-receive relative to this script.
10# Errors if a repo already has a different post-receive hook (use --force to overwrite).
11
12set -euo pipefail
13
14SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
15HOOK="$SCRIPT_DIR/hooks/post-receive"
16FORCE=false
17
18if [ "${1:-}" = "--force" ]; then
19 FORCE=true
20 shift
21fi
22
23if [ ! -f "$HOOK" ]; then
24 echo "error: $HOOK not found" >&2
25 exit 1
26fi
27
28if [ $# -eq 0 ]; then
29 echo "usage: $0 [--force] <repo.git ... | repos-dir>" >&2
30 exit 1
31fi
32
33repos=()
34for arg in "$@"; do
35 # Strip trailing slash to avoid double slashes in paths
36 arg="${arg%/}"
37 if [ -d "$arg" ] && [ ! -d "$arg/hooks" ]; then
38 # Looks like a directory containing repos, not a repo itself
39 for repo in "$arg"/*.git; do
40 [ -d "$repo" ] && repos+=("$repo")
41 done
42 else
43 repos+=("$arg")
44 fi
45done
46
47if [ ${#repos[@]} -eq 0 ]; then
48 echo "no repos found" >&2
49 exit 1
50fi
51
52installed=0
53skipped=0
54overwritten=0
55errors=0
56
57for repo in "${repos[@]}"; do
58 hooks_dir="$repo/hooks"
59 existing="$hooks_dir/post-receive"
60 mkdir -p "$hooks_dir"
61
62 if [ -f "$existing" ]; then
63 if diff -q "$HOOK" "$existing" >/dev/null 2>&1; then
64 echo " = $repo (up to date)"
65 skipped=$((skipped + 1))
66 continue
67 fi
68
69 if [ "$FORCE" = true ]; then
70 cp "$HOOK" "$existing"
71 chmod +x "$existing"
72 echo " ⚡ $repo (overwritten)"
73 overwritten=$((overwritten + 1))
74 continue
75 fi
76
77 echo " ✗ $repo (existing hook differs)" >&2
78 errors=$((errors + 1))
79 continue
80 fi
81
82 cp "$HOOK" "$existing"
83 chmod +x "$existing"
84 echo " ✓ $repo"
85 installed=$((installed + 1))
86done
87
88echo ""
89echo "installed: $installed skipped: $skipped overwritten: $overwritten errors: $errors"
90
91if [ "$errors" -gt 0 ]; then
92 exit 1
93fi