#!/bin/bash -e
#
# This script is intended as a helper when closing a release.
#
source debian/debian.env

# Parse args
usage="$0 [-c] [-d] [-s]"$'\n\n'
usage+="-c 			Include config changes in the closing commit."$'\n'
usage+="-d 			Dry run (do not change files or commit)."$'\n'
usage+="-s 			Skip master kernel changelog entries (used when bootstraping new kernels)."
while getopts "cds" opt; do
	case $opt in
	c) commit_configs=1 ;;
	d) dry_run=1 ;;
	s) skip_master_entries=1 ;;
	*) echo usage: "${usage}"; exit ;;
	esac
done

hl() { echo -e "\e[1m$*\e[0m"; }

run() {
	# Quote args for echo or eval
	local quoted=()
	for token; do
		quoted+=( "$(printf '%q' "$token")" )
	done
	# Run
	if [ "$dry_run" ]; then
		hl "DRY RUN: ${quoted[*]}"
	else
		hl "${quoted[*]}"
		eval "${quoted[*]}"
		echo
	fi
}

# Check if the "debian.<branch>/" directory exists.
if [ ! -d "$DEBIAN" ]; then
	echo "You must run this script from the top directory of this repository."
	exit 1
fi
branch="${DEBIAN#*.}"

# Check if changelog is open
series=$(dpkg-parsechangelog -l"$DEBIAN/changelog" -SDistribution)
if [ "$series" != 'UNRELEASED' ]; then
	echo "The last entry of the changelog is already released."
	exit 1
fi

# Update configs
run fakeroot debian/rules clean updateconfigs
changes=$(git diff HEAD -- "./$DEBIAN/config/")
if ! [ "$commit_configs" ] && [ "$changes" ]; then
	echo "Config has changed! please, review it and commit."
	exit 1
fi

# Derivatives have at least one base kernel.
if [ "$branch" != 'master' ]; then
	# For backports, insert the changes from the base derivative.
	# Straight derivatives and backports such as hwe and hwe-edge, should
	# skip that step and fetch the entries directly from the master kernel.
	version=$(dpkg-parsechangelog -l"$DEBIAN/changelog" -SVersion)
	if [[ $version == *~* ]]; then
		base_version=$(dpkg-parsechangelog -l"$DEBIAN/changelog" -SVersion -c1 -o1)
		base_changelog="${DEBIAN%-*}/changelog"
		if [ -f "$base_changelog" ] && [ "$DEBIAN" != "${DEBIAN%-*}" ]; then
			run ./debian/scripts/misc/insert-ubuntu-changes "$DEBIAN/changelog" "${base_version%%~*}" "${version%%~*}" "$base_changelog"
			skip_master_entries=1
		fi
	fi

	if ! [ "$skip_master_entries" ]; then
	    offset=0
	    # Loop through each entry of the current changelog, searching for an
	    # entry that refers to the master version used as base (ie a line
	    # containing "[ Ubuntu: 4.15.0-39.42 ]"):
	    while true; do
		    changes=$(dpkg-parsechangelog -l"$DEBIAN/changelog" -SChanges -c1 -o"$offset")
		    if ! [ "$changes" ]; then
			    echo "Failed to retrieve base master version from changelog file: $DEBIAN/changelog"
			    exit 1
		    fi
		    base_master_version=$(echo "$changes" | sed -n -r -e '/^\s.*\[ Ubuntu: ([0-9.-]*) \]$/{s//\1/p;q}')
		    [ "$base_master_version" ] && break
		    offset=$(( offset + 1 ))
	    done
	    master_version=$(dpkg-parsechangelog -ldebian.master/changelog -SVersion)
	    if ! [ "$master_version" ]; then
		    echo "Failed to retrieve current master version from changelog: $DEBIAN/changelog"
		    exit 1
	    fi
	    run ./debian/scripts/misc/insert-ubuntu-changes "$DEBIAN/changelog" "$base_master_version" "$master_version"
	fi
fi

# Insert local changes
run fakeroot debian/rules insertchanges

# This should be the last step. If there were no changes to the
# changelog, there is nothing to release, so nothing to commit.
changes=$(git diff HEAD)
if ! [ "$changes" ] && ! [ "$dry_run" ]; then
	hl "No changes to commit."
	exit 1
fi

# Find the current series from previous changelog entries:
series=''
offset=0
while true; do
	series=$(dpkg-parsechangelog -l"$DEBIAN/changelog" -SDistribution -c1 -o"$offset")
	if [ "$series" ] && [ "$series" != 'UNRELEASED' ]; then
		break
	fi
	offset=$(( offset + 1 ))
done
if ! [ "$series" ]; then
	echo "Failed to retrieve the package series from changelog: $DEBIAN/changelog"
	exit 1
fi
# Close the changelog
run dch --nomultimaint -c "$DEBIAN/changelog" -r -D "$series" ''

# Commit changes
package=$(dpkg-parsechangelog -l"$DEBIAN/changelog" -SSource)
prefix="Ubuntu$(echo "$package" | sed -r -e 's/linux(-?)/\1/')-"
version=$(dpkg-parsechangelog -l"$DEBIAN/changelog" -SVersion)
run git commit -sam "UBUNTU: $prefix$version"

# This should only show the tag. If it starts tagging, we might revisit
# where it is called, or not fail if it points to the same thing, and
# warns/errors out if the tag exists, but do not point to the same
# thing.
alt_version="${version//\~/_}"
head=$(git rev-parse HEAD)
echo "git tag -sm '$prefix$version' '$prefix$alt_version' $head"
