Skip to content

Commit e3d96b3

Browse files
authored
Merge pull request #217 from sysprog21/refine-git-hooks
Refine git hooks
2 parents 47465ba + a1c5a5e commit e3d96b3

File tree

3 files changed

+114
-83
lines changed

3 files changed

+114
-83
lines changed

scripts/pre-commit.hook

Lines changed: 94 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -65,45 +65,55 @@ CPPCHECK_OPTS+=" --force $(cppcheck_suppressions) $(cppcheck_build_unmatched)"
6565
CPPCHECK_OPTS+=" --cppcheck-build-dir=.out ."
6666

6767
RETURN=0
68+
69+
# Disallow non-ASCII characters in workspace path
70+
workspace=$(git rev-parse --show-toplevel)
71+
if echo "$workspace" | grep -q "[一-龥]"; then
72+
echo "[!] The workspace path '$workspace' contains non-ASCII characters." >&2
73+
exit 1
74+
fi
75+
6876
CLANG_FORMAT=$(which clang-format)
6977
if [ $? -ne 0 ]; then
70-
echo "[!] clang-format not installed. Unable to check source file format policy." >&2
71-
exit 1
78+
echo "[!] clang-format not installed. Unable to check source file format policy." >&2
79+
exit 1
7280
fi
7381

7482
CPPCHECK=$(which cppcheck)
7583
mkdir -p .out
7684
if [ $? -ne 0 ]; then
77-
echo "[!] cppcheck not installed. Unable to perform static analysis." >&2
78-
exit 1
85+
echo "[!] cppcheck not installed. Unable to perform static analysis." >&2
86+
exit 1
7987
fi
8088

81-
# Expected Cppcheck version is 1.90+
82-
# First, Cppcheck 2.x
83-
if [ -z "$($CPPCHECK --version | grep -E '^Cppcheck\s2')" ]; then
84-
# Second, Cppcheck 1.x
85-
CPPCHECK_VER=$($CPPCHECK --version | sed -Ee 's/Cppcheck 1.([0-9]+)/\1/;q')
86-
if [ $CPPCHECK_VER -lt 90 ]; then
87-
echo "[!] cppcheck version must be at least 1.90." >&2
88-
echo -e " Check 'Developer Info' for building Cppcheck from source:\n" \
89-
" https://cppcheck.sourceforge.net/devinfo/" >&2
90-
exit 1
91-
fi
89+
# Check that cppcheck's version is at least 1.90.
90+
cppcheck_ver=$("$CPPCHECK" --version)
91+
if echo "$cppcheck_ver" | grep -qE '^Cppcheck\s2'; then
92+
: # Version 2.x is acceptable.
93+
else
94+
# For version 1.x, extract the minor version and compare.
95+
minor_version=$(echo "$cppcheck_ver" | sed -Ee 's/Cppcheck 1\.([0-9]+)/\1/;q')
96+
if [ "$minor_version" -lt 90 ]; then
97+
echo "[!] cppcheck version must be at least 1.90." >&2
98+
echo -e " See Developer Info for building cppcheck from source:\n"
99+
echo -e " https://cppcheck.sourceforge.io/devinfo/" >&2
100+
exit 1
101+
fi
92102
fi
93103

94104
ASPELL=$(which aspell)
95105
if [ $? -ne 0 ]; then
96-
echo "[!] aspell not installed. Unable to do spelling check." >&2
97-
exit 1
106+
echo "[!] aspell not installed. Unable to do spelling check." >&2
107+
exit 1
98108
fi
99109
if [ -z "$(aspell dump dicts | grep -E '^en$')" ]; then
100-
echo "[!] aspell-en not installed. Unable to do spelling check." >&2
101-
exit 1
110+
echo "[!] aspell-en not installed. Unable to do spelling check." >&2
111+
exit 1
102112
fi
103113

104114
DIFF=$(which colordiff)
105115
if [ $? -ne 0 ]; then
106-
DIFF=diff
116+
DIFF=diff
107117
fi
108118

109119
if command -v sha1sum >/dev/null 2>&1; then
@@ -115,42 +125,63 @@ else
115125
exit 1
116126
fi
117127

