#!/bin/bash
set -e

dkms_dir="$1"
abi_flavour="$2"
sign="$3"
pkgname="$4"
pkgdir="$5"
package="$6"
shift 6

here=$(dirname "$(readlink -f "${0}")")

srcdir=$(pwd)
cd "$dkms_dir" || exit 1

built_using_record()
{
	local subst="$1"
	local built_using="$2"
	if [ ! -f "$subst" ]; then
		touch "$subst"
	fi
	if ! grep -q -s "^linux:BuiltUsing=" "$subst"; then
		echo "linux:BuiltUsing=" >>"$subst"
	fi
	sed -i -e "s/^\(linux:BuiltUsing=.*\)/\1$built_using, /" "$subst"
}

# ABI: returns present in $? and located path in lpackage_path when found.
package_present()
{
	for lpackage_path in "$1"_*.deb
	do
		break
	done
	[ -f "$lpackage_path" ]
}

# Download and extract the DKMS package -- note there may be more
# than one package to install.
for package_path in "$@"
do
	package_file=$(basename "$package_path")
	echo "II: dkms-build downloading $package ($package_file)"
	rpackage=$( echo "$package_path" | sed -e 's@.*/@@' -e 's@_.*@@' )
	lpackage=$( echo "$rpackage" | sed -e 's@=.*@@' )

	while true
	do
		if package_present "$lpackage"; then
			break
		fi
		case "$package_path" in
		pool/*)
			# Attempt download from the launchpad librarian first.
			"$here/file-downloader" "https://launchpad.net/ubuntu/+archive/primary/+files/$package_file" || true
			if package_present "$lpackage"; then
				break
			fi

			# Download from the available pools.
			for pool in $( grep -h '^deb ' /etc/apt/sources.list /etc/apt/sources.list.d/*.list | awk '{print $2}' | sort -u )
			do
				if package_present "$lpackage"; then
					break
				fi
				url="$pool/$package_path"
				"$here/file-downloader" "$url" && break || true
				# No components in PPAs.
				url=$(echo "$url" | sed -e 's@/pool/[^/]*/@/pool/main/@')
				"$here/file-downloader" "$url" && break || true
			done
			;;
		http*:*)
			"$here/file-downloader" "$package_path"
			;;
		*/*)
			cp -p "$package_path" .
			;;
		*)
			apt-get download "$rpackage"
			;;
		esac
		break
	done
	if ! package_present "$lpackage"; then
		echo "EE: $lpackage not found"
		exit 1
	fi

	dpkg -x "$lpackage"_*.deb "$package"

	lversion=$( echo "$lpackage_path" | sed -e 's@.*/@@' -e 's@_[^_]*$@@' -e 's@.*_@@')
	#built_using_record "$srcdir/debian/$pkgname.substvars" "$built_using$lpackage (= $lversion)"
done

# Pick out the package/version from the dkms.conf.
for dkms_conf in "$package/usr/src"/*/"dkms.conf"
do
	break
done
# It seems some packages have a # in the name which works fine if the
# package is installed directly, but not so much if we build it out
# of the normal location.
sed -i -e '/^PACKAGE_NAME=/ s/#//g' "$dkms_conf"
cat - <<'EOF' >>"$dkms_conf"
POST_BUILD="ubuntu-save-objects ${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build ${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/objects $POST_BUILD"
EOF
ubuntu_script="$(dirname "$dkms_conf")/ubuntu-save-objects"
cat - <<'EOF' >"$ubuntu_script"
#!/bin/sh
from="$1"
to="$2"
script="$3"
shift 2

# Copy the objects.
echo "II: copying objects to '$to'"
mkdir -p "$to"
(cd "$from" && find -name \*.o -o -name \*.o.ur-\* | cpio -Lpd "$to")

# Call the original post_install script if there is one.
[ "$script" = '' ] && exit 0

shift
exec "$(dirname "$0")/$script" "$@"
EOF
chmod +x "$ubuntu_script"
dkms_package=$( sed -ne 's/PACKAGE_NAME="\(.*\)"/\1/p' "$dkms_conf" )
dkms_version=$( sed -ne 's/PACKAGE_VERSION="\(.*\)"/\1/p' "$dkms_conf" )

# Build the DKMS binaries.
echo "II: dkms-build building $package"
rc=0
/usr/sbin/dkms build --no-prepare-kernel --no-clean-kernel \
	-k "$abi_flavour" \
	--sourcetree "$dkms_dir/source" \
	--dkmstree "$dkms_dir/build" \
	--kernelsourcedir "$dkms_dir/headers/linux-headers-$abi_flavour" \
	"$dkms_conf" || rc=1

# Find the log and add it to our own.
for log in "$dkms_dir/build/$dkms_package/$dkms_version/$abi_flavour"/*/"log/make.log"
do
	break
done
sed -e "s@$dkms_dir@<<DKMSDIR>>@g" <"$log"

# If this build failed then exit here.
[ "$rc" != 0 ] && exit "$rc"

# Install and optionally sign the modules we have built.
pkgdir="$pkgdir/$package"
echo "II: dkms-build installing $package into $pkgdir"
install -d "$pkgdir"
find "$dkms_dir/build/$dkms_package/$dkms_version/$abi_version" -name \*.ko |
while read module; do
	vmodule=$( basename "$module" )
	case "$sign" in
	--*)
		echo "copying $vmodule"
		cp "$module" "$pkgdir"
		;;
	*)
		echo "signing $vmodule"
		$sign "$module" "$pkgdir/$vmodule"
		;;
	esac
done

find "$dkms_dir/build/$dkms_package/$dkms_version/objects" -name \*.o -print | \
while read object
do
	"$srcdir/debian/scripts/fix-filenames" "$object" "$dkms_dir"
done

# Finally see if there is a dkms-package specific post processor present.  Hand
# it the original source directory, destination package directory, the objects
# as squirreled away, and the log in case it is useful.  Finally pass a formed
# signing command line in case we need to do that.
dkms_build_specific="$srcdir/$0--$package"
dkms_build_generic=$(echo "$dkms_build_specific" | sed -e 's/-[0-9][0-9]*$/-N/')
for dkms_build in "$dkms_build_specific" "$dkms_build_generic"
do
	if [ ! -e "$dkms_build" ]; then
		continue
	fi
	echo "II: dkms-build override $(basename "$dkms_build") found, executing"
	$SHELL "$dkms_build" \
		"$srcdir" \
		"$dkms_dir/build/$dkms_package/$dkms_version/objects" \
		"$log" \
		"$dkms_dir" \
		"$abi_flavour" \
		"$sign" \
		"$pkgname" \
		"$pkgdir" \
		"$package" \
		"$@" || exit 1
	break
done

echo "II: dkms-build build $package complete"
