#!/hint/bash
. "lib/common.bash"

httpserver() {
	read -r verb path version || exit
	if [[ $verb != GET ]]; then
		printf "HTTP/1.1 405 Method Not Allowed\\r\\nContent-Type: text/plain\\r\\nContent-length: 0\\r\\n\\r\\n"
		exit
	fi
	path="$(cd / && realpath -ms "$path")"
	if ! [[ -f "$1/$path" ]]; then
		printf "HTTP/1.1 404 Not found\\r\\nContent-Type: text/plain\\r\\nContent-length: 0\\r\\n\\r\\n"
		exit
	fi
	printf "HTTP/1.1 200 OK\\r\\nContent-Type: text/plain\\r\\nContent-length: %d\\r\\n\\r\\n" "$(stat -L -c %s "$1/$path")"
	cat "$1/$path"
}

eval "__common_$(declare -f setup)"
setup() {
	__common_setup
	local repo arch

	# Set up rsync server
	cat <<-eot >"${TMP}/rsyncd.conf"
		use chroot = no
		[rsyncd]
		  path = ${TMP}/rsyncd
	eot
	local rsyncport
	rsyncport=$(./lib/runserver "$TMP/rsyncd.pid" \
		rsync --daemon --config "${TMP}/rsyncd.conf")

	# Set up rsync contents
	for repo in core core-testing; do
		mkdir -p -- "${TMP}/rsyncd/archlinux/${repo}/os/x86_64"
		touch -- "${TMP}/rsyncd/archlinux/${repo}/os/x86_64/${repo}.db.tar.gz"
		ln -sT -- "${repo}.db.tar.gz" "${TMP}/rsyncd/archlinux/${repo}/os/x86_64/${repo}.db"
	done
	mkdir -p -- "${TMP}/rsyncd/archlinux"/{pool,sources}/{packages,community}
	date +%s > "${TMP}/rsyncd/archlinux/lastupdate"
	date +%s > "${TMP}/rsyncd/archlinux/lastsync"

	for repo in core core-testing community community-testing; do
		mkdir -p -- "${TMP}/rsyncd/archlinux32/i686/${repo}"
		touch -- "${TMP}/rsyncd/archlinux32/i686/${repo}/${repo}.db.tar.gz"
		ln -sT -- "${repo}.db.tar.gz" "${TMP}/rsyncd/archlinux32/i686/${repo}/${repo}.db"
	done
	mkdir -p -- "${TMP}/rsyncd/archlinux32/pool"
	date +%s > "${TMP}/rsyncd/archlinux32/lastupdate"
	date +%s > "${TMP}/rsyncd/archlinux32/lastsync"

	for repo in core core-testing community community-testing; do
		mkdir -p -- "${TMP}/rsyncd/archlinuxarm/armv7h/${repo}"
		touch -- "${TMP}/rsyncd/archlinuxarm/armv7h/${repo}/${repo}.db.tar.gz"
		ln -sT -- "${repo}.db.tar.gz" "${TMP}/rsyncd/archlinuxarm/armv7h/${repo}/${repo}.db"
	done
	date +%s > "${TMP}/rsyncd/archlinuxarm/lastupdate"
	date +%s > "${TMP}/rsyncd/archlinuxarm/lastsync"

	# Configure db-import to use that rsyncd server
	sed -i /STAGING=/d "${TMP}/config.local"
	cat <<-eot >"${TMP}/config.local.packages"
		source ${DBSCRIPTS_CONFIG@Q}
		source ../config.local.packages
		ARCHTAGS=('core-x86_64' 'core-testing-x86_64')
		ARCHMIRROR=rsync://localhost:${rsyncport@Q}/rsyncd/archlinux/
	eot
	cat <<-eot >"${TMP}/config.local.community"
		source ${DBSCRIPTS_CONFIG@Q}
		source ../config.local.community
		ARCHTAGS=('community-x86_64' 'community-testing-x86_64')
		ARCHMIRROR=rsync://localhost:${rsyncport@Q}/rsyncd/archlinux/
	eot
	cat <<-eot >"${TMP}/config.local.archlinux32"
		source ${DBSCRIPTS_CONFIG@Q}
		source ../config.local.archlinux32
		ARCHTAGS=('core-i686' 'core-testing-i686' 'community-i686' 'community-testing-i686')
		ARCHMIRROR=rsync://localhost:${rsyncport@Q}/rsyncd/archlinux32/
	eot
	cat <<-eot >"${TMP}/config.local.archlinuxarm"
		source ${DBSCRIPTS_CONFIG@Q}
		source ../config.local.archlinuxarm
		ARCHTAGS=('core-armv7h' 'core-testing-armv7h' 'community-armv7h' 'community-testing-armv7h')
		ARCHMIRROR=rsync://localhost:${rsyncport@Q}/rsyncd/archlinuxarm/
	eot

	# Set up HTTP server
	local httpport
	httpport=$(./lib/runserver "$TMP/httpd.pid" \
		bash -c "$(declare -f httpserver); httpserver \"\$@\"" -- "$TMP/httpd")

	# Set up HTTP contents
	mkdir -- "$TMP/httpd"
	cat <<-eot >"$TMP/httpd/blacklist.txt"
		slavery:freedom:fsf:slavekit:Obviously
	eot

	# Configure db-import to use that HTTP server
	export XDG_CONFIG_HOME="${TMP}/home/.config"
	mkdir -p "$XDG_CONFIG_HOME"/libretools
	cat <<-eot >"$XDG_CONFIG_HOME"/libretools/libretools.conf
		BLACKLIST=http://localhost:${httpport@Q}/blacklist.txt
	eot

	# Set up repo contents
	for arch in x86_64 i686 armv7h; do
		for repo in core core-testing community community-testing libre; do
			mkdir -p -- "${TMP}/ftp/${repo}/os/${arch}"
			touch -- "${TMP}/ftp/${repo}/os/${arch}/${repo}.db.tar.gz"
			ln -sT -- "${repo}.db.tar.gz" "${TMP}/ftp/${repo}/os/${arch}/${repo}.db"
		done
	done
	mkdir -p -- "${TMP}/ftp"/{pool,sources}/{packages,community,archlinux32,alarm}
	date +%s > "${TMP}/ftp/lastupdate"
	date +%s > "${TMP}/ftp/lastsync"
}
eval "__common_$(declare -f teardown)"
teardown() {
	xargs -a "${TMP}/httpd.pid" kill --
	xargs -a "${TMP}/rsyncd.pid" kill --
	__common_teardown
}