128+
# Get staged filenames (added, copied, or modified) into an array.
129+
FILES=($(git diff --cached --name-only --diff-filter=ACM))
130+
binary_files=()
131+
132+
for file in "${FILES[@]}"; do
133+
# Get MIME info for the file.
134+
mime_info=$(file --mime "$file")
135+
# Extract a friendly filename (everything before the colon).
136+
name=$(file "$file" | cut -d ":" -f1)
137+
138+
if echo "$mime_info" | grep -qi binary; then
139+
binary_files+=("$name")
140+
echo "[!] '$name' appears to be a binary blob."
141+
fi
142+
done
143+
144+
if [ "${#binary_files[@]}" -gt 0 ]; then
145+
echo "WARNING: Binary data found"
146+
fi
147+
118148
FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep -E "\.(c|cpp|h)$")
119149
for FILE in $FILES; do
120-
nf=$(git checkout-index --temp $FILE | cut -f 1)
121-
tempdir=$(mktemp -d) || exit 1
122-
newfile=$(mktemp ${tempdir}/${nf}.XXXXXX) || exit 1
123-
basename=$(basename $FILE)
124-
125-
source="${tempdir}/${basename}"
126-
mv $nf $source
127-
cp .clang-format $tempdir
128-
$CLANG_FORMAT $source > $newfile 2>> /dev/null
129-
$DIFF -u -p -B --label="modified $FILE" --label="expected coding style" \
130-
"${source}" "${newfile}"
131-
r=$?
132-
rm -rf "${tempdir}"
133-
if [ $r != 0 ] ; then
134-
echo "[!] $FILE does not follow the consistent coding style." >&2
135-
RETURN=1
136-
fi
137-
if [ $RETURN -eq 1 ]; then
138-
echo "" >&2
139-
echo "Make sure you indent as the following:" >&2
140-
echo " clang-format -i $FILE" >&2
141-
echo
142-
fi
150+
nf=$(git checkout-index --temp $FILE | cut -f 1)
151+
tempdir=$(mktemp -d) || exit 1
152+
newfile=$(mktemp ${tempdir}/${nf}.XXXXXX) || exit 1
153+
basename=$(basename $FILE)
154+
155+
source="${tempdir}/${basename}"
156+
mv $nf $source
157+
cp .clang-format $tempdir
158+
$CLANG_FORMAT $source > $newfile 2>> /dev/null
159+
$DIFF -u -p -B \
160+
--label="modified $FILE" --label="expected coding style" \
161+
"${source}" "${newfile}"
162+
r=$?
163+
rm -rf "${tempdir}"
164+
if [ $r != 0 ] ; then
165+
echo "[!] $FILE does not follow the consistent coding style." >&2
166+
RETURN=1
167+
fi
168+
if [ $RETURN -eq 1 ]; then
169+
echo "" >&2
170+
echo "Make sure you indent as the following:" >&2
171+
echo " clang-format -i $FILE" >&2
172+
echo
173+
fi
143174
done
144175

145176
if [ ! -z "${FILES[*]}" ]; then
146-
echo "Following files need to be cleaned up:"
147-
echo "${FILES[*]}"
177+
echo "Following files need to be cleaned up:"
178+
echo "${FILES[*]}"
148179
fi
149180

150181
$SHA1SUM -c scripts/checksums 2>/dev/null >/dev/null
151182
if [ $? -ne 0 ]; then
152-
echo "[!] You are not allowed to change the header file queue.h or list.h" >&2
153-
exit 1
183+
echo "[!] You are not allowed to change the header file queue.h or list.h" >&2
184+
exit 1
154185
fi
155186

156187
# Prevent unsafe functions
@@ -159,26 +190,26 @@ banned="([^f]gets\()|(sprintf\()|(strcpy\()"
159190
status=0
160191
for file in $(git diff --staged --name-only | grep -E "\.(c|cc|cpp|h|hh|hpp)\$")
161192
do
162-
filepath="${root}/${file}"
163-
output=$(grep -nrE "${banned}" "${filepath}")
164-
if [ ! -z "${output}" ]; then
165-
echo "Dangerous function detected in ${filepath}"
166-
echo "${output}"
167-
echo
168-
echo "Read 'Common vulnerabilities guide for C programmers' carefully."
169-
echo " https://security.web.cern.ch/security/recommendations/en/codetools/c.shtml"
170-
RETURN=1
171-
fi
193+
filepath="${root}/${file}"
194+
output=$(grep -nrE "${banned}" "${filepath}")
195+
if [ ! -z "${output}" ]; then
196+
echo "Dangerous function detected in ${filepath}"
197+
echo "${output}"
198+
echo
199+
echo "Read 'Common vulnerabilities guide for C programmers' carefully."
200+
echo " https://security.web.cern.ch/security/recommendations/en/codetools/c.shtml"
201+
RETURN=1
202+
fi
172203
done
173204

