tor/scripts/git/pre-push.git-hook
Alexander Færøy 22552ad88e Update scripts to use main instead of master.
When talking about the "master" Tor checkout, we now refer to it as "the
primary Tor repository". The "master" branch is instead called "main".

See: tpo/core/team#2.
2021-05-25 00:20:58 +00:00

131 lines
4.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# git pre-push hook script to:
# 0) Call the pre-commit hook, if it is available
# 1) prevent "fixup!" and "squash!" commit from ending up in main, release-*
# or maint-*
# 2) Disallow pushing branches other than main, release-*
# and maint-* to origin (e.g. gitweb.torproject.org)
#
# To install this script, copy it into .git/hooks/pre-push path in your
# local copy of git repository. Make sure it has permission to execute.
# Furthermore, make sure that TOR_UPSTREAM_REMOTE_NAME environment
# variable is set to local name of git remote that corresponds to upstream
# repository on e.g. git.torproject.org.
#
# The following sample script was used as starting point:
# https://github.com/git/git/blob/master/templates/hooks--pre-push.sample
# Are you adding a new check to the git hooks?
# - Common checks belong in the pre-commit hook
# - Push-only checks belong in the pre-push hook
echo "Running pre-push hook"
z40=0000000000000000000000000000000000000000
upstream_name=${TOR_UPSTREAM_REMOTE_NAME:-"upstream"}
# The working directory
workdir=$(git rev-parse --show-toplevel)
# The .git directory
# If $workdir is a worktree, then $gitdir is not $workdir/.git
gitdir=$(git rev-parse --git-dir)
cd "$workdir" || exit 1
remote="$1"
remote_name=$(git remote --verbose | grep "$2" | awk '{print $1}' | head -n 1)
ref_is_upstream_branch() {
if [ "$1" == "refs/heads/main" ] ||
[[ "$1" == refs/heads/release-* ]] ||
[[ "$1" == refs/heads/maint-* ]]; then
return 1
fi
}
# shellcheck disable=SC2034
while read -r local_ref local_sha remote_ref remote_sha
do
if [ "$local_sha" = $z40 ]; then
# Handle delete
:
else
if [ "$remote_sha" = $z40 ]; then
# New branch, examine commits not in main
range="main...$local_sha"
else
# Update to existing branch, examine new commits
range="$remote_sha..$local_sha"
fi
# Call the pre-commit hook for the common checks, if it is executable
pre_commit=${gitdir}/hooks/pre-commit
if [ -x "$pre_commit" ]; then
# Only check the files newly modified in this branch
CHECK_FILTER="git diff --name-only --diff-filter=ACMR $range"
# Use the appropriate owned tor source list to filter the changed
# files
# This is the layout in 0.3.5
# Keep these lists consistent:
# - OWNED_TOR_C_FILES in Makefile.am
# - CHECK_FILES in pre-commit.git-hook and pre-push.git-hook
# - try_parse in check_cocci_parse.sh
CHECK_FILES="$($CHECK_FILTER \
src/lib/*/*.[ch] \
src/core/*/*.[ch] \
src/feature/*/*.[ch] \
src/app/*/*.[ch] \
src/test/*.[ch] \
src/test/*/*.[ch] \
src/tools/*.[ch] \
)"
export TOR_EXTRA_PRE_COMMIT_CHECKS=1
# We want word splitting here, because file names are space
# separated
# shellcheck disable=SC2086
if ! "$pre_commit" $CHECK_FILES ; then
exit 1
fi
fi
if [[ "$remote_name" != "$upstream_name" ]]; then
echo "Not pushing to upstream - refraining from further checks"
continue
fi
if (ref_is_upstream_branch "$local_ref" == 0 ||
ref_is_upstream_branch "$remote_ref" == 0) &&
[ "$local_ref" != "$remote_ref" ]; then
if [ "$remote" == "origin" ]; then
echo >&2 "Not pushing: $local_ref to $remote_ref"
echo >&2 "If you really want to push this, use --no-verify."
exit 1
else
continue
fi
fi
# Check for fixup! commit
commit=$(git rev-list -n 1 --grep '^fixup!' "$range")
if [ -n "$commit" ]; then
echo >&2 "Found fixup! commit in $local_ref, not pushing"
echo >&2 "If you really want to push this, use --no-verify."
exit 1
fi
# Check for squash! commit
commit=$(git rev-list -n 1 --grep '^squash!' "$range")
if [ -n "$commit" ]; then
echo >&2 "Found squash! commit in $local_ref, not pushing"
echo >&2 "If you really want to push this, use --no-verify."
exit 1
fi
fi
done
exit 0