[Ovirt-devel] [PATCH release] server-side git hook: improve merge detection/prohibition

Jim Meyering jim at meyering.net
Mon Mar 23 19:34:20 UTC 2009


FYI, I've just pushed this to the vcs-admin branch of "ovirt-release",
and am about to install it on the server, so it won't be possible to
produce another "diamond" like you currently see in ovirt-node.

>From 458d8b1df86a0f4ba9b3ae335e058a2afb04e698 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering at redhat.com>
Date: Mon, 23 Mar 2009 20:29:04 +0100
Subject: [PATCH release] improve merge detection/prohibition

* update: Document hooks.denymerge.BRANCH_NAME.
When looking for merge commits, check all that are being pushed,
not just the first one.
---
 git-hook/update |   48 ++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 42 insertions(+), 6 deletions(-)
 mode change 100644 => 100755 git-hook/update

diff --git a/git-hook/update b/git-hook/update
old mode 100644
new mode 100755
index 9c80b36..c82015e
--- a/git-hook/update
+++ b/git-hook/update
@@ -1,7 +1,7 @@
 #!/bin/sh
 #
 # An example hook script to blocks unannotated tags from entering.
-# Called by git-receive-pack with arguments: refname sha1-old sha1-new
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
 #
 # To enable this hook, rename this file to "update".
 #
@@ -16,6 +16,11 @@
 # hooks.allowdeletebranch
 #   This boolean sets whether deleting branches will be allowed in the
 #   repository.  By default they won't be.
+#
+# hooks.allowbadwhitespace
+#   This boolean sets whether you may push a commit that adds bad whitespace.
+#   By default, you may not.
+#
 # hooks.denypush.branch.BRANCH_NAME
 #   If defined to a string that looks like an email address, this option
 #   disables push access to the specified branch.  When a push fails as
@@ -23,14 +28,24 @@
 #   email address.  For example, run this on the server to deny all push
 #   access to "master":
 #
+#   For example, enable it with this:
 #   git config hooks.denypush.branch.master master-branch-owner at example.com
 #
+# hooks.denymerge.BRANCH_NAME
+#   When this boolean is true, you may not push a merge commit to BRANCH_NAME.
+#   By default, you may.
+#

 # --- Command line
 refname="$1"
 oldrev="$2"
 newrev="$3"

+is_merge_commit()
+{
+	git rev-parse --verify --quiet $1^2 > /dev/null
+}
+
 # --- Safety check
 if [ -z "$GIT_DIR" ]; then
 	echo "Don't run this script from the command line." >&2
@@ -51,17 +66,19 @@ allowdeletetag=$(git config --bool hooks.allowdeletetag)

 # check for no description
 projectdesc=$(sed -e '1q' "$GIT_DIR/description")
-if [ -z "$projectdesc" -o "$projectdesc" = "Unnamed repository; edit this file to name it for gitweb." ]; then
+case "$projectdesc" in
+"Unnamed repository"* | "")
 	echo "*** Project description file hasn't been set" >&2
 	exit 1
-fi
+	;;
+esac

 # --- Check types
 # if $newrev is 0000...0000, it's a commit to delete a ref.
 if [ "$newrev" = "0000000000000000000000000000000000000000" ]; then
 	newrev_type=delete
 else
-	newrev_type=$(git-cat-file -t $newrev)
+	newrev_type=$(git cat-file -t $newrev)
 fi

 check_diff=no
@@ -87,15 +104,34 @@ case "$refname","$newrev_type" in
 		;;
 	refs/heads/*,commit)
 		# branch
- 		check_diff=yes
+		check_diff=yes
 		branch=${1##refs/heads/}
 		deny_push_email=$(git config "hooks.denypush.branch.$branch")
 		case $deny_push_email in
 			'') ;;
-			*) printf "$0: %s\n" "commit on branch '$branch'" \
+			*) printf "error: *** %s\n" \
+			      "commit on branch '$branch'" \
 			      "locked by $deny_push_email" >&2
 			 exit 1;;
 		esac
+
+		# When enabled, this prohibits pushing a merge commit.
+		# Enable this hook for branch "next" with e.g.,
+		# git config --bool hooks.denymerge.next true
+		deny_merge=$(git config --bool "hooks.denymerge.$branch")
+		case $deny_merge in
+		    true)
+			for r in $(git rev-list $newrev ^$oldrev); do
+			  is_merge_commit $r && {
+			    printf "error: *** %s\n" \
+			  "You may not push merge commits to branch $branch." \
+			  "Did you forget to rebase? ($r)" >&2
+			  exit 1
+			  }
+			done
+			;;
+		esac
+
 		;;
 	refs/heads/*,delete)
 		# delete branch
--
1.6.2.rc1.285.gc5f54




More information about the ovirt-devel mailing list