#!/bin/sh -e
# See http://jdebp.uk./FGA/slashpackage.html
if test \! -d package || test \! -d source
then
	echo "You are not in the right directory." 1>&2
	exit 100
fi

buildtools="xmlto"

check_buildtools() {
	local tool
	# Check build command dependencies.
	for tool in ${buildtools}
	do
		if ! > /dev/null command -v "${tool}"
		then
			echo "${tool} is a required tool for building this package." 1>&2
			exit 100
		fi
	done
}

export CDPATH=

# Create and populate the build directory.
install -d -m 0755 build
( cd source && ( 2>/dev/null pax -w -r -l -u -- * ../build/ || true ) )

# Bootstrap.
if ! bootstrap_redo=$(command -v redo) ||
   ! > /dev/null command -v redo-ifchange ||
   ! > /dev/null command -v redo-ifdelete
then
	printf 1>&2 '%s\n' 'System lacks redo, redo-ifchange, or redo-ifdelete; and requires a bootstrap redo.'
	install -d -m 0755 build/bootstrap
	(
		cd build
		if ! test -x bootstrap/redo
		then
			printf 1>&2 '%s\n' 'Creating a minimal bootstrap redo.'
			cppflags=''
			if cxx=$(command -v clang++)
			then
				cxxflags='-g -O3 -std=gnu++11'
				ldflags='-g'
			elif cxx=$(command -v g++)
			then
				cxxflags=' -g -O3 -std=gnu++11'
				ldflags='-g'
			elif cxx=$(command -v c++)
			then
				cxxflags=' -g -O3 -std=gnu++11'
				ldflags='-g'
			elif cxx=$(command -v owcc)
			then
				cxxflags=' -g'
				ldflags='-g'
			else
				echo "Cannot find clang++, g++, c++, or owcc." 1>&2
				exit 100
			fi
			sources="main.cpp redo.cpp popt-named.cpp popt-simple.cpp popt-compound-1arg.cpp popt-bool.cpp popt-string.cpp popt-integral.cpp popt-unsigned.cpp popt-table.cpp popt-top-table.cpp popt.cpp jobserver.cpp FileDescriptorOwner.cpp DefaultEnvironment.cpp ProcessEnvironment.cpp ErrorReporter.cpp tai64.cpp tai64n.cpp wait.cpp lockfile.cpp"
			ln -f -- wait.cpp.waitid wait.cpp
			"${cxx}" ${cppflags} ${cxxflags} ${ldflags} -D VERSION='"bootstrap"' -D MINIMAL=1 -o bootstrap/redo $sources
			rm -f -- wait.cpp
		else
			printf 1>&2 '%s\n' 'Re-using existing minimal bootstrap redo, unchanged.'
		fi
		ln -f -- bootstrap/redo bootstrap/redo-ifchange
		ln -f -- bootstrap/redo bootstrap/redo-ifcreate
		ln -f -- bootstrap/redo bootstrap/redo-ifdelete
	)
	extrapath="./bootstrap"
	bootstrap_redo=build/bootstrap/redo
fi

# Rebuild.
if > /dev/null command -v setlock &&
   ! > /dev/null expr -- "${MAKEFLAGS}" : "--jobs" &&
   ! > /dev/null expr -- "${REDOFLAGS}" : "--jobs"
then
	case "`uname`" in
	(Linux) cpus="`grep -F -c processor /proc/cpuinfo`" ;;
	(*BSD) cpus="`sysctl -n hw.ncpu`" ;;
	(*) cpus=''
	esac
fi
check_buildtools
PATH="${extrapath:+${extrapath}:}${PATH}" "${bootstrap_redo}" --directory build ${cpus:+--jobs "${cpus}"} -- all

# Atomically update the release directories ./command, ./library, ./include, and so forth.
# The build and release directories need not be on the same disc volume.
# And the files released must not be potentially overwritable and truncatable by the compiler/linker during subsequent builds.
# But released files can be links to other released files, of course.
install -d -m 0755 command manual guide guide/commands guide/commands/html config config/zsh

# ##############################################################################
# Low-level file and directory manipulation.
case "`uname`" in
(Linux)
	rename_symbolic_link() {
		! test -e "$2" || mv -f -- "$2" "$2"{old}
		mv -f -- "$1" "$2"
		rm -f -- "$2"{old}
	}
	make_symbolic_link() {
		ln -f -n -s -- "$1" "$2"
	}
	;;
(*)
	rename_symbolic_link() {
		mv -f -h -- "$1" "$2"
	}
	make_symbolic_link() {
		ln -f -h -s -- "$1" "$2"
	}
	;;
esac

# ##############################################################################
# Build all of the {new} files
cat package/commands1 |
while read -r c
do
	rm -f -- command/"$c"{new}
	install -m 0755 -p -- build/command/"$c" command/"$c"{new}
	strip command/"$c"{new}
	chmod 0555 command/"$c"{new}
	rm -f -- manual/"$c".1{new}
	install -m 0444 -p -- build/manual/"$c".1 manual/"$c".1{new}
	rm -f -- manual/"$c".xml{new}
	install -m 0444 -p -- build/"$c".xml manual/"$c".xml{new}
	rm -f -- guide/commands/"$c".xml{new}
	ln -f -- manual/"$c".xml{new} guide/commands/"$c".xml{new}
	rm -f -- guide/commands/html/"$c".html{new}
	install -m 0444 -p -- build/slashdoc/"$c".html guide/commands/html/"$c".html{new}
done
cat package/aliases1 |
while read -r c a
do
	rm -f -- command/"$a"{new}
	ln -f -- command/"$c"{new} command/"$a"{new}
	rm -f -- manual/"$a".1{new}
	install -m 0444 -p -- build/manual/"$a".1 manual/"$a".1{new}
	rm -f -- manual/"$a".xml{new}
	install -m 0444 -p -- build/"$a".xml manual/"$a".xml{new}
	rm -f -- guide/commands/"$a".xml{new}
	ln -f -- manual/"$a".xml{new} guide/commands/"$a".xml{new}
	rm -f -- guide/commands/html/"$a".html{new}
	install -m 0444 -p -- build/slashdoc/"$a".html guide/commands/html/"$a".html{new}
done
for section in 1
do
	make_symbolic_link . manual/man${section}{new}
	make_symbolic_link . manual/docbook${section}{new}
done
for locale in en_GB.UTF-8 en.UTF-8 en
do
	make_symbolic_link . manual/"${locale}"{new}
done
# Z shell completions
for i in _redo _pkg-helper _cubehash
do
	rm -f -- config/zsh/"$i"{new}
	install -m 0444 -p -- build/zsh/"$i" config/zsh/"$i"{new}
done 
# Main guide pages
cat package/guidepages |
while read -r i
do
	rm -f -- guide/"$i".html{new}
	install -m 0444 -p -- build/guide/"$i".html guide/"$i".html{new}
done
# Other guide pages
for i in COPYING
do
	rm -f -- guide/"$i"{new}
	install -p -m 0644 -- build/"$i" guide/"$i"{new}
done
for i in guide.css
do
	rm -f -- guide/"$i"{new}
	install -p -m 0644 -- build/guide/"$i" guide/"$i"{new}
done
for i in docbook-xml.css
do
	rm -f -- guide/commands/"$i"{new}
	install -m 0444 -p -- build/guide/"$i" guide/commands/"$i"{new}
done

# ##############################################################################
# Rename the ...{new} directories and files
(
	cat package/commands1
	awk '{print $2;}' package/aliases1
) |
while read -r c
do
	mv -f -- command/"$c"{new} command/"$c"
	mv -f -- manual/"$c".1{new} manual/"$c".1
	mv -f -- manual/"$c".xml{new} manual/"$c".xml
	mv -f -- guide/commands/"$c".xml{new} guide/commands/"$c".xml
	mv -f -- guide/commands/html/"$c".html{new} guide/commands/html/"$c".html
done
for section in 1
do
	rename_symbolic_link manual/man${section}{new} manual/man${section}
	rename_symbolic_link manual/docbook${section}{new} manual/docbook${section}
done
for locale in en_GB.UTF-8 en.UTF-8 en
do
	rename_symbolic_link manual/"${locale}"{new} manual/"${locale}"
done
# Z shell completions
for i in _redo _pkg-helper _cubehash
do
	mv -f -- config/zsh/"$i"{new} config/zsh/"$i"
done 
# Main guide pages
cat package/guidepages |
while read -r i
do
	mv -f -- guide/"$i".html{new} guide/"$i".html
done
# Other guide pages
for i in COPYING guide.css commands/docbook-xml.css
do
	mv -f -- guide/"$i"{new} guide/"$i"
done
