Files
platform/scripts/setup/machine-setup/lib/files.sh
T
pastilhasandClaude Opus 5 2b9e16c11e port the shell section, and make one starship config serve both audiences
os-user-shell.ts:33 calls scripts/setup/starship.toml "the prompt config the
owner's own install uses — one file, both audiences". It was not: the original
machine script wrote a DIFFERENT config inline, so the owner got a prompt that
only disabled language modules while every member got the repo file with its
custom format. Two prompts, one comment claiming otherwise.

This deploys the same file the platform does, which makes the comment true.
Verified with cmp against a fresh account: byte-identical to what a member gets.

Nothing overwrites any more:

  .config/starship.toml and .tmux.conf go through install_config, so they are
  written when absent, skipped when identical, and KEPT when they differ — with
  the cp printed, so taking ours stays the reader's decision. On this host that
  is what happens: the existing config differs and is left alone.

  The starship line in .zshrc is marker-wrapped by append_once. Verified over
  three consecutive runs: one block, not three. The original appended it
  unguarded every time.

The login shell is now its own question. Having zsh on the machine and being
handed it at every login are different decisions, and `chsh` made the second one
silently. It also adds the shell to /etc/shells first, which chsh requires.

.tmux.conf lives here now, with the rest of the dotfiles, rather than in user
creation where the original put it only because that is where $USER_HOME first
exists.

One bug found by running it: install_config returns 2 for "kept yours", which is
an outcome rather than a failure — but still non-zero, so calling it as a plain
command under `set -e` ended the run before `case $?` could read it. Captured with
&& / || at both call sites, and the contract is documented where the function is
defined so the next caller does not repeat it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 20:45:25 +00:00

82 lines
2.6 KiB
Bash

#!/bin/bash
# =============================================================================
# machine-setup — writing files into somebody's home
# =============================================================================
#
# Definitions only, like the other lib/ files.
#
# ── The rule ──
#
# A setup script may create a config file. It may not silently replace one the
# user wrote. The original did the second: `cp .tmux.conf $USER_HOME/` on every
# run, over whatever was there, and five separate `cat >>` into .zshrc with no
# guard — so a second pass duplicated the starship init, the nvim PATH, bun, deno
# and the aliases.
#
# Both of those are the same mistake in different shapes: writing without looking
# first. The two helpers here are the two safe shapes.
[[ -n "${MACHINE_SETUP_FILES_LOADED:-}" ]] && return 0
MACHINE_SETUP_FILES_LOADED=1
# Put a config file in place, unless the user has their own.
#
# Three outcomes, and the caller can tell them apart by the return code:
#
# 0 installed — there was nothing there
# 1 identical — already exactly this, nothing done
# 2 kept — theirs differs, left alone
#
# Converging when there is nothing to lose and keeping what the user wrote when
# there is. The third case prints how to take ours, so the choice stays with
# them.
#
# NOTE for callers: 1 and 2 are outcomes, not failures — but they are still
# non-zero, so calling this as a plain command under `set -e` ends the script
# before the result can be read. Always capture it:
#
# install_config "$src" "$dest" "$user" && rc=0 || rc=$?
install_config() {
local src="$1" dest="$2" owner="$3"
if [[ -f "$dest" ]]; then
if cmp -s "$src" "$dest"; then
return 1
fi
warn "kept your ${dest} — it differs from the one shipped here"
echo " to take ours instead: cp ${src} ${dest}"
return 2
fi
install -D -m 0644 -o "$owner" -g "$owner" "$src" "$dest"
return 0
}
# Append a block to a file exactly once.
#
# The block is wrapped in markers naming what it is, so a second run recognises
# its own work instead of adding it again — and so a human reading the file can
# see which lines came from here and delete them as a unit.
#
# append_once ~/.zshrc bun <<'EOF'
# export PATH="$HOME/.bun/bin:$PATH"
# EOF
#
# Returns 0 if it wrote, 1 if the block was already there.
append_once() {
local file="$1" name="$2"
local begin="# >>> machine-setup: ${name} >>>"
local end="# <<< machine-setup: ${name} <<<"
if [[ -f "$file" ]] && grep -qF "$begin" "$file"; then
return 1
fi
{
echo ""
echo "$begin"
cat
echo "$end"
} >>"$file"
}