ambevar-dotfiles/.local/bin/homeinit

295 lines
7.2 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
[ -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 "$XDG_BIN_HOME" ] && XDG_BIN_HOME="$XDG_DATA_HOME/../bin"
## Hardcoded in .mbsyncrc:
MAIL_CACHE="$HOME/.cache/mail"
usage() {
cat <<EOF>&2
Usage: ${0##*/}
Initialize user profile: install packages, set up folders, etc.
Options:
-g DEVICE: Device where to sync ~/.gnupg.
-u: Skip large updates (packages, emails, 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
Tip:
- Run `guix pull -C my-channels.scm' to run the Guix corresponding to your
substitute server.
- 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)
SUBSTITUTE_URLS="$OPTARG $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
}
################################################################################
#
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")"
guix package --profile="$PROFILE" --install openssh gnupg git stow password-store pinentry-tty pinentry-gtk2 cryptsetup recutils --substitute-urls="$SUBSTITUTE_URLS"
source "$PROFILE"/etc/profile
fi
has_gpg_keys() {
[ -n "$(ls -1 ~/.gnupg/private-*)" ]
}
is_laptop() {
[ -n "$(ls -1 /sys/class/power_supply/)" ]
}
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 ~/personal
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/transmission-daemon .emacs.d "$XDG_DATA_HOME" .mpv projects; do
mkdir -pv "$HOME/$i"
done
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.
[ -e ~/.bash_profile ] && mv -v ~/.bash_profile ~/.bash_profile.old
stow -v . || exit 1
popd
guix_install_profile() {
local profile
local manifest
manifest=$HOME/.package-lists/guix-$i-manifest.scm
if [ -f "$manifest"]; then
warning "Manifest $manifest not found."
else
profile=$HOME/.guix-extra-profiles/$i/$i
mkdir -p $(dirname "$profile")
~/.config/guix/current/bin/guix package --manifest=$HOME/.package-lists/guix-$i-manifest.scm --keep-failed --profile="$profile" --substitute-urls="$SUBSTITUTE_URLS"
if [ -f "$profile"/etc/profile ]; then
. "$profile"/etc/profile
fi
fi
}
section "System packages"
if inpath guix; then
if [ ! -e ~/.cache/guix ]; then
message "First 'guix pull'"
guix pull --substitute-urls="$SUBSTITUTE_URLS"
hash guix
fi
~/.config/guix/current/bin/guix package --manifest=$HOME/.package-lists/guix-default-manifest.scm --keep-failed --substitute-urls="$SUBSTITUTE_URLS"
. ~/.guix-profile/etc/profile
for i in main emacs next texlive; do
guix_install_profile "$i"
done
if $is_laptop; then
guix_install_profile laptop 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