#!/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 () { 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 }