174205
# static analysis
175206
echo "Running static analysis..."
176207
$CPPCHECK $CPPCHECK_OPTS >/dev/null
177208
if [ $? -ne 0 ]; then
178-
RETURN=1
179-
echo "" >&2
180-
echo "Fail to pass static analysis." >&2
181-
echo
209+
RETURN=1
210+
echo "" >&2
211+
echo "Fail to pass static analysis." >&2
212+
echo
182213
fi
183214

184215
# non-ASCII filenames are not allowed.
@@ -187,12 +218,12 @@ fi
187218
if test $(git diff --cached --name-only --diff-filter=A -z $against |
188219
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
189220
then
190-
cat <<\EOF
221+
cat <<\EOF
191222
ERROR: Attempt to add a non-ASCII file name.
192223
This can cause problems if you want to work with people on other platforms.
193224
To be portable it is advisable to rename the file.
194225
EOF
195-
RETURN=1
226+
RETURN=1
196227
fi
197228

198229
exit $RETURN

scripts/pre-push.hook

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ NC='\033[0m' # No Color
1414
# Bump copyright year
1515
commit=$(git rev-list --skip 1 --grep '^Bump copyright' 0b8be2c15160c216e8b6ec82c99a000e81c0e429...HEAD)
1616
if [ x"$commit" != x"50c5ac53d31adf6baac4f8d3db6b3ce2215fee40" ] ; then
17-
echo -e "${RED}ERROR${NC}: This repository is insane."
18-
echo -e "Make sure you did fork from https://github.com/sysprog21/lab0-c recently."
19-
echo ""
20-
exit 1
17+
echo -e "${RED}ERROR${NC}: This repository is insane."
18+
echo -e "Make sure you did fork from https://github.com/sysprog21/lab0-c recently."
19+
echo ""
20+
exit 1
2121
fi
2222

2323
# Show hints
@@ -27,24 +27,24 @@ echo ""
2727

2828
# only run this if you are pushing to master
2929
if [[ $current_branch = $protected_branch ]] ; then
30-
echo -e "${YELLOW}Running pre push to master check...${NC}"
31-
32-
echo -e "${YELLOW}Trying to build tests project...${NC}"
30+
echo -e "${YELLOW}Running pre push to master check...${NC}"
3331

34-
# build the project
35-
make
32+
echo -e "${YELLOW}Trying to build tests project...${NC}"
3633

37-
# $? is a shell variable which stores the return code from what we just ran
38-
rc=$?
39-
if [[ $rc != 0 ]] ; then
40-
echo -e "${RED}Failed to build the project, please fix this and push again${NC}"
41-
echo ""
42-
exit $rc
43-
fi
34+
# build the project
35+
make
4436

45-
# Everything went OK so we can exit with a zero
46-
echo -e "${GREEN}Pre-push check passed!${NC}"
37+
# $? is a shell variable which stores the return code from what we just ran
38+
rc=$?
39+
if [[ $rc != 0 ]] ; then
40+
echo -e "${RED}Failed to build the project, please fix this and push again${NC}"
4741
echo ""
42+
exit $rc
43+
fi
44+
45+
# Everything went OK so we can exit with a zero
46+
echo -e "${GREEN}Pre-push check passed!${NC}"
47+
echo ""
4848
fi
4949

5050
exit 0

scripts/prepare-commit-msg.hook

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ EOF
4949
# Prompt the user about aborting the commit.
5050
read -rp "Do you want to abort this commit? (y/N): " answer
5151
if [[ "$answer" =~ ^[Yy]$ ]]; then
52-
echo "Commit aborted by user." >&2
53-
exit 1
52+
echo "Commit aborted by user." >&2
53+
exit 1
5454
fi
5555

5656
exit 0

0 commit comments

Comments
 (0)