diff --git a/README.md b/README.md new file mode 100644 index 0000000..41833dd --- /dev/null +++ b/README.md @@ -0,0 +1,75 @@ +Versioners +========== + +This is a set of scripts that I use for automatically tagging, and generating version/build metadata for, mercurial and git projects. They provide your automation with quite a bit of information about the version being built, where it is built, and who built it. + +Assumptions +=========== + +*PRIMARILY, THIS ASSUMES YOU ARE USING A BASH SCRIPT-CAPABLE BUILD ENVIRONMENT. THESE ARE BASH SCRIPTS.* + +This assumes you want your project versioned like this: + + (MAJOR)-(BUILD) + +... Where MAJOR will default to the name of the current branch, or the value of MAJOR on the previous tag (of the current branch). BUILD will default to 0, or the BUILD of the last tag (on the current branch) plus one. + +All builds will be tagged thusly: + + (BRANCH),(MAJOR),(BUILD) + +If you want your project to use a MAJOR that is NOT equal to the branch name (e.g. you want branch 'master' to be '1.1'), then you must set an initial tag on that branch, e.g: + + master,1.1,0 + +... And then the scripts will use 1.1, instead of 'master', as the MAJOR version component. + +Operating System Info +===================== + +There are two variables, OS_NAME and OS_VERSION, automatically provided by the script. + +OS_NAME possible values: +* win +* osx +* el (RedHat/CentOS/Fedora linux) + +OS_VERSION will contain the version number of the OS_NAME in question, except for 'win', which does not have compact or sane version numbers. + +These don't support debian yet - feel free to submit a patch. + +Generate a version +================== + +Two scripts, 'gitversion' and 'hgversion' generate version metadata for git and hg, respectively. The data output by these two is meant to be consumed by bash. + + []$ hgversion + TAG="6.3.0" + BRANCH="6.3.0" + MAJOR="6.3.0" + BUILD="0" + SHA1="9392ee5cc8da" + OS_NAME="${OS_NAME:-win}" + OS_VERSION="${OS_VERSION:-}" + ARCH="${ARCH:-i686}" + VERSION="6.3.0-0" + BUILDHOST="akesterson-pc" + BUILDUSER="akesterson" + BUILDDIR="/c/Users/akesterson/source/upstream/hg/project" + SOURCE="http://bitbucket.org/akesterson/project" + REBUILDING=1 + +This can be piped into a bash script for later sourcing. You can source this into a variety of other languages as well (python or ruby), but the ${:-} syntax is bash specific, and might confuse other languages. + +Cutting a Tag +============= + +To cut a tag, just run 'gittag' or 'hgtag': + + []$ gittag + +... This will tag the current revision with a new build number. UNLESS: + +* The current revision has already been tagged (e.g., this is just a rebuild) +* The buildnumber that we were going to use has been tagged somewhere else on this branch +* This is not marked as a rebuild, but someone else just tagged the version with the same build number we would have (e.g., distributed build systems) \ No newline at end of file diff --git a/gitversion b/gitversion new file mode 100644 index 0000000..9c3cdb6 --- /dev/null +++ b/gitversion @@ -0,0 +1,80 @@ +#!/bin/bash + +BRANCH=$2 +if [ "${BRANCH}" == "" ]; then + BRANCH=$(git branch | grep '^\*\s*.*' | cut -d ' ' -f 2) +fi + +REBUILDING=0 +SHA1=$(git rev-parse HEAD) +TAG=$(git describe --tags `git rev-list --tags --max-count=1` 2>/dev/null) +BUILD=0 +if [ "$TAG" == "" ]; then + BUILD=0 + REBUILDING=1 + MAJOR=$BRANCH +else + MAJOR=$(echo $TAG | cut -d , -f 2) + BUILD=$(echo $TAG | cut -d , -f 3) + TAGSHA=$(git rev-list $TAG | head -n 1) + if [ "$TAGSHA" != "$SHA1" ]; then + BUILD=$(expr $BUILD + 1) + REBUILDING=1 + else + SHA1=$TAGSHA + fi +fi + +if [ "$TAG" == "" ] || [ "$TAG" == "tip" ]; then + if [ "$MAJOR" == "default" ]; then + TAG="0.0" + else + TAG="$MAJOR" + fi +fi + +OS_NAME="" +OS_VERSION="" +if [ "$OS_NAME" == "" ] && [ "$(uname)" == "Darwin" ]; then + OS_NAME="osx" +elif [ "$OS_NAME" == "" ] && [ -f /etc/redhat-release ]; then + OS_NAME="el" +elif [ "$OS_NAME" == "" ] && [ "$(uname | grep -i '^MINGW')" != "" ] || [ "$(uname)" == "Cygwin" ]; then + OS_NAME="win" +fi + +if [ "$OS_VERSION" == "" ] && [ "$OS_NAME" == "el" ]; then + OS_VERSION=$(cat /etc/redhat-release | grep -o "release [0-9]" | cut -d " " -f 2) + RHEL_VERSION=$OS_VERSION +elif [ "$OS_VERSION" == "" ] && [ "$OS_NAME" == "osx" ]; then + OS_VERSION="$(sw_vers | grep 'ProductVersion:' | grep -o '[0-9]*\.[0-9]*\.[0-9]*')" +elif [ "$OS_VERSION" == "" ] && [ "$OS_NAME" == "win" ]; then + echo "OS_VERSION unsupported on Microsoft Windows." >&2 +fi + +if [ "$ARCH" == "" ]; then + if [ "$OS_NAME" == "osx" ]; then + ARCH=$(uname -m) + elif [ "$OS_NAME" != "win" ]; then + ARCH=$(uname -i) + elif [ "$OS_NAME" == "win" ]; then + ARCH=$(uname -m) + fi +fi + +SOURCE=$(git remote show origin | grep "Fetch URL" | cut -d : -f 2- | cut -d ' ' -f 2-) + +echo "TAG=\"${TAG}\"" +echo "BRANCH=\"${BRANCH}\"" +echo "MAJOR=\"${MAJOR}\"" +echo "BUILD=\"${BUILD}\"" +echo "SHA1=\"${SHA1}\"" +echo "OS_NAME=\"\${OS_NAME:-$OS_NAME}\"" +echo "OS_VERSION=\"\${OS_VERSION:-$OS_VERSION}\"" +echo "ARCH=\"\${ARCH:-$ARCH}\"" +echo "VERSION=\"${MAJOR}-${BUILD}\"" +echo "BUILDHOST=\"$(hostname)\"" +echo "BUILDUSER=\"$(whoami)\"" +echo "BUILDDIR=\"$(pwd)\"" +echo "SOURCE=\"${SOURCE}\"" +echo "REBUILDING=$REBUILDING" diff --git a/hgversion b/hgversion new file mode 100644 index 0000000..c7198a9 --- /dev/null +++ b/hgversion @@ -0,0 +1,82 @@ +#!/bin/bash + +BRANCH=$2 +if [ "${BRANCH}" == "" ]; then + BRANCH=$(hg identify -b) +fi + +REBUILDING=0 +SHA1=$(hg identify -i | grep -Eo "[a-zA-Z0-9]+") +TAG=$(hg identify -t) +LASTTAGGEDBUILD=$(hg log -r $(hg identify -n):0 --branch $BRANCH --template "{tags}\n" | grep -v "^$" | grep "build|" | head -n 1) +BUILD=0 +if [ "$TAG" == "" ]; then + BUILD=0 + REBUILDING=1 + MAJOR=$BRANCH +else + MAJOR=$(echo $TAG | cut -d , -f 2) + BUILD=$(echo $TAG | cut -d , -f 3) + SHORTTAGSHA=${TAGSHA:0:12} + hg log -r ${SHA1} | grep "Added tag build|${BRANCH}|${BUILD} for changeset ${SHORTTAGSHA}" >/dev/null + if [ $? -ne 0 ] && [ "$TAGSHA" != "$SHA1" ]; then + BUILD=$(expr $BUILD + 1) + REBUILDING=1 + else + SHA1=$TAGSHA + fi +fi + +if [ "$TAG" == "" ] || [ "$TAG" == "tip" ]; then + if [ "$MAJOR" == "default" ]; then + TAG="0.0" + else + TAG="$MAJOR" + fi +fi + +OS_NAME="" +OS_VERSION="" +if [ "$OS_NAME" == "" ] && [ "$(uname)" == "Darwin" ]; then + OS_NAME="osx" +elif [ "$OS_NAME" == "" ] && [ -f /etc/redhat-release ]; then + OS_NAME="el" +elif [ "$OS_NAME" == "" ] && [ "$(uname | grep -i '^MINGW')" != "" ] || [ "$(uname)" == "Cygwin" ]; then + OS_NAME="win" +fi + +if [ "$OS_VERSION" == "" ] && [ "$OS_NAME" == "el" ]; then + OS_VERSION=$(cat /etc/redhat-release | grep -o "release [0-9]" | cut -d " " -f 2) + RHEL_VERSION=$OS_VERSION +elif [ "$OS_VERSION" == "" ] && [ "$OS_NAME" == "osx" ]; then + OS_VERSION="$(sw_vers | grep 'ProductVersion:' | grep -o '[0-9]*\.[0-9]*\.[0-9]*')" +elif [ "$OS_VERSION" == "" ] && [ "$OS_NAME" == "win" ]; then + echo "OS_VERSION unsupported on Microsoft Windows." >&2 +fi + +if [ "$ARCH" == "" ]; then + if [ "$OS_NAME" == "osx" ]; then + ARCH=$(uname -m) + elif [ "$OS_NAME" != "win" ]; then + ARCH=$(uname -i) + elif [ "$OS_NAME" == "win" ]; then + ARCH=$(uname -m) + fi +fi + +SOURCE=$(cat .hg/hgrc | grep default | cut -d = -f 2 | sed s/"^ *"//g) + +echo "TAG=\"${TAG}\"" +echo "BRANCH=\"${BRANCH}\"" +echo "MAJOR=\"${MAJOR}\"" +echo "BUILD=\"${BUILD}\"" +echo "SHA1=\"${SHA1}\"" +echo "OS_NAME=\"\${OS_NAME:-$OS_NAME}\"" +echo "OS_VERSION=\"\${OS_VERSION:-$OS_VERSION}\"" +echo "ARCH=\"\${ARCH:-$ARCH}\"" +echo "VERSION=\"${MAJOR}-${BUILD}\"" +echo "BUILDHOST=\"$(hostname)\"" +echo "BUILDUSER=\"$(whoami)\"" +echo "BUILDDIR=\"$(pwd)\"" +echo "SOURCE=\"${SOURCE}\"" +echo "REBUILDING=$REBUILDING" diff --git a/taggit b/taggit new file mode 100644 index 0000000..7ed2a7e --- /dev/null +++ b/taggit @@ -0,0 +1,27 @@ +#!/bin/bash + +if [ "$MAKETAG" == "false" ]; then + exit 0 +fi + +if [ ! -f version ]; then + ${dirname $BASH_SOURCE)/genversion > version +fi + +. ~/.buildtoolsrc +git pull + +TAGSHA1=$(git rev-list $TAG | head -n 1) +if [ $REBUILDING -eq 0 ]; then + echo "This is a rebuild of a previous tag, not tagging or pushing" >&2 +elif [ "$TAGSHA1" != "" ] && [ "$TAGSHA1" != "$SHA1" ]; then + echo "Someone else tagged my buildnumber (branch|${MAJOR}|${BUILD}) onto $TAGSHA1, while I built it from $SHA1 ... "'Help!' >&2 + exit 1 +elif [ "$TAGSHA1" != "" ] && [ "$TAGSHA1" == "$SHA1" ]; then + echo "Someone else built this version at the same time I did, and we both tagged the same SHA1 with the same build tag. Not pushing my tag." +else + git tag -f -a "build,${MAJOR},${BUILD}" $SHA1 + if [ "$PUSHTAG" != "false" ]; then + git push + fi +fi diff --git a/taghg b/taghg new file mode 100644 index 0000000..eb81b24 --- /dev/null +++ b/taghg @@ -0,0 +1,30 @@ +#!/bin/bash + +if [ "$MAKETAG" == "false" ]; then + exit 0 +fi + +if [ ! -f version ]; then + ${dirname $BASH_SOURCE)/genversion > version +fi + +. ~/.buildtoolsrc +. version +hg pull -u --branch $(hg branch) + +TAGSHA1=$(cat .hgtags | grep "build,${MAJOR},${BUILD}" | cut -d " " -f 1) +echo "$TAGSHA1" | grep "^$SHA1" >/dev/null 2>&1 +SHORTSHAMATCH=$? +if [ $REBUILDING -eq 0 ]; then + echo "This is a rebuild of a previous tag, not tagging or pushing" >&2 +elif [ "$TAGSHA1" != "" ] && [ $SHORTSHAMATCH -ne 0 ]; then + echo "Someone else tagged my buildnumber (branch|${MAJOR}|${BUILD}) onto $TAGSHA1, while I built it from $SHA1 ... "'Help!' >&2 + exit 1 +elif [ "$TAGSHA1" != "" ] && [ $SHORTSHAMATCH -eq 0 ]; then + echo "Someone else built this version at the same time I did, and we both tagged the same SHA1 with the same build tag. Not pushing my tag." +else + hg tag -f -r ${SHA1} "build|${MAJOR}|${BUILD}" + if [ "$PUSHTAG" != "false" ]; then + hg push + fi +fi