summaryrefslogtreecommitdiff
path: root/hooks/git/pre-push_signed-off-by
blob: baaa8771eedd0760c21519321af4704c556d21bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#!/bin/bash

# some of this is from
# https://lubomir.github.io/en/2016-05-04-signoff-hooks.html

remote="$1"
url="$2"

z40=0000000000000000000000000000000000000000

while read local_ref local_sha remote_ref remote_sha; do
    if [ "$local_sha" = $z40 ]; then
        # Permit deletion of branches
        :
    elif echo "$remote_ref" | grep -Eq "^refs/heads/(wip|tmp)/"; then
        # wip/ branches may contain commits which are not signed off
        :
    elif echo "$remote_ref" | grep -Eq "^refs/dgit/"; then
        # let's not interfere with a dgit push
        :
    elif echo "$remote_ref" | grep -Eq "^refs/tags/(archive/)?debian"; then
        # let Debian upload tags through
        :
    elif [ $(git config --get --type=bool --default=false \
                 branch.${local_ref#refs/heads/}.signOffOptional) \
               = "true" ]; then
        # some local branches may be configured not to require signing
        # off wherever they are pushed
        :
    else
        if [ "$remote_sha" = $z40 ]
        then
            # New branch, examine all commits
            range="$local_sha"
        else
            # Update to existing branch, examine new commits
            range="$remote_sha..$local_sha"
        fi

        # Check for WIP commit
        commit=$(git rev-list -n 1 -i --grep '^WIP' "$range")
        if [ -n "$commit" ]
        then
            echo >&2 "Found WIP commit in $local_ref, not pushing"
            exit 1
        fi

        # Check for commits without sign-off
        if [ "$remote_sha" = $z40 ]; then
            # New branch is pushed, we only want to check commits that are not
            # on master.
            range="$(git merge-base master "$local_sha")..$local_sha"
        fi
        while read ref; do
            msg=$(git log -n 1 --format=%B "$ref")
            if ! grep -q '^Signed-off-by: ' <<<"$msg" \
		    && ! grep -q '^Commit Debian 3.0 (quilt) metadata$' <<<"$msg"; then
                # allow merge commits through
                if [ -z "$(git rev-list -1 --merges $ref~1..$ref)" ]; then
                   echo >&2 "Unsigned-off non-merge commit $ref"
                   exit 1
                fi
            fi
        done < <(git rev-list "$range")
        # The process substitution above is a hack to make sure loop runs in
        # the same shell and can actually exit the whole script.
    fi
done

exit 0