396 lines
8.6 KiB
Bash
Executable file
396 lines
8.6 KiB
Bash
Executable file
#!/bin/sh
|
|
set -eu
|
|
|
|
# See `parse_args()` for enabling dry run.
|
|
dry_run="no"
|
|
|
|
is_dry_run() {
|
|
test "${dry_run}" = "yes"
|
|
}
|
|
|
|
setup_colors() {
|
|
if [ -t 1 ]; then
|
|
sgr0="$(printf '\033[0m')"
|
|
bold="$(printf '\033[1m')"
|
|
red="$(printf '\033[31m')"
|
|
green="$(printf '\033[32m')"
|
|
yellow="$(printf '\033[33m')"
|
|
blue="$(printf '\033[34m')"
|
|
else
|
|
sgr0=''
|
|
bold=''
|
|
red=''
|
|
green=''
|
|
yellow=''
|
|
blue=''
|
|
fi
|
|
}
|
|
|
|
setup_commands() {
|
|
dry=''
|
|
is_dry_run && dry="echo "
|
|
|
|
APT="${dry}apt"
|
|
APT_FILE="${dry}apt-file"
|
|
CD="${dry}cd"
|
|
CHSH="${dry}chsh"
|
|
CURL="${dry}curl"
|
|
DPKG="${dry}dpkg"
|
|
GIT="${dry}git"
|
|
GZIP="${dry}gzip"
|
|
HELP2MAN="${dry}help2man"
|
|
LN="${dry}ln"
|
|
MKDIR="${dry}mkdir"
|
|
MV="${dry}mv"
|
|
PANDOC="${dry}pandoc"
|
|
RM="${dry}rm"
|
|
RMDIR="${dry}rmdir"
|
|
SED="${dry}sed"
|
|
STOW="${dry}stow"
|
|
SU="${dry}su"
|
|
TAR="${dry}tar"
|
|
UNZIP="${dry}unzip"
|
|
UPDATE_GRUB="${dry}update-grub"
|
|
USERADD="${dry}useradd"
|
|
USERMOD="${dry}usermod"
|
|
}
|
|
|
|
usage() {
|
|
echo "Usage: $(basename "$0") [-h] [-n]"
|
|
echo ""
|
|
echo " -h print this help and exit."
|
|
echo " -n dry run, don't make changes."
|
|
}
|
|
|
|
error() {
|
|
printf "${red}ERROR:${sgr0} %s\n" "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
info() {
|
|
printf "${green}->${sgr0} %s\n" "$1"
|
|
}
|
|
|
|
title() {
|
|
echo "${blue}${bold}=> ${1}${sgr0}"
|
|
}
|
|
|
|
skipped() {
|
|
echo "${yellow}SKIPPED:${sgr0} ${1}"
|
|
}
|
|
|
|
apt_install() {
|
|
title "Install APT packages"
|
|
|
|
info "Updating package database"
|
|
${APT} update
|
|
|
|
info "Installing APT packages"
|
|
${APT} install -y \
|
|
apt-file \
|
|
ascii \
|
|
build-essential \
|
|
ca-certificates \
|
|
cmake \
|
|
cmake-doc \
|
|
curl \
|
|
exuberant-ctags \
|
|
g++ \
|
|
gcc \
|
|
git \
|
|
git-crypt \
|
|
gnupg \
|
|
help2man \
|
|
htop \
|
|
jq \
|
|
make \
|
|
man-db \
|
|
nodejs \
|
|
pandoc \
|
|
pkg-config \
|
|
psmisc \
|
|
python3 \
|
|
python3-virtualenv \
|
|
ripgrep \
|
|
rsync \
|
|
shellcheck \
|
|
sshpass \
|
|
stow \
|
|
sudo \
|
|
tmux \
|
|
unzip \
|
|
zsh
|
|
|
|
info "Updating apt-file database"
|
|
${APT_FILE} update
|
|
}
|
|
|
|
grub_disable_timeout() {
|
|
title "Disable GRUB timeout"
|
|
|
|
${SED} -i.original -e 's/^GRUB_TIMEOUT=.*/GRUB_TIMEOUT=0/' /etc/default/grub
|
|
${UPDATE_GRUB}
|
|
}
|
|
|
|
ensure_usr_local_man_manN() {
|
|
title "Make sure we have directories for all man page sections"
|
|
|
|
for dir in $(seq -f '/usr/local/man/man%.0f' 9); do
|
|
${MKDIR} -vp "${dir}"
|
|
done
|
|
}
|
|
|
|
user_setup() {
|
|
title "Setup user: $1"
|
|
|
|
if user_exists "$1"; then
|
|
info "User $1 exists. Updating..."
|
|
user_update "$1"
|
|
else
|
|
info "Creating user $1"
|
|
user_new "$1"
|
|
fi
|
|
|
|
user_allow_sudo_nopasswd "$1"
|
|
}
|
|
|
|
user_exists() {
|
|
id -u "$1" >/dev/null 2>&1
|
|
}
|
|
|
|
user_new() {
|
|
empty_skel="$(mktemp -d)"
|
|
|
|
${USERADD} \
|
|
-m ` # Create home directory.` \
|
|
-k "$empty_skel" ` # Copy files from this directory into the new home.` \
|
|
-U ` # Create a groups with the same name as the user.` \
|
|
-G staff ` # Other groups the new user will be a member of.` \
|
|
-s /bin/zsh ` # The new user's login shell. ` \
|
|
"$1" ` # The new user's name.` \
|
|
2>&1 ` # Silently.` \
|
|
|
|
${RMDIR} "$empty_skel"
|
|
}
|
|
|
|
# Add user $1 to the `staff` group...
|
|
# ...and change shell to `zsh` and get rid of bash files.
|
|
user_update() {
|
|
info "Adding $1 to group staff"
|
|
${USERMOD} -aG staff "$1"
|
|
|
|
info "Changing login shell to zsh"
|
|
${CHSH} -s /bin/zsh "$1"
|
|
|
|
info "Removing bash leftover files"
|
|
for f in .bash_history .bash_logout .bashrc .profile; do
|
|
${RM} -vf "/home/${1}/${f}"
|
|
done
|
|
}
|
|
|
|
# Allow `sudo` without password for user $1.
|
|
user_allow_sudo_nopasswd() {
|
|
info "Enabling sudo without password for ${1}"
|
|
contents="$1 ALL=(ALL:ALL) NOPASSWD:ALL"
|
|
sudoers_file="/etc/sudoers.d/${1}_nopasswd"
|
|
if is_dry_run; then
|
|
echo "echo \"$contents\" >$sudoers_file"
|
|
else
|
|
echo "$contents" >"$sudoers_file"
|
|
fi
|
|
}
|
|
|
|
# Deploy dotfiles for user $1 from URL $2.
|
|
deploy_dotfiles() {
|
|
title "Deploy dotfiles"
|
|
|
|
dotfiles_dir="/home/$1/.dotfiles"
|
|
if [ -d "${dotfiles_dir}" ]; then
|
|
skipped "${dotfiles_dir} exists"
|
|
else
|
|
info "Cloning dotfiles"
|
|
${SU} "$1" -c "git clone $2 ${dotfiles_dir}"
|
|
(
|
|
info "Installing dotfiles"
|
|
${CD} "${dotfiles_dir}"
|
|
${SU} "$1" -c "./install.sh -y"
|
|
)
|
|
fi
|
|
}
|
|
|
|
install_broot() (
|
|
title "Install broot v${1}"
|
|
|
|
${MKDIR} broot
|
|
${CD} broot
|
|
pkg="broot-${1}"
|
|
|
|
info "Creating directory structure"
|
|
for subdir in bin share/man/man1 share/zsh/vendor-completions; do
|
|
${MKDIR} -p "${pkg}/${subdir}"
|
|
done
|
|
|
|
info "Downloading release archive"
|
|
archive="broot_${1}"
|
|
${CURL} -LO "https://github.com/Canop/broot/releases/download/v${1}/broot_${1}.zip"
|
|
|
|
info "Extracting release archive"
|
|
${MKDIR} "${archive}"
|
|
${UNZIP} -d "${archive}" "broot_${1}.zip"
|
|
|
|
info "Packaging executable"
|
|
${MV} -v "${archive}/x86_64-linux/broot" "${pkg}/bin/"
|
|
|
|
info "Packaging man page"
|
|
${MV} -v "${archive}/broot.1" "${pkg}/share/man/man1/"
|
|
|
|
info "Packaging zsh completions"
|
|
for completion in _br _broot; do
|
|
${MV} -v "${archive}/completion/${completion}" "${pkg}/share/zsh/vendor-completions/"
|
|
done
|
|
|
|
info "Installing package"
|
|
${MV} "${pkg}" /usr/local/stow/
|
|
${STOW} -v -d /usr/local/stow "${pkg}"
|
|
)
|
|
|
|
install_eza() (
|
|
title "Install eza v${1}"
|
|
|
|
${MKDIR} eza
|
|
${CD} eza
|
|
pkg="eza-${1}"
|
|
|
|
info "Creating directory structure"
|
|
for subdir in bin share/man/man1 share/man/man5 share/zsh/vendor-completions; do
|
|
${MKDIR} -p "${pkg}/${subdir}"
|
|
done
|
|
|
|
info "Packaging executable from release archive"
|
|
${CURL} -LO "https://github.com/eza-community/eza/releases/download/v${1}/eza_x86_64-unknown-linux-gnu.tar.gz"
|
|
${TAR} -xf eza_x86_64-unknown-linux-gnu.tar.gz
|
|
${MV} -v eza "${pkg}/bin/"
|
|
|
|
info "Cloning repository for man pages and shell completions"
|
|
${GIT} clone --branch "v${1}" --depth 1 https://github.com/eza-community/eza.git repo
|
|
|
|
info "Generating man pages"
|
|
for page in eza.1 eza_colors.5 eza_colors-explanation.5; do
|
|
${SED} -i -e "s/\$version/v${1}/g" "repo/man/${page}.md"
|
|
${PANDOC} \
|
|
--standalone \
|
|
--from markdown \
|
|
--to man \
|
|
--output "${pkg}/share/man/man${page##*.}/${page}" \
|
|
"repo/man/${page}.md"
|
|
${GZIP} -n9 "${pkg}/share/man/man${page##*.}/${page}"
|
|
done;
|
|
|
|
info "Packaging zsh comletions"
|
|
${MV} -v "repo/completions/zsh/_eza" "${pkg}/share/zsh/vendor-completions/"
|
|
|
|
info "Installing package"
|
|
${MV} "${pkg}" /usr/local/stow/
|
|
${STOW} -v -d /usr/local/stow "${pkg}"
|
|
)
|
|
|
|
install_fd() (
|
|
title "Install fd v${1}"
|
|
|
|
${MKDIR} fd
|
|
${CD} fd
|
|
pkg="fd-${1}"
|
|
|
|
info "Downloading release archive"
|
|
${CURL} -LO "https://github.com/sharkdp/fd/releases/download/v${1}/fd_${1}_amd64.deb"
|
|
|
|
info "Extracting release archive"
|
|
${DPKG} --extract "fd_${1}_amd64.deb" .
|
|
${MV} -v usr "${pkg}"
|
|
|
|
info "Installing package"
|
|
${MV} "${pkg}" /usr/local/stow/
|
|
${STOW} -v -d /usr/local/stow "${pkg}"
|
|
)
|
|
|
|
install_git_delta() (
|
|
title "Install git-delta v${1}"
|
|
|
|
${MKDIR} git-delta
|
|
${CD} git-delta
|
|
pkg="git-delta-${1}"
|
|
|
|
info "Downloading release archive"
|
|
${CURL} -LO "https://github.com/dandavison/delta/releases/download/${1}/git-delta_${1}_amd64.deb"
|
|
|
|
info "Extracting release archive"
|
|
${DPKG} --extract "git-delta_${1}_amd64.deb" .
|
|
${MV} -v usr "${pkg}"
|
|
|
|
info "Creating additional directories"
|
|
for subdir in share/man/man1 share/zsh/vendor-completions; do
|
|
${MKDIR} -p "${pkg}/${subdir}"
|
|
done
|
|
|
|
info "Cloning repository for shell completions"
|
|
${GIT} clone --branch "${1}" --depth 1 https://github.com/dandavison/delta.git repo
|
|
|
|
info "Packaging zsh completions"
|
|
${MV} -v "repo/etc/completion/completion.zsh" "${pkg}/share/zsh/vendor-completions/_delta"
|
|
|
|
info "Generating man pages"
|
|
${HELP2MAN} --no-info --output "git-delta.1" "${pkg}/bin/delta"
|
|
${SED} -i -e 's/\x1b\[[0-9;]*[Mm]//g' git-delta.1
|
|
${GZIP} -n9 git-delta.1
|
|
${MV} -v git-delta.1.gz "${pkg}/share/man/man1/"
|
|
|
|
info "Installing package"
|
|
${MV} "${pkg}" /usr/local/stow/
|
|
${STOW} -v -d /usr/local/stow "${pkg}"
|
|
)
|
|
|
|
parse_args() {
|
|
while getopts 'hn' opt; do
|
|
case "$opt" in
|
|
h) # help
|
|
usage
|
|
exit 0
|
|
;;
|
|
n) # dry run
|
|
dry_run="yes"
|
|
;;
|
|
*) # invalid argument
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
require_root() {
|
|
[ "$(id -u)" -eq 0 ] || error "This script must be run as root!"
|
|
}
|
|
|
|
user="fernando"
|
|
dotfiles_url="https://git.schauenburg.me/fernando/dotfiles.git"
|
|
|
|
main() {
|
|
setup_colors
|
|
parse_args "$@"
|
|
is_dry_run || require_root
|
|
setup_commands
|
|
|
|
apt_install
|
|
|
|
install_broot 1.36.1
|
|
install_eza 0.18.7
|
|
install_fd 9.0.0
|
|
install_git_delta 0.17.0
|
|
|
|
grub_disable_timeout
|
|
ensure_usr_local_man_manN
|
|
user_setup "$user"
|
|
deploy_dotfiles "$user" "$dotfiles_url"
|
|
}
|
|
|
|
main "$@"
|