#!/bin/sh
# n: semi-automate a new upstream OpenStack release for the Debian package in
# the current directory, as driven by the osbpo deb-status page. The osbpo
# release name is derived from the current debian/<release> git branch.
# Usage, from inside the package's git checkout:  n [source-package-name]

set -e

PKG=${1:-$(basename "$PWD")}
SAVED_STTY=
WORKDIR=

die () {
	echo "E: $*" >&2
	exit 1
}

cleanup () {
	if [ -n "$SAVED_STTY" ]; then
		stty "$SAVED_STTY" 2>/dev/null || true
	fi
	if [ -n "$WORKDIR" ]; then
		rm -rf "$WORKDIR"
	fi
}

[ -f debian/changelog ] || die "$PWD has no debian/changelog: not a package checkout."
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || die "$PWD is not a git checkout."
BRANCH=$(git rev-parse --abbrev-ref HEAD)
case "$BRANCH" in
debian/*)
	RELEASE=${BRANCH#debian/}
	;;
*)
	die "cannot derive the OpenStack release from branch '$BRANCH' (expected debian/<release>)."
	;;
esac
STATUS_URL=${OSBPO_STATUS_URL:-https://osbpo.debian.net/deb-status/trixie-${RELEASE}.html}

echo "==> $PKG: checking $STATUS_URL"
WORKDIR=$(mktemp -d "${TMPDIR:-/tmp}/n.XXXXXX")
trap cleanup EXIT
curl -fsSL "$STATUS_URL" >"$WORKDIR/page.html" || die "could not fetch $STATUS_URL"

ROW=$(awk -v pkg="$PKG" '
	/<tr class=/ {
		cls = $0
		sub(/^.*class="/, "", cls)
		sub(/".*$/, "", cls)
		n = 0
	}
	/<td>/ {
		line = $0
		gsub(/<[^>]*>/, "", line)
		sub(/^[ \t]+/, "", line)
		sub(/[ \t]+$/, "", line)
		v[++n] = line
	}
	/<\/tr>/ {
		if (v[2] == pkg) {
			print v[3], v[5], v[6]
			exit
		}
	}
' "$WORKDIR/page.html")
[ -n "$ROW" ] || die "$PKG not found on the status page (excluded from packaging?)."

set -- $ROW
DEBVER_PAGE=$1
UPSTREAM=$2
STATUS=$3
echo "==> $PKG: Debian $DEBVER_PAGE / upstream $UPSTREAM (status: $STATUS)"

case "$STATUS" in
OK)
	echo "I: $PKG is already up to date, nothing to do."
	exit 0
	;;
MISSING)
	die "$PKG is missing from Debian: initial packaging must be done by hand."
	;;
esac

CURVER=$(dpkg-parsechangelog -SVersion)
case "$CURVER" in
*:*)
	EPOCH=${CURVER%%:*}:
	;;
*)
	EPOCH=
	;;
esac
TARGET=${EPOCH}${UPSTREAM}-1
if dpkg --compare-versions "$CURVER" ge "$TARGET"; then
	echo "I: $PKG is already at $CURVER locally (>= $TARGET): nothing to do (osbpo may not have picked up the upload yet)."
	exit 0
fi

[ -z "$(git status --porcelain)" ] || die "work tree not clean: commit or stash first."

echo "==> Fetching upstream tags"
./debian/rules fetch-upstream-remote || die "fetch-upstream-remote failed."

if ! git rev-parse -q --verify "refs/tags/$UPSTREAM" >/dev/null; then
	die "tag $UPSTREAM not found after fetch (check: git tag -l | grep -F $UPSTREAM)."
fi

echo "==> Merging tag $UPSTREAM"
if ! git merge --no-edit -X theirs "$UPSTREAM"; then
	git merge --abort 2>/dev/null || true
	die "merge of $UPSTREAM failed: resolve manually."
fi

echo "==> Bumping changelog to $TARGET"
dch --newversion "$TARGET" -m "New upstream release." --distribution unstable || die "dch failed."

git --no-pager diff -u

printf '\n==> Review the debian/changelog diff above. Type y to commit it, build, tag/push and upload (any other key aborts): '
SAVED_STTY=$(stty -g 2>/dev/null) || die "cannot prompt for confirmation without a tty."
stty raw -echo min 1 time 0
KEY=$(dd bs=1 count=1 2>/dev/null) || true
stty "$SAVED_STTY"
SAVED_STTY=
echo "$KEY"
if [ "$KEY" != "y" ]; then
	die "aborted: the $TARGET changelog entry is left uncommitted (revert with: git checkout debian/changelog)."
fi

echo "==> Committing changelog"
git commit -m "New upstream release." debian/changelog || die "commit failed."

echo "==> Generating orig tarball for $UPSTREAM"
./debian/rules gen-orig-xz || die "gen-orig-xz failed."

echo "==> Building with gbp buildpackage"
if ! gbp buildpackage; then
	die "build failed: fix, then continue by hand with gbp buildpackage, then tag/push and upload."
fi

echo "==> Tagging and pushing"
DEBVER=$(dpkg-parsechangelog -SVersion)
DEBVER_NO_EPOCH=$(echo "$DEBVER" | sed -e 's/^[[:digit:]]*://' -e 's/~/_/g')
git tag -s "debian/${DEBVER_NO_EPOCH}" -m "Debian release ${DEBVER}"
git push
git push --tags

echo "==> Uploading"
cd ../build-area
CHANGES_FILE=$(ls -tr *.changes | tail -n 1)
debsign --re-sign -k 'A0B1A9F3508956130E7A425CD416AD15AC6B43FE!' "$CHANGES_FILE"
dput "$CHANGES_FILE"
echo "I: $PKG updated to $TARGET."
