tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

pre-push.git-hook (4625B)


      1 #!/usr/bin/env bash
      2 
      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 main, release-*
      6 #    or maint-*
      7 # 2) Disallow pushing branches other than main, release-*
      8 #    and maint-* to origin (e.g. gitweb.torproject.org)
      9 #
     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.
     15 #
     16 # The following sample script was used as starting point:
     17 # https://github.com/git/git/blob/master/templates/hooks--pre-push.sample
     18 
     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
     22 
     23 echo "Running pre-push hook"
     24 
     25 z40=0000000000000000000000000000000000000000
     26 
     27 upstream_name=${TOR_UPSTREAM_REMOTE_NAME:-"upstream"}
     28 
     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)
     34 
     35 cd "$workdir" || exit 1
     36 
     37 remote="$1"
     38 remote_name=$(git remote --verbose | grep "$2" | awk '{print $1}' | head -n 1)
     39 
     40 
     41 ref_is_upstream_branch() {
     42     if [ "$1" == "refs/heads/main" ] ||
     43         [[ "$1" == refs/heads/release-* ]] ||
     44         [[ "$1" == refs/heads/maint-* ]]; then
     45         return 1
     46     fi
     47 }
     48 
     49 # shellcheck disable=SC2034
     50 while read -r local_ref local_sha remote_ref remote_sha
     51 do
     52     if [ "$local_sha" = $z40 ]; then
     53         # Handle delete
     54         :
     55     else
     56         if [ "$remote_sha" = $z40 ]; then
     57             # New branch, examine commits not in main
     58             range="main...$local_sha"
     59         else
     60             # Update to existing branch, examine new commits
     61             range="$remote_sha..$local_sha"
     62         fi
     63 
     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] \
     84                           )"
     85 
     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
     92             fi
     93         fi
     94 
     95         if [[ "$remote_name" != "$upstream_name" ]]; then
     96             echo "Not pushing to upstream - refraining from further checks"
     97             continue
     98         fi
     99 
    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
    109             fi
    110         fi
    111 
    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
    118         fi
    119 
    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
    126         fi
    127     fi
    128 done
    129 
    130 exit 0