#!/bin/sh # # An example hook script to blocks unannotated tags from entering. # Called by git-receive-pack with arguments: refname sha1-old sha1-new # # To enable this hook, make this file executable by "chmod +x update". # # Config # ------ # hooks.allowunannotated # This boolean sets whether unannotated tags will be allowed into the # repository. By default they won't be. # hooks.allowdeletetag # This boolean sets whether deleting tags will be allowed in the # repository. By default they won't be. # hooks.allowdeletebranch # This boolean sets whether deleting branches will be allowed in the # repository. By default they won't be. # hooks.denycreatebranch # This boolean sets whether remotely creating branches will be denied # in the repository. By default this is allowed. # # hooks.denybadwhitespace # This boolean sets whether you may push a commit that adds bad whitespace. # By default, you may. # # 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 # a result of this option, the resulting diagnostic includes the specified # email address. For example, run this on the server to deny all push # access to "master": # # git config hooks.denypush.branch.master master-branch-owner@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. To deny merge commits to the "next" branch: # # git config --bool hooks.denymerge.next true # # --- 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 echo " (if you want, you could supply GIT_DIR then run" >&2 echo " $0 )" >&2 exit 1 fi if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then echo "Usage: $0 " >&2 exit 1 fi # --- Config allowunannotated=$(git config --bool hooks.allowunannotated) allowdeletebranch=$(git config --bool hooks.allowdeletebranch) denycreatebranch=$(git config --bool hooks.denycreatebranch) allowdeletetag=$(git config --bool hooks.allowdeletetag) # check for no description projectdesc=$(sed -e '1q' "$GIT_DIR/description") case "$projectdesc" in "Unnamed repository"* | "") echo "*** Project description file hasn't been set" >&2 exit 1 ;; esac # --- Check types # if $newrev is 0000...0000, it's a commit to delete a ref. zero="0000000000000000000000000000000000000000" if [ "$newrev" = "$zero" ]; then newrev_type=delete else newrev_type=$(git-cat-file -t $newrev) fi check_diff=no case "$refname","$newrev_type" in refs/tags/*,commit) # un-annotated tag short_refname=${refname##refs/tags/} if [ "$allowunannotated" != "true" ]; then echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 exit 1 fi ;; refs/tags/*,delete) # delete tag if [ "$allowdeletetag" != "true" ]; then echo "*** Deleting a tag is not allowed in this repository" >&2 exit 1 fi ;; refs/tags/*,tag) # annotated tag ;; refs/heads/*,commit) # branch if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then echo "*** Creating a branch is not allowed in this repository" >&2 exit 1 fi check_diff=yes branch=${1##refs/heads/} deny_push_email=$(git config "hooks.denypush.branch.$branch") case $deny_push_email in '') ;; *) 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) is_merge_commit $newrev && { printf "error: *** %s\n" \ "You may not push merge commits to branch $branch." \ "Did you forget to rebase? ($newrev)" >&2 exit 1 } ;; esac ;; refs/heads/*,delete) # delete branch if [ "$allowdeletebranch" != "true" ]; then echo "*** Deleting a branch is not allowed in this repository" >&2 exit 1 fi ;; refs/remotes/*,commit) # tracking branch check_diff=yes ;; refs/remotes/*,delete) # delete tracking branch if [ "$allowdeletebranch" != "true" ]; then echo "*** Deleting a tracking branch is not allowed in this repository" >&2 exit 1 fi ;; *) # Anything else (is there anything else?) echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 exit 1 ;; esac if [ $check_diff = yes ]; then denybadwhitespace=$(git config --bool hooks.denybadwhitespace) if [ "$denybadwhitespace" = "true" ]; then test "$oldrev" = 0000000000000000000000000000000000000000 \ && exit 0 exec git --no-pager diff --check $oldrev $newrev -- fi fi # --- Finished exit 0