#!/bin/bash
# Copyright 2014 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

#
# Script to make git repository selection simple
set -eu
set -o pipefail
SCRIPT_NAME=$(basename $0)
SCRIPT_HOME=$(cd $(dirname $0); pwd)

function show_options {
    echo "Usage: $SCRIPT_NAME [options] local_repo [...]"
    echo "    e.g. use locally cloned repositories as input:"
    echo "            $SCRIPT_NAME -l /my/local/neutron /a/local/nova"
    echo "    e.g. use the url of remote \"origin\" of the locally cloned repositories as input:"
    echo "            $SCRIPT_NAME -r origin /my/local/neutron /a/local/nova"
    echo "    e.g. use the values from a git manifest generated by disk-image-builder:"
    echo "            $SCRIPT_NAME -m tripleo-git-manifest"
    echo "    The above examples will set the location and reference to use."
    echo "    The reference will be set to the current HEAD reference of the local repository"
    echo
    echo "    To source the export commands produced by running this script and set the variables"
    echo "    for the current shell you can run the script as follows:"
    echo "        source <( $SCRIPT_NAME -l /path/to/repo )"
    echo
    echo "Display source-repositories element environment variables"
    echo
    echo "Options:"
    echo "    -h, --help                           -- print this help."
    echo "    -l, --local                          -- use the local path location of the repository"
    echo "    -r <remote>, --remote <remote>       -- remote of the local repo to use to get the repo url"
    echo "    -m <manifest>, --manifest <manifest> -- git manifest file as produced by running devtest"
    echo
    echo "Echo the appropriate environment variables to use a local git repository"
    echo "for input into image building via the source-repositories element"
    echo
    echo "The \"local_repo\" argment is the path to a locally cloned git repository from which to"
    echo "take the settings.  The name of the remote \"origin\" will be used to determine the name"
    echo "of the repository (nova, etc) for use in the diskimage-builder environment variables."
    echo
    echo "Using the -l flag will result in the full path to the local repository being used"
    echo "as the location to clone from for that repository in diskimage-builder"
    echo
    echo "Specifying a remote via the -r flag will result in the url associated with that remote"
    echo "in the local repository being used for the location to clone from for that repository"
    echo "in diskimage-builder"
    echo
    exit $1
}

TEMP=`getopt -o h,l,n,r:,m: -l help,local,no-echo,no_echo,remote:,manifest: -n $SCRIPT_NAME -- "$@"`
if [ $? != 0 ]; then
    echo "Terminating..." >&2
    exit 1
fi

# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"

while true ; do
    case "$1" in
        -h|--help) show_options 0 >&2;;
        -l|--local) USE_LOCAL=1; shift 1;;
        -r|--remote) USE_REMOTE=1; REMOTE=$2; shift 2;;
        -m|--manifest) USE_MANIFEST=1; MANIFEST=$2; shift 2;;
        --) shift ; break ;;
        *) echo "Error: unsupported option $1." ; exit 1 ;;
    esac
done

USE_LOCAL=${USE_LOCAL:-0}
USE_REMOTE=${USE_REMOTE:-0}
REMOTE=${REMOTE:-""}
USE_MANIFEST=${USE_MANIFEST:-0}

if [[ "$((USE_LOCAL + USE_REMOTE + USE_MANIFEST))" != "1" ]]; then
    echo "Choose to either clone the local path (-l)" >&2
    echo "OR" >&2
    echo "to use the remote (-r <remote>) defined in the local repo to lookup the repo URL" >&2
    echo "OR" >&2
    echo "to parse repos and SHA1s from a manifest file (-m <manifest-file>)" >&2
    show_options 1 >&2
fi

function transform_manifest {
    while read name _type _dest loc ref; do
        name_transformed=$(echo "$name" | tr '[:upper:]-' '[:lower:]_')
        echo "export DIB_REPOLOCATION_${name_transformed}=$loc"
        echo "export DIB_REPOREF_${name_transformed}=$ref"
    done
}

function use_manifest {
    for manifest in "${MANIFEST}"; do
        transform_manifest < ${manifest}
    done | sort -ut _ -k3
}


function get_location {
    local remote_name=${1:-""}
    if [[ -n "${remote_name}" ]] ; then
        git config --get remote.${remote_name}.url
    elif [[ "${USE_LOCAL}" == "1" ]]; then
        # Find the .git directory
        local dir="$(pwd)"
        while [[ "${dir}" != "/" ]]; do
            if [[ -d "${dir}/.git" ]]; then
                echo ${dir}
                break
            fi
            dir="$(dirname $dir})"
        done
    else
        echo -n "Internal Error: get_location called with [${remote_name}]" >&2
        echo " and USE_LOCAL is ${USE_LOCAL}" >&2
        exit 1
    fi
}

function get_ref {
    git rev-parse HEAD
}

function get_name {
    local remote_name=${1:-""}
    name=$(get_location ${remote_name})
    echo $(basename ${name##*:} .git)
}

function use_repos {
    declare -A a
    for dir in "${REPOS[@]}"; do
        if [[ ! -d ${dir} ]] ; then
            echo "Not a directory: ${dir}" >&2
            exit 1
        fi
        pushd ${dir} > /dev/null 2>&1
        REPONAME=$(get_name ${REMOTE})
        REPONAME_VAR=${REPONAME//[^a-zA-Z0-9]/_}
        a[DIB_REPOLOCATION_${REPONAME_VAR}]=$(get_location ${REMOTE})
        a[DIB_REPOREF_${REPONAME_VAR}]=$(get_ref)
        echo "export DIB_REPOLOCATION_${REPONAME_VAR}=${a[DIB_REPOLOCATION_${REPONAME_VAR}]}"
        echo "export DIB_REPOREF_${REPONAME_VAR}=${a[DIB_REPOREF_${REPONAME_VAR}]}"
        popd > /dev/null 2>&1
    done
}


if [[ "${USE_MANIFEST}" == "1" ]] ; then
    use_manifest
else
    if (( $# <= 0 )); then echo "Local repository location is required" >&2; show_options 1 >&2; fi
    REPOS=( "${@}" )
    use_repos
fi

