#!/bin/bash -e
# Copyright (c) 2017 TurnKey GNU/Linux - http://www.turnkeylinux.org
# 
# tkldev-changelog
# ----------------
# A tool to easily update turnkey appliance changelogs
#
# This file is part of tkldev-tools.
# 
# tkldev-tools is free software; you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.

fatal() { echo "FATAL [$(basename $0)]: $@" 1>&2; exit 1; }
warning() { echo "WARNING [$(basename $0)]: $@"; }
info() { echo "INFO [$(basename $0)]: $@"; }

usage() {
    if [[ $# -ne 0 ]]; then
        echo "ERROR: $@"
        echo
        exit_code=1
    fi
cat<<EOF
Syntax: $(basename $0) [appliance-name]
When run in the root directory of an appliance's source code, this script will
create a new changelog entry at the top of an existing changelog file & opens
the file for editing in vim.

Prerequisites:

    devscripts (debian package - hard dependency)
    vim (debian package - optional; vim-tiny is pre-installed and will work)
    configured local tz-data (optional - otherwise will fall back to UTC)

Arguments::

    appliance-name      - e.g., core
    -a|--author         - Update the author name and email address of the most
                          recent entry (do not leave open for editing).
    -d|--date           - Update the date of the most recent entry (do not
                          leave open for editing).
    -e|--edit           - Edit the most recent entry (rather than generating a
                          new one) - implies -d|--date & -n|--name, but leaves
                          open for editing.
    -n|--new-minor      - Create new minor version changelog entry (e.g. 16.1).
                          Leaves open for editing. (Default action if no switch
                          specified).
    -N|--new-major      - Create new major version changelog entry (e.g. 17.0).
                          Leaves open for editing.

Environment::

    DEBFULLNAME         - full name of operator e.g. "Joe Bloggs"
    FULLNAME            - full name of operator (if DEBFULLNAME not set)
    DEBEMAIL            - email address of operator e.g. "joe@blogs.com"
    EMAIL               - email address of operator (if DEBEMAIL not set)
    EXTRA_TEXT          - additional changelog points to include in new entry
                          if not set; then by default it will read from 
                          "/turnkey/fab/common/changes"
    DEVDEBUG            - turn on debugging

Future plans:

    - create new changelog (probably via switch?)
    - support specifiying a path (currently must be run in root of appliance
      source code)
    - do something better with the EXTRA_TEXT (e.g. include in common?)
    - support alternate text editors?

EOF
    exit $exit_code
}

[[ -z "$DEVDEBUG" ]] || set -x
which dch > /dev/null || fatal "dch not found; please install 'devscripts'"
which vim > /dev/null || fatal "vim not found; call yourself a developer?!?"
[ -f changelog ] || fatal "no changelog in local dir"

APP=$(basename $PWD)
COMMON_CHANGES="${FAB_PATH}/common/changes"
APP_CHANGELOGS=$(tkldev-makefile-info "$PWD/Makefile" -i \
    | grep -E "^${FAB_PATH}/common/" \
    | sed -En "s|^([a-z0-9/-]+)/mk/turnkey/*([a-z0-9-]+).mk|\1/changes/\2.changelog|p")

if [ -z "$EXTRA_TEXT" ] && [ "$APP" != "core" ]; then
    EXTRA_TEXT=$(tkldev-changelog-extractor "$PWD/changelog" "${FAB_PATH}/common/changes/turnkey.changelog" $APP_CHANGELOGS)
fi

EXTRA_TEXT_FILE="$(mktemp /tmp/tkldev-changelog.XXXXXX)"
trap "rm -f $EXTRA_TEXT_FILE" EXIT
echo "$EXTRA_TEXT" > "$EXTRA_TEXT_FILE"

author_name=${DEBFULLNAME:-$FULLNAME}
author_email=${DEBEMAIL:-$EMAIL}
if [[ -z "$author_name" ]] || [[ -z "$author_email" ]]; then
    unset changed
    if [[ -f "$HOME/.bashrc.d/tkldev-author" ]]; then
        source $HOME/.bashrc.d/tkldev-author
    fi
    if [[ -z "$author_name" ]] && [[ -z "$DEBFULLNAME" ]]; then
        warning "DEBFULLNAME (or FULLNAME) not set in env"
        read -p "Enter fullname: " author_name
        changed=true
    fi
    if [[ -z "$author_email" ]] && [[ -z "$DEBEMAIL" ]]; then
        warning "DEBEMAIL (or EMAIL) not set in env"
        read -p "Enter email: " author_email
        changed=true
    fi
    if [[ "$changed" == 'true' ]]; then
        read -p "Set permanently? (will save to $HOME/.bashrc.d/tkldev-author) [y]/n: " save
        case $save in
            [yY]|yes|YES|"")
                cat > $HOME/.bashrc.d/tkldev-author <<EOF
# This file was generated by tkldev-changelog
export DEBFULLNAME="$author_name"
export DEBEMAIL="$author_email"
EOF
                chmod +x $HOME/.bashrc.d/tkldev-author
                source $HOME/.bashrc.d/tkldev-author
                ;;
            *)
                export DEBFULLNAME="$author_name"
                export DEBEMAIL="$author_email"
                ;;
        esac
    fi
