#!/bin/bash # MKit - simple install helper # See LICENSE file for copyright and license details. _MKIT_IMPORTED="" die() { # # Exit with message and non-zero exit status # echo "fatal: $*" >&2 exit 4 } mkit_import() { # # Import mkit module $1.sh # # Check for module, source it and die with reasonable message if needed. # local modname=$1 local modpath test "$modname" == mkit && die "cannot re-import core module: $modname" __mkit__is_imported "$modname" && return 0 modpath="$MKIT_DIR/include/$modname.sh" test -f "$modpath" || die "no such module: $modpath" bash -n "$modpath" || die "bad syntax: $modpath" #shellcheck disable=SC1090,SC1091 . "$modpath" || die "failed to import: $modname" _MKIT_IMPORTED+=":$modname" } __mkit__is_imported() { # # True if module $1 is already imported # local modname=$1 grep -qw -e "$modname" <<<"$_MKIT_IMPORTED" } mkit_import ini mkit_import target debug() { # # Print debug message # $MKIT_DEBUG || return 0 echo "MKIT_DEBUG: ${FUNCNAME[1]}()" "$@" >&2 } debug_var() { # # Print debug message # $MKIT_DEBUG || return 0 local __mkit_debug_var_name__ # variable name to debug local decl # declare string for __mkit_debug_var_name__ in "$@"; do { decl=$(declare -p "$__mkit_debug_var_name__") decl=${decl#declare ?? } echo "MKIT_DEBUG: ${FUNCNAME[1]}(): $decl" } >&2 done } __compver() { # # True if version $1 matches our version # # We're following a particular convention described in SemVer # issue #363: # # https://github.com/semver/semver/issues/363 # # In short: If our X is 0, check first two fragments, otherwise # check just the x. Fragments must equal. # local their_ver=$1 # their version local our_x # our X local our_y # our Y local our_z # our z local their_x # their X local their_y # their Y local their_z # their Z local diff_x='=' # difference in X: '=' for equal, 'o' for different local diff_y='=' # ^^ ...... in Y local diff_z='=' # ^^ ...... in Z read -r their_x their_y their_z <<<"$(__parse_ver_xyz "$their_ver")" || die read -r our_x our_y our_z <<<"$(__parse_ver_xyz "$MKIT_VERSION")" || die test "$their_x" -eq "$our_x" || diff_x=o test "$their_y" -eq "$our_y" || diff_y=o test "$their_z" -eq "$our_z" || diff_z=o debug_var MKIT_VERSION our_x our_y our_z their_ver their_x their_y their_z diff_x diff_y diff_z case $our_x.$our_y:$diff_x.$diff_y.$diff_z in *.*:=.=.=) return 0 ;; *.*:o.?.?) return 1 ;; 0.0:=.=.o) __compver_hint_async ;; 0.*:=.=.?) __compver_hint_async ;; 0.*:=.o.?) return 1 ;; *.*:=.=.o) __compver_hint_async ;; *) warn "MKit bug while comparing versions!" \ " .. MKit could not handle version difference; here's dump:" \ " ...... MKIT_VERSION=$MKIT_VERSION" \ " ...... their_ver=$their_ver" \ " ...... our_x=$our_x our_y=$our_y our_z=$our_z" \ " ...... their_x=$their_x their_y=$their_y their_z=$their_z" \ " ...... diff_x=$diff_x diff_y=$diff_y diff_z=$diff_z" return 1 ;; esac } __parse_ver_xyz() { # # Print space-separated X, Y and Z from version $1 # local ver=$1 local xyz xyz=$(grep -oE '^[0-9]+[.][0-9]+[.][0-9]+' <<<"$ver") test -n "$xyz" || { warn "could not parse version: $ver" } echo "${xyz//./ }" } __compver_hint_async() { # # Warn about the version being async # # Versions where later fragments are different are considered # compatible, but when MKit is updated, the best practice is # to consult the changelog and see if fixes or new features # enable optimizing or removing workarounds from the mkit.ini # file. # # For that reason we will inform the maintainer about this # fact. # # Because in typical MKit usage the MKit itself is embedded # in the same git repository as the file, it should be easy # to maintain the synchronicity. # warn "hint: mkit.ini version is out of sync: MKit: $MKIT_VERSION, mkit.ini: $their_ver" \ "hint: .. To hide this hint, consider updating mkit.ini based" \ "hint: .. on changes between these versions and update version" \ "hint: .. directive (\`#mkit version=..\`) to match MKit." } __chkiniversion() { # # Check if ini version is supported # # Look for "#mkit version=0.0.0" or similar in first or last # 3 lines of the file; then check if the version is supported. # local ver_line # line declaring version local their_ver # the declared version ver_line=$( { head -3 "$MKIT_INI" tail -3 "$MKIT_INI" } | grep -m 1 -E '^#mkit +version *= *v?[0-9]+\.[0-9]+\.[0-9]+' ) test -n "$ver_line" \ || die "version directive ('#mkit version=x.y.z') not found in: $MKIT_INI" their_ver="$(tr -d '[:blank:]v' <<<"${ver_line##*=}")" __compver "$their_ver" \ || die "bad mkit.ini version: $their_ver does not match $MKIT_VERSION" } mkit_init() { # # Do basic initialization # # Check for ini file and some variables # $MKIT_DRY && MKIT_DEBUG=true #shellcheck disable=SC2034 MKIT_PROJ_PKGNAME=$(ini 1value "project:pkgname") test -n "$MKIT_PROJ_PKGNAME" || die "failed to determine pkgname: project:pkgname in $MKIT_INI" test -f "$MKIT_INI" || die "cannot find mkit.ini: $MKIT_INI" __chkiniversion } warn() { # # Print warning message # printf '%s\n' "$@" >&2 }