#!/usr/bin/env sh

# Shell script to automate Arch Linux's installation. It can be executed
# by running the following command inside a live media environment:
#
#   sh <(curl -Ls git.io/vzWco)

# Exits if any command or pipe fails, or if variables are unset.
set -e -u -o pipefail

# Pass list of packages from environment to `pacstrap`.
EXTRA_PKG="${EXTRA_PKG:-"bash-completion bc dhcpcd diffutils efibootmgr expac \
  linux linux-firmware man-db man-pages netctl openssh pkgfile vim"}"

# Wrapping the script inside curly brackets ensures it will be executed only
# if the closing bracket is reached, preventing undesired behavior if the
# connection is terminated when the script is being downloaded.
{
  prompt() {
    [ "$4" = "show" ] && printf "%s\n" "$(echo "$3" | column)"
    printf "%s" "$1"
    while read -r VAR ; do
      echo "$VAR" | grep -Eqx "$3" && break
      printf "Invalid input! Try again: "
    done
    eval "$2='$VAR'"
  }

  { # disk partitioning
    lsblk -dnpe 2,7,11 -o NAME,SIZE | column
    printf "Choose the disk and set the root partition size: "
    read -r DISK ROOTSIZE

    parted --script --align optimal -- "$DISK" mklabel gpt \
      mkpart primary fat32 1M 100M name 1 'boot' set 1 boot on \
      mkpart primary ext3 100M "$ROOTSIZE" name 2 'root' \
      mkpart primary ext3 "$ROOTSIZE" 100% name 3 'home'

    mkfs.ext4 /dev/disk/by-partlabel/root
    mkfs.vfat -F32 /dev/disk/by-partlabel/boot
    mkfs.ext4 /dev/disk/by-partlabel/home

    mount PARTLABEL=root /mnt
    mkdir -p /mnt/boot /mnt/home
    mount PARTLABEL=boot /mnt/boot
    mount PARTLABEL=home /mnt/home
  }

  { # mirror configuration and base system install
    PLACES="$(reflector --list-countries | awk '{print $(NF - 1)}')"
    prompt "Country (or nearest location): " COUNTRY "$PLACES" show
    reflector --country "$COUNTRY" --save /etc/pacman.d/mirrorlist

    pacstrap /mnt base base-devel $EXTRA_PKG
    genfstab -U -p /mnt >> /mnt/etc/fstab
  }

  { # locale and timezone configuration
    LANGUAGES="$(grep -Eo "[a-z]+_[A-Z]+" /etc/locale.gen | sort -u)"
    prompt "Language for the system: " LNG "$LANGUAGES" show

    sed -i "s/#$LNG/$LNG/" /mnt/etc/locale.gen
    arch-chroot /mnt locale-gen
    LOCALE="$(awk '!/#/ {print $1; exit}' /mnt/etc/locale.gen)"
    echo "LANG=$LOCALE" > /mnt/etc/locale.conf

    ln -sf "/usr/share/zoneinfo/$(tzselect)" /mnt/etc/localtime
    arch-chroot /mnt hwclock --systohc --utc
  }

  { # hostname, user account and password configuration
    HNAME="[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]"
    prompt "Enter the hostname: " HOST "($HNAME)(\.($HNAME)){0,3}" hide
    echo "$HOST" > /mnt/etc/hostname
    sed -i "7a 127.0.1.1\t$HOST.localdomain\t$HOST" /mnt/etc/hosts

    echo "Password for superuser:"
    until arch-chroot /mnt passwd ; do : ; done

    UNAME="[a-z_]([a-z0-9_]{,30}[$]|[a-z0-9_]{,31})"
    prompt "Enter the username: " USER "$UNAME" hide
    arch-chroot /mnt useradd -m -g users -G wheel "$USER"

    echo "Password for $USER:"
    until arch-chroot /mnt passwd "$USER" ; do : ; done
    echo "%wheel ALL=(ALL) ALL" > /mnt/etc/sudoers.d/99_enable_wheel
  }

  { # bootloader installation
    arch-chroot /mnt efibootmgr --disk "$DISK" --part 1 \
      --create --label "Arch Linux" --loader /vmlinuz-linux --unicode \
      "root=/dev/disk/by-partlabel/root rw initrd=\\initramfs-linux.img"
  }
}