#!/bin/bash # ============================================================================= # machine-setup — the development environment # ============================================================================= # # Definitions only, like the other lib/ files. [[ -n "${MACHINE_SETUP_DEV_LOADED:-}" ]] && return 0 MACHINE_SETUP_DEV_LOADED=1 # ----------------------------------------------------------------------------- # git # ----------------------------------------------------------------------------- # # Read and written as the account, not as root. `git config --global` writes to # $HOME/.gitconfig, so running it under sudo without -H would write root's. # # ── Why this asks before touching an existing identity ── # # The original set all four values unconditionally on every run. Re-running it on # a machine somebody already uses replaces the name and email they had with # whatever is typed — and prompt_value accepts an empty answer, so pressing # Enter twice wrote `user.name = ""`. An empty name is worse than none at all: # unset makes git refuse to commit and say why, empty makes it commit with a # blank author and never mention it. # # ── And why it is worth being careful about here in particular ── # # docs/agent-git-identity.md: every agent Officer runs commits AS THE OWNER, # because it runs as the owner. So this is not only the human's identity — it is # what `git log` will attribute every agent commit on this machine to. # Run from / rather than wherever the script was launched. # # `git config --global` reads and writes $HOME/.gitconfig and needs no repository # — but git still stats the working directory on the way, looking for one. The # script is typically launched from somewhere under the invoking user's home, # which is 0750, so the target account cannot stat it and every call dies with # # fatal: failed to stat '': Permission denied # # Found because the writes failed silently: the section reported "written" while # nothing had been. Both wrappers now run in a subshell from /, which every # account can stat, and their exit status is checked by the caller. git_get() { (cd / && sudo -H -u "$USERNAME" git config --global --get "$1" 2>/dev/null); } git_set() { (cd / && sudo -H -u "$USERNAME" git config --global "$1" "$2"); } # Is there anything configured at all? git_has_identity() { [[ -n "$(git_get user.name)" || -n "$(git_get user.email)" ]]; } # Ask for a value that must not be empty. The original's prompt accepted empty # and wrote it; this re-asks. ask_required() { local __var="$1" message="$2" default="$3" answer="" while [[ -z "$answer" ]]; do if ! read -rp " ${message}${default:+ [$default]}: " answer; then echo "" fail "No answer." fi answer="${answer:-$default}" [[ -z "$answer" ]] && warn "This one cannot be left blank." done printf -v "$__var" '%s' "$answer" }