#!/usr/bin/env bash set -euo pipefail REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" QUICK=no DO_COMMIT=no INSTALL_HOOK=no DRY_RUN=no usage() { cat <&2 usage >&2 exit 2 ;; esac shift done log() { printf '\033[1;32m[sync]\033[0m %s\n' "$*"; } warn() { printf '\033[1;33m[warn]\033[0m %s\n' "$*"; } root_cp() { if [[ "$DRY_RUN" == "yes" ]]; then log " would copy $1 -> $2" return 0 fi if [[ $EUID -eq 0 ]]; then cp "$1" "$2" elif cp "$1" "$2" 2>/dev/null; then : # readable as current user — done elif command -v sudo >/dev/null 2>&1; then sudo cp "$1" "$2" else warn "need root to copy $1" return 1 fi } rsync_portage() { # -L: dereference symlinks so /etc/portage symlinks back into the repo # are copied as content, never re-created as self-referencing symlinks. # Broken symlinks are excluded (rsync -L aborts on dangling referents). local exfile exfile="$(mktemp)" printf '.gitkeep\nmake.profile\n' >"$exfile" find /etc/portage -type l ! -exec test -e {} \; -printf '%P\n' >>"$exfile" local -a opts=(-aL --delete "--exclude-from=$exfile") [[ "$DRY_RUN" == "yes" ]] && opts+=(-n) log "portage /etc/portage -> repo/portage/etc/portage" rsync "${opts[@]}" /etc/portage/ "$REPO_DIR/portage/etc/portage/" rm -f "$exfile" } sync_portage() { rsync_portage if [[ -e /etc/portage/make.profile ]]; then log "profile: $(readlink /etc/portage/make.profile)" if [[ "$DRY_RUN" != "yes" ]]; then printf '%s\n' "$(readlink /etc/portage/make.profile)" >"$REPO_DIR/portage/PROFILE" else log " would write: portage/PROFILE" fi fi log "world /var/lib/portage/world -> repo" if [[ -L /var/lib/portage/world ]] && [[ "$(readlink -f /var/lib/portage/world)" == "$REPO_DIR/portage/var/lib/portage/world" ]]; then log " already a symlink into the repo — no copy needed" else root_cp /var/lib/portage/world "$REPO_DIR/portage/var/lib/portage/world" fi if [[ -s /var/lib/portage/world_sets ]]; then log "world_sets /var/lib/portage/world_sets -> repo" root_cp /var/lib/portage/world_sets "$REPO_DIR/portage/var/lib/portage/world_sets" fi } sync_system() { log "fstab /etc/fstab -> repo/fstab/etc/fstab" root_cp /etc/fstab "$REPO_DIR/fstab/etc/fstab" if [[ -f /etc/greetd/config.toml ]]; then log "greetd /etc/greetd/config.toml -> repo/config.toml" root_cp /etc/greetd/config.toml "$REPO_DIR/config.toml" fi } install_hook() { local hook=/etc/portage/postsync.d/update-dotfiles if [[ "$DRY_RUN" == "yes" ]]; then log " would write: $hook" return 0 fi log "writing $hook" if [[ $EUID -eq 0 ]]; then mkdir -p /etc/portage/postsync.d cat >"$hook" </dev/null 2>&1; then sudo tee "$hook" >/dev/null <