#!/bin/bash
# Repackage a Debian source tree for dh-openrc 1.0.2 (openrc-helper).
#
# Usage:
#   dh-openrc-repack <paquete>
#
# Example:
#   dh-openrc-repack alsa-utils    # works in ~/ALSA-UTILS
#
# Install:
#   sudo install -m 755 dh-openrc-repack /usr/bin/dh-openrc-repack

set -euo pipefail

readonly PROG="${0##*/}"
readonly GIT_NAME="Aitor Cuadrado Zubizarreta"
readonly GIT_EMAIL="aitor@genuen.org"
readonly PACKAGER_EMAIL="aitor@genuen.org"
readonly GBP_KEY="DF796A7247135DA9471FC5B872623EE3A542DC5B"
# Changelog bullet text (without leading "*"). Use \n for a wrapped continuation line.
readonly CHANGELOG_ENTRY=$'Rebuild with dh-openrc 1.0.2: depend on openrc-helper instead of\nopenrc, so system upgrades no longer block openrc updates.'

usage() {
	cat <<EOF
Usage: ${PROG} <paquete>

Uses ~/<PAQUETE> as working directory, where <PAQUETE> is the package
name in uppercase (e.g. alsa-utils -> ~/ALSA-UTILS).

Example:
  ${PROG} alsa-utils
EOF
}

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

need_cmd() {
	command -v "$1" >/dev/null 2>&1 || die "required command not found: $1"
}

clean_build_area() {
	local dir="$1"
	local pattern f removed=0

	for pattern in '*-dbgsym_*.deb' '*.build' '*.buildinfo' '*.changes'; do
		shopt -s nullglob
		for f in "${dir}"/${pattern}; do
			rm -f -- "${f}"
			removed=1
		done
		shopt -u nullglob
	done

	if (( removed )); then
		echo "==> Removed dbgsym packages and build metadata from ${dir}"
	fi
}

format_top_changelog_entry() {
	local changelog="${1}"
	local bullet="${2}"

	need_cmd awk

	# Allow "\n" in single-quoted strings too.
	bullet="${bullet//\\n/$'\n'}"

	awk -v bullet="${bullet}" '
		function print_bullet(text,    n, lines, i) {
			n = split(text, lines, "\n")
			print "  * " lines[1]
			for (i = 2; i <= n; i++) {
				if (lines[i] != "") {
					print "    " lines[i]
				}
			}
		}
		BEGIN { in_first = 1; skipping_body = 0 }
		in_first && /^ -- / {
			in_first = 0
			skipping_body = 0
			print
			next
		}
		in_first && skipping_body { next }
		in_first && /\([^)]+\).*; urgency=/ {
			print
			print ""
			print_bullet(bullet)
			print ""
			skipping_body = 1
			next
		}
		{ print }
	' "${changelog}" > "${changelog}.tmp"
	mv "${changelog}.tmp" "${changelog}"
}

main() {
	local package="${1:-}"
	local work_dir pkg_dir dsc_file current_version new_version

	[[ -n "${package}" ]] || { usage; exit 1; }
	[[ "${package}" =~ ^[a-z0-9][a-z0-9.+:-]*$ ]] || die "invalid package name: ${package}"

	work_dir="${HOME}/$(echo "${package}" | tr '[:lower:]' '[:upper:]')"

	need_cmd git
	need_cmd gbp
	need_cmd apt-get
	need_cmd sed
	need_cmd dpkg-parsechangelog

	mkdir -p "${work_dir}"
	cd "${work_dir}" || die "cannot enter ${work_dir}"

	echo "==> Working directory: ${work_dir}"
	echo "==> Downloading source for ${package} from the repository"
	apt-get source "${package}"

	pkg_dir="${work_dir}/${package}"
	mkdir -p "${pkg_dir}"
	cd "${pkg_dir}" || die "cannot enter ${pkg_dir}"

	if [[ ! -d .git ]]; then
		echo "==> Initializing git repository"
		git init
	fi

	git config user.name "${GIT_NAME}"
	git config user.email "${GIT_EMAIL}"
	export DEBEMAIL="${PACKAGER_EMAIL}"

	dsc_file="$(find "${work_dir}" -maxdepth 1 -name "${package}_*.dsc" -type f | sort | tail -n 1)"
	[[ -n "${dsc_file}" ]] || die "no .dsc found in ${work_dir} for ${package}"
	echo "==> Importing ${dsc_file}"
	gbp import-dsc --pristine-tar "${dsc_file}"

	[[ -f debian/control ]] || die "debian/control not found after import"

	if grep -q 'dh-openrc' debian/control; then
		echo "==> Updating dh-openrc build dependency to >= 1.0.2"
		sed -i \
			-e 's/dh-openrc (>= 1\.0\.[0-9][^)]*)/dh-openrc (>= 1.0.2)/g' \
			-e 's/dh-openrc,/dh-openrc (>= 1.0.2),/g' \
			debian/control
	else
		echo "${PROG}: warning: debian/control has no dh-openrc build dependency" >&2
	fi

	if ! grep -qE 'dh .*--with .*openrc|--with=.*openrc' debian/rules 2>/dev/null; then
		echo "${PROG}: warning: debian/rules does not appear to use dh --with openrc" >&2
	fi

	echo "==> Recording rebuild rationale in git"
	git add -A
	if git diff --cached --quiet; then
		echo "${PROG}: warning: no changes to commit before gbp dch" >&2
	else
		git commit -m "${CHANGELOG_ENTRY%%$'\n'*}"
	fi

	current_version="$(dpkg-parsechangelog -S Version)"
	echo
	echo "Versión actual en debian/changelog: ${current_version}"
	echo
	read -rp "Nueva versión: " new_version
	[[ -n "${new_version}" ]] || die "new version cannot be empty"

	echo "==> Creating changelog entry"
	echo "    gbp dch --ignore-branch --auto --full --new-version=${new_version}"
	gbp dch --ignore-branch --auto --full --new-version="${new_version}"

	echo "==> Tidying debian/changelog"
	sed -i \
		-e 's/ UNRELEASED;/ unstable;/g' \
		-e 's/ UNRELEASED$/ unstable/' \
		-e '/^  \[ .* \]$/d' \
		debian/changelog
	format_top_changelog_entry debian/changelog "${CHANGELOG_ENTRY}"

	git add -A
	git commit -a -m "Set distribution to unstable"

	mkdir -p "${work_dir}/build-area"
	echo "==> Building package"
	gbp buildpackage -j4 -tc \
		--git-export-dir="../build-area" \
		--git-ignore-branch \
		-k"${GBP_KEY}" \
		--git-pristine-tar

	clean_build_area "${work_dir}/build-area"

	echo
	echo "Done. Binary packages should be in ${work_dir}/build-area/"
}

main "$@"
