Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 94 additions & 63 deletions scripts/pre-commit.hook
Original file line number Diff line number Diff line change
Expand Up @@ -65,45 +65,55 @@ CPPCHECK_OPTS+=" --force $(cppcheck_suppressions) $(cppcheck_build_unmatched)"
CPPCHECK_OPTS+=" --cppcheck-build-dir=.out ."

RETURN=0

# Disallow non-ASCII characters in workspace path
workspace=$(git rev-parse --show-toplevel)
if echo "$workspace" | grep -q "[一-龥]"; then
echo "[!] The workspace path '$workspace' contains non-ASCII characters." >&2
exit 1
fi

CLANG_FORMAT=$(which clang-format)
if [ $? -ne 0 ]; then
echo "[!] clang-format not installed. Unable to check source file format policy." >&2
exit 1
echo "[!] clang-format not installed. Unable to check source file format policy." >&2
exit 1
fi

CPPCHECK=$(which cppcheck)
mkdir -p .out
if [ $? -ne 0 ]; then
echo "[!] cppcheck not installed. Unable to perform static analysis." >&2
exit 1
echo "[!] cppcheck not installed. Unable to perform static analysis." >&2
exit 1
fi

# Expected Cppcheck version is 1.90+
# First, Cppcheck 2.x
if [ -z "$($CPPCHECK --version | grep -E '^Cppcheck\s2')" ]; then
# Second, Cppcheck 1.x
CPPCHECK_VER=$($CPPCHECK --version | sed -Ee 's/Cppcheck 1.([0-9]+)/\1/;q')
if [ $CPPCHECK_VER -lt 90 ]; then
echo "[!] cppcheck version must be at least 1.90." >&2
echo -e " Check 'Developer Info' for building Cppcheck from source:\n" \
" https://cppcheck.sourceforge.net/devinfo/" >&2
exit 1
fi
# Check that cppcheck's version is at least 1.90.
cppcheck_ver=$("$CPPCHECK" --version)
if echo "$cppcheck_ver" | grep -qE '^Cppcheck\s2'; then
: # Version 2.x is acceptable.
else
# For version 1.x, extract the minor version and compare.
minor_version=$(echo "$cppcheck_ver" | sed -Ee 's/Cppcheck 1\.([0-9]+)/\1/;q')
if [ "$minor_version" -lt 90 ]; then
echo "[!] cppcheck version must be at least 1.90." >&2
echo -e " See Developer Info for building cppcheck from source:\n"
echo -e " https://cppcheck.sourceforge.io/devinfo/" >&2
exit 1
fi
fi

ASPELL=$(which aspell)
if [ $? -ne 0 ]; then
echo "[!] aspell not installed. Unable to do spelling check." >&2
exit 1
echo "[!] aspell not installed. Unable to do spelling check." >&2
exit 1
fi
if [ -z "$(aspell dump dicts | grep -E '^en$')" ]; then
echo "[!] aspell-en not installed. Unable to do spelling check." >&2
exit 1
echo "[!] aspell-en not installed. Unable to do spelling check." >&2
exit 1
fi

DIFF=$(which colordiff)
if [ $? -ne 0 ]; then
DIFF=diff
DIFF=diff
fi

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

# Get staged filenames (added, copied, or modified) into an array.
FILES=($(git diff --cached --name-only --diff-filter=ACM))
binary_files=()

for file in "${FILES[@]}"; do
# Get MIME info for the file.
mime_info=$(file --mime "$file")
# Extract a friendly filename (everything before the colon).
name=$(file "$file" | cut -d ":" -f1)

if echo "$mime_info" | grep -qi binary; then
binary_files+=("$name")
echo "[!] '$name' appears to be a binary blob."
fi
done

if [ "${#binary_files[@]}" -gt 0 ]; then
echo "WARNING: Binary data found"
fi

FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep -E "\.(c|cpp|h)$")
for FILE in $FILES; do
nf=$(git checkout-index --temp $FILE | cut -f 1)
tempdir=$(mktemp -d) || exit 1
newfile=$(mktemp ${tempdir}/${nf}.XXXXXX) || exit 1
basename=$(basename $FILE)

source="${tempdir}/${basename}"
mv $nf $source
cp .clang-format $tempdir
$CLANG_FORMAT $source > $newfile 2>> /dev/null
$DIFF -u -p -B --label="modified $FILE" --label="expected coding style" \
"${source}" "${newfile}"
r=$?
rm -rf "${tempdir}"
if [ $r != 0 ] ; then
echo "[!] $FILE does not follow the consistent coding style." >&2
RETURN=1
fi
if [ $RETURN -eq 1 ]; then
echo "" >&2
echo "Make sure you indent as the following:" >&2
echo " clang-format -i $FILE" >&2
echo
fi
nf=$(git checkout-index --temp $FILE | cut -f 1)
tempdir=$(mktemp -d) || exit 1
newfile=$(mktemp ${tempdir}/${nf}.XXXXXX) || exit 1
basename=$(basename $FILE)

source="${tempdir}/${basename}"
mv $nf $source
cp .clang-format $tempdir
$CLANG_FORMAT $source > $newfile 2>> /dev/null
$DIFF -u -p -B \
--label="modified $FILE" --label="expected coding style" \
"${source}" "${newfile}"
r=$?
rm -rf "${tempdir}"
if [ $r != 0 ] ; then
echo "[!] $FILE does not follow the consistent coding style." >&2
RETURN=1
fi
if [ $RETURN -eq 1 ]; then
echo "" >&2
echo "Make sure you indent as the following:" >&2
echo " clang-format -i $FILE" >&2
echo
fi
done

if [ ! -z "${FILES[*]}" ]; then
echo "Following files need to be cleaned up:"
echo "${FILES[*]}"
echo "Following files need to be cleaned up:"
echo "${FILES[*]}"
fi

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

# Prevent unsafe functions
Expand All @@ -159,26 +190,26 @@ banned="([^f]gets\()|(sprintf\()|(strcpy\()"
status=0
for file in $(git diff --staged --name-only | grep -E "\.(c|cc|cpp|h|hh|hpp)\$")
do
filepath="${root}/${file}"
output=$(grep -nrE "${banned}" "${filepath}")
if [ ! -z "${output}" ]; then
echo "Dangerous function detected in ${filepath}"
echo "${output}"
echo
echo "Read 'Common vulnerabilities guide for C programmers' carefully."
echo " https://security.web.cern.ch/security/recommendations/en/codetools/c.shtml"
RETURN=1
fi
filepath="${root}/${file}"
output=$(grep -nrE "${banned}" "${filepath}")
if [ ! -z "${output}" ]; then
echo "Dangerous function detected in ${filepath}"
echo "${output}"
echo
echo "Read 'Common vulnerabilities guide for C programmers' carefully."
echo " https://security.web.cern.ch/security/recommendations/en/codetools/c.shtml"
RETURN=1
fi
done

# static analysis
echo "Running static analysis..."
$CPPCHECK $CPPCHECK_OPTS >/dev/null
if [ $? -ne 0 ]; then
RETURN=1
echo "" >&2
echo "Fail to pass static analysis." >&2
echo
RETURN=1
echo "" >&2
echo "Fail to pass static analysis." >&2
echo
fi

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

exit $RETURN
36 changes: 18 additions & 18 deletions scripts/pre-push.hook
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ NC='\033[0m' # No Color
# Bump copyright year
commit=$(git rev-list --skip 1 --grep '^Bump copyright' 0b8be2c15160c216e8b6ec82c99a000e81c0e429...HEAD)
if [ x"$commit" != x"50c5ac53d31adf6baac4f8d3db6b3ce2215fee40" ] ; then
echo -e "${RED}ERROR${NC}: This repository is insane."
echo -e "Make sure you did fork from https://github.com/sysprog21/lab0-c recently."
echo ""
exit 1
echo -e "${RED}ERROR${NC}: This repository is insane."
echo -e "Make sure you did fork from https://github.com/sysprog21/lab0-c recently."
echo ""
exit 1
fi

# Show hints
Expand All @@ -27,24 +27,24 @@ echo ""

# only run this if you are pushing to master
if [[ $current_branch = $protected_branch ]] ; then
echo -e "${YELLOW}Running pre push to master check...${NC}"

echo -e "${YELLOW}Trying to build tests project...${NC}"
echo -e "${YELLOW}Running pre push to master check...${NC}"

# build the project
make
echo -e "${YELLOW}Trying to build tests project...${NC}"

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

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

# Everything went OK so we can exit with a zero
echo -e "${GREEN}Pre-push check passed!${NC}"
echo ""
fi

exit 0
4 changes: 2 additions & 2 deletions scripts/prepare-commit-msg.hook
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ EOF
# Prompt the user about aborting the commit.
read -rp "Do you want to abort this commit? (y/N): " answer
if [[ "$answer" =~ ^[Yy]$ ]]; then
echo "Commit aborted by user." >&2
exit 1
echo "Commit aborted by user." >&2
exit 1
fi

exit 0