ambevar-dotfiles/.local/bin/homeinit

305 lines
8.0 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

#!/bin/sh
# TODO: Guix pull on commit specified in package-lists/guix-version?
# TODO: On foreign distro, use local package manager to install Guix. (Start with pacman.)
# TODO: Make functions to make it easier to re-order calls?
HTTPS_ROOT=https://gitlab.com/
SSH_ROOT=git@gitlab.com:
ROOT=$HTTPS_ROOT
PROFILE=/tmp/homeinit-$USER/homeinit
[ -z "$SOURCEDIR" ] && SOURCEDIR="$HOME/personal"
[ -z "$XDG_CONFIG_HOME" ] && XDG_CONFIG_HOME="$HOME/.config"
[ -z "$XDG_DATA_HOME" ] && XDG_DATA_HOME="$HOME/.local/share"
[ -z "$EMACS_MIN_VERSION" ] && EMACS_MIN_VERSION=26
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
cat <<EOF>&2
Usage: ${0##*/}
Initialize user profile: install packages, set up folders, etc.
Options:
-u: Skip large updates (packages, emails, etc.)
Environment variables:
SOURCEDIR=$SOURCEDIR
XDG_CONFIG_HOME=$XDG_CONFIG_HOME
XDG_DATA_HOME=$XDG_DATA_HOME
EMACS_MIN_VERSION=$EMACS_MIN_VERSION
Direct link:
${HTTPS_ROOT}ambrevar/dotfiles/raw/master/.local/bin/homeinit
EOF
exit
fi
OPT_UPDATE=true
if [ "$1" = "-u" ]; then
OPT_UPDATE=false
shift
fi
RED='\033[0;31m\033[1m'
GREEN='\033[0;32m\033[1m'
YELLOW='\033[0;33m\033[1m'
BOLD='\033[0m\033[1m'
NORMAL='\033[0m'
section() {
echo -e "$GREEN==> $@$NORMAL"
}
message() {
echo -e "$YELLOW:: $@$NORMAL"
}
warning() {
echo -e "${YELLOW}WARNING:: $@$NORMAL"
}
## "ln" wrapper.
## If $2 is a folder, create the link in it using the basename of $1.
## Existing files are no clobbered, unless they already are a symlink.
lnn() { # $1=TARGET $2=LINK|FOLDER
if [ -d "$2" ]; then
set -- "$1" "$2/$(basename "$1")"
fi
if [ ! -e "$2" ] || [ -h "$2" ]; then
ln -svnf "$1" "$2"
fi
}
inpath() {
for i; do
if ! command -v "$i" >/dev/null 2>&1; then
return 1
fi
done
return 0
}
################################################################################
#
section "Initial packages"
if inpath guix; then
## OpenSSH is not an input of Git, upstream does not want to increase the
## closure size that much.
mkdir "$(dirname "$PROFILE")"
guix package --profile="$PROFILE" --install openssh gnupg git stow password-store pinentry-tty
source "$PROFILE"/etc/profile
elif inpath pacman; then
sudo pacman --noconfirm -S --needed openssh gnupg git stow password-store
fi
section "GPG"
if [ -d ~/.gnupg ]; then
ROOT=$SSH_ROOT
## Set up gpg-agent to authenticate to SSH_ROOT.
chmod -R go-rwx ~/.gnupg
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
if [ "$GPG_TTY" != "not a tty" ]; then
## If a TTY, since our ~/.gnupg/gpg-agent.conf exists and specifies a
## pinentry, we must force the TTY version or else it won't work from a TTY.
gpgconf --kill gpg-agent
cat<<EOF>"$(dirname "$PROFILE")/gpg-agent.conf"
## 1-day timeout
default-cache-ttl 86400
max-cache-ttl 86400
## SSH
enable-ssh-support
default-cache-ttl-ssh 86400
max-cache-ttl-ssh 86400
## Force pinentry (should be pinentry-tty)
pinentry-program $(readlink -f $(which pinentry))
EOF
gpg-agent --home-dir ~/.gnupg --use-standard-socket -daemon --options "$(dirname "$PROFILE")/gpg-agent.conf"
fi
## Start gpg-agent manually since SSH requests do not do it automatically.
gpg-connect-agent updatestartuptty /bye
if [ -e "$SOURCEDIR" ]; then
git -C "$SOURCEDIR" pull
else
git clone ${SSH_ROOT}Ambrevar/personal
fi
if [ -e ~/.password-store ]; then
git -C ~/.password-store pull
else
git clone ${SSH_ROOT}Ambrevar/password-store ~/.password-store
## The following is necessary to make sure the 'diff' GPG filter is properly set up.
pass git init
fi
else
warning "~/.gnupg not found."
fi
section "Persistent folders"
for i in .config .emacs.d .local/share projects temp; do
mkdir -pv "$HOME/$i"
done
section "dotfiles"
if [ -e ~/dotfiles ]; then
git -C ~/dotfiles remote set-url origin ${ROOT}Ambrevar/dotfiles
git -C ~/dotfiles pull
else
git clone ${ROOT}Ambrevar/dotfiles
fi
pushd ~/dotfiles
## .bash_profile may prevent .profile from being parsed, so we move it.
[ -e ~/.bash_profile ] && mv -v ~/.bash_profile ~/.bash_profile.old
stow -v . || exit 1
popd
section "System packages"
if inpath guix; then
if [ ! -e ~/.cache/guix/pull ]; then
message "Update Guix to yesterday's version"
git clone https://git.savannah.gnu.org/git/guix.git /tmp/guix
YESTERDAY_COMMIT=$(git -C /tmp/guix log --until=yesterday -n 1 --format=%H)
guix pull --commit=$YESTERDAY_COMMIT
unset YESTERDAY_COMMIT
rm -rv /tmp/guix
elif $OPT_UPDATE
CURRENT_COMMIT=$(guix --version 2>/dev/null | awk '{print $4; exit}')
REPO=$HOME/.cache/guix/pull/"$(ls -1 ~/.cache/guix/pull)"
CURRENT_COMMIT_DATE=git -C "$REPO" log -n 1 --format=%ct $CURRENT_COMMIT
git -C $REPO pull
LATEST_COMMIT_DATE=git -C "$REPO" log -n 1 --format=%ct
[ -z "$GUIX_DISTRO_AGE_WARNING" ] && GUIX_DISTRO_AGE_WARNING=$((7 * 24 * 60 * 60))
if [ $(($LATEST_COMMIT_DATE - $CURRENT_COMMIT)) -gt $GUIX_DISTRO_AGE_WARNING ]; then
message "Update Guix since it's older than a week."
YESTERDAY_COMMIT=$(git -C "$REPO" log --until=yesterday -n 1 --format=%H)
guix pull --commit=$YESTERDAY_COMMIT
unset YESTERDAY_COMMIT
fi
unset LATEST_COMMIT_DATE
unset CURRENT_COMMIT_DATE
unset REPO
unset CURRENT_COMMIT
fi
## TODO: The manifest will uninstall other unspecified packages. Is this
## really what we want?
export GUIX_PACKAGE_PATH=$HOME/.guix-packages
guix package --manifest=$HOME/.package-lists/guix-manifest.scm --keep-failed
elif inpath pacman; then
pacman_list=""
if [ -f ~/.package-lists/arch-official ]; then
pacman_list="$(cat ~/.package-lists/arch-official)"
fi
sudo pacman --noconfirm -S --needed base base-devel $pacman_list
if ! inpath cower; then
mkdir -p /tmp/cower
pushd /tmp/cower
curl https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=cower > PKGBUILD
makepkg --noconfirm -si
popd
fi
if ! inpath pacaur; then
mkdir -p /tmp
cower -d pacaur
pushd /tmp/pacaur
makepkg --noconfirm -si
popd
fi
if $OPT_UPDATE && [ -f ~/.package-lists/arch-aur ]; then
pacaur --noconfirm --noedit -y --needed "$(cat ~/.package-lists/arch-aur)"
fi
pacman_list=$(pacman -Qdtq)
if [ -n "$pacman_list" ]; then
sudo pacman --noconfirm -Rs "$pacman_list"
fi
fi
section "Bookmarks"
if inpath qutebrowser; then
mkdir -pv "$XDG_CONFIG_HOME/qutebrowser/bookmarks"
lnn "$SOURCEDIR/bookmarks/bookmarks" "$XDG_CONFIG_HOME/qutebrowser/bookmarks/urls"
lnn "$SOURCEDIR/bookmarks/quickmarks" "$XDG_CONFIG_HOME/qutebrowser/"
fi
section "Emacs"
if ! inpath emacs; then
message "Emacs: Installing latest development version"
pushd "$HOME/projects"
[ -e emacs ] || git clone https://git.savannah.gnu.org/git/emacs.git
mkdir -pv ../emacs-build
cd ../emacs-build
../emacs/configure \
--disable-gtk-deprecation-warnings \
--without-pop \
--without-kerberos \
--without-kerberos5 \
--with-x-toolkit=gtk3 \
--with-jpeg \
--with-tiff \
--with-gif \
--with-png \
--with-rsvg \
--with-xml2 \
--with-imagemagick \
--with-xft \
--with-libotf \
--without-gsettings \
--without-gconf \
--with-gnutls \
--with-modules \
--with-threads
sudo make install
popd
fi
if inpath emacs; then
message "Emacs cache folder"
mkdir -pv "$HOME/.cache/emacs/"
if ! inpath guix; then
if $OPT_UPDATE; then
message "Emacs ELPA packages"
yes | emacs --batch -l ~/.emacs.d/init.el --eval '(progn (package-refresh-contents) (package-install-selected-packages))'
fi
fi
message "Emacs local packages"
if [ -e ~/.local/share/emacs/site-lisp ]; then
for i in ~/.local/share/emacs/site-lisp/*; do
echo "$i"
git -C "$i" pull
done
else
mkdir -pv ~/.local/share/emacs/site-lisp
fi
fi
if inpath guix; then
section "Cleanup initial packages"
rm -rv "$(dirname "$PROFILE")"
fi
section "locate db"
if [ -x ~/.local/bin/updatedb-local ]; then
~/.local/bin/updatedb-local
fi
section "Mail"
lnn "$SOURCEDIR/mail/mbsyncrc" "$HOME/.mbsyncrc"
lnn "$SOURCEDIR/mail/authinfo.gpg" "$HOME/.authinfo.gpg"
mkdir -pv "$HOME/.cache/mail/"
while IFS= read -r i; do
## Warning: We need to eval here to expand the "~".
mkdir -pv $(eval echo $i)
done <<EOF
$(awk '/^Path/ {print $2}' ~/.mbsyncrc)
EOF
if $OPT_UPDATE; then
mbsync -aV
mu index --maildir=~/.cache/mail
fi