git-bin/pre-receive-check-policy

260 lines
5.9 KiB
Bash
Executable File

#!/bin/bash
# This script checks gnome.org policy about how people are supposed to
# use git; the intent of the policy is to keep people from shooting
# themselve in the foot.
#
# Eventually, we'd like to have an ability to override policy; one way
# it could work is that if you did 'git push --exec=force' and you
# were a member of the right group, then run-git-or-special-cmd
# would set an environment variable that this script would interpret.
# Used in some of the messages
server=git.labs.libre-entreprise.org
GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
in_import() {
test -e "$GIT_DIR/pending"
}
forced() {
test -n "$GNOME_GIT_FORCE"
}
check_commit() {
commit=$1
email="$(git log $commit -1 --pretty=format:%ae)"
case "$email" in
*localhost.localdomain|*\(none\))
if ! in_import && ! forced ; then
cat <<EOF >&2
---
The commits you are trying to push contain the author email
address '$email'. Please configure your
username and email address. See:
http://live.gnome.org/Git/Help/AuthorEmail
For instructions about how to do this and how to fix your
existing commits.
---
EOF
exit 1
fi
;;
esac
subject="$(git log $commit -1 --pretty=format:%s)"
if expr "$subject" : ".*Merge branch.*of.*\(git\|ssh\):" > /dev/null 2>&1; then
if ! in_import && ! forced ; then
cat <<EOF >&2
---
The commit:
EOF
git log $commit -1 >&2
cat <<EOF >&2
Looks like it was produced by typing 'git pull' without the --rebase
option when you had local changes. Running 'git pull --rebase' now
will fix the problem. Then please try, 'git push' again. Please see:
http://live.gnome.org/Git/Help/ExtraMergeCommits
---
EOF
exit 1
fi
fi
}
check_ref_update() {
oldrev=$1
newrev=$2
refname=$3
change_type=update
if expr $oldrev : "^0\+$" > /dev/null 2>&1; then
change_type=create
fi
if expr $newrev : "^0\+$" > /dev/null 2>&1; then
if [ x$change_type = xcreate ] ; then
# Deleting an invalid ref, allow
return 0
fi
change_type=delete
fi
case $refname in
refs/heads/*)
# Branch update
branchname=${refname#refs/heads/}
range=
case $change_type in
create)
range="$newrev"
;;
delete)
# We really don't like to allow deleting any branch, but
# people need to do it to clean up accidentally pushed
# branches. Deleting master, however, has no purpose other
# than getting around the no-fast-forward restrictions
if [ "x$branchname" = xmaster ] ; then
cat <<EOF >&2
---
You are trying to delete the branch 'master'.
---
EOF
exit 1
fi
;;
update)
range="$oldrev..$newrev"
if [ `git merge-base $oldrev $newrev` != $oldrev ] && ! forced ; then
# Non-fast-forward update. Right now we have
# receive.denyNonFastforwards in the git configs for
# our repositories anyways, but catching it here would
# allow overriding without having to change the config
# temporarily.
cat <<EOF >&2
---
You are trying to update the branch '$branchname' in a way that is not
a fast-forward update. Please see:
http://live.gnome.org/Git/Help/NonFastForward
---
EOF
exit 1
fi
;;
esac
# For new commits introduced with this branch update, we want to run some
# checks to catch common mistakes.
#
# Expression here is same as in post-receive-notify-cia; we take
# all the branches in the repo, as "^/ref/heads/branchname", other than the
# branch we are actualy committing to, and exclude commits already on those
# branches from the list of commits between $oldrev and $newrev.
if [ -n "$range" ] ; then
for merged in $(git rev-parse --symbolic-full-name --not --branches | \
egrep -v "^\^$refname$" | \
git rev-list --reverse --stdin "$range"); do
check_commit $merged
done
fi
;;
refs/tags/*)
# Tag update
tagname=${refname#refs/tags/}
case $change_type in
create)
object_type=`git cat-file -t $newrev`
case $object_type in
commit)
# Lightweight tag; we allow an import containing these
# tags, but forbid them in general
if ! in_import && ! forced ; then
cat <<EOF >&2
---
You are trying to push the lightweight tag '$tagname'. You should use
a signed tag instead. See:
http://live.gnome.org/Git/Help/LightweightTags
---
EOF
exit 1
fi
;;
tag)
# Annotated tag
;;
*)
# git is happy to allow tagging random objects, we aren't
cat <<EOF >&2
---
You are trying to push the tag '$tagname', which points to an object
of type $object_type. (It should point to a commit or tag object.)
---
EOF
exit 1
;;
esac
;;
delete)
# Deleting a tag is probably someone trying to work-around
# not being able to update a tag. Disallowing lightweight
# tags will cut down on accidentally pushing tags called 'list'
# or whatever. During import we allow the user to clean up
# accidentally pushed tags.
if ! in_import && ! forced ; then
cat <<EOF >&2
---
You are trying to delete the tag '$tagname'.
http://live.gnome.org/Git/Help/TagUpdates
---
EOF
exit 1
fi
;;
update)
if ! forced ; then
cat <<EOF >&2
---
You are trying to replace the tag '$tagname' with a new tag. Please see:
http://live.gnome.org/Git/Help/TagUpdates
---
EOF
exit 1
fi
;;
esac
;;
refs/remotes/*)
# Remote tracking branch
cat <<EOF >&2
---
You are trying to push the remote tracking branch:
$refname
to $server.
---
EOF
exit 1
;;
*)
# Something else
cat <<EOF >&2
---
You are trying to push the ref:
$refname
to $server. This isn't a branch or tag.
---
EOF
exit 1
;;
esac
return 0
}
if [ $# = 3 ] ; then
check_ref_update $@
else
while read oldrev newrev refname; do
check_ref_update $oldrev $newrev $refname
done
fi
exit 0