version: Bump version to 0.4.6.11
[tor.git] / scripts / git / pre-push.git-hook
blobf0a3a250ec7254e4bbef46274655e52810d61420
1 #!/usr/bin/env bash
3 # git pre-push hook script to:
4 # 0) Call the pre-commit hook, if it is available
5 # 1) prevent "fixup!" and "squash!" commit from ending up in master, release-*
6 # or maint-*
7 # 2) Disallow pushing branches other than master, release-*
8 # and maint-* to origin (e.g. gitweb.torproject.org)
10 # To install this script, copy it into .git/hooks/pre-push path in your
11 # local copy of git repository. Make sure it has permission to execute.
12 # Furthermore, make sure that TOR_UPSTREAM_REMOTE_NAME environment
13 # variable is set to local name of git remote that corresponds to upstream
14 # repository on e.g. git.torproject.org.
16 # The following sample script was used as starting point:
17 # https://github.com/git/git/blob/master/templates/hooks--pre-push.sample
19 # Are you adding a new check to the git hooks?
20 # - Common checks belong in the pre-commit hook
21 # - Push-only checks belong in the pre-push hook
23 echo "Running pre-push hook"
25 z40=0000000000000000000000000000000000000000
27 upstream_name=${TOR_UPSTREAM_REMOTE_NAME:-"upstream"}
29 # The working directory
30 workdir=$(git rev-parse --show-toplevel)
31 # The .git directory
32 # If $workdir is a worktree, then $gitdir is not $workdir/.git
33 gitdir=$(git rev-parse --git-dir)
35 cd "$workdir" || exit 1
37 remote="$1"
38 remote_name=$(git remote --verbose | grep "$2" | awk '{print $1}' | head -n 1)
41 ref_is_upstream_branch() {
42 if [ "$1" == "refs/heads/master" ] ||
43 [[ "$1" == refs/heads/release-* ]] ||
44 [[ "$1" == refs/heads/maint-* ]]; then
45 return 1
49 # shellcheck disable=SC2034
50 while read -r local_ref local_sha remote_ref remote_sha
52 if [ "$local_sha" = $z40 ]; then
53 # Handle delete
55 else
56 if [ "$remote_sha" = $z40 ]; then
57 # New branch, examine commits not in master
58 range="master...$local_sha"
59 else
60 # Update to existing branch, examine new commits
61 range="$remote_sha..$local_sha"
64 # Call the pre-commit hook for the common checks, if it is executable
65 pre_commit=${gitdir}/hooks/pre-commit
66 if [ -x "$pre_commit" ]; then
67 # Only check the files newly modified in this branch
68 CHECK_FILTER="git diff --name-only --diff-filter=ACMR $range"
69 # Use the appropriate owned tor source list to filter the changed
70 # files
71 # This is the layout in 0.3.5
72 # Keep these lists consistent:
73 # - OWNED_TOR_C_FILES in Makefile.am
74 # - CHECK_FILES in pre-commit.git-hook and pre-push.git-hook
75 # - try_parse in check_cocci_parse.sh
76 CHECK_FILES="$($CHECK_FILTER \
77 src/lib/*/*.[ch] \
78 src/core/*/*.[ch] \
79 src/feature/*/*.[ch] \
80 src/app/*/*.[ch] \
81 src/test/*.[ch] \
82 src/test/*/*.[ch] \
83 src/tools/*.[ch] \
86 export TOR_EXTRA_PRE_COMMIT_CHECKS=1
87 # We want word splitting here, because file names are space
88 # separated
89 # shellcheck disable=SC2086
90 if ! "$pre_commit" $CHECK_FILES ; then
91 exit 1
95 if [[ "$remote_name" != "$upstream_name" ]]; then
96 echo "Not pushing to upstream - refraining from further checks"
97 continue
100 if (ref_is_upstream_branch "$local_ref" == 0 ||
101 ref_is_upstream_branch "$remote_ref" == 0) &&
102 [ "$local_ref" != "$remote_ref" ]; then
103 if [ "$remote" == "origin" ]; then
104 echo >&2 "Not pushing: $local_ref to $remote_ref"
105 echo >&2 "If you really want to push this, use --no-verify."
106 exit 1
107 else
108 continue
112 # Check for fixup! commit
113 commit=$(git rev-list -n 1 --grep '^fixup!' "$range")
114 if [ -n "$commit" ]; then
115 echo >&2 "Found fixup! commit in $local_ref, not pushing"
116 echo >&2 "If you really want to push this, use --no-verify."
117 exit 1
120 # Check for squash! commit
121 commit=$(git rev-list -n 1 --grep '^squash!' "$range")
122 if [ -n "$commit" ]; then
123 echo >&2 "Found squash! commit in $local_ref, not pushing"
124 echo >&2 "If you really want to push this, use --no-verify."
125 exit 1
128 done
130 exit 0