######################################################################

# __releaseImportedPackage PKGBASE ARCH DBFILE [POOLDIR]
#
# This is different from common.bash:releasePackage because
# - it doesn't mess with VCS
# - it adds the package to the .db file
__releaseImportedPackage() {
	local pkgbase=$1
	local arch=$2
	local dbfile=$3
	local pooldir=$4
	local repodir="${dbfile%/*}"
	local dir restore pkgfiles pkgfile pkgs

	dir="$TMP/import-build/$pkgbase"
	if ! [[ -d "$dir" ]]; then
		mkdir -p -- "$dir"
		cp -t "$dir" -- "fixtures/${pkgbase}"/*
	fi
	pushd "$dir"
	__buildPackage
	restore="$(shopt -p nullglob || true)"
	shopt -s nullglob
	pkgfiles=(*-{"$arch",any}"$PKGEXT"{,.sig})
	$restore
	popd

	mkdir -p "$repodir"
	if [[ -z $pooldir ]]; then
		mv -t "$repodir" -- "${pkgfiles[@]/#/"$dir/"}"
	else
		mkdir -p "$pooldir"
		mv -t "$pooldir" -- "${pkgfiles[@]/#/"$dir/"}"
		ln -sr -t "$repodir" -- "${pkgfiles[@]/#/"$pooldir/"}"
	fi

	pushd "$repodir"
	pkgs=()
	for pkgfile in "${pkgfiles[@]}"; do
		if [[ "$pkgfile" = *.sig ]]; then
			continue
		fi
		pkgs+=("$pkgfile")
	done
	repo-add -q "${dbfile##*/}" "${pkgs[@]}"
	popd
}

__updateImportedPackage() {
	pushd "$TMP/import-build/$1"
	local pkgrel
	pkgrel=$(. PKGBUILD; expr ${pkgrel} + 1)
	sed "s/pkgrel=.*/pkgrel=${pkgrel}/" -i PKGBUILD
	popd
}

__isLinkTo() {
	[[ -L $1 ]]
	[[ $1 -ef $2 ]]
}

__doesNotExist() {
	local file
	for file in "$@"; do
		if stat "$file" 2>/dev/null; then
			echo "TEST ERROR: File shouldn't exist, but does: $file"
			return 1
		fi
	done
}
