123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- #!/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"
- return 3
- }
- 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
- ;;
- async)
- local status_desc # status description (in square brackets)
- status_desc=$(git status -sb | grep '^##.*' | grep -o '\[[^]]*\]$')
- grep -qw behind <<<"$status_desc" && return 0
- grep -qw ahead <<<"$status_desc" && return 0
- return 1
- ;;
- *)
- 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
- ;;
- reldiff_brief)
- git rev-list --oneline "$(git_fact latest_tag)..HEAD"
- ;;
- 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"
- }
-
- git_lastsummary() {
- #
- # Show last commit summary
- #
- # 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.
- #
- git_present || {
- echo UNKNOWN_SUMMARY
- warn "no git present; could not determine last summary"
- return 3
- }
- git_bool dirty && {
- echo "(index is dirty)"
- return
- }
- git log -1 --format=oneline HEAD \
- | cut -d' ' -f2-
- }
-
- make_bmeta() {
- #
- # Compose build metadata string
- #
- local is_tagged=T # T if tagged (clean, no metadata), F if devel
- local brname # current branch name
- local ghash # current commit short hash
- 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 | sed 's/[^[:alnum:]]/_/g')
- ghash=$(git_fact latest_sha)
- fi
- {
- if test "$is_tagged" == F; then
- test -n "$stamp" && echo "t$stamp"
- echo "$brname"
- echo "g$ghash"
- test -n "$MKIT_UPSTREAM" && echo "u$MKIT_UPSTREAM"
- git_bool async && "$MKIT_ASYNC" && echo async
- "$MKIT_IN_CI" && test -z "$MKIT_UPSTREAM" && git_bool async && {
- warn "branch is out-of sync with upstream; git hash might be misleading" \
- " (hint: if this is due to CI auto-rebase, set MKIT_UPSTREAM to original shorthash)"
- }
- fi
- git_bool dirty && echo dirty
- } | paste -sd.
- }
-
- make_suffix() {
- local bmeta
- bmeta=$(make_bmeta)
- test -n "$bmeta" || return 0
- echo "+$bmeta"
- }
-
- 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 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
- suffix=$(make_suffix)
- test -n "$prerl" && suffix="-$prerl$suffix"
- echo "$xyz$suffix"
- }
|