fi

unset set_author set_date new_min_set new_maj_set new edit
if [[ $# -eq 0 ]]; then
    # if no args; then default to '-n|--new-minor'
    new_min_set=1
    new=minor
    edit=y
fi
while [[ $# -gt 0 ]]; do
    case $1 in
        -h|--help)
            usage;;
        -a|--author)
            set_author=y
            edit=n
            shift;;
        -d|--date)
            set_date=y
            edit=n
            shift;;
        -e|--edit)
            set_author=y
            set_date=y
            edit=y
            shift;;
        -n|--new-minor)
            new_min_set=1
            new=minor
            edit=y
            shift;;
        -N|--new-major)
            new_maj_set=1
            new=major
            edit=y
            shift;;
    esac
done

OLD_VER=$(head -1 changelog | cut -d' ' -f1 | sed "s|^.*${APP}-||")
MAJ="$(echo ${OLD_VER} | cut -d. -f1)"
MIN="$(echo ${OLD_VER} | cut -d. -f2)"

if [[ -n "$new_min_set" ]] && [[ -n "$new_maj_set" ]]; then
    usage "-n|--new-minor & -N|--new-major can't both be set; doesn't make sense."
elif [[ "$new" == 'minor' ]]; then
    MIN="$(( $(echo ${OLD_VER} | cut -d. -f2) +1 ))"
elif [[ "$new" == 'major' ]]; then
    MAJ=$(( $MAJ +1 ))
    MIN=0
fi

NEW_VER=${MAJ}.${MIN}
NAME="turnkey-${APP}-${NEW_VER}"

OLD_FILE="$(cat changelog)"

if [[ -n "$set_date" ]]; then
    dch --changelog changelog --release --force-distribution turnkey --urgency low
fi
if [[ -n "$set_author" ]]; then
    sed -i "0,\|^ -- |s|^.*> \(.*\)| -- $author_name <$author_email> \1|" changelog
fi
if [[ "$edit" == 'y' ]]; then
    if [[ -n "$new" ]]; then
        dch --changelog changelog --release-heuristic log --package $NAME --newversion 1 --force-distribution turnkey --urgency low
        sed -i "3s|\*.*|\* |" changelog
        sed -e "4r ${EXTRA_TEXT_FILE}" -i changelog
    else
        sed -i '3i\ \ * \n' changelog
    fi
    OLD_HASH="$(sha512sum changelog)"
    vim "+call cursor(3, 7)" changelog
    if echo "$OLD_HASH" | sha512sum -c --status; then
        echo "no changes made, reverting"
        echo "$OLD_FILE" > changelog
    fi
fi
