#!/bin/bash
# =====================================================================
# Rename a machine, as far as anything is allowed to.
#
#   owuivm-set-name <machine-id>
#
# Reads the wanted name from /var/lib/owuivm/incoming/<id>.name, which
# the desktop tool wrote as the operator, and records it in the override
# file. Same staging trick as owuivm-insert-media, and for the same
# reason: a systemd unit instance carries one string, and that string is
# the machine id.
#
# WHY AN OVERRIDE FILE AND NOT AN EDIT TO configs/vms.toml
#
# Because that file is mostly comments, and they are the useful part of
# it - what an id is, why the ISO glob is not `*.iso`, what the prompt
# fields do. No TOML writer preserves comments, so a program that edits
# the registry in place is a program that deletes its own documentation
# the first time someone presses Rename.
#
# So the registry stays exactly as shipped and this writes a separate,
# tiny file that readers merge over the top. Only `name` is overridable,
# which is also the only field that is safe to change: `id` is identity
# and the rest is prompt text.
# =====================================================================
set -euo pipefail

INCOMING=${OWUIVM_INCOMING_DIR:-/var/lib/owuivm/incoming}
OVERRIDES=${OWUIVM_NAME_OVERRIDES:-/var/lib/owuivm/registry/vm-names.toml}
REGISTRY=${OWUIVM_REGISTRY:-/var/lib/owuivm/registry/vms.toml}

id="${1:-}"
[[ "$id" =~ ^[a-z0-9][a-z0-9-]{0,30}$ ]] || { echo "bad machine id '$id'" >&2; exit 64; }

if [ -r "$REGISTRY" ]; then
  grep -qE "^[[:space:]]*id[[:space:]]*=[[:space:]]*\"$id\"" "$REGISTRY" \
    || { echo "no machine '$id' in $REGISTRY" >&2; exit 64; }
fi

src="$INCOMING/$id.name"
[ -f "$src" ] || { echo "no name staged for $id" >&2; exit 65; }
[ ! -h "$src" ] || { echo "$src is a symlink; refusing" >&2; exit 65; }

# First line only, trimmed. A name is a label in a window title and in a
# report; a newline in it would be a second line of a TOML file.
wanted=$(head -c 200 "$src" | head -1 | tr -d '\r' | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
rm -f -- "$src"
[ -n "$wanted" ] || { echo "the name was empty" >&2; exit 64; }
# Printable, and nothing that would need escaping in a TOML basic string.
printf '%s' "$wanted" | grep -qP '^[^\x00-\x1f"\\]{1,40}$' \
  || { echo "a name must be 1-40 printable characters and no quotes or backslashes" >&2; exit 64; }

tmp=$(mktemp "${OVERRIDES}.XXXXXX")
trap 'rm -f "$tmp"' EXIT
{
  echo '# Machine display names, set from the Tool Server VM Maintenance app.'
  echo '# Merged over the `name` field in vms.toml. Delete a line to go back'
  echo '# to the shipped name; delete the file to reset all of them.'
  echo '[names]'
  # Every other machine's current override, kept.
  if [ -r "$OVERRIDES" ]; then
    grep -E '^[a-z0-9-]+[[:space:]]*=' "$OVERRIDES" | grep -vE "^$id[[:space:]]*=" || true
  fi
  printf '%s = "%s"\n' "$id" "$wanted"
} > "$tmp"
chmod 0644 "$tmp"
mv -f "$tmp" "$OVERRIDES"
trap - EXIT
echo "$id is now called $wanted"
