#! /usr/bin/zsh -feu

# SHORT:
# Given a .changes file, upload & install it (partially).
# Also, create git tag & do the git push to remote


# This is just a wrapper around debi & dput (or reprepro)

# 1/ Normally invoked as a post-build hook by git-buildpackage.
# The cmdline is not user-controllable, hence only via env. variables.

# It receives GBP_* vars, though.

# The following `env' variables can specify the behaviour:
# INSTALL_IMMEDIATELY ...  whether to invoke debi(1).
# DPUT_TARGETS
# DPUT_OPTIONS ... is passed to dput(1) maybe with addition of more options.

# todo:
# could use GBP_CHANGES_FILE even after building with debuild!

# 2/ When invoked manually, we use:
# MBS_SNAP_TARGETS in place of DPUT_TARGETS

# mmc: is the cwd in the git repo?

# todo: source @@SHAREDIR@@/functions
source /usr/share/build-system/functions.sh
possibly_trace

function usage(){
    setopt POSIX_ARGZERO
    cat <<EOF
usage: ${0##*/} [+-ufin] [--] ARGS...
dput(1) options basically
-u don\'t check the signaure
-f force RE-upload
-i install immediatelly
-n do not install
-I upgrade only
-d {DISTRO}
-r release, so use the MBS_TARGETS, and hence dput(1) in those

Environment:
DPUT_TARGETS
EOF
    unsetopt POSIX_ARGZERO
}

# defaults:
# fixme: this is set in ~/.gbp.conf (by git-buildpackage)
# DEBRELEASE_DEBS_DIR ?

if [[ -n ${GBP_BUILD_DIR-} ]]; then
    BUILD_AREA=${GBP_BUILD_DIR%/*}
else
    # fixme: $TMPDIR/gbp !!!
    BUILD_AREA=/gbp
fi

# I like these defaults better:
: ${INSTALL_IMMEDIATELY=y}
DEBI_OPTIONS+=()


DISTRO=${MBS_DISTRO-}
release=n

# we compose options for `dput'
typeset -T DPUT_OPTIONS dput_options

# in particular the `targets'
# Convert from MBS_TARGETS into a Zsh array. My standard!
typeset -T MBS_TARGETS mbs_targets ":"
typeset -T DPUT_TARGETS dput_targets

# possible input via this variable:  why SNAP ?
[ -z "$DPUT_TARGETS" ] && dput_targets=${MBS_SNAP_TARGETS-}

# make it manually invokable:
while getopts :ufiIrd:n OPT; do
    case $OPT in
        u|+u)
            dput_options+=("--unchecked")
            ;;
        f)
            dput_options+=("--force")
            ;;
        n)
            INSTALL_IMMEDIATELY=n
            ;;
        i)
            INSTALL_IMMEDIATELY=y
            # fixme: just remove "--upgrade"
            DEBI_OPTIONS=()
            ;;
        I) # useless?
            INSTALL_IMMEDIATELY=y
            DEBI_OPTIONS+=("--upgrade")
            ;;
        r)
            # fixme: here we overwrite!
            [ -z "$DPUT_TARGETS" ] &&
                dput_targets=($mbs_targets)
            release=y
            ;;
        d)
            DISTRO=$OPTARG
            ;;
        *)
            usage
            exit 2
    esac
done
shift $(( OPTIND - 1 ))
OPTIND=1

# if still arguments remain,
if [ $# -gt 0 ]
then
    GBP_CHANGES_FILE=$1
else
    GBP_CHANGES_FILE=$(deb-pkg-find-changes)
fi

if [ -z "${GBP_CHANGES_FILE-}" ]; then
    echo "did not provide the Changes file!"
    usage
    exit 2
fi

REPREPRO_COLOR=blue

upload_to_reprepro()
{
    cecho $REPREPRO_COLOR "First remove development packages"
    # first remove ... If I decided for only a minor version bump
    # todo: improve this somehow?
    # fixme: if only an ARCH specific changes file, then don't do this:
    reprepro-remove-obsolete "UNRELEASED" $GBP_CHANGES_FILE

    # Distribution: release
    DISTRO=$(sed -n -e '/^Distribution: /{s/Distribution: //;p}' $GBP_CHANGES_FILE)

    # fixme: if the distro is not local?
    # acceptable in reprepro: resolves Codename, Suite and AlsoAcceptFor
    if test -n "$DISTRO"  &&
        reprepro --basedir "$REPREPRO_BASE_DIR" \
            listfilter "$DISTRO" 'Package (= zzz_none_matches)' >/dev/null 2>&1;
    then
        cecho $REPREPRO_COLOR "Putting into Reprepro: ${GBP_CHANGES_FILE}"
        reprepro --basedir "$REPREPRO_BASE_DIR" -V --ignore=surprisingbinary \
                 include "$DISTRO" $GBP_CHANGES_FILE
    fi

    return 0;
}

# dput/install into (local) reprepro:
# $GBP_BUILD_DIR is the build directory: I don't need it.
if [ -n "${REPREPRO_BASE_DIR-}" -a -n "${GBP_CHANGES_FILE}" ]
then
    upload_to_reprepro
fi
# todo: remove local from dput_targets!



## Install  (this is even faster)
if [ ${INSTALL_IMMEDIATELY} = "y" ]
then
    cecho green "installing immediately ${GBP_CHANGES_FILE}"
    if [ -n "${GBP_CHANGES_FILE}" ]; then
        set -x
        sudo debi ${DEBI_OPTIONS-} $GBP_CHANGES_FILE
    else
        sudo debi ${DEBI_OPTIONS-} --debs-dir $BUILD_AREA
    fi
else
    cecho green "not requested to install immediately"
    echo "** If you want to install:"
    # cecho gray:
    echo "debi --debs-dir $BUILD_AREA"
fi


## upload
# note that  `local' is basically wrong. reprepro is done natively.
if [ -z "${dput_targets}" ]; then
    cecho green "no Dput targets"
else
    for TARGET in ${dput_targets}
    do
        if [[ $TARGET = local  &&
                  -z "${REPREPRO_BASE_DIR-}" ]]; then
            # echo "sorry, where is reprepro?"
            continue
        fi

        cecho blue "Uploading to $TARGET"

        if [ -z ${GBP_CHANGES_FILE-} ]; then
            if ! debrelease --debs-dir=$BUILD_AREA --dput $TARGET; then
                (echo "Failed to upload to $TARGET"; echo )>&2
            fi
        else
            set -x
            if ! dput --unchecked $dput_options $TARGET $GBP_CHANGES_FILE;
            then
                cecho yellow "target $TARGET failed, but not fatal!"
            fi
        fi
    done
fi


# post-action:
if [[ $release = y ]]
then
    reprepro-git-commit $GBP_CHANGES_FILE

    # tag=$(deb-parse-changes $GBP_CHANGES_FILE)
    # so convert it somehow!
    tag=$(awk -F ': '  -e  \
              '/Version: / {version=$2}
/Distribution:/ {distribution=$2}
END {printf "%s/%s", distribution, version}' $GBP_CHANGES_FILE)
    # bug:  2:version is invalid tag!
    : ${tag::=${tag/:/_}}
    if [[ -z $(git rev-parse --tags="$tag*" 2> /dev/null) ]]
    then
        # I make the tag with hierarchy:
        if [[ -z $(git-sum) && -z $(git-segment) ]]
        then
            git tag -m 'release' $tag HEAD
        else
            # todo: the whole graph or from the current branch?
            git-store-hierarchy -t $tag $(git branch --show-current)
        fi
        post-tag-hook
    fi
fi
