#!/bin/bash # MKit - simple install helper # See LICENSE file for copyright and license details. mkit_import ini git_bool() { # # Get git bool (ie. exit status counts) $1 # local bool_name=$1 # name of boolean to get git_present || warn "can't give bool outside git repo: $bool_name" case "$bool_name" in dirty_files) git diff-files | grep -qm 1 . ;; dirty_index) git diff-index HEAD | grep -qm 1 . ;; dirty) git_bool dirty_files || git_bool dirty_index ;; *) warn "unknown git bool asked: $bool_name" return 2 ;; esac } git_fact() { # # Get git fact $1 # local fact_name=$1 # name of fact to get git_present || warn "can't give fact outside git repo: $fact_name" case "$fact_name" in latest_tag) git log --format="%d" \ | sed 's/,/\n/g' \ | sed 's/^[[:blank:]]*//' \ | grep -E '^\(?tag' \ | tr -cd '[[:digit:]].v\n' \ | grep . -m 1 ;; latest_version) git_fact latest_tag | git_tag2ver ;; current_branch) git rev-parse --abbrev-ref HEAD ;; reldiff) git log --oneline "$(git_fact latest_tag)..HEAD" --name-only ;; latest_sha) git log -1 --pretty=format:%h HEAD ;; latest_cdate) git log -1 --format=%ct HEAD ;; *) warn "unknown git fact asked: $fact_name" ;; esac } git_present() { # # True if we're in a git repo # git rev-parse HEAD >&/dev/null } git_tag2ver() { # # Convert tag to version # sed s/^v// } git_ver2tag() { # # Convert version to tag # sed s/^/v/ } git_lasthash() { # # Show last commit hash (with .dirty suffix if needed) # # We can't do it outside git repo (or without git) but we should # not be asked to; targets that don't require git should make use # of cache built by dist target. # local last_hash # last commit hash git_present || { echo UNKNOWN_HASH warn "no git present; could not determine last hash" return 3 } last_hash=$(git rev-parse HEAD) echo -n "$last_hash" git_bool dirty && echo -n ".dirty" } semver() { # # Build proper SemVer version string # # Build version string from available info using following # logic: # # 1. Use version from last git tag (or mkit.ini if there is no # tag, which is possible on new project) # 2. if set, add project:prerl (from mkit.ini) as pre-release ID # (afer dash) # 3. if we are at a later commit than the last tag, add branch # name and commit sha1 to build metadata (after plus sign) # 4. if the tree is "dirty", i.e. has uncommited changes, # add "dirty" to build metadata # # The version is compatible with SemVer 2.0.0. # # Examples: # # foo v1.0.7 # all clear; proper release # foo v1.0.7-beta # mkit.ini: project:prerl="beta" # foo v1.0.7-beta+g1aef811.master # ^^ + some commits after # foo v1.0.7-beta+gf14fc4f.api2 # ^^ + on a feature branch # foo v1.0.7-beta+gf14fc4f.api2.dirty # ^^ + tree edited # foo v1.0.7-beta+dirty # tag OK but tree edited # foo v1.0.7+dirty # ^^ but no pre-release id # # Note that versions with "dirty" should be perceived as kind of # dangerous outside developer's own machine. Versions with sha1 are # safer but must not be released. # # FIXME: Using project:prerl for release IDs may not be compatible with # release strategy implemented in release.sh # local xyz # base version string local prerl # pre-release keyword (from mkit.ini, eg. 'beta') local latest_tag # latest git tag local brname # current branch name local ghash # current commit short hash local is_tagged=T # T if tagged (clean, no metadata), F if devel local is_dirty=F # F if dirty, T if clean local stamp # timestamp or nothing (see $MKIT_TSTAMP) local suffix # version suffix prerl=$(ini 1value project:prerl) case $MKIT_TSTAMP in none) stamp= ;; btime) stamp=$(date -u +%Y%m%d%H%M%S) ;; ctime) stamp=$(date -d @"$(git_fact latest_cdate)" -u +%Y%m%d%H%M%S) ;; esac grep ":" <<<"$prerl" \ && warn "colon in project:prerl may corrupt version data: $prerl" git_present || { echo UNKNOWN_VERSION warn "no git present; could not determine SemVer" return 3 } latest_tag=$(git_fact latest_tag) case $latest_tag in v*) xyz=${latest_tag:1} ;; "") warn "no tags, using base version from mkit.ini (ok for new project)" xyz=$(ini 1value project:version) ;; *) warn "bad form of last tag, using base version from mkit.ini: tag is '$latest_tag'" xyz=$(ini 1value project:version) ;; esac if ! git describe --tags --exact-match HEAD >&/dev/null; then # we are at a later commit than the last tag is_tagged=F brname=$(git_fact current_branch) ghash=$(git_fact latest_sha) fi git_bool dirty && is_dirty=T case "$is_dirty:$is_tagged:$stamp" in F:T:*) suffix="" ;; T:T:) suffix="+dirty" ;; T:T:*) suffix="+t$stamp.dirty" ;; F:F:) suffix="+$brname.g$ghash" ;; F:F:*) suffix="+t$stamp.$brname.g$ghash" ;; T:F:) suffix="+$brname.g$ghash.dirty" ;; T:F:*) suffix="+t$stamp.$brname.g$ghash.dirty" ;; *) suffix=MKIT_BUG warn "MKIT_BUG: bad dirt/commit detection" ;; esac test -n "$prerl" && suffix="-$prerl$suffix" echo "$xyz$suffix" }