templates / hooks--updateon commit update-hook: abort early if the project description is unset (0a0d080)
   1#!/bin/sh
   2#
   3# An example hook script to mail out commit update information.
   4# It can also blocks tags that aren't annotated.
   5# Called by git-receive-pack with arguments: refname sha1-old sha1-new
   6#
   7# To enable this hook, make this file executable by "chmod +x update".
   8#
   9# Config
  10# ------
  11# hooks.mailinglist
  12#   This is the list that all pushes will go to; leave it blank to not send
  13#   emails frequently.  The log email will list every log entry in full between
  14#   the old ref value and the new ref value.
  15# hooks.announcelist
  16#   This is the list that all pushes of annotated tags will go to.  Leave it
  17#   blank to just use the mailinglist field.  The announce emails list the
  18#   short log summary of the changes since the last annotated tag
  19# hooks.allowunannotated
  20#   This boolean sets whether unannotated tags will be allowed into the
  21#   repository.  By default they won't be.
  22#
  23# Notes
  24# -----
  25# All emails have their subjects prefixed with "[SCM]" to aid filtering.
  26# All emails include the headers "X-Git-Refname", "X-Git-Oldrev",
  27# "X-Git-Newrev", and "X-Git-Reftype" to enable fine tuned filtering and info.
  28
  29# --- Constants
  30EMAILPREFIX="[SCM] "
  31LOGBEGIN="- Log -----------------------------------------------------------------"
  32LOGEND="-----------------------------------------------------------------------"
  33DATEFORMAT="%F %R %z"
  34
  35# --- Command line
  36refname="$1"
  37oldrev="$2"
  38newrev="$3"
  39
  40# --- Safety check
  41if [ -z "$GIT_DIR" ]; then
  42        echo "Don't run this script from the command line." >&2
  43        echo " (if you want, you could supply GIT_DIR then run" >&2
  44        echo "  $0 <ref> <oldrev> <newrev>)" >&2
  45        exit 1
  46fi
  47
  48if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
  49        echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
  50        exit 1
  51fi
  52
  53# --- Config
  54projectdesc=$(cat $GIT_DIR/description)
  55recipients=$(git-repo-config hooks.mailinglist)
  56announcerecipients=$(git-repo-config hooks.announcelist)
  57allowunannotated=$(git-repo-config --bool hooks.allowunannotated)
  58
  59# check for no description
  60if [ -z "$projectdesc" -o "$projectdesc" = "Unnamed repository; edit this file to name it for gitweb" ]; then
  61        echo "*** Project description file hasn't been set" >&2
  62        exit 1
  63fi
  64
  65# --- Check types
  66newrev_type=$(git-cat-file -t $newrev)
  67
  68case "$refname","$newrev_type" in
  69        refs/tags/*,commit)
  70                # un-annotated tag
  71                refname_type="tag"
  72                short_refname=${refname##refs/tags/}
  73                if [ "$allowunannotated" != "true" ]; then
  74                        echo "*** The un-annotated tag, $short_refname is not allowed in this repository" >&2
  75                        echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
  76                        exit 1
  77                fi
  78                ;;
  79        refs/tags/*,tag)
  80                # annotated tag
  81                refname_type="annotated tag"
  82                short_refname=${refname##refs/tags/}
  83                # change recipients
  84                if [ -n "$announcerecipients" ]; then
  85                        recipients="$announcerecipients"
  86                fi
  87                ;;
  88        refs/heads/*,commit)
  89                # branch
  90                refname_type="branch"
  91                short_refname=${refname##refs/heads/}
  92                ;;
  93        refs/remotes/*,commit)
  94                # tracking branch
  95                refname_type="tracking branch"
  96                short_refname=${refname##refs/remotes/}
  97                # Should this even be allowed?
  98                echo "*** Push-update of tracking branch, $refname.  No email generated." >&2
  99                exit 0
 100                ;;
 101        *)
 102                # Anything else (is there anything else?)
 103                echo "*** Update hook: unknown type of update, \"$newrev_type\", to ref $refname" >&2
 104                exit 1
 105                ;;
 106esac
 107
 108# Check if we've got anyone to send to
 109if [ -z "$recipients" ]; then
 110        # If the email isn't sent, then at least give the user some idea of what command
 111        # would generate the email at a later date
 112        echo "*** No recipients found - no email will be sent, but the push will continue" >&2
 113        echo "*** for $0 $1 $2 $3" >&2
 114        exit 0
 115fi
 116
 117# --- Email parameters
 118committer=$(git show --pretty=full -s $newrev | grep "^Commit: " | sed -e "s/^Commit: //")
 119describe=$(git describe $newrev 2>/dev/null)
 120if [ -z "$describe" ]; then
 121        describe=$newrev
 122fi
 123
 124# --- Email (all stdout will be the email)
 125(
 126# Generate header
 127cat <<-EOF
 128From: $committer
 129To: $recipients
 130Subject: ${EMAILPREFIX}$projectdesc $refname_type, $short_refname now at $describe
 131X-Git-Refname: $refname
 132X-Git-Reftype: $refname_type
 133X-Git-Oldrev: $oldrev
 134X-Git-Newrev: $newrev
 135
 136Hello,
 137
 138This is an automated email from the git hooks/update script, it was
 139generated because a ref change was pushed to the repository.
 140
 141Updating $refname_type, $short_refname,
 142EOF
 143
 144case "$refname_type" in
 145        "tracking branch"|branch)
 146                if expr "$oldrev" : '0*$' >/dev/null
 147                then
 148                        # If the old reference is "0000..0000" then this is a new branch
 149                        # and so oldrev is not valid
 150                        echo "  as a new  $refname_type"
 151                    echo "        to  $newrev ($newrev_type)"
 152                        echo ""
 153                        echo $LOGBEGIN
 154                        # This shows all log entries that are not already covered by
 155                        # another ref - i.e. commits that are now accessible from this
 156                        # ref that were previously not accessible
 157                        git log $newrev --not --all
 158                        echo $LOGEND
 159                else
 160                        # oldrev is valid
 161                        oldrev_type=$(git-cat-file -t "$oldrev")
 162
 163                        # Now the problem is for cases like this:
 164                        #   * --- * --- * --- * (oldrev)
 165                        #          \
 166                        #           * --- * --- * (newrev)
 167                        # i.e. there is no guarantee that newrev is a strict subset
 168                        # of oldrev - (would have required a force, but that's allowed).
 169                        # So, we can't simply say rev-list $oldrev..$newrev.  Instead
 170                        # we find the common base of the two revs and list from there
 171                        baserev=$(git-merge-base $oldrev $newrev)
 172
 173                        # Commit with a parent
 174                        for rev in $(git-rev-list $newrev --not $baserev --all)
 175                        do
 176                                revtype=$(git-cat-file -t "$rev")
 177                                echo "       via  $rev ($revtype)"
 178                        done
 179                        if [ "$baserev" = "$oldrev" ]; then
 180                                echo "      from  $oldrev ($oldrev_type)"
 181                        else
 182                                echo "  based on  $baserev"
 183                                echo "      from  $oldrev ($oldrev_type)"
 184                                echo ""
 185                                echo "This ref update crossed a branch point; i.e. the old rev is not a strict subset"
 186                                echo "of the new rev.  This occurs, when you --force push a change in a situation"
 187                                echo "like this:"
 188                                echo ""
 189                                echo " * -- * -- B -- O -- O -- O ($oldrev)"
 190                                echo "            \\"
 191                                echo "             N -- N -- N ($newrev)"
 192                                echo ""
 193                                echo "Therefore, we assume that you've already had alert emails for all of the O"
 194                                echo "revisions, and now give you all the revisions in the N branch from the common"
 195                                echo "base, B ($baserev), up to the new revision."
 196                        fi
 197                        echo ""
 198                        echo $LOGBEGIN
 199                        git log $newrev --not $baserev --all
 200                        echo $LOGEND
 201                        echo ""
 202                        echo "Diffstat:"
 203                        git-diff-tree --no-color --stat -M -C --find-copies-harder $baserev..$newrev
 204                fi
 205                ;;
 206        "annotated tag")
 207                # Should we allow changes to annotated tags?
 208                if expr "$oldrev" : '0*$' >/dev/null
 209                then
 210                        # If the old reference is "0000..0000" then this is a new atag
 211                        # and so oldrev is not valid
 212                        echo "        to  $newrev ($newrev_type)"
 213                else
 214                        echo "        to  $newrev ($newrev_type)"
 215                        echo "      from  $oldrev"
 216                fi
 217
 218                # If this tag succeeds another, then show which tag it replaces
 219                prevtag=$(git describe --abbrev=0 $newrev^ 2>/dev/null)
 220                if [ -n "$prevtag" ]; then
 221                        echo "  replaces  $prevtag"
 222                fi
 223
 224                # Read the tag details
 225                eval $(git cat-file tag $newrev | \
 226                        sed -n '4s/tagger \([^>]*>\)[^0-9]*\([0-9]*\).*/tagger="\1" ts="\2"/p')
 227                tagged=$(date --date="1970-01-01 00:00:00 +0000 $ts seconds" +"$DATEFORMAT")
 228
 229                echo " tagged by  $tagger"
 230                echo "        on  $tagged"
 231
 232                echo ""
 233                echo $LOGBEGIN
 234                echo ""
 235
 236                if [ -n "$prevtag" ]; then
 237                        git rev-list --pretty=short "$prevtag..$newrev" | git shortlog
 238                else
 239                        git rev-list --pretty=short $newrev | git shortlog
 240                fi
 241
 242                echo $LOGEND
 243                echo ""
 244                ;;
 245        *)
 246                # By default, unannotated tags aren't allowed in; if
 247                # they are though, it's debatable whether we would even want an
 248                # email to be generated; however, I don't want to add another config
 249                # option just for that.
 250                #
 251                # Unannotated tags are more about marking a point than releasing
 252                # a version; therefore we don't do the shortlog summary that we
 253                # do for annotated tags above - we simply show that the point has
 254                # been marked, and print the log message for the marked point for
 255                # reference purposes
 256                #
 257                # Note this section also catches any other reference type (although
 258                # there aren't any) and deals with them in the same way.
 259                if expr "$oldrev" : '0*$' >/dev/null
 260                then
 261                        # If the old reference is "0000..0000" then this is a new tag
 262                        # and so oldrev is not valid
 263                        echo "  as a new  $refname_type"
 264                        echo "        to  $newrev ($newrev_type)"
 265                else
 266                        echo "        to  $newrev ($newrev_type)"
 267                        echo "      from  $oldrev"
 268                fi
 269                echo ""
 270                echo $LOGBEGIN
 271                git-show --no-color --root -s $newrev
 272                echo $LOGEND
 273                echo ""
 274                ;;
 275esac
 276
 277# Footer
 278cat <<-EOF
 279
 280hooks/update
 281---
 282Git Source Code Management System
 283$0 $1 \\
 284  $2 \\
 285  $3
 286EOF
 287#) | cat >&2
 288) | /usr/sbin/sendmail -t
 289
 290# --- Finished
 291exit 0