123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- #!/bin/bash
- # MKit - simple install helper
- # See LICENSE file for copyright and license details.
-
- mkit_import ini
- mkit_import facts
-
- __release__bump_version() {
- #
- # Bump version on stdin by level $1 (x, y or z)
- #
- local rlevel=$1 # release level
- local old # old version
- local oldx # ... X
- local oldz # ... Z
- local oldy # ... Y
- local tmpy # Y parsing cache
- local new # bumped version
- read -r old
- oldx=${old%.*.*}
- oldz=${old#*.*.}
- tmpy=${old%.*}
- oldy=${tmpy#*.}
- case $rlevel in
- x) new="$((oldx+MKIT_BUMPSIZE)).0.0" ;;
- y) new="$oldx.$((oldy+MKIT_BUMPSIZE)).0" ;;
- z) new="$oldx.$oldy.$((oldz+MKIT_BUMPSIZE))" ;;
- *) die "invalid release level: $1" ;;
- esac
- echo "$new"
- }
-
- __release__check() {
- #
- # Die if blocking condition $1 is detected
- #
- local condition=$1 # condition name
- local oracle # expected value
- case "$condition" in
- git_present)
- git rev-parse HEAD >&/dev/null\
- || die "cannot do this outside git repo"
- ;;
- at_relsrc)
- oracle=$(ini 1value project:relsrc)
- git_fact current_branch \
- | grep -qFxe "$oracle" \
- || die "you are not on release source branch: $oracle"
- ;;
- not_dirty)
- git diff --shortstat 2>/dev/null \
- | grep -q . \
- && die "tree is dirty!"
- ;;
- tags_ok)
- git_fact latest_tag \
- | grep -q . \
- || die "cannot find latest tag"
- ;;
- vbump_hot)
- git diff-tree --no-commit-id --name-only -r HEAD \
- | grep -qFx mkit.ini \
- || die "last change must be version bump in mkit.ini"
- ;;
- no_wip)
- git_fact reldiff_brief \
- | grep -iE \
- -e '^[^ ]+ WIP ' \
- -e '^[^ ]+ WIP$' \
- -e '^[^ ]+ WIP:' \
- && die "WIP commit since $(git_fact latest_tag)"
- ;;
- ini_version)
- oracle=$(git_fact latest_version | __release__bump_version "$rlevel")
- ini 1value project:version \
- | grep -qFxe "$oracle" \
- || die "new version not in mkit.ini: $oracle"
- ;;
- *)
- die "unknown release check: $condition"
- ;;
- esac
- }
-
- __release() {
- #
- # Prepare release
- #
- # Span release routines: make a signed tag, check branch
- # and update release branch
- #
- # FIXME: Using project:prerl as build.sh:semver() does may not be
- # compatible with this release strategy
- #
- local rlevel=$1 # release level (x, y or z)
- local newtag # new tag
- local relsrc # release source branch (if any)
- local reldst # release destination branch (if any)
-
- __release__check git_present
- __release__check at_relsrc
- __release__check not_dirty
- __release__check tags_ok
- __release__check vbump_hot
- __release__check no_wip
- __release__check ini_version
-
- newtag=$(git_fact latest_version | __release__bump_version "$rlevel" | git_ver2tag )
- set -e
- debug_var newtag
- $MKIT_DRY && return
- git tag -m "$(__release_msg)" "$newtag"
-
- relsrc=$(ini 1value project:relsrc)
- reldst=$(ini 1value project:reldst)
- debug_var relsrc reldst
- if test -n "$reldst" && test "$reldst" != "$relsrc"; then
- git branch -f "$reldst" "$newtag"
- fi
- }
-
- __release_msg() {
- #
- # Generate message for annotated tag
- #
- # The last commit before issuing a release must be "Bump version" commit
- # suggested by __release__vbump_gitmsg() and manually edited by user. Since the
- # commit contains changelog, this function just uses the message body.
- #
- # The sort message (first line) is replaced with a nicer one (with project
- # name, codename and version).
- #
- echo "$(ini 1value project:name) $newtag - $(ini 1value project:codename)"
- echo
- git show -s --format=%B \
- | tail -n +3
- }
-
- __release__update_ini() {
- #
- # Change project:version in mkit.ini at path $2 to value $1
- #
- local version=$1 # new version
- local inifile=$2 # mkit.ini path
- local tmp # mkit.ini cache
- tmp=$(mktemp -t mkit.__release__update_ini.XXXXXXXX)
- <"$inifile" perl -e '
- my $hit = 0;
- my $done = 0;
- foreach (<STDIN>) {
- if ($done) { print; next; }
- elsif (m/\[project\]/) { $hit++; print; next; }
- elsif (m/\[/) { $hit = 0; print; next; }
- elsif ($hit) { s/\bversion\b( *)=( *).*/version$1=$2$ARGV[0]/ and $done++; print; }
- else { print; next; }
- }
- ' "$version" >"$tmp" || die "failed to update version in mkit.ini"
- mv "$tmp" "$inifile"
- }
-
- __release__vbump() {
- #
- # Do version bump at level $1
- #
- # Perform checks, compute new version, update mkit.ini and initiate
- # 'Bump version' commit with changelog template.
- #
- local rlevel=$1 # bump level (x, y or z)
- local nextver # version after the bump
- local cache # cache for the message
- __release__check git_present
- __release__check at_relsrc
- __release__check not_dirty
- nextver=$(ini 1value project:version | __release__bump_version "$rlevel")
- debug_var nextver
- $MKIT_DRY && return
- __release__update_ini "$nextver" mkit.ini \
- || die "failed to update version in mkit.ini"
- git add mkit.ini \
- || die "failed to add mkit.ini to the index"
- cache=$(mktemp -t "mkit.__release__vbump_gitmsg.XXXXXXXX")
- __release__vbump_gitmsg "$nextver" > "$cache"
- git commit -e -F "$cache" # note: reading from stdin will break vim
- rm "$cache"
- }
-
- __release__vbump_gitmsg() {
- #
- # Compose git message template for 'Bump version' commit
- #
- local nextver=$1
- echo "Bump version to $nextver"
- echo ""
- echo "Overview of changes:"
- echo ""
- git_fact reldiff \
- | sed '
- s/^[a-f0-9]\{7\} /\n * &/; t PATHS
- s/^/ /
- :PATHS
- '
- }
-
- release() {
- #
- # Perform release on Z level
- #
- __release z
- }
-
- release_x() {
- #
- # Perform release on X level
- #
- __release x
- }
-
- release_y() {
- #
- # Perform release on Y level
- #
- __release y
- }
-
- release_z() {
- #
- # Perform release on Z level
- #
- __release z
- }
-
- vbump() {
- #
- # Perform version bump on Z level
- #
- __release__vbump z
- }
-
- vbump_x() {
- #
- # Perform version bump on X level
- #
- __release__vbump x
- }
-
- vbump_y() {
- #
- # Perform version bump on Y level
- #
- __release__vbump y
- }
-
- vbump_z() {
- #
- # Perform version bump on Z level
- #
- __release__vbump z
- }
|