Files

96 lines
3.4 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}"
read_env_value() {
local key="$1"
[[ -f "$ENV_FILE" ]] || return 0
local value
value="$(sed -n "s/^${key}=//p" "$ENV_FILE" | tail -n 1)"
case "$value" in
\"*\") value="${value#\"}"; value="${value%\"}" ;;
\'*\') value="${value#\'}"; value="${value%\'}" ;;
esac
printf '%s\n' "$value"
}
configured_value() {
local key="$1"
local default_value="$2"
local value
value="${!key:-}"
if [[ -z "$value" ]]; then
value="$(read_env_value "$key")"
fi
printf '%s\n' "${value:-$default_value}"
}
resolve_app_path() {
local key="$1"
local raw="$2"
local clean candidate resolved current part
local -a parts=()
case "$raw" in
""|/*|.|..|../*|*/../*|*/..) echo "unsafe ${key} path" >&2; return 1 ;;
esac
if [[ "$raw" =~ [[:cntrl:]] ]]; then
echo "unsafe ${key} path" >&2
return 1
fi
clean="${raw#./}"
[[ -n "$clean" ]] || { echo "unsafe ${key} path" >&2; return 1; }
command -v realpath >/dev/null 2>&1 || { echo "realpath is required" >&2; return 1; }
candidate="$ROOT_DIR/$clean"
resolved="$(realpath -m -- "$candidate")" || { echo "unsafe ${key} path" >&2; return 1; }
case "$resolved" in
"$ROOT_DIR"/*) ;;
*) echo "unsafe ${key} path" >&2; return 1 ;;
esac
current="$ROOT_DIR"
IFS='/' read -r -a parts <<< "$clean"
for part in "${parts[@]}"; do
[[ -z "$part" || "$part" == "." ]] && continue
current="$current/$part"
if [[ -L "$current" ]]; then
echo "unsafe ${key} path" >&2
return 1
fi
done
printf '%s\n' "$resolved"
}
ensure_dir() {
local key="$1"
local raw
local path
raw="$(configured_value "$key" "$2")"
path="$(resolve_app_path "$key" "$raw")"
mkdir -p -- "$path"
[[ "$(resolve_app_path "$key" "$raw")" == "$path" ]] || { echo "unsafe ${key} path" >&2; return 1; }
}
ensure_dir "APP_DATA_DIR_1" "./data/workspace"
ensure_dir "APP_DATA_DIR_2" "./data/home-config"
ensure_dir "APP_DATA_DIR_3" "./data/home-share"
ensure_dir "APP_DATA_DIR_4" "./data/home-agents"
ensure_dir "APP_DATA_DIR_5" "./data/home-claude"
ensure_dir "APP_DATA_DIR_6" "./data/home-opencode"
CUSTOM_ENV_FILE_RAW="$(configured_value "CUSTOM_ENV_FILE" "./data/custom.env")"
CUSTOM_ENV_FILE_ABS="$(resolve_app_path "CUSTOM_ENV_FILE" "$CUSTOM_ENV_FILE_RAW")"
mkdir -p -- "$(dirname -- "$CUSTOM_ENV_FILE_ABS")"
touch -- "$CUSTOM_ENV_FILE_ABS"
echo '[opencode-workstation:init] initialized persistent directories:'
echo " $(resolve_app_path APP_DATA_DIR_1 "$(configured_value APP_DATA_DIR_1 "./data/workspace")") -> /workspace"
echo " $(resolve_app_path APP_DATA_DIR_2 "$(configured_value APP_DATA_DIR_2 "./data/home-config")") -> /home/opencode/.config"
echo " $(resolve_app_path APP_DATA_DIR_3 "$(configured_value APP_DATA_DIR_3 "./data/home-share")") -> /home/opencode/.local/share"
echo " $(resolve_app_path APP_DATA_DIR_4 "$(configured_value APP_DATA_DIR_4 "./data/home-agents")") -> /home/opencode/.agents"
echo " $(resolve_app_path APP_DATA_DIR_5 "$(configured_value APP_DATA_DIR_5 "./data/home-claude")") -> /home/opencode/.claude"
echo " $(resolve_app_path APP_DATA_DIR_6 "$(configured_value APP_DATA_DIR_6 "./data/home-opencode")") -> /home/opencode/.opencode"
echo " ${CUSTOM_ENV_FILE_ABS} -> custom env_file"
echo '[opencode-workstation:init] default serve address: http://0.0.0.0:4096'
echo '[opencode-workstation:init] ACP port: 8765'