Dry run by default: the script reads from both hosts (tokens, owners, names, license, SSH) and prints a plan; --apply creates the repositories and the Gitea -> GitHub push mirror after a final yes. Choosing GitHub applies the AGPL-3.0 license to the Gitea repository. A failed step is reported with what exists and how to continue; nothing is ever deleted. create-project.sh is now the entry point; the work lives in src/lib/, one responsibility per file. .gitignore gets !src/lib (the Python template ignores any lib/ folder). Tests grow to 599 checks, with a stub curl and ssh, and guards for the file structure. Task: MIL-002#1 Task: MIL-002#2 Task: MIL-002#3 Task: MIL-002#4 Task: MIL-002#5 Task: MIL-002#6 Refs #9 Refs #10 Refs #11 Refs #12 Refs #13 Refs #14 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
69 lines
1.9 KiB
Bash
69 lines
1.9 KiB
Bash
# shellcheck shell=bash
|
|
# shellcheck disable=SC2004,SC2034,SC2154 # shared state and arrays are declared in constants.sh
|
|
# prompts.sh - Interactive questions with validation of every answer.
|
|
#
|
|
# Part of create-project.sh: sourced by it, never run on its own.
|
|
#
|
|
# Provides: prompt_value, prompt_choice, prompt_yes_no
|
|
|
|
# prompt_value LABEL DEFAULT VALIDATOR HINT: ask until VALIDATOR accepts the
|
|
# answer; the accepted answer is returned in REPLY.
|
|
prompt_value() {
|
|
local label="$1" default="$2" validator="$3" hint="$4" answer
|
|
while true; do
|
|
if [[ -n $default ]]; then
|
|
printf '%s [%s]: ' "$label" "$default" >&2
|
|
else
|
|
printf '%s: ' "$label" >&2
|
|
fi
|
|
IFS= read -r answer || die "no input available for '$label'"
|
|
answer="$(trim "$answer")"
|
|
answer="${answer:-$default}"
|
|
if "$validator" "$answer"; then
|
|
REPLY="$answer"
|
|
return 0
|
|
fi
|
|
warn "invalid $label: $hint"
|
|
done
|
|
}
|
|
|
|
# prompt_choice LABEL DEFAULT CHOICE...: the answer is returned in REPLY.
|
|
prompt_choice() {
|
|
local label="$1" default="$2" answer
|
|
shift 2
|
|
while true; do
|
|
printf '%s (%s) [%s]: ' "$label" "$(IFS=/ && echo "$*")" "$default" >&2
|
|
IFS= read -r answer || die "no input available for '$label'"
|
|
answer="$(trim "$answer")"
|
|
answer="${answer:-$default}"
|
|
answer="${answer,,}"
|
|
if in_list "$answer" "$@"; then
|
|
REPLY="$answer"
|
|
return 0
|
|
fi
|
|
warn "invalid $label: choose one of $*"
|
|
done
|
|
}
|
|
|
|
# prompt_yes_no LABEL DEFAULT: DEFAULT is y or n; REPLY is 1 (yes) or 0 (no).
|
|
prompt_yes_no() {
|
|
local label="$1" default="$2" answer
|
|
while true; do
|
|
printf '%s (y/n) [%s]: ' "$label" "$default" >&2
|
|
IFS= read -r answer || die "no input available for '$label'"
|
|
answer="$(trim "$answer")"
|
|
answer="${answer:-$default}"
|
|
case "${answer,,}" in
|
|
y | yes)
|
|
REPLY=1
|
|
return 0
|
|
;;
|
|
n | no)
|
|
REPLY=0
|
|
return 0
|
|
;;
|
|
esac
|
|
warn "invalid $label: answer y or n"
|
|
done
|
|
}
|