123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- #!/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
- }
|