#!/bin/sh set -eu # Return the commitid of the given ref in the given repo dir. If the worktree # or index is dirty, also appends -dirty. # # $ git_hash_dirty ../.. HEAD # 1be01ddc6e430ca3aa9beea3587d16750efb3241-dirty git_hash_dirty() { ( cd "$1" x=$(git rev-parse HEAD) if ! git diff-index --quiet HEAD; then x="$x-dirty" fi echo "$x" ) } case $# in 0|1) # extra_hash_or_dir is either: # - a git commitid # or # - the path to a git repo from which to calculate the real hash. # # It gets embedded as an additional commit hash in built # binaries, to help us locate the exact set of tools and code # that were used. extra_hash_or_dir="${1:-}" if [ -z "$extra_hash_or_dir" ]; then # Nothing, empty extra hash is fine. extra_hash="" elif [ -e "$extra_hash_or_dir/.git" ]; then extra_hash=$(git_hash_dirty "$extra_hash_or_dir" HEAD) elif ! expr "$extra_hash_or_dir" : "^[0-9a-f]*$"; then echo "Invalid extra hash '$extra_hash_or_dir', must be a git commit or path to a git repo" >&2 exit 1 else extra_hash="$extra_hash_or_dir" fi # Load the base version and optional corresponding git hash # from the VERSION file. If there is no git hash in the file, # we use the hash of the last change to the VERSION file. version_file="$(dirname $0)/../VERSION.txt" IFS=".$IFS" read -r major minor patch base_git_hash <"$version_file" if [ -z "$base_git_hash" ]; then base_git_hash=$(git rev-list --max-count=1 HEAD -- "$version_file") fi git_hash=$(git_hash_dirty . HEAD) # The number of extra commits between the release base to git_hash. change_count=$(git rev-list --count HEAD "^$base_git_hash") ;; 6) # Test mode: rather than run git commands and whatnot, take in # all the version pieces as arguments. git_hash=$1 extra_hash=$2 major=$3 minor=$4 patch=$5 change_count=$6 ;; *) echo "Usage: $0 [extra-git-commitid-or-dir]" exit 1 esac # Shortened versions of git hashes, so that they fit neatly into an # "elongated" but still human-readable version number. short_git_hash=$(echo "$git_hash" | cut -c1-9) short_extra_hash=$(echo "$extra_hash" | cut -c1-9) # Convert major/minor/patch/change_count into an adjusted # major/minor/patch. This block is where all our policies on # versioning are. if expr "$minor" : "[0-9]*[13579]$" >/dev/null; then # Odd minor numbers are unstable builds. if [ "$patch" != "0" ]; then # This is a fatal error, because a non-zero patch number # indicates that we created an unstable VERSION.txt in violation # of our versioning policy, and we want to blow up loudly to # get that fixed. echo "Unstable release $major.$minor.$patch has a non-zero patch number, which is not allowed" >&2 exit 1 fi patch="$change_count" change_suffix="" elif [ "$change_count" != "0" ]; then # Even minor numbers are stable builds, but stable builds are # supposed to have a zero change count. Therefore, we're currently # describing a commit that's on a release branch, but hasn't been # tagged as a patch release yet. # # We used to change the version number to 0.0.0 in that case, but that # caused some features to get disabled due to the low version number. # Instead, add yet another suffix to the version number, with a change # count. change_suffix="-$change_count" else # Even minor number with no extra changes. change_suffix="" fi # Hack for 1.1: add 1000 to the patch number. We switched from using # the proprietary repo's change_count over to using the OSS repo's # change_count, and this was necessary to avoid a backwards jump in # release numbers. if [ "$major.$minor" = "1.1" ]; then patch="$((patch + 1000))" fi # At this point, the version number correctly reflects our # policies. All that remains is to output the various vars that other # code can use to embed version data. if [ -z "$extra_hash" ]; then long_version_suffix="$change_suffix-t$short_git_hash" else long_version_suffix="$change_suffix-t$short_git_hash-g$short_extra_hash" fi cat <