#!/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 <&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 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) 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<"$(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 <