The pre-push hook validates the commit messages utilising 'echo' to send the captured data from the git commit through grep. Commit messages may occasionally contain strings that could appear to be escape sequences such as doxygen style references to \struct. The '\' 'c' escape sequence can be interpreted to supress all further output [0] which then breaks the processing and string matching. Unfortunatley for us, doxygen's class reference constructed in the same form as \struct can be interpreted as the escape sequence to supress further output. [0] https://www.gnu.org/software/bash/manual/bash.html#Bash-Builtins Update the pre-push hook to explicitly disable escape sequence interpretation using the '-E' flag. This is not available on the posix-compliant shell 'dash', so also switch to bash explicitly to prevent potential failures. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
110 lines
2.7 KiB
Bash
Executable file
110 lines
2.7 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
# A hook script to prevent pushing unsuitable commits to the master or
|
|
# integration branches. Criteria to determine unsuitable commits are listed
|
|
# below.
|
|
#
|
|
# Information about the commits which are being pushed is supplied as lines to
|
|
# the standard input in the form:
|
|
#
|
|
# <local ref> <local sha1> <remote ref> <remote sha1>
|
|
|
|
z40=0000000000000000000000000000000000000000
|
|
|
|
remote_name="$1"
|
|
remote_url="$2"
|
|
|
|
while read -r local_ref local_sha remote_ref remote_sha
|
|
do
|
|
case "$remote_ref" in
|
|
refs/heads/master)
|
|
;;
|
|
refs/heads/integration/*)
|
|
;;
|
|
*)
|
|
continue
|
|
esac
|
|
|
|
# If the remote branch gets deleted, there's nothing to check.
|
|
if [ "$local_sha" = $z40 ]
|
|
then
|
|
continue
|
|
fi
|
|
|
|
# Check if we are creating a new branch or updating an existing one.
|
|
if [ "$remote_sha" = $z40 ]
|
|
then
|
|
if [ "$remote_ref" = "refs/heads/master" ]
|
|
then
|
|
# There are known invalid commits in the full history,
|
|
# skip the checks if we are pushing the master branch
|
|
# (for instance to an empty repository).
|
|
continue
|
|
else
|
|
# We're pushing a new integration branch, check all
|
|
# commits on top of the master branch.
|
|
range="remotes/$remote_name/master..$local_sha"
|
|
fi
|
|
else
|
|
# Update to existing branch, examine new commits only.
|
|
range="$remote_sha..$local_sha"
|
|
fi
|
|
|
|
#
|
|
# Find invalid commits.
|
|
#
|
|
errors=0
|
|
for commit in $(git rev-list "$range")
|
|
do
|
|
msg=$(git cat-file commit "$commit")
|
|
|
|
# 1. The commit message shall not contain a local changelog.
|
|
if echo -E "$msg" | grep -q '^--- *$'
|
|
then
|
|
echo >&2 "Found local changelog in commit $commit"
|
|
errors=$((errors+1))
|
|
fi
|
|
|
|
# 2. The commit message shall have Signed-off-by lines
|
|
# corresponding the committer and the author.
|
|
committer=$(echo "$msg" | grep '^committer ' | head -1 | \
|
|
cut -d ' ' -f 2- | rev | cut -d ' ' -f 3- | rev)
|
|
if ! echo -E "$msg" | grep -F -q "Signed-off-by: ${committer}"
|
|
then
|
|
echo >&2 "Missing committer Signed-off-by in commit $commit"
|
|
errors=$((errors+1))
|
|
fi
|
|
|
|
author=$(echo "$msg" | grep '^author ' | head -1 | \
|
|
cut -d ' ' -f 2- | rev | cut -d ' ' -f 3- | rev)
|
|
if ! echo -E "$msg" | grep -F -q "Signed-off-by: ${author}"
|
|
then
|
|
echo >&2 "Missing author Signed-off-by in commit $commit"
|
|
errors=$((errors+1))
|
|
fi
|
|
|
|
# 3. A Reviewed-by or Acked-by is required.
|
|
if ! echo -E "$msg" | grep -q '^\(Reviewed\|Acked\)-by: '
|
|
then
|
|
echo >&2 "No Reviewed-by or Acked-by in commit $commit"
|
|
errors=$((errors+1))
|
|
fi
|
|
|
|
# 4. The commit message shall not contain a Change-Id.
|
|
if echo -E "$msg" | grep -q '^Change-Id:'
|
|
then
|
|
echo >&2 "Found Change-Id in commit $commit"
|
|
errors=$((errors+1))
|
|
fi
|
|
done
|
|
|
|
if [ $errors != 0 ]
|
|
then
|
|
echo >&2 "Found $errors errors in $local_ref, not pushing"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
exit 0
|