#!/bin/bash
# 
# tagpkg -l <package> <release>
# tagpkg <package> <release> <tag>
# 

# Default endpoints
GITROOT=${GITROOT:=https://:@gitlab.cern.ch:8443/atlas-tdaq-software}

USER=${USER:=$(id -un)}

_this=$(dirname $(readlink -f ${BASH_SOURCE[0]}))

usage()
{
    echo "usage:"
    echo "    tagpkg [ --msg=\"...\" ] [ --title=\"...\"] [ --labels=label1,label2,... ] [ --edit ] <package> <release> <tag> [ <feature-branch> ] [ -- pkg tag pkg2 tag2... ]"
    echo "    tagpkg -l [ <package> [<release>] ] "
    echo 
    echo "   Submit or list the tag of a package in a release."
    echo
    echo "   --msg=...     Sets the commit message in the project. Default '\${USER} submitted ${pkg} with tag \${tag}'."
    echo "   --title=...   Sets the title for the merge request. Default '\${tag} for \${release}'."
    echo "   --labels=...  Sets a list of Gitlab labels in the merge request. "
    echo "                 See: https://gitlab.cern.ch/atlas-tdaq-software/tdaq-cmake/-/labels"
    echo "   --edit        Call editor on commit message."

    echo "   Examples:"
    echo "       # list version in release"
    echo "       tagpkg -l hltsv nightly"
    echo
    echo "       # submit tag to a release"
    echo "       tagpkg hltsv nightly hltsv-01-00-32"
    echo "       tagpkg hltsv tdaq-08-03-01 hltsv-01-00-32"
    echo
    echo "       # Submit multiple tags to the same merge request"
    echo "       tagpkg hltsv tdaq-08-03-01 hltsv-01-00-32 feature/new"
    echo "       tagpkg dcm   tdaq-08-03-01 dcm-02-00-01   feature/new"
}

list_tag=0

to_shift=3
while [ $# -gt 0 ]
do
    case $1 in
        -h|--help)
            usage
            exit 0
            ;;
        # Custom commit message for putting the tag in
        --msg=*)
            COMMIT_MSG=${1#--msg=}
            shift
            ;;
        # Custom title
        --title=*)
            TITLE_MSG=${1#--title=}
            shift
            ;;
        # Gitlab labels
        --labels=*)
            IFS=, read -ra LABELS < <(echo "${1#--labels=}")
            for l in ${LABELS[@]}
            do
              LABEL_OPTIONS="${LABEL_OPTIONS} --push-option=merge_request.label=${l}"
            done
            shift
            ;;
        -e|--edit)
            EDIT_OPTION=-e
            shift;
            ;;
        -l|--list)
            list_tag=1
            to_shift=2
            shift
            ;;
        *)
            break;
            ;;
    esac
done

[ $# -lt ${to_shift} ] && { usage; exit 1; }

pkg=$1
branch=$2
tag=$3

shift ${to_shift}

# Translate what were symbolic links in the old tag collector.
# Have to hardcode them for now, and there is no 'prod' or 'dev' !
case ${branch} in
    nightly)
        branch=tdaq-99-00-00
        project=tdaq-cmake
        ;;
    *-nightly)
        project=$(echo ${branch} | sed "s;nightly;cmake;")
        branch=$(echo ${branch} | sed "s;nightly;99-00-00;")
        ;;
    *)
        project=$(echo ${branch} | sed "s;[0-9].*$;cmake;")
        ;;
esac

tc=$(mktemp -d) || { echo "You have an invalid TMPDIR ?"; exit 2; }

# Comment this line for debugging
trap "rm -rf ${tc}" EXIT

commit=${tc}/commit
if [ -z "${COMMIT_MSG}" ]; then
    echo "${USER} submitted ${pkg} with tag ${tag}" > ${commit}
else
    echo "${COMMIT_MSG}" > ${commit}
fi

# Always clone top level project to simplify and speed up some operations
git clone -q -b ${branch} ${GITROOT}/${project}.git ${tc}/${project} || exit 1
cd ${tc}/${project}

# Get package to tag
git submodule -q update -i ${pkg} || exit 1

# If listing tag is requested
if [ ${list_tag} -eq 1 ]; then
    cd ${pkg}
    printf "%-20s %-30s %-s\n" ${pkg} $(git describe --tags) $(git rev-parse HEAD)
    exit 0
fi

# Either create new branch, or use the one defined on command line.
if [ $# -ge 1 -a "$1" != "--" ]; then
    new_branch="$1"
    user_branch=1
    shift
else
    new_branch="${USER}/${branch}/${pkg}"
fi

# Put everything on the new branch
git checkout -q ${new_branch} 2> /dev/null || git checkout -q -b ${new_branch} || { echo "Cannot create ${new_branch}"; exit 2; }

tag_pkg()
{
    echo -n "Submitting: ${pkg} ${tag} to ${branch}"

    git submodule -q update -i ${pkg}

    # Now make the change for the package
    cd ${pkg} || exit 1

    oldref=$(git rev-parse HEAD)

    # This works for tags, SHAs, HEAD, the second try for branches
    git checkout -q ${tag} 2> /dev/null || git checkout -q origin/${tag} 2> /dev/null

    if [ $? -ne 0 ]; then
        echo " $(tput setaf 1) Invalid tag or reference for ${pkg} : ${tag} ! $(tput sgr0)"
        exit 1
    fi
    ref=$(git rev-parse HEAD)
    echo " $(tput setaf 2) Tag or reference ok for ${pkg} : ${tag} ${ref}$(tput sgr0)"

    echo >> ${commit}
    echo "=== ${pkg} ===" >> ${commit}
    echo >> ${commit}
    git log --no-merges --format="%s (%an)" ${oldref}..${ref} >> ${commit}

    cd ..
}

tag_pkg

if [ -z "${TITLE_MSG}" ]; then
  TITLE_MSG="${pkg} with tag ${tag} for ${branch}"
fi

if [ $# -gt 0 -a "$1" = "--" ]; then
    shift
    while [ $# -ge 2 ]
    do
        pkg=$1
        tag=$2
        tag_pkg
        shift 2
    done
fi

cd ${tc}/${project}
git commit -q ${EDIT_OPTION} -aF ${commit} || exit 1

# default is to push to new branch
dest=${new_branch}

# except for magic 99 branches and no manual branch specified
case "${branch}" in
   tdaq-99-*|tdaq-common-99-*)
     [ "${user_branch}" != "1" ] && dest=${branch}
     ;;
esac

case "${dest}" in
   tdaq-99-*|tdaq-common-99-*)
      ;;
   *)
      PUSH_OPTIONS="--push-option=merge_request.create --push-option=merge_request.remove_source_branch --push-option=merge_request.target=${branch} ${LABEL_OPTIONS}"
esac

# Now just try to push and see what happens, this should
# always succeed for 'Developer' rights, and give an error message otherwise.
git push -q ${PUSH_OPTIONS} origin ${new_branch}:${dest} 
