#!/bin/sh

set -e

# Script to semi-automate updating Devuan forked packages.
# Optional argument is git tag to merge

suite=unstable

exit_with_msg()
{
    echo "$1"
    exit $2
}

usage()
{
    exit_with_msg "Usage: $0 [ -b ] [ -t ] [ -f ] [ -s suite ] [ <hint> ]" 2
}

# parse command line
while getopts ftbs: opt
do
    case $opt in
	b) do_build=$opt;;
	t) do_tag=$opt;;
	f) force=$opt;;
	s) suite=$OPTARG;;
      \?) usage;;
    esac
done

shift $(($OPTIND - 1))

[ $# -gt 1 ] && usage

git rev-parse --is-inside-work-tree >/dev/null || {
    echo Not a git repository
    exit 1
}

expand_gbp_config ()
{
    f=$(gbp config "$1")
    expansions="{
    		  'pkg': '$(dpkg-parsechangelog -S Source)',
    		  'version': '$(dpkg-parsechangelog -S Version | cut -d: -f2- | tr "~" "_")'
	        }"

    python3 -c "print('$f' % $expansions)"
}

debian_get_dsc()
{
    url=$1
    curl -fSs $url
}

deb822_get()
{
    grep "^$1:" | cut -d: -f2- | sed 's/^[[:space:]]*//'
}

git_remote_name()
{
    vcs_git=$1
    for u in $vcs_git $(echo $vcs_git | sed 's#^http.\?://#git@#; s#/#:#') # Try both http:// and git@ schemes
    do
	match=$(git remote -v | grep $u | cut -f1 | uniq)
	[ -z "$match" ] || {
	    echo "$match" && break
	}
    done
}

debian_dsc_url()
{
    p=$1
    v=$2
    pfx=$(echo $p | grep --only-matching '^\(lib\)\?.')
    printf "http://deb.debian.org/debian/pool/main/%s/%s/%s_%s.dsc" $pfx $p $p ${v#*:}
}

debian_suite()
{
    suite=$1

    case $suite in
	jessie|experimental|*stable|testing)
	    deb_suite=$suite
	    ;;
	*)
	    debian_jessie=8
	    ascii_a=97
	    debian_v=$(($(printf "%d" "'$suite") - $ascii_a + $debian_jessie + 1))
	    sub_suite=${suite#*-}
	    deb_suite=$(awk -F, "\$1==\"$debian_v\" { print \$3 }" /usr/share/distro-info/debian.csv)${sub_suite:+-${sub_suite}}
	    ;;
    esac
    [ -z "$deb_suite" ] && exit_with_msg 'Failed to find Debian suite codename' 1
    echo $deb_suite
}

debian_version()
{
    src=$1
    suite=$2
    rmadison -s $suite -a source $src | cut -d'|' -f2 | sort -n | tail -1 | tr -d '[:space:]'
}

importdsc()
{
    debian_branch=$1
    url=$2

    gbp import-dsc --debian-tag='debian/%(version)s' --debian-branch=$debian_branch $url
}

cd $(git rev-parse --show-toplevel)

[ -z "$(git status --porcelain)" ] || {
    echo "ERROR: Tree not clean." && exit_with_msg "$(git status)" 1
}

devuan_remote=$(git_remote_name 'https://git.devuan.org/devuan')
[ -z "${devuan_remote}" ] && exit_with_msg 'Devuan remote not found' 1

git fetch $devuan_remote

git checkout suites/$suite

grep -q '^Origin: \+Devuan' debian/control || exit_with_msg "d/control missing Origin: Devuan. Is this a Devuan package?" 1

git pull --ff-only ${devuan_remote} suites/$suite

src=$(dpkg-parsechangelog -S Source)

[ -z "$(rmadison -u https://api.pkginfo.devuan.org/madison -s $suite -a source $src)" ] && exit_with_msg "Source $src not present in Devuan $suite" 1

debian_version=$(debian_version $src $(debian_suite $suite))
devuan_version=$(dpkg-parsechangelog -S Version)

if [ $(git cat-file -p HEAD | grep ^parent -c) -gt 1 -a "${debian_version}" = "${devuan_version}" ]
then
    echo Found manually resolved merge. Going to release.
else
    dpkg --compare-versions $debian_version gt $devuan_version  || \
	exit_with_msg "Devuan src:$src/$devuan_version in suites/$suite already up to date with Debian version $debian_version."

    echo Updating src:$src $devuan_version to Debian version: $debian_version.
fi

debian_dsc=$(debian_get_dsc $(debian_dsc_url $src $debian_version))
debian_git=$(echo "$debian_dsc" | deb822_get Vcs-Git)

if [ -z "$debian_git" ]
then

    debian_branch=debian/master
    debian_tag=debian/$debian_version
    git show-ref --tags $debian_tag --quiet || \
	importdsc $debian_branch $(debian_dsc_url $src $debian_version) || \
	exit_with_msg "If verification has failed install debian-keyring package or set DGET_VERIFY=no in ~/.devscripts." 1

else

    debian_remote=$(git_remote_name $debian_git)
    [ -z "${debian_remote}" ] && {
	debian_remote=debian
	echo Debian git remote not found, adding $debian_git as $debian_remote
	git remote add $debian_remote $debian_git
    }
    git fetch $debian_remote
    debian_branch=$(git remote show $debian_remote |  grep 'HEAD branch' | cut -d' ' -f5)
    debian_tag=${1:-$(git tag -l $debian_remote/$debian_branch "*$(echo $debian_version|tr ':~' '%_')")}
    if [ -z "$debian_tag" ]
    then
	if [ -n "$force" ]
	then
	    common_ancestor=$(git merge-base suites/$suite $debian_branch)
	    debian_branch=debian/$debian_version
	    git branch $debian_branch $common_ancestor
	    importdsc $debian_branch $(debian_dsc_url $src $debian_version)
	    debian_tag=debian/$debian_version
	else
	    debian_maintainer="$(echo "$debian_dsc" | deb822_get Maintainer)"
	    echo "Tag matching $debian_version not found in $debian_remote/$debian_branch."
	    echo "Specify tag on command line or"
	    echo "specify -f to import dsc or"
	    exit_with_msg "request '$debian_maintainer' to update repostory at $debian_git." 1
	fi
    fi

    echo "Trying tag $debian_tag."
fi

git show-ref --tags $debian_tag --quiet || \
    exit_with_msg "Tag $debian_tag not found" 1

[ "$(git check-attr -a debian/changelog)" = 'debian/changelog: merge: dpkg-mergechangelogs' ] || {
    echo Setting up debian/changelog to use dpkg-mergechangelogs
    echo debian/changelog merge=dpkg-mergechangelogs >> .git/info/attributes
}

git merge $debian_tag || {
    echo 'Fixup and commit merge manually'
    exit_with_msg "Then re-run $0" 1
}

grep -q '1.0\|native' debian/source/format || \
    git push ${devuan_remote} $(expand_gbp_config buildpackage.upstream-tag | sed 's/-[^-]*$//')

if [ -n "$(quilt series)" ]
then
    quilt push -a
    quilt pop -a
    rm -r .pc/
fi

devuan_version="${debian_version}devuan1"
dch --newversion ${devuan_version} "Merge tag $debian_tag."
dch --release --no-force-save-on-release ${suite:+--distribution ${suite}}
git commit -m "Version ${devuan_version}." debian/changelog

[ -z "$do_build" ] || \
    gbp buildpackage

[ -z "$do_tag" ] || \
    gbp buildpackage --git-tag-only
