imapfilter convenience wrapper

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #!/bin/bash
  2. # MKit - simple install helper
  3. # See LICENSE file for copyright and license details.
  4. _MKIT_IMPORTED=""
  5. die() {
  6. #
  7. # Exit with message and non-zero exit status
  8. #
  9. echo "fatal: $*" >&2
  10. exit 4
  11. }
  12. mkit_import() {
  13. #
  14. # Import mkit module $1.sh
  15. #
  16. # Check for module, source it and die with reasonable message if needed.
  17. #
  18. local modname=$1
  19. local modpath
  20. test "$modname" == mkit && die "cannot re-import core module: $modname"
  21. __mkit__is_imported "$modname" && return 0
  22. modpath="$MKIT_DIR/include/$modname.sh"
  23. test -f "$modpath" || die "no such module: $modpath"
  24. bash -n "$modpath" || die "bad syntax: $modpath"
  25. #shellcheck disable=SC1090,SC1091
  26. . "$modpath" || die "failed to import: $modname"
  27. _MKIT_IMPORTED+=":$modname"
  28. }
  29. __mkit__is_imported() {
  30. #
  31. # True if module $1 is already imported
  32. #
  33. local modname=$1
  34. grep -qw -e "$modname" <<<"$_MKIT_IMPORTED"
  35. }
  36. mkit_import ini
  37. mkit_import target
  38. debug() {
  39. #
  40. # Print debug message
  41. #
  42. $MKIT_DEBUG || return 0
  43. echo "MKIT_DEBUG: ${FUNCNAME[1]}()" "$@" >&2
  44. }
  45. debug_var() {
  46. #
  47. # Print debug message
  48. #
  49. $MKIT_DEBUG || return 0
  50. local __mkit_debug_var_name__ # variable name to debug
  51. local decl # declare string
  52. for __mkit_debug_var_name__ in "$@"; do
  53. {
  54. decl=$(declare -p "$__mkit_debug_var_name__")
  55. decl=${decl#declare ?? }
  56. echo "MKIT_DEBUG: ${FUNCNAME[1]}(): $decl"
  57. } >&2
  58. done
  59. }
  60. __compver() {
  61. #
  62. # True if version $1 matches our version
  63. #
  64. # We're following a particular convention described in SemVer
  65. # issue #363:
  66. #
  67. # https://github.com/semver/semver/issues/363
  68. #
  69. # In short: If our X is 0, check first two fragments, otherwise
  70. # check just the x. Fragments must equal.
  71. #
  72. local their_ver=$1 # their version
  73. local our_x # our X
  74. local our_y # our Y
  75. local our_z # our z
  76. local their_x # their X
  77. local their_y # their Y
  78. local their_z # their Z
  79. local diff_x='=' # difference in X: '=' for equal, 'o' for different
  80. local diff_y='=' # ^^ ...... in Y
  81. local diff_z='=' # ^^ ...... in Z
  82. read -r their_x their_y their_z <<<"$(__parse_ver_xyz "$their_ver")" || die
  83. read -r our_x our_y our_z <<<"$(__parse_ver_xyz "$MKIT_VERSION")" || die
  84. test "$their_x" -eq "$our_x" || diff_x=o
  85. test "$their_y" -eq "$our_y" || diff_y=o
  86. test "$their_z" -eq "$our_z" || diff_z=o
  87. debug_var MKIT_VERSION our_x our_y our_z their_ver their_x their_y their_z diff_x diff_y diff_z
  88. case $our_x.$our_y:$diff_x.$diff_y.$diff_z in
  89. *.*:=.=.=) return 0 ;;
  90. *.*:o.?.?) return 1 ;;
  91. 0.0:=.=.o) __compver_hint_async ;;
  92. 0.*:=.=.?) __compver_hint_async ;;
  93. 0.*:=.o.?) return 1 ;;
  94. *.*:=.=.o) __compver_hint_async ;;
  95. *) warn "MKit bug while comparing versions!" \
  96. " .. MKit could not handle version difference; here's dump:" \
  97. " ...... MKIT_VERSION=$MKIT_VERSION" \
  98. " ...... their_ver=$their_ver" \
  99. " ...... our_x=$our_x our_y=$our_y our_z=$our_z" \
  100. " ...... their_x=$their_x their_y=$their_y their_z=$their_z" \
  101. " ...... diff_x=$diff_x diff_y=$diff_y diff_z=$diff_z"
  102. return 1 ;;
  103. esac
  104. }
  105. __parse_ver_xyz() {
  106. #
  107. # Print space-separated X, Y and Z from version $1
  108. #
  109. local ver=$1
  110. local xyz
  111. xyz=$(grep -oE '^[0-9]+[.][0-9]+[.][0-9]+' <<<"$ver")
  112. test -n "$xyz" || {
  113. warn "could not parse version: $ver"
  114. }
  115. echo "${xyz//./ }"
  116. }
  117. __compver_hint_async() {
  118. #
  119. # Warn about the version being async
  120. #
  121. # Versions where later fragments are different are considered
  122. # compatible, but when MKit is updated, the best practice is
  123. # to consult the changelog and see if fixes or new features
  124. # enable optimizing or removing workarounds from the mkit.ini
  125. # file.
  126. #
  127. # For that reason we will inform the maintainer about this
  128. # fact.
  129. #
  130. # Because in typical MKit usage the MKit itself is embedded
  131. # in the same git repository as the file, it should be easy
  132. # to maintain the synchronicity.
  133. #
  134. warn "hint: mkit.ini version is out of sync: MKit: $MKIT_VERSION, mkit.ini: $their_ver" \
  135. "hint: .. To hide this hint, consider updating mkit.ini based" \
  136. "hint: .. on changes between these versions and update version" \
  137. "hint: .. directive (\`#mkit version=..\`) to match MKit."
  138. }
  139. __chkiniversion() {
  140. #
  141. # Check if ini version is supported
  142. #
  143. # Look for "#mkit version=0.0.0" or similar in first or last
  144. # 3 lines of the file; then check if the version is supported.
  145. #
  146. local ver_line # line declaring version
  147. local their_ver # the declared version
  148. ver_line=$(
  149. {
  150. head -3 "$MKIT_INI"
  151. tail -3 "$MKIT_INI"
  152. } | grep -m 1 -E '^#mkit +version *= *v?[0-9]+\.[0-9]+\.[0-9]+'
  153. )
  154. test -n "$ver_line" \
  155. || die "version directive ('#mkit version=x.y.z') not found in: $MKIT_INI"
  156. their_ver="$(tr -d '[:blank:]v' <<<"${ver_line##*=}")"
  157. __compver "$their_ver" \
  158. || die "bad mkit.ini version: $their_ver does not match $MKIT_VERSION"
  159. }
  160. mkit_init() {
  161. #
  162. # Do basic initialization
  163. #
  164. # Check for ini file and some variables
  165. #
  166. $MKIT_DRY && MKIT_DEBUG=true
  167. #shellcheck disable=SC2034
  168. MKIT_PROJ_PKGNAME=$(ini 1value "project:pkgname")
  169. test -n "$MKIT_PROJ_PKGNAME" || die "failed to determine pkgname: project:pkgname in $MKIT_INI"
  170. test -f "$MKIT_INI" || die "cannot find mkit.ini: $MKIT_INI"
  171. __chkiniversion
  172. }
  173. warn() {
  174. #
  175. # Print warning message
  176. #
  177. printf '%s\n' "$@" >&2
  178. }