blob: aa0b9f818a836e0bd0290ffa3c23856663621519 [file] [log] [blame]
#!/bin/bash
#
# Copyright 2011-2016 Nest Labs Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# Description:
# This file attempts to find and generate a package version
# including, if necessary, the number of commits from the last
# GIT tag and the current GIT hash corresponding to HEAD for the
# current branch.
#
# This is largely cobbled together from similar scripts in other
# packages that are maintained in GIT (linux, u-boot, parted, etc.).
#
# This can produce version information such as:
#
# 1.0.1
# 1.0.1-dirty
# 1.0.1-00032-gab50dbb
# 1.0.1-00032-gab50dbb-dirty
#
# Constants
ROOTDIR=${PREFIX}/
BINDIR=${ROOTDIR}bin
DATADIR=${ROOTDIR}share
DEVICEDIR=${ROOTDIR}dev
CONFDIR=${ROOTDIR}etc
LIBDIR=${ROOTDIR}lib
LIBEXECDIR=${ROOTDIR}libexec
VARDIR=${ROOTDIR}var
LOGDIR=${VARDIR}/log
MANDIR=${ROOTDIR}man
SBINDIR=${ROOTDIR}sbin
USRDIR=${ROOTDIR}usr
USRBINDIR=${USRDIR}/bin
USRDATADIR=${USRDIR}/share
USRLIBDIR=${USRDIR}/lib
USRLIBEXECDIR=${USRDIR}/libexec
USRSBINDIR=${USRDIR}/sbin
AWK=${USRBINDIR}/awk
BASENAME=${USRBINDIR}/basename
CAT=${BINDIR}/cat
ECHO="${BINDIR}/echo"
NULL=${DEVICEDIR}/null
PRINTF=${USRBINDIR}/printf
RM=${BINDIR}/rm
SED=${BINDIR}/sed
VERSION=""
#
# usage <status>
#
# Description:
# This routine prints out the proper command line usage for this
# program and then exits with the specified status.
#
# Input(s):
# status - Exit status to exit the program with.
#
# Returns:
# This subroutine does not return.
#
usage() {
local name=`${BASENAME} ${0}`
${ECHO} "Usage: ${name} [options] [ <project root> ]"
if [ ${1} -ne 0 ]; then
${ECHO} "Try '${name} -h' for more information."
fi
if [ ${1} -ne 1 ]; then
${CAT} << EOF
-b, --build-version=VERSION Specify VERSION as the build version to generate
extra build information against.
-h, --help Print this help, then exit.
EOF
fi
exit ${1}
}
#
# gitversion <string> <directory> <version>
#
# Description:
# This routine prints out any GIT version information appended to the
# end of the package version, including the number of commits from
# the last GIT tag and the current GIT hash corresponding to HEAD
# for the current branch.
#
# Input(s):
# string - The current version string which may be empty.
# directory - The current directory.
# version - The optional current package version.
#
# Returns:
# N/A
#
gitversion() {
local string="${1}"
local dir="${2}"
local version="${3}"
local head
local exact
local dtag
local gitversion
# Retrieve the shortened, unique GIT hash associated with the
# 'HEAD' GIT object
head=`test -d .git && git rev-parse --verify --short HEAD 2> ${NULL}`
# If we found a hash, we are actually in a GIT repository; continue.
if [ -n "${head}" ]; then
# Check to see if we have a position in GIT that is
# exactly at an existing tag (e.g. 1.0.2). If we are,
# just use it and add a dirty qualifier. Otherwise,
# work through the logic to determine how far off the
# tag the tree is.
exact="`git describe --exact-match 2> ${NULL}`"
if [ -z "${exact}" ] || [ -n "${version}" ] && [ "${version}" != "${exact}" ]; then
dtag="`git describe 2> ${NULL}`"
# If we are n commits away from a tag, then
# print n and a shortened version of the
# hash. Otherwise, just print the hash.
#
# If we are at an exact version, then there
# won't be a delta or a hash, just use the
# exact tag.
if [ -n "${dtag}" ]; then
if [ "${dtag}" == "${exact}" ]; then
gitversion="${dtag}"
else
gitversion=`${PRINTF} "${dtag}" | ${AWK} -F '-' '{printf("%s-%05d-%s", $(NF-2),$(NF-1),$(NF))}' 2> ${NULL}`
fi
else
gitversion=`${PRINTF} "g${head}"`
fi
else
gitversion="${exact}"
fi
# Update the index if we are in a writable directory
# so that we can successfully check for a dirty (has
# uncommitted changes or unresolved merges) tree.
if [ -w "${dir}" ]; then
git update-index --refresh --unmerged > ${NULL}
fi
# Now check for such a dirty tree and add to the "string"
# if we found one.
if git diff-index --name-only HEAD | read dummy; then
if [ -n "${gitversion}" ]; then
gitversion="${gitversion}-dirty"
else
gitversion="dirty"
fi
fi
else
gitversion="${version}"
fi
if [ -n "${string}" ] && [ -n "${gitversion}" ]; then
string="${string}-${gitversion}"
else
string="${gitversion}"
fi
${PRINTF} "${string}"
}
#
# Main Program Body
#
while [ ${#} -gt 0 ]; do
if [ ${1:0:1} == "-" ]; then
if [ "${1}" == "-h" ] || [ "${1}" == "--help" ]; then
usage 0
elif [ "${1}" == "-b" ] || [ "${1}" == "--build-version" ]; then
version="${2}"
shift 2
else
${ECHO} "Unknown argument '${1}'."
usage 1
fi
else
break
fi
done
if [ ${#} -gt 1 ]; then
usage 1
elif [ ${#} -eq 1 ]; then
tree="${1}"
else
tree="."
fi
if [ "${tree}" != "." ]; then
cd "${tree}"
fi
VERSION="`gitversion \"${VERSION}\" . ${version}`"
${PRINTF} "${VERSION}"