dx/dxkit/core/flag.sh

185 lines
4.5 KiB
Bash

#!/usr/bin/env bash
# dxkit/core/flags.sh
#
# Shared CLI flag parsing for build and init commands.
#
# Parses flags into exported RUN_* and other control vars.
# Both build::run and init::run call flag::parse before doing any work,
# so --skip-* flags work identically whether passed to dx build or dx init.
#
# Usage:
# flag::parse "$@"
# flag::parse --init --skip-vendors --port=8082
declare -A _REGISTERED_FLAGS=()
function flag::defaults() {
flag::set --framework yii2-advanced
flag::set --skip-vendors false
flag::set --skip-framework-init false
flag::set --skip-framework-config false
}
function flag::register() {
for flag in "$@"; do
_REGISTERED_FLAGS["$flag"]=1
done
}
function flag::registered() {
[[ -n "${_REGISTERED_FLAGS["$1"]:-}" ]]
}
function flag::set() {
local var
var="$(flag::to_var "$1")"
export "${var}"="${2:-true}"
}
function flag::enable() { flag::set "$1" true; }
function flag::disable() { flag::set "$1" false; }
function flag::enabled() {
local var
var="$(flag::to_var "$1")"
[[ "${!var:-false}" == true ]]
}
function flag::to_var() {
local flag="${1#--}"
flag="${flag//-/_}"
echo "${flag^^}"
}
function flag::value() {
local flag="$1"
local default="${2:-}"
# Look for --flag=value in the raw args
local var
var="$(flag::to_var "$flag")"
# Check if set as a var (from flag::parse)
if [[ -n "${!var:-}" ]]; then
echo "${!var}"
return 0
fi
echo "$default"
}
function flag::load_defaults() {
local defaults_file
defaults_file="$(ctx::artifact)/.dx-flags"
[[ -f "$defaults_file" ]] || return 0
# Read non-empty, non-comment lines as flags
local flags=()
while IFS= read -r line; do
[[ -z "$line" || "$line" == "#"* ]] && continue
flags+=("$line")
done < "$defaults_file"
[[ ${#flags[@]} -eq 0 ]] && return 0
flag::parse "${flags[@]}"
}
function flag::scaffold_defaults_file() {
local file="$(ctx::artifact)/.dx-flags"
[[ -f "$file" ]] && return 0 # already exists, don't overwrite
cat > "$file" <<EOF
# .dx-flags — local developer flag defaults
# Uncomment to enable. This file is gitignored.
#
# --skip-vendors
# --skip-framework-init
# --skip-framework-config
EOF
log::fs_write "Created .dx-flags — edit to set your local flag defaults"
}
function flag::parse() {
for arg in "$@"; do
case "$arg" in
--framework=*) export APP_FRAMEWORK="${arg#*=}" ;;
--dev) export ENVIRONMENT="dev" ;;
--qly) export ENVIRONMENT="qly" ;;
--prd) export ENVIRONMENT="prd" ;;
--project=*) export PROJECT_NAME="${arg#*=}" ;;
--port=*) export APP_PORT="${arg#*=}" ;;
--db=*) export DB_ENGINE="${arg#*=}" ;;
--db-port=*) export DB_PORT="${arg#*=}" ;;
--debug) set -x ;;
--help) return 1 ;;
--*)
if [[ "$arg" == *"="* ]]; then
# --flag=value form
local flag_name="${arg%%=*}"
local flag_value="${arg#*=}"
if [[ ${#_REGISTERED_FLAGS[@]} -gt 0 ]] && ! flag::registered "$flag_name"; then
log::error "Unknown flag: '${flag_name}'"
return 1
fi
local var
var="$(flag::to_var "$flag_name")"
export "${var}"="$flag_value"
else
if [[ ${#_REGISTERED_FLAGS[@]} -gt 0 ]] && ! flag::registered "$arg"; then
log::error "Unknown flag: '${arg}'"
return 1
fi
flag::enable "$arg"
fi
;;
*)
log::error "Unknown argument: '${arg}'"
return 1
;;
esac
done
}
# Write local overrides to env/local.env so subsequent dx commands
# (dx up, dx init, etc.) see the same values without re-passing flags.
#
# Only writes vars that differ from their defaults, keeping local.env minimal.
# Called by build::run after flag::parse.
function flag::persist_overrides() {
local local_env
local_env="$(ctx::artifact)/env/local.env"
# Vars that are meaningful to persist across commands
local persist_vars=(
ENVIRONMENT
PROJECT_NAME
APP_PORT
DB_ENGINE
DB_PORT
USE_VHOSTS
)
# Build the new content
local content=""
for var in "${persist_vars[@]}"; do
[[ -n "${!var:-}" ]] && content+="export ${var}=\"${!var}\"\n"
done
[[ -z "$content" ]] && return 0
printf "%b" "$content" > "$local_env"
log::info "Persisted overrides to env/local.env"
}
# ============================================
# Specify Defaults
# ============================================
flag::defaults
flag::load_defaults