ambevar-dotfiles/.local/bin/homeinit

334 lines
8.1 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
USER_NAME=Ambrevar
SUBSTITUTE_URLS=https://ci.guix.gnu.org
EXTRA_SUBSTITUTE_URLS=
## Hardcoded in .mbsyncrc:
MAIL_CACHE="$HOME/.cache/mail"
[ -z "$SOURCEDIR" ] && SOURCEDIR="$PERSONAL"
[ -z "$XDG_CONFIG_HOME" ] && XDG_CONFIG_HOME="$HOME/.config"
[ -z "$XDG_DATA_HOME" ] && XDG_DATA_HOME="$HOME/.local/share"
[ -z "$XDG_BIN_HOME" ] && XDG_BIN_HOME="$XDG_DATA_HOME/../bin"
usage() {
cat <<EOF>&2
Usage: ${0##*/}
Initialize user profile: install packages, set up folders, etc.
Options:
-g DEVICE: Device where to sync ~/.gnupg from, e.g. '/dev/sda1'.
-u: Skip large updates (large packages, email cache, etc.)
-s URLS: Extra substitute URLs for Guix (space separated).
Example: 'http://192.168.1.2:8080'.
Environment variables:
SOURCEDIR=$SOURCEDIR
XDG_CONFIG_HOME=$XDG_CONFIG_HOME
XDG_DATA_HOME=$XDG_DATA_HOME
XDG_BIN_HOME=$XDG_BIN_HOME
Tips:
- Run the following command to install the Guix corresponding to your substitute
server:
guix pull -C my-channels.scm
- Copy the email cache to '$MAIL_CACHE' to speed up the process.
Direct link:
${HTTPS_ROOT}ambrevar/dotfiles/raw/master/.local/bin/homeinit
EOF
exit
}
OPT_UPDATE=true
OPT_DEVICE=""
while getopts ":hg:s:u" opt; do
case $opt in
h)
usage
exit ;;
g)
OPT_DEVICE="$OPTARG" ;;
s)
EXTRA_SUBSTITUTE_URLS="$OPTARG $EXTRA_SUBSTITUTE_URLS" ;;
u)
OPT_UPDATE=false ;;
\?)
usage
exit 1 ;;
esac
done
shift $(($OPTIND - 1))
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"
}
info() {
echo -e "$@"
}
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
}
## Pass substitute URLs dynamically to avoid overriding the daemon settings.
run_guix() {
if [ -z "$EXTRA_SUBSTITUTE_URLS" ]; then
guix "$@"
else
guix --substitute-urls="$EXTRA_SUBSTITUTE_URLS $SUBSTITUTE_URLS" "$@"
fi
}
run_current_guix() {
if [ -z "$EXTRA_SUBSTITUTE_URLS" ]; then
~/.config/guix/current/bin/guix "$@"
else
~/.config/guix/current/bin/guix --substitute-urls="$EXTRA_SUBSTITUTE_URLS $SUBSTITUTE_URLS" "$@"
fi
}
################################################################################
#
section "Initial packages"
if inpath guix; then
mkdir -p ~/.config/guix
## OpenSSH is not an input of Git, upstream does not want to increase the
## closure size that much.
mkdir -p "$(dirname "$PROFILE")"
run_guix package --profile="$PROFILE" --install openssh gnupg git stow password-store pinentry-tty pinentry-gtk2 cryptsetup recutils
source "$PROFILE"/etc/profile
fi
has_gpg_keys() {
[ -n "$(ls -1 ~/.gnupg/private-*)" ]
}
is_laptop() {
[ -n "$(ls -1 /sys/class/power_supply/ 2>/dev/null)" ]
}
if ! has_gpg_keys; then
section "GPG sync"
if [ -n "$OPT_DEVICE" ]; then
section "GnuPG"
sudo cryptsetup open "$OPT_DEVICE" gpg_backup
sudo mount -o compress=zstd /dev/mapper/gpg_backup /mnt
cp -a /mnt/public/.gnupg ~/
sudo umount /mnt
sudo cryptsetup close gpg_backup
else
warning "No device specified."
fi
fi
section "GPG"
if has_gpg_keys; 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" ] || [ -z "$INSIDE_EMACS" ]; then
## If a TTY, since our ~/.gnupg/gpg-agent.conf exists and specifies the Emacs
## pinentry, we must force the TTY version or else it won't work from a TTY.
## Same if not in Emacs (e.g. Xterm).
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 --homedir ~/.gnupg --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}$USER_NAME/personal "$SOURCEDIR"
fi
if [ -e ~/.password-store ]; then
git -C ~/.password-store pull
else
git clone ${SSH_ROOT}$USER_NAME/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 "$MAIL_CACHE" ~/.config ~/.config/guix ~/.config/guix-gaming-channels ~/.config/transmission-daemon ~/.emacs.d "$XDG_DATA_HOME" ~/.mpv ~/projects; do
mkdir -pv "$i"
done
## TODO: Stow Gaming, Dictionaries, etc.
section "Gaming"
lnn "$SOURCEDIR/games/games.scm.gpg" ~/.config/guix-gaming-channels/
section "Dictionaries"
lnn "$SOURCEDIR/dictionaries/.aspell.en.pws" ~/
lnn "$SOURCEDIR/dictionaries/.aspell.fr.pws" ~/
section "dotfiles"
if [ -e ~/dotfiles ]; then
git -C ~/dotfiles remote set-url origin ${ROOT}$USER_NAME/dotfiles
git -C ~/dotfiles pull
else
git clone ${ROOT}$USER_NAME/dotfiles ~/dotfiles || exit 1
fi
pushd ~/dotfiles
## .bash_profile may prevent .profile from being parsed, so we move it.
for i in ~/.bash_profile ~/.bashrc; do
[ -e "$i" ] && mv -v "$i" "$i".old
done
stow -v . || exit 1
popd
guix_install_profile() {
local profile
local manifest
manifest=$HOME/.package-lists/guix-$1-manifest.scm
if [ -f "$manifest" ]; then
if [ "$1" = "default" ]; then
info "Installing default profile..."
run_current_guix package --manifest="$manifest" --keep-failed
. ~/.guix-profile/etc/profile
else
profile=$HOME/.guix-extra-profiles/$1/$1
if [ ! -d "$HOME/.guix-extra-profiles/$1/$1" ]; then
info "Installing profile '$profile'..."
mkdir -p $(dirname "$profile")
run_current_guix package --manifest="$manifest" --keep-failed --profile="$profile"
if [ -f "$profile"/etc/profile ]; then
. "$profile"/etc/profile
fi
else
info "Profile '$profile' already installed."
fi
fi
else
warning "Manifest '$manifest' not found."
fi
}
section "System packages"
if inpath guix; then
if [ ! -e ~/.cache/guix ]; then
message "First 'guix pull'"
run_guix pull
hash guix
fi
for i in default main emacs nyxt texlive; do
guix_install_profile "$i"
done
if is_laptop; then
guix_install_profile laptop
guix_install_profile laptop-gaming
else
guix_install_profile gaming
fi
if $OPT_UPDATE; then
for i in blender chromium electrum racket; do
guix_install_profile "$i"
done
fi
else
warning "Package manager not supported. Install Guix."
fi
if inpath emacs; then
message "Emacs cache folder"
mkdir -pv "$HOME/.cache/emacs/"
message "Emacs local packages"
if [ -e "$XDG_DATA_HOME"/emacs/site-lisp ]; then
for i in "$XDG_DATA_HOME"/emacs/site-lisp/*; do
echo "$i"
git -C "$i" pull
done
else
mkdir -pv "$XDG_DATA_HOME"/emacs/site-lisp
fi
fi
if inpath guix; then
section "Cleanup initial packages"
rm -rv "$(dirname "$PROFILE")"
fi
if [ -x "$XDG_BIN_HOME"/updatedb-local ]; then
section "locate db"
"$XDG_BIN_HOME"/updatedb-local
fi
section "Mail"
# lnn "$SOURCEDIR/mail/authinfo.gpg" "$HOME/.authinfo.gpg" ## Only if not using password-store.
mkdir -pv "$MAIL_CACHE"
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="$MAIL_CACHE"
notmuch new
fi