#!/usr/bin/env bash # PROGRAMMING NOTE: apparently some git commands report # inaccurate information if the current directory isn't # root repository directory where the source files live. orig_dir="$(pwd)" top_srcdir="$1" vers_part="$2" cd "$top_srcdir" INFILE=configure.ac MIN_GIT_VERSION="1.8" # (earlier versions of git return inaccurate results) #----------------------------------------------------------- # vercomp -- compare versions #----------------------------------------------------------- # # $1: first version to be compared (e.g. "1.2.3") # $2: expected relationship (e.g. ">") # $3: second version to be compared (e.g. "1.2") # # The algorithm takes into account leading zeros as well # as missing components (4.08 < 4.08.01, 3.2.0.9 > 3.2), # but only exact equality is supported for text strings # which have non-numeric components (1.2rc3 = 1.2rc3). # # Returns: 0 = success if relationship is true # Returns: 1 = failure if relationship is false # # We use 0 for true and 1 for false so that the caller # can do such things as: # # if vercomp 1.2.3 '>' 1.2.0; then # echo "True!" # else # echo "FALSE!" # fi # #----------------------------------------------------------- vercomp() { local op _vercomp $1 $3 case $? in 0) op='=';; 1) op='>';; 2) op='<';; esac if [[ $op != $2 ]]; then return 1 else return 0 fi } #----------------------------------------------------------- # (vercomp helper function) #----------------------------------------------------------- _vercomp() { # rc = 0: $1 = $2 $1 equals $2 # rc = 1: $1 > $2 $1 greater than $2 # rc = 2: $1 < $2 $1 less than $2 if [[ $1 == $2 ]]; then return 0 fi local IFS=. local i ver1=($1) ver2=($2) # Fill empty fields in ver1 with zeros for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)); do ver1[i]=0 done for ((i=0; i<${#ver1[@]}; i++)); do if [[ -z ${ver2[i]} ]]; then # Fill empty fields in ver2 with zeros ver2[i]=0 fi if [[ 10#${ver1[i]} > 10#${ver2[i]} ]]; then return 1 fi if [[ 10#${ver1[i]} < 10#${ver2[i]} ]]; then return 2 fi done return 0 } #------------------------------------------------------------------------------ # M A I N #------------------------------------------------------------------------------ # Extract the VERS_MAJ, VERS_INT and VERS_MIN values from $INFILE VERS_MAJ=$(grep -o -a -m 1 '^VERS_MAJ=[0-9][0-9]*' $INFILE) VERS_INT=$(grep -o -a -m 1 '^VERS_INT=[0-9][0-9]*' $INFILE) VERS_MIN=$(grep -o -a -m 1 '^VERS_MIN=[0-9][0-9]*' $INFILE) VERS_DEV=$(grep -o -a -m 1 '^VERS_DEV=[0-9][0-9]*' $INFILE) # Result of above is "VERS_xxx=n". The below does the assignment. eval $VERS_MAJ eval $VERS_INT eval $VERS_MIN eval $VERS_DEV # PROGRAMMING NOTE: must check for the existence of both the .git # directory as well as the git command itself since either may exist # or not exist independent of the other. Only when both are true # can we then safely query/use the git repository values. if ! test -d "./.git" || ! type "git" >/dev/null 2>/dev/null; then # Can't query the git repository since the .git directory doesn't # exist (i.e. this directory isn't a git repository clone) or else # the git command doesn't exist (i.e. git itself isn't installed) VERS_BLD="0" git_hash="" modified_str="" else # The current directory appears to be a git repository clone AND the # git command exists (i.e. git *IS* installed), so we can safely ask # git for some repository values that we can then use in our VERSION. # Determine if any local modifications exist. PLEASE NOTE that doing # "update-index --refresh" beforehand is seemingly critical to ensure # accurate "diff-index" results with some versions of git. git update-index --refresh -q > /dev/null 2>&1 git diff-index --quiet HEAD if test "$?" == "0"; then modified_str="" else # Check for possibly inaccurate results gitvers=$(git --version | egrep -o "([0-9]{1,}\.)+[0-9]{1,}" | head -n 1) if vercomp $gitvers '>' $MIN_GIT_VERSION; then modified_str="-modified" else modified_str="-modified(?)" # (indicate questionable results) fi fi # Extract the short git hash of the repository (usually the last commit) git_hash=-g$(git rev-parse --short HEAD) # Count the number of commits and use that as our "build" number # PROGRAMMING NOTE: we purposely do NOT use the simpler, newer, easier, # slightly faster, and harder to get wrong "rev-list --count" technique, # since older gits that come with some still in use older distros likely # don't understand the "--count" option. Thus, we use the slightly # slower, older, more complex and much easier to get wrong technique # of piping the output of "log --pretty..." into "wc -l". Please also # note that, unlike many broken implementations that are out there, we # correctly use "tformat" and not "format" to ensure an accurate count. VERS_BLD=$(($(git log --pretty=tformat:'' | wc -l))) if test "$VERS_BLD" == "0"; then # Try "format" instead of "tformat"... VERS_BLD=$(($(git log --pretty=format:'' | wc -l))) if test "$VERS_BLD" != "0"; then # increment by 1 (because "format" was used, not "tformat") VERS_BLD=$((++VERS_BLD)) else # Last chance: use new "rev-list --count" method VERS_BLD=$(($(git rev-list --count HEAD))) fi fi fi # Make sure all required variables have a value if test "x$VERS_MAJ" = "x"; then VERS_MAJ=0 fi if test "x$VERS_INT" = "x"; then VERS_INT=0 fi if test "x$VERS_MIN" = "x"; then VERS_MIN=0 fi if test "x$VERS_BLD" = "x"; then VERS_BLD=0 fi if test "x$VERS_DEV" = "x"; then VERS_DEV=0 fi # Determine whether this is an official formal release version, # or a between formal releases intermediate development version. if test "$VERS_DEV" == "0"; then dev_string="" # (official formal release version) else dev_string="-DEV" # (between release development version) fi # Construct a quoted VERSION string value QUOTE='"' VERSION="${QUOTE}${VERS_MAJ}.${VERS_INT}.${VERS_MIN}.${VERS_BLD}-SDL${dev_string}${git_hash}${modified_str}${QUOTE}" # Finally, return (via echo) the desired version component back to the caller if test "$vers_part" == "VERS_MAJ"; then echo $VERS_MAJ elif test "$vers_part" == "VERS_INT"; then echo $VERS_INT elif test "$vers_part" == "VERS_MIN"; then echo $VERS_MIN elif test "$vers_part" == "VERS_BLD"; then echo $VERS_BLD elif test "$vers_part" == "VERS_DEV"; then echo $VERS_DEV elif test "$vers_part" == "VERSION"; then echo $VERSION else echo $VERSION fi # DONE! Exit back to caller... cd "$orig_dir" exit 0