Welcome to little lamb

Code » comain » release » tree

[release] / mkrelease

#!/bin/sh

. "$(dirname $0)"/libcomain

if test ! -e meta/version; then error 2 "File 'meta/version' missing"; fi
ver="$(cat meta/version)"

force=0
if test "$1" = "-f"; then
    force=1
    shift
    if test "$1" = "-f"; then
        force=2
        shift
    fi
fi

major=$(echo $ver | cut -d. -f1)
minor=$(echo $ver | cut -d. -f2)
rev=$(echo $ver | cut -d. -f3)

if test $(expr match "$rev" "[0-9]\+rc") -gt 0; then
    rc="$(echo $rev | sed -e 's/^.*rc//')"
    rev="$(echo $rev | sed -e 's/rc.*$//')"
else
    rc=0
fi

case "$1" in
    rel) test $rc -eq 0 && error 1 "current version not an rc"
        rc=0 ;;
    major) major=$(($major + 1)); minor=0; rev=0 ; rc=0 ;;
    minor) minor=$(($minor + 1)); rev=0 ; rc=0 ;;
    rev) rev=$(($rev + 1)) ; rc=0 ;;
    rc)
        if test $rc -gt 0; then
            rc=$(( rc + 1 ))
        else
            error 2 "current version not an rc; try major|minor|rev rc"
        fi
        ;;
    *) error 1 "you need to specify 'major', 'minor', 'rev', 'rc' or 'rel'"
esac
shift

if test $# -eq 1; then
    if test "$1" = "rc"; then
        test $rc -gt 0 && error 2 "cannot use rc on rc"
        rc=$(( rc + 1 ))
    else
        error 1 "invalid argument: $1"
    fi
    shift
fi

test $rc -gt 0 && rev="${rev}rc$rc"

test $# -eq 0 || error 1 "Too many arguments"

new=$major.$minor.$rev

printf "Bumping $ver to $new ? [yN] "
read a
case "$a" in
    [Yy]) ;;
    ""|[Nn]) exit 0 ;;
    *) error 3 "invalid answer" ;;
esac

echo " => bumping $ver to $new..."
date="$(date +%Y-%m-%d)"

if test "$(git symbolic-ref --short HEAD)" != "master"; then
    error 2 "master is not checked out"
fi
if test -n "$(git status -s)"; then
    error 2 "working tree not clean"
fi

was_master=$(git show-ref --heads --hash master)
if ! test "$(git show-ref --heads --hash dev)" = "$was_master"; then
    if test $force -ge 1; then
        force=$(( $force - 1 ))
        echo "Ignoring that dev and master differ..."
        was_master=
    else
        error 4 "dev and master differ (-f to ignore)"
    fi
fi

if test $force -ge 1; then
    echo "Ignoring possible XXX/TODO/FIXME..."
elif ! git xxx -q; then
    echo "  -> Might be things left to do..."
    git xxx
    echo "Use -f to force the release anyway."
    exit 5
fi

if test $rc -eq 0; then

    echo "  -> Checking for new man pages..."
    git diff --name-only --diff-filter=A $(cat meta/version) -- src/doc \
        | grep -v src/doc/include/ | while read -r file ; do
        test -L "$file" && continue
        echo "    * Updating $file..."
        { head -n 2 "$file"; echo "% $prjname $new"; echo "% $date"; tail -n +3 "$file"; } > "$file.tmp"
        mv -f "$file.tmp" "$file"
    done

    echo "  -> Checking for modified man pages..."
    git diff --name-only --diff-filter=M $(cat meta/version) -- src/doc \
        | grep -v src/doc/include/ | while read -r file ; do
        test -L "$file" && continue
        echo "    * Updating $file..."
        { head -n 2 "$file"; echo "% $prjname $new"; echo "% $date"; tail -n +5 "$file"; } > "$file.tmp"
        mv -f "$file.tmp" "$file"
    done

    if test -n "$(git status -s)"; then
        echo "  -> Adding automatic changes..."
        run git add -e -- src/doc
    fi

fi # rc == 0

echo "  -> Updating meta/HISTORY"
line="# version $new [released on $date]"
if test ! -e meta/HISTORY; then
    test $rc -eq 0 && cat >meta/HISTORY.tmp <<EOF
# Current development

- Nothing yet.

$line

- First release.
EOF
else
    exec 5>&1 >meta/HISTORY.tmp
    head -2 meta/HISTORY
    test $rc -eq 0 && cat <<EOF
- Nothing yet.

$line

EOF
    git log --reverse --no-decorate \
        --format='- %s%n%w(,2,2)%+b%nThanks to %an <%ae>%n%n' \
        $ver..master \
        | awk -vskip=0 '/Thanks to Olivier Brunel/ { skip=1; next }
            // { if (skip) { skip=0 } else { print } }'
    tail -n +3 meta/HISTORY
    exec 1>&5 5<&-
fi
if test -e meta/HISTORY.tmp; then
    mv -f meta/HISTORY{.tmp,}
    echo "  -> Review updated HISTORY..."
    ${EDITOR:vim} meta/HISTORY
fi

echo "  -> Updating meta/version : $new"
echo $new > meta/version

echo "  -> Updating meta/released-on : $date"
echo $date > meta/released-on

echo "  -> Commit changes..."
git add meta/{version,released-on,HISTORY}
git commit -m "Release version $new"

if test $rc -eq 0; then
    echo "  -> Tag & fast-forward release"
    git checkout release
    git merge --ff-only master
else
    echo "  -> Tag"
fi
git tag -a $new -m "Release version $new

$(getchangelog $rc)"

if test -n "$was_master"; then
    echo "  -> Reset dev & rebase dev-wip..."
    git branch -f dev master
    git rebase --onto dev $was_master dev-wip
else
    echo "  -> Check out (untouched) dev-wip..."
    git checkout dev-wip
fi

echo "done."