# return tags in decreasing date order
# args: workdir.

mst_otsb_vcs_hg_tags () {

    hg -R "$1" log -r "reverse(sort(tag(),date))" -T "{tags}\n"
}

# return tags in decreasing date order
# args: workdir.

mst_otsb_vcs_git_tags () (

    # modified from https://stackoverflow.com/a/7261049
    # this returns all tags across all branches in reverse chronological order

    GIT_DIR="$1/.git"
    export GIT_DIR
    git describe --abbrev=0 --tags --always $(git rev-list --tags) | uniq
)


# args: workdir
mst_otsb_vcs_hg_version () {

    hg -R "$1" log -r tip --template '{node|short}'

}

mst_otsb_vcs_git_version () {

    GIT_DIR="$1/.git"				\
	git log -n 1 --pretty=format:'%h'

}

# args: src destdir package_name branch/tag
mst_otsb_vcs_hg_clone () {

    local src=$1
    local destdir=$2
    local package_name=${3:-$(basename $src)}

    hg -q clone "$src" "$destdir"
}

# args: src destdir package_name branch/tag
mst_otsb_vcs_git_clone () {

    local src=$1
    local destdir=$2
    local package_name=${3:-$(basename $src .git)}

    git clone -q $src $destdir
}

# args: src destdir package_name branch/tag
mst_otsb_vcs_hg_checkout () {

    local destdir=$1
    local tag=${2:-default}

    hg -q -R "$destdir" update -r $tag
}

# args: src destdir package_name branch/tag
mst_otsb_vcs_git_checkout () {

    local destdir=$1
    local branch=${2:-master}

    GIT_WORK_TREE=$destdir \
	GIT_DIR=$destdir/.git \
	git checkout -q $branch
}


_mst_otsb_vcs_choose () {

    local label=$1
    shift

    local value

    values='@'$(otsb_join @ "${@}")'@'

    while [ "$value" = '' ] ; do
	otsb_warn Choose a $label : $@

	read value

	if [[ "$values" != *@$value@* ]] ; then

            otsb_warn "unknown $label '$value'; try again"
	    value=

	else

	    break
	fi

    done

    echo $value
}

# args: cmd args
mst_otsb_vcs () {

    local vcs=$1
    local cmd=$2
    shift 2

    local proxy=mst_otsb_vcs_${vcs}_${cmd}

    if ! otsb_has_command $proxy ; then
	otsb_die "unsupported vcs or command: $vcs $cmd"
    fi

    $proxy "${@}"
}


# args: vcs src branch/tag
mst_otsb_vcs_tarball_from_clone () {

    local version=latest

    local save_OPTIND=$OPTIND
    OPTIND=1
    while getopts :p:t:v:V:T: opt
    do
        case $opt in

            t ) local _mktarball="$OPTARG" ;;

            T ) local _pre_mktarball_hook="$OPTARG" ;;

	    v ) local version="$OPTARG" ;;

	    V ) local _fix_version="$OPTARG" ;;

	    p ) local package_name="$OPTARG";;

            : ) otsb_die "$FUNCNAME: unknown option or missing argument: -$OPTARG" ;;

        esac

    done

    shift $((OPTIND -1))
    OPTIND=$save_OPTIND

    local vcs=$1
    local src=$2
    shift 2

    : ${package_name:=$(basename $src .git)}

    local tmpdir;
    tmpdir=$(otsb_mktemp_dir)
    test $? -eq 0 || otsb_die "unable to create temporary directory"

    local destdir=$tmpdir/src
    mkdir "$destdir"

    mst_otsb_vcs $vcs clone "$src" "$destdir"
    test $? -eq 0 || otsb_die "error retrieving $src"

    case $version in

	choose )
	    local tags=( $(mst_otsb_vcs $vcs tags "$destdir" ) )
	    version=$(_mst_otsb_vcs_choose 'tag' "${tags[@]}")
	    ;;

	tip|head )
	    version=$(mst_otsb_vcs $vcs version "$destdir")
	    ;;

	latest )
	    local tags=( $(mst_otsb_vcs $vcs tags "$destdir" ) )
	    version=${tags[0]}
	    ;;

    esac

    test $? -eq 0 || otsb_die "error getting version for $package_name from $src; see $destdir"


    mst_otsb_vcs $vcs checkout "$destdir" "$version"
    test $? -eq 0 || otsb_die "error checking out version '$version'; see $destdir"

    if [ "$_fix_version" != '' ] ; then
	version=$($_fix_version "$version")
    fi

    local tarball

    if [ "$_pre_mktarball_hook" != '' ]; then
        ( cd "$destdir"; eval $_pre_mktarball_hook 2> pre-mktarball-hook.log >&2 )
        test $? -eq 0 \
            || otsb_die "error running pre-mktarball-hook for $package_name from $src; see $destdir/pre-mktarball-hook.log"
    fi

    if [ "$_mktarball" = '' ]; then
        local package=$package_name-$version
	tarball="$package.tar.gz"

	rsync -a $destdir/ $tmpdir/$package \
	    && tar -C $tmpdir --exclude-vcs -czf $tarball $package
    else

	tarball=$($_mktarball "$version" "$tmpdir" "$destdir")
    fi

    test $? -eq 0 || otsb_die "error generating tarball for $package_name from $src; see $destdir"

    /bin/rm -rf $tmpdir
    echo $tarball
}

# args: vcs src package_name branch/tag
mst_otsb_vcs_archive_from_clone  () {

    local tarball
    tarball=$(mst_otsb_vcs_tarball_from_clone "$@" )
    test $? -eq 0 || otsb_die "error retrieving tarball ($FUNCNAME ${@})"

    mst_otsb_set_latest_archive "$tarball"
}

mst_otsb_set_latest_archive () (

    local tarball=$1

    cd "$otsbv_import_root"

    rm -f latest				\
	&& ln -s "$tarball" latest		\
	&& unset otsbv_archive			\
	&& mst_otsb_set_archive

    test $? -eq 0 || otsb_die "$FUNCNAME: error setting latest archive to $tarball"
)
