aboutsummaryrefslogtreecommitdiffstats
path: root/.githooks/pre-push
blob: 94abea9aec1ff5618a0b7b307d68523dc705694c (plain) (blame)
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
#!/bin/sh
# Refuse to push a release tag that disagrees with the VERSION file it points
# at. Tags are cut by contrib/release, which makes the two agree by
# construction -- so a mismatch reaching this hook means a tag made by hand,
# and pushing it would publish a version string the source itself contradicts.
# (VERSION is the floor contrib/version falls back to without git; v0.1.1
# shipped with the floor still saying 0.1.0, which is why this hook exists.)
#
# Install with `make hooks`. Skip with `git push --no-verify` when you mean to.
set -eu

# stdin: <local ref> <local sha> <remote ref> <remote sha> per ref being pushed.
status=0
while read -r _ sha remote _; do
    case "$remote" in refs/tags/v[0-9]*) ;; *) continue ;; esac
    tagged="${remote#refs/tags/v}"
    commit="$(git rev-parse -q --verify "$sha^{commit}" 2>/dev/null)" || continue
    floor="$(git show "$commit:VERSION" 2>/dev/null)" || floor="(no VERSION file)"
    if [ "$floor" != "$tagged" ]; then
        echo "pre-push: refusing v$tagged -- the commit it tags has VERSION=$floor." >&2
        echo "  cut releases with contrib/release, which bumps and tags together;" >&2
        echo "  delete this tag (git tag -d v$tagged) and re-cut, or --no-verify." >&2
        status=1
    fi
done
exit $status