-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathgithooker.sh
executable file
·174 lines (132 loc) · 4.83 KB
/
githooker.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#!/bin/bash
hook_dir=".githooks"
GIT_HOOK_DIR=".git/hooks"
######### NOTHING TO CONFIGURE BEYONG THIS LINE ############
BASE="$(git rev-parse --show-toplevel)"
# colors for output messages
r="\x1B[31m" # red
y="\x1B[33m" # yellow
g="\x1B[32m" # green
d="\x1B[39m" # default
b="\x1B[1m" # bold
u="\x1B[0m" # unbold
cc="$d" # current color
# both helper_{enable,disable} are the actual commands.
# but their names are sacrificed for .githooker/{enable,disable}
function actual_disable {
hook="$1"
# remove hook extension if there
if [[ $1 = *"."* ]]; then
hook="$(basename $1 | cut -d "." -f1)"
fi
link="$BASE/$GIT_HOOK_DIR/$hook"
# check if it is a link and not a file
if [ -L "$link" ]; then
unlink "$link" > /dev/null
# print log line based on whether it was an enabled or oprhaned hook
path_of_linked_script_by_hook="$(find "$BASE"/$hook_dir -name "$(basename $hook)*")"
if [ -z "$path_of_linked_script_by_hook" ] || [ ! -f "$path_of_linked_script_by_hook" ]; then
echo -e "\t$b$hook$u hook ${r}deleted${d}"
else
echo -e "\t$b$hook$u hook ${y}disabled${d}"
fi
else
echo -e "\t${r}[ERROR]${d} found hook in $b$GIT_HOOK_DIR$u is not a link! Please manual debug:$b $link $u"
fi
}
function actual_enable {
hook="$1"
# get hook extension if missing and available
if [[ $1 != *"."* ]]; then
hook="$(find "$hook_dir" -name "$1*")"
fi
hook_without_extensions="$(basename $1 | cut -d "." -f1)"
ln -s -f ../../"$hook" "$GIT_HOOK_DIR/$hook_without_extensions"
# Note: "../.." is necessary because git hooks spawn in $GIT_HOOK_DIR
echo -e "\t$b$hook_without_extensions$u hook ${g}enabled${d}"
}
# used by interactive
function answer {
read -r user_answer
if [ "$user_answer" = "y" ] || [ "$user_answer" = "yes" ]; then
echo "yes"
fi
}
function generic_toggle {
if [ "$3" = "--all" ]; then
for hook in $2; do
$1 "$hook" 2> /dev/null
done
else
command="$1"; shift; shift;
for hook in $@; do
$command "$hook" 2> /dev/null
done
fi
}
# actual commands/task which can be invoked
function disable {
generic_toggle "actual_disable" "$BASE/$GIT_HOOK_DIR/*" $@
}
function enable {
generic_toggle "actual_enable" "$BASE/$hook_dir/*" $@
}
function interactive {
echo -e "\n${b}[INFO]${u} each ${b}hook$u will be listed with its ${b}status$u. Say yes or no to change hook state. (y/${b}N$u)"
for hook in "$BASE/$hook_dir/"*; do
hook_without_extension="$(cut -d '.' -f1 "$hook")"
if [ -f "$BASE/$GIT_HOOK_DIR/$hook_without_extension" ]; then
echo -e "\n\t${g}${b}$hook_without_extension${u} hook is enabled${d}. Do you want to ${b}disable${u} it? (y/N)"
if [ "$(answer)" = "yes" ]; then
actual_disable "$hook"
fi
else
echo -e "\n\t${y}${b}$hook_without_extension${u} hook is disabled${d}. Do you want to ${b}enable${u} it? (y/N)"
if [ "$(answer)" = "yes" ]; then
actual_enable "$hook"
fi
fi
done
# searching for orphaned hooks in ./$GIT_HOOK_DIR
for hook in "$BASE/$GIT_HOOK_DIR/"*; do
# early return if file is sample file
if [[ "$hook" == *".sample" ]]; then
continue
fi
hook_script="$(find "$BASE/$hook_dir" -name "$(basename $hook)*")"
if [ -z $hook_script ] || [ ! -f $hook_script ]; then
echo -e "\n\t${r}$(basename $hook) hook is orphaned.$u Do you want to ${b}delete$u it? (y/N)${d}"
if [ "$(answer)" = "yes" ]; then
actual_disable "$hook"
fi
fi
done
}
function list {
echo -e "\n${b}[INFO]${u} listing all hooks ${b}(${g}enabled${d}/${y}disabled${d}/${r}orphaned${d})${u}"
# looping over .githooks dir and checking (enabled/disabled hooks)
for hook_absolute_path in "$BASE/$hook_dir/"*; do
hook="$(basename $hook_absolute_path)"
hook_without_extension="$(echo "$hook" | cut -d '.' -f1)"
if [ -f "$BASE/$GIT_HOOK_DIR/$hook_without_extension" ]; then
cc="$g"
else
cc="$y"
fi
echo -e "\t${b}${cc}$hook_without_extension${d}${u}"
done
# searching for orphaned hooks / broken links
for file in "$BASE/$GIT_HOOK_DIR/"*; do
if [[ $file == *".sample" ]]; then
continue
fi
path_of_linked_script_by_hook="$(find "$BASE"/$hook_dir -name "$(basename $file)*")"
if [ -z "$path_of_linked_script_by_hook" ] || [ ! -f "$path_of_linked_script_by_hook" ]; then
echo -e "\t${r}$(basename $file)${d}"
fi
done
}
# one may run .githooker command before creating .githooks
mkdir -p "$hook_dir"
command=$1; shift
$command $@