Working Saturnin-based meta-command

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #!/bin/bash
  2. # MKit - simple install helper
  3. # See LICENSE file for copyright and license details.
  4. mkit_import ini
  5. mkit_import facts
  6. _bump_version() {
  7. #
  8. # Bump version on stdin by level $1 (x, y or z)
  9. #
  10. local rlevel=$1 # release level
  11. local old # old version
  12. local oldx # ... X
  13. local oldz # ... Z
  14. local oldy # ... Y
  15. local tmpy # Y parsing cache
  16. local new # bumped version
  17. read -r old
  18. oldx=${old%.*.*}
  19. oldz=${old#*.*.}
  20. tmpy=${old%.*}
  21. oldy=${tmpy#*.}
  22. case $rlevel in
  23. x) new="$((oldx+MKIT_BUMPSIZE)).0.0" ;;
  24. y) new="$oldx.$((oldy+MKIT_BUMPSIZE)).0" ;;
  25. z) new="$oldx.$oldy.$((oldz+MKIT_BUMPSIZE))" ;;
  26. *) die "invalid release level: $1" ;;
  27. esac
  28. echo "$new"
  29. }
  30. _relck() {
  31. #
  32. # Die if blocking condition $1 is detected
  33. #
  34. local condition=$1 # condition name
  35. local oracle # expected value
  36. case "$condition" in
  37. git_present)
  38. git rev-parse HEAD >&/dev/null\
  39. || die "cannot do this outside git repo"
  40. ;;
  41. at_relsrc)
  42. oracle=$(ini 1value project:relsrc)
  43. git_fact current_branch \
  44. | grep -qFx "$oracle" \
  45. || die "you are not on release source branch: $oracle"
  46. ;;
  47. not_dirty)
  48. git diff --shortstat 2>/dev/null \
  49. | grep -q . \
  50. && die "tree is dirty!"
  51. ;;
  52. tags_ok)
  53. git_fact latest_tag \
  54. | grep -q . \
  55. || die "cannot find latest tag"
  56. ;;
  57. vbump_hot)
  58. git diff-tree --no-commit-id --name-only -r HEAD \
  59. | grep -qFx mkit.ini \
  60. || die "last change must be version bump in mkit.ini"
  61. ;;
  62. no_wip)
  63. git_fact reldiff \
  64. | grep '^....... WIP ' \
  65. && die "WIP commit since $(git_fact latest_tag)"
  66. ;;
  67. ini_version)
  68. oracle=$(git_fact latest_version | _bump_version "$rlevel")
  69. ini 1value project:version \
  70. | grep -qFx "$oracle" \
  71. || die "new version not in mkit.ini: $oracle"
  72. ;;
  73. *)
  74. die "unknown release check: $condition"
  75. ;;
  76. esac
  77. }
  78. _release() {
  79. #
  80. # Prepare release
  81. #
  82. # Span release routines: make a signed tag, check branch
  83. # and update release branch
  84. #
  85. # FIXME: Using project:prerl as build.sh:semver() does may not be
  86. # compatible with this release strategy
  87. #
  88. local rlevel=$1 # release level (x, y or z)
  89. local newtag # new tag
  90. local relsrc # release source branch (if any)
  91. local reldst # release destination branch (if any)
  92. _relck git_present
  93. _relck at_relsrc
  94. _relck not_dirty
  95. _relck tags_ok
  96. _relck vbump_hot
  97. _relck no_wip
  98. _relck ini_version
  99. newtag=$(git_fact latest_version | _bump_version "$rlevel" | git_ver2tag )
  100. set -e
  101. debug_var newtag
  102. $MKIT_DRY && return
  103. git tag -m "$(_release_msg)" "$newtag"
  104. relsrc=$(ini 1value project:relsrc)
  105. reldst=$(ini 1value project:reldst)
  106. debug_var relsrc reldst
  107. if test -n "$reldst" && test "$reldst" != "$relsrc"; then
  108. git branch -f "$reldst" "$newtag"
  109. fi
  110. }
  111. _release_msg() {
  112. #
  113. # Generate message for annotated tag
  114. #
  115. # The last commit before issuing a release must be "Bump version" commit
  116. # suggested by _vbump_gitmsg() and manually edited by user. Since the
  117. # commit contains changelog, this function just uses the message body.
  118. #
  119. # The sort message (first line) is replaced with a nicer one (with project
  120. # name, codename and version).
  121. #
  122. echo "$(ini 1value project:name) $newtag - $(ini 1value project:codename)"
  123. echo
  124. git show -s --format=%B \
  125. | tail -n +3
  126. }
  127. _vbump() {
  128. #
  129. # Do version bump at level $1
  130. #
  131. # Perform checks, compute new version, update mkit.ini and initiate
  132. # 'Bump version' commit with changelog template.
  133. #
  134. local rlevel=$1 # bump level (x, y or z)
  135. local nextver # version after the bump
  136. _relck git_present
  137. _relck at_relsrc
  138. _relck not_dirty
  139. nextver=$(ini 1value project:version | _bump_version "$rlevel")
  140. debug_var nextver
  141. $MKIT_DRY && return
  142. update_version "$nextver" mkit.ini \
  143. || die "failed to update version in mkit.ini"
  144. git add mkit.ini \
  145. || die "failed to add mkit.ini to the index"
  146. git commit -e -m "$(_vbump_gitmsg)"
  147. }
  148. _vbump_gitmsg() {
  149. #
  150. # Compose git message template for 'Bump version' commit
  151. #
  152. echo "Bump version"
  153. echo ""
  154. echo "Overview of changes:"
  155. echo ""
  156. git_fact reldiff \
  157. | sed '
  158. s/^[a-f0-9]\{7\} / * &/; t PATHS
  159. s/^/ /
  160. :PATHS
  161. '
  162. }
  163. release() {
  164. #
  165. # Perform release on Z level
  166. #
  167. _release z
  168. }
  169. release_x() {
  170. #
  171. # Perform release on X level
  172. #
  173. _release x
  174. }
  175. release_y() {
  176. #
  177. # Perform release on Y level
  178. #
  179. _release y
  180. }
  181. release_z() {
  182. #
  183. # Perform release on Z level
  184. #
  185. _release z
  186. }
  187. vbump() {
  188. #
  189. # Perform version bump on Z level
  190. #
  191. _vbump z
  192. }
  193. vbump_x() {
  194. #
  195. # Perform version bump on X level
  196. #
  197. _vbump x
  198. }
  199. vbump_y() {
  200. #
  201. # Perform version bump on Y level
  202. #
  203. _vbump y
  204. }
  205. vbump_z() {
  206. #
  207. # Perform version bump on Z level
  208. #
  209. _vbump z
  210. }