imapfilter convenience wrapper

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #!/bin/bash
  2. # MKit - simple install helper
  3. # See LICENSE file for copyright and license details.
  4. mkit_import ini
  5. git_bool() {
  6. #
  7. # Get git bool (ie. exit status counts) $1
  8. #
  9. local bool_name=$1 # name of boolean to get
  10. git_present || {
  11. warn "can't give bool outside git repo: $bool_name"
  12. return 3
  13. }
  14. case "$bool_name" in
  15. dirty_files)
  16. git diff-files | grep -qm 1 .
  17. ;;
  18. dirty_index)
  19. git diff-index HEAD | grep -qm 1 .
  20. ;;
  21. dirty)
  22. git_bool dirty_files || git_bool dirty_index
  23. ;;
  24. async)
  25. local status_desc # status description (in square brackets)
  26. status_desc=$(git status -sb | grep '^##.*' | grep -o '\[[^]]*\]$')
  27. grep -qw behind <<<"$status_desc" && return 0
  28. grep -qw ahead <<<"$status_desc" && return 0
  29. return 1
  30. ;;
  31. *)
  32. warn "unknown git bool asked: $bool_name"
  33. return 2
  34. ;;
  35. esac
  36. }
  37. git_fact() {
  38. #
  39. # Get git fact $1
  40. #
  41. local fact_name=$1 # name of fact to get
  42. git_present || warn "can't give fact outside git repo: $fact_name"
  43. case "$fact_name" in
  44. latest_tag)
  45. git log --format="%d" \
  46. | sed 's/,/\n/g' \
  47. | sed 's/^[[:blank:]]*//' \
  48. | grep -E '^\(?tag' \
  49. | tr -cd '[[:digit:]].v\n' \
  50. | grep . -m 1
  51. ;;
  52. latest_version)
  53. git_fact latest_tag | git_tag2ver
  54. ;;
  55. current_branch)
  56. git rev-parse --abbrev-ref HEAD
  57. ;;
  58. reldiff)
  59. git log --oneline "$(git_fact latest_tag)..HEAD" --name-only
  60. ;;
  61. reldiff_brief)
  62. git rev-list --oneline "$(git_fact latest_tag)..HEAD"
  63. ;;
  64. latest_sha)
  65. git log -1 --pretty=format:%h HEAD
  66. ;;
  67. latest_cdate)
  68. git log -1 --format=%ct HEAD
  69. ;;
  70. *)
  71. warn "unknown git fact asked: $fact_name"
  72. ;;
  73. esac
  74. }
  75. git_present() {
  76. #
  77. # True if we're in a git repo
  78. #
  79. git rev-parse HEAD >&/dev/null
  80. }
  81. git_tag2ver() {
  82. #
  83. # Convert tag to version
  84. #
  85. sed s/^v//
  86. }
  87. git_ver2tag() {
  88. #
  89. # Convert version to tag
  90. #
  91. sed s/^/v/
  92. }
  93. git_lasthash() {
  94. #
  95. # Show last commit hash (with .dirty suffix if needed)
  96. #
  97. # We can't do it outside git repo (or without git) but we should
  98. # not be asked to; targets that don't require git should make use
  99. # of cache built by dist target.
  100. #
  101. local last_hash # last commit hash
  102. git_present || {
  103. echo UNKNOWN_HASH
  104. warn "no git present; could not determine last hash"
  105. return 3
  106. }
  107. last_hash=$(git rev-parse HEAD)
  108. echo -n "$last_hash"
  109. git_bool dirty && echo -n ".dirty"
  110. }
  111. git_lastsummary() {
  112. #
  113. # Show last commit summary
  114. #
  115. # We can't do it outside git repo (or without git) but we should
  116. # not be asked to; targets that don't require git should make use
  117. # of cache built by dist target.
  118. #
  119. git_present || {
  120. echo UNKNOWN_SUMMARY
  121. warn "no git present; could not determine last summary"
  122. return 3
  123. }
  124. git_bool dirty && {
  125. echo "(index is dirty)"
  126. return
  127. }
  128. git log -1 --format=oneline HEAD \
  129. | cut -d' ' -f2-
  130. }
  131. make_bmeta() {
  132. #
  133. # Compose build metadata string
  134. #
  135. local is_tagged=T # T if tagged (clean, no metadata), F if devel
  136. local brname # current branch name
  137. local ghash # current commit short hash
  138. if ! git describe --tags --exact-match HEAD >&/dev/null;
  139. then # we are at a later commit than the last tag
  140. is_tagged=F
  141. brname=$(git_fact current_branch | sed 's/[^[:alnum:]]/_/g')
  142. ghash=$(git_fact latest_sha)
  143. fi
  144. {
  145. if test "$is_tagged" == F; then
  146. test -n "$stamp" && echo "t$stamp"
  147. echo "$brname"
  148. echo "g$ghash"
  149. test -n "$MKIT_UPSTREAM" && echo "u$MKIT_UPSTREAM"
  150. git_bool async && "$MKIT_ASYNC" && echo async
  151. "$MKIT_IN_CI" && test -z "$MKIT_UPSTREAM" && git_bool async && {
  152. warn "branch is out-of sync with upstream; git hash might be misleading" \
  153. " (hint: if this is due to CI auto-rebase, set MKIT_UPSTREAM to original shorthash)"
  154. }
  155. fi
  156. git_bool dirty && echo dirty
  157. } | paste -sd.
  158. }
  159. make_suffix() {
  160. local bmeta
  161. bmeta=$(make_bmeta)
  162. test -n "$bmeta" || return 0
  163. echo "+$bmeta"
  164. }
  165. semver() {
  166. #
  167. # Build proper SemVer version string
  168. #
  169. # Build version string from available info using following
  170. # logic:
  171. #
  172. # 1. Use version from last git tag (or mkit.ini if there is no
  173. # tag, which is possible on new project)
  174. # 2. if set, add project:prerl (from mkit.ini) as pre-release ID
  175. # (afer dash)
  176. # 3. if we are at a later commit than the last tag, add branch
  177. # name and commit sha1 to build metadata (after plus sign)
  178. # 4. if the tree is "dirty", i.e. has uncommited changes,
  179. # add "dirty" to build metadata
  180. #
  181. # The version is compatible with SemVer 2.0.0.
  182. #
  183. # Examples:
  184. #
  185. # foo v1.0.7 # all clear; proper release
  186. # foo v1.0.7-beta # mkit.ini: project:prerl="beta"
  187. # foo v1.0.7-beta+g1aef811.master # ^^ + some commits after
  188. # foo v1.0.7-beta+gf14fc4f.api2 # ^^ + on a feature branch
  189. # foo v1.0.7-beta+gf14fc4f.api2.dirty # ^^ + tree edited
  190. # foo v1.0.7-beta+dirty # tag OK but tree edited
  191. # foo v1.0.7+dirty # ^^ but no pre-release id
  192. #
  193. # Note that versions with "dirty" should be perceived as kind of
  194. # dangerous outside developer's own machine. Versions with sha1 are
  195. # safer but must not be released.
  196. #
  197. # FIXME: Using project:prerl for release IDs may not be compatible with
  198. # release strategy implemented in release.sh
  199. #
  200. local xyz # base version string
  201. local prerl # pre-release keyword (from mkit.ini, eg. 'beta')
  202. local latest_tag # latest git tag
  203. local stamp # timestamp or nothing (see $MKIT_TSTAMP)
  204. local suffix # version suffix
  205. prerl=$(ini 1value project:prerl)
  206. case $MKIT_TSTAMP in
  207. none) stamp= ;;
  208. btime) stamp=$(date -u +%Y%m%d%H%M%S) ;;
  209. ctime) stamp=$(date -d @"$(git_fact latest_cdate)" -u +%Y%m%d%H%M%S) ;;
  210. esac
  211. grep ":" <<<"$prerl" \
  212. && warn "colon in project:prerl may corrupt version data: $prerl"
  213. git_present || {
  214. echo UNKNOWN_VERSION
  215. warn "no git present; could not determine SemVer"
  216. return 3
  217. }
  218. latest_tag=$(git_fact latest_tag)
  219. case $latest_tag in
  220. v*) xyz=${latest_tag:1} ;;
  221. "") warn "no tags, using base version from mkit.ini (ok for new project)"
  222. xyz=$(ini 1value project:version) ;;
  223. *) warn "bad form of last tag, using base version from mkit.ini: tag is '$latest_tag'"
  224. xyz=$(ini 1value project:version) ;;
  225. esac
  226. suffix=$(make_suffix)
  227. test -n "$prerl" && suffix="-$prerl$suffix"
  228. echo "$xyz$suffix"
  229. }