#!/bin/sh
set -e

# install an alpine chroot at /rw
# works on any linux distro with kernel 2.6.22 or later
# ed <irc.rizon.net> MIT-Licensed

# declare where the chroot should be placed
chroot_dir="/rw"

# declare mirror, version and architecture to use
alpine_mirror="https://mirror.leaseweb.com/alpine"
alpine_version="edge"
sys_arch="x86_64"

# generate remaining variables
main_repo="$alpine_mirror/$alpine_version/main"
comm_repo="$alpine_mirror/$alpine_version/community"

# pretty-print messages
msg() { printf '\033[33m[*]\033[0m %s\n' "$1" >&2; }
inf() { printf '\033[32m[+]\033[0m %s\n' "$1" >&2; }
err() { printf '\033[31m[!]\033[0m %s\n' "$1" >&2; }

# ensure we aren't clobbering
[ -e "$chroot_dir" ] &&
{
	err "chroot directory already exists: $chroot_dir"
	exit 1
}

# checks if a command exists
have()
{
	command -v $1 >/dev/null
}

# check that we have all necessary binaries
for x in awk mktemp xz
do
	have $x ||
	{
		err "need program: $x"
		exit 1
	}
done

have curl || have wget ||
{
	err "need either curl or wget"
	exit 1
}

# downloads a link to STDOUT
download()
{
	msg "get $1"
	
	have curl &&
	{
		curl "$1"
		return $?
	}
	
	wget -qO- "$1"
	return $?
}

# create temp directory, delete it on exit
tmp="$(mktemp -d)"
msg "using temp dir $tmp"
cleanup()
{
	msg "deleting temp dir $tmp"
	rm -rf "$tmp"
}
trap cleanup EXIT

# determine current version of the necessary alpine packages
download "$main_repo/$sys_arch" |
awk '
	/[">]alpine-keys-[0-9][^<"]*.apk[<"]/ {
		sub(/.*alpine-keys-/, "")
		sub(/\.apk.*/, "")
		keys_ver=$0
	}
	/[">]apk-tools-static-[0-9][^<"]*.apk[<"]/ {
		sub(/.*apk-tools-static-/, "")
		sub(/\.apk.*/, "")
		tools_ver=$0
	}
	END {
		print keys_ver, tools_ver
	}
' > "$tmp/ver"
read keys_ver tools_ver <"$tmp/ver"

# check that all the versions were detected
[ -z "$keys_ver" ] || [ -z "$tools_ver" ] &&
{
	err "cannot continue without knowing the current version of alpine-keys and apk-tools-static."
	msg "determined version of alpine-keys: $keys_ver"
	msg "determined version of apk-tools-static: $tools_ver"
	exit 1
}

# download and extract keys + tools
cd "$tmp"
download "$main_repo/$sys_arch/alpine-keys-$keys_ver.apk" > keys.apk
download "$main_repo/$sys_arch/apk-tools-static-$tools_ver.apk" > tools.apk

tar -xzf keys.apk
tar -xzf tools.apk

msg "creating initial alpine structure"
./sbin/apk.static -U --root "$chroot_dir" --initdb add alpine-base || true

msg "copying in keys and repo list"
cp -pvR etc/apk/keys "$chroot_dir"/etc/apk
cat > "$chroot_dir/etc/apk/repositories" <<EOF
$main_repo
$comm_repo
EOF

msg "installing alpine"
./sbin/apk.static -U --root "$chroot_dir" --initdb add alpine-base

msg "creating chroot script"
cat > "$chroot_dir/enter" <<"EOF"
#!/bin/sh
set -e
cd "$(dirname "$0")"
cp /etc/resolv.conf etc/
mount | grep -q "on /rw/sys" || {
  mount -t proc none proc
  mount -o bind /sys sys
  mount -o bind /dev dev
}
chmod 777 dev/shm
chroot . /bin/sh -l
umount dev sys proc
EOF
chmod 755 "$chroot_dir/enter"

inf "you can now enter the alpine chroot by running $chroot_dir/enter"
msg "then consider making a user account:  adduser -s /bin/ash -Du 1000 ed"
