#!/bin/bash

PTX_PATCHES_HEADER="# generated by git-ptx-patches"

function _md5sum() {
	local sum=$(md5sum)
	echo "# $sum git-ptx-patches magic"
}

if [ ! -L .ptxdist/patches ]; then
	echo "Error: This is not patched by ptxdist. Aborting."
	exit 1
fi

if [ ! -L .ptxdist/series ]; then
	echo "Error: .ptxdist/series must be a symbolic link. Aborting."
	exit 1
fi

remove_old=no
tag=base

if grep -q "$PTX_PATCHES_HEADER" .ptxdist/series; then
	echo "Found series file generated by git-ptx-patches."
	lines=$(cat .ptxdist/series | wc -l)
	lines=$[lines-1]
	magic=$(head -n$lines .ptxdist/series | _md5sum)
	if grep -q "^$magic" .ptxdist/series; then
		remove_old=yes
	else
		echo "Warning: .ptxdist/series was modified."
	fi
fi

if [ "x$1" = "x--force-remove" ]; then
	remove_old="force"
	shift
fi

while getopts "ft:n:" opt; do
	case "${opt}" in
		f)
			remove_old="force"
			;;
		t)
			tag="${OPTARG}"
			range="${tag}"
			;;
	esac
done
shift $((${OPTIND} - 1))

tag2=$(grep "#tag:" .ptxdist/series | awk "/#tag:${tag}/{if (getline) print \$1}" | sed 's,#tag:,,')
range="${tag}..${tag2}"

echo "$PTX_PATCHES_HEADER" > .ptxdist/series.0
:> .ptxdist/series.1
if grep -q "^#tag:" .ptxdist/series; then
	tagline=$(grep "#tag:${tag}" .ptxdist/series)
	t=$(echo "${tagline}"|cut -d' ' -f1)
	if [ "#tag:${tag}" == "${t}" ]; then
		tagopt=$(echo "${tagline}"|cut -d' ' -s -f2-)
		sed -e "/$PTX_PATCHES_HEADER/d" -n -e "0,/#tag:${tag}/p" .ptxdist/series >> .ptxdist/series.0
		# Remove patches before #tag:${tag} so they don't get rm'd with remove_old=yes
		sed -i --follow-symlinks "0,/#tag:${tag}/d" .ptxdist/series
		if [ -n "${tag2}" ]; then
			sed -n -e "/#tag:${tag2}/,/git-ptx-patches magic/p" .ptxdist/series > .ptxdist/series.1
			sed -i "/git-ptx-patches magic/d" .ptxdist/series.1
			sed -i --follow-symlinks "/#tag:${tag2}/,/git-ptx-patches magic/d" .ptxdist/series
		fi
	else
		echo "series contains #tag:* lines, but could not find #tag:${tag} line in series. Aborting."
		exit 1
	fi
else
	if [ "${tag}" != "base" ]; then
		echo "When using series with no #tag:* lines, you must use base tag."
		exit 1
	fi
	echo "#tag:${tag} --start-number 1" >> .ptxdist/series.0
fi

case "$remove_old" in
	"no") ;;
	"yes")
		echo "Removing old patches ..."
		while read patch para; do
			case "${patch}" in
				""|"#"*) continue ;;
				*) rm .ptxdist/patches/$patch ;;
			esac
		done < .ptxdist/series
		;;
	"force")
		echo "Removing old patches (forced) ..."
		find .ptxdist/patches/ | while read file; do
			case "$file" in
				".ptxdist/patches/") continue ;;
				".ptxdist/patches/series") continue ;;
				".ptxdist/patches/autogen.sh") continue ;;
				*)
					if grep -q "${file##\.ptxdist/patches/}" .ptxdist/series.{0,1}; then
						echo "Keep base patch ${file}"
					else
						rm -rf "$file"
					fi
					;;
			esac
		done
		;;
esac

if git format-patch -h 2>&1 | grep -q signature; then
	GIT_EXTRA_ARGS="--no-signature"
fi

cat .ptxdist/series.0 > .ptxdist/series
git format-patch -N $GIT_EXTRA_ARGS ${tagopt} -o .ptxdist/patches/ ${range} | sed -e 's,^.ptxdist/patches/,,' > .ptxdist/series.auto
cat .ptxdist/series.auto >> .ptxdist/series
cat .ptxdist/series.1 >> .ptxdist/series
cat .ptxdist/series | _md5sum >> .ptxdist/series

# The first line of the patch is 'From <some-git-hash> ...'
# remove it to avoid unnecessary changes in the patch files.
find .ptxdist/patches/ ! -type d | sed -e 's,^.ptxdist/patches/,,' | \
while read patch para; do
	case "$patch" in
		"series"|"autogen.sh") continue ;;
		*) ;;
	esac
	if grep -q "$patch" .ptxdist/series.auto; then
		p=".ptxdist/patches/$patch"
		tail -n+2 "$p" > ".$patch.ptx-patches"
		mv ".$patch.ptx-patches" "$p"
	else
		if grep -q "$patch" .ptxdist/series.{0,1}; then
			echo "Base patch \"$patch\"!"
		else
			echo "Old patch \"$patch\"!"
		fi
	fi
done | sort
