260 lines
5.9 KiB
Bash
Executable File
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
|