Fix set -e bug causing silent exit after valid input
- Replace all `[[ condition ]] && die` with `if/fi` — the && pattern exits silently when the condition is false under set -e - Removed -e from set flags (kept -uo pipefail), all error paths are now explicit - Declare `input` as local in ask/ask_yn/ask_choice to prevent leakage - Use `read -r input || true` to handle EOF safely - Fix ask_choice arithmetic to avoid (()) triggering exit on false Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
452a603cdf
commit
431e5493fc
3 changed files with 24 additions and 22 deletions
|
|
@ -41,7 +41,7 @@ ensure_git() {
|
|||
fi
|
||||
warn "git not found."
|
||||
ask_yn _install "Install git now?" "y"
|
||||
[[ "$_install" != "y" ]] && die "git is required."
|
||||
if [[ "$_install" != "y" ]]; then die "git is required."; fi
|
||||
install_pkg git
|
||||
command -v git &>/dev/null || die "git installation failed."
|
||||
success "git installed: $(git --version)"
|
||||
|
|
@ -69,7 +69,8 @@ ensure_container_runtime() {
|
|||
"podman (recommended)" \
|
||||
"docker"
|
||||
|
||||
case "$_runtime" in
|
||||
local runtime_choice="$_runtime"
|
||||
case "$runtime_choice" in
|
||||
podman*)
|
||||
_install_podman
|
||||
CONTAINER_CMD="podman"
|
||||
|
|
|
|||
19
lib/utils.sh
19
lib/utils.sh
|
|
@ -18,26 +18,27 @@ header() { echo -e "\n${BOLD}${CYAN}━━━ $* ━━━${RESET}\n"; }
|
|||
# ask VAR "prompt" "default"
|
||||
ask() {
|
||||
local var="$1" prompt="$2" default="$3"
|
||||
local input
|
||||
if [[ -n "$default" ]]; then
|
||||
echo -ne "${BOLD}${prompt}${RESET} ${CYAN}[${default}]${RESET}: "
|
||||
else
|
||||
echo -ne "${BOLD}${prompt}${RESET}: "
|
||||
fi
|
||||
read -r input
|
||||
read -r input || true
|
||||
if [[ -z "$input" && -n "$default" ]]; then
|
||||
eval "$var=\"$default\""
|
||||
eval "$var=\"\$default\""
|
||||
else
|
||||
eval "$var=\"$input\""
|
||||
eval "$var=\"\$input\""
|
||||
fi
|
||||
}
|
||||
|
||||
# ask_yn VAR "prompt" "y|n"
|
||||
ask_yn() {
|
||||
local var="$1" prompt="$2" default="$3"
|
||||
local options
|
||||
local input options
|
||||
if [[ "$default" == "y" ]]; then options="Y/n"; else options="y/N"; fi
|
||||
echo -ne "${BOLD}${prompt}${RESET} ${CYAN}[${options}]${RESET}: "
|
||||
read -r input
|
||||
read -r input || true
|
||||
input="${input:-$default}"
|
||||
if [[ "$input" =~ ^[Yy]$ ]]; then
|
||||
eval "$var=y"
|
||||
|
|
@ -50,18 +51,20 @@ ask_yn() {
|
|||
ask_choice() {
|
||||
local var="$1" prompt="$2"; shift 2
|
||||
local options=("$@")
|
||||
local input idx
|
||||
echo -e "${BOLD}${prompt}${RESET}"
|
||||
for i in "${!options[@]}"; do
|
||||
echo -e " ${CYAN}$((i+1))${RESET}) ${options[$i]}"
|
||||
done
|
||||
echo -ne "Choice ${CYAN}[1]${RESET}: "
|
||||
read -r input
|
||||
read -r input || true
|
||||
input="${input:-1}"
|
||||
if [[ "$input" =~ ^[0-9]+$ ]] && (( input >= 1 && input <= ${#options[@]} )); then
|
||||
eval "$var=\"${options[$((input-1))]}\""
|
||||
idx=$(( input - 1 ))
|
||||
else
|
||||
eval "$var=\"${options[0]}\""
|
||||
idx=0
|
||||
fi
|
||||
eval "$var=\"\${options[$idx]}\""
|
||||
}
|
||||
|
||||
require_cmd() {
|
||||
|
|
|
|||
22
wizard.sh
22
wizard.sh
|
|
@ -2,7 +2,7 @@
|
|||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ Context Studio Wizard — Project Setup ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
set -euo pipefail
|
||||
set -uo pipefail
|
||||
|
||||
WIZARD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
|
|
@ -17,17 +17,17 @@ collect_project_info() {
|
|||
header "Project Details"
|
||||
|
||||
ask PROJECT_NAME "Project name" ""
|
||||
[[ -z "$PROJECT_NAME" ]] && die "Project name is required."
|
||||
if [[ -z "$PROJECT_NAME" ]]; then die "Project name is required."; fi
|
||||
|
||||
local default_dir="$HOME/projects/$(slugify "$PROJECT_NAME")"
|
||||
ask PROJECT_DIR "Project location" "$default_dir"
|
||||
[[ -z "$PROJECT_DIR" ]] && die "Project location is required."
|
||||
if [[ -z "$PROJECT_DIR" ]]; then die "Project location is required."; fi
|
||||
PROJECT_DIR="${PROJECT_DIR/#\~/$HOME}"
|
||||
|
||||
if [[ -e "$PROJECT_DIR" ]]; then
|
||||
warn "Directory already exists: $PROJECT_DIR"
|
||||
ask_yn _continue "Continue anyway?" "n"
|
||||
[[ "$_continue" != "y" ]] && die "Aborted."
|
||||
if [[ "$_continue" != "y" ]]; then die "Aborted."; fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -41,14 +41,13 @@ collect_workflow_info() {
|
|||
|
||||
if [[ "$WORKFLOW_SOURCE" == "Clone from existing repo" ]]; then
|
||||
ask WORKFLOW_REPO "Workflow repo URL" ""
|
||||
[[ -z "$WORKFLOW_REPO" ]] && die "Repo URL is required."
|
||||
if [[ -z "$WORKFLOW_REPO" ]]; then die "Repo URL is required."; fi
|
||||
else
|
||||
ask PROJECT_DESC "Project description" "A software project"
|
||||
ask TECH_STACK "Tech stack (e.g. Node.js, Rust, Python)" "Node.js"
|
||||
ask_choice AGENT_PRESET "Agent preset" \
|
||||
"minimal (5 agents: coordinator, 2 coders, researcher, tester)" \
|
||||
"standard (9 agents: 2 coordinators, 3 coders, 2 researchers, tester, reviewer)"
|
||||
# Normalize to short key
|
||||
case "$AGENT_PRESET" in
|
||||
minimal*) AGENT_PRESET="minimal" ;;
|
||||
*) AGENT_PRESET="standard" ;;
|
||||
|
|
@ -63,15 +62,15 @@ confirm_summary() {
|
|||
echo -e " ${BOLD}Location${RESET} : $PROJECT_DIR"
|
||||
echo -e " ${BOLD}Core${RESET} : $CS_CORE_DIR"
|
||||
if [[ "${WORKFLOW_SOURCE:-}" == "Clone from existing repo" ]]; then
|
||||
echo -e " ${BOLD}Workflow${RESET} : clone $WORKFLOW_REPO"
|
||||
echo -e " ${BOLD}Workflow${RESET} : clone ${WORKFLOW_REPO:-}"
|
||||
else
|
||||
echo -e " ${BOLD}Workflow${RESET} : generate ($AGENT_PRESET preset)"
|
||||
echo -e " ${BOLD}Workflow${RESET} : generate (${AGENT_PRESET:-minimal} preset)"
|
||||
echo -e " ${BOLD}Description${RESET} : ${PROJECT_DESC:-}"
|
||||
echo -e " ${BOLD}Tech stack${RESET} : ${TECH_STACK:-}"
|
||||
fi
|
||||
echo ""
|
||||
ask_yn _ok "Create project?" "y"
|
||||
[[ "$_ok" != "y" ]] && die "Aborted."
|
||||
if [[ "$_ok" != "y" ]]; then die "Aborted."; fi
|
||||
}
|
||||
|
||||
# ── Build ──────────────────────────────────────────────────────────────────
|
||||
|
|
@ -82,15 +81,14 @@ build_project() {
|
|||
create_devcontainer "$PROJECT_DIR" "$PROJECT_NAME"
|
||||
|
||||
if [[ "${WORKFLOW_SOURCE:-}" == "Clone from existing repo" ]]; then
|
||||
clone_workflow "$PROJECT_DIR" "$WORKFLOW_REPO"
|
||||
clone_workflow "$PROJECT_DIR" "${WORKFLOW_REPO:-}"
|
||||
else
|
||||
generate_workflow "$PROJECT_DIR" "$PROJECT_NAME" \
|
||||
"${PROJECT_DESC:-A software project}" \
|
||||
"${TECH_STACK:-Node.js}" \
|
||||
"$AGENT_PRESET"
|
||||
"${AGENT_PRESET:-minimal}"
|
||||
fi
|
||||
|
||||
# Init git repo
|
||||
git -C "$PROJECT_DIR" init -q
|
||||
git -C "$PROJECT_DIR" add .
|
||||
git -C "$PROJECT_DIR" commit -q -m "Initial project setup via Context Studio Wizard"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue