Add stack

This commit is contained in:
gigirassy
2026-05-01 07:02:53 +02:00
parent 3527b6aa9e
commit 0eecdce1c6
+227
View File
@@ -0,0 +1,227 @@
#!/usr/bin/env bash
set -uo pipefail
CONFIG_FILE="${STACK_CONF:-$HOME/stack.conf}"
COMPOSE_CANDIDATES=(
"compose.yml"
"compose.yaml"
"docker-compose.yml"
"docker-compose.yaml"
)
usage() {
cat <<'EOF'
Usage:
stack start
stack add .
stack add foldername
stack add folder1 folder2 folder3
EOF
}
strip_quotes() {
local s="$1"
s="${s#\"}"
s="${s%\"}"
s="${s#\'}"
s="${s%\'}"
printf '%s' "$s"
}
resolve_path() {
local input="$1"
if command -v realpath >/dev/null 2>&1; then
realpath -m "$input"
else
python3 - "$input" <<'PY'
import os, sys
print(os.path.abspath(os.path.expanduser(sys.argv[1])))
PY
fi
}
ensure_config_exists() {
if [[ ! -f "$CONFIG_FILE" ]]; then
mkdir -p "$(dirname "$CONFIG_FILE")"
cat > "$CONFIG_FILE" <<EOF
STACK_HOME=$HOME
# one folder per line below
EOF
fi
}
load_config() {
STACK_HOME=""
STACK_DIRS=()
while IFS= read -r line || [[ -n "$line" ]]; do
line="${line%$'\r'}"
[[ -z "$line" ]] && continue
[[ "$line" =~ ^[[:space:]]*# ]] && continue
if [[ "$line" == STACK_HOME=* ]]; then
STACK_HOME="$(strip_quotes "${line#STACK_HOME=}")"
continue
fi
STACK_DIRS+=("$(strip_quotes "$line")")
done < "$CONFIG_FILE"
[[ -z "$STACK_HOME" ]] && STACK_HOME="$HOME"
}
compose_cmd() {
if docker compose version >/dev/null 2>&1; then
printf 'docker compose'
elif command -v docker-compose >/dev/null 2>&1; then
printf 'docker-compose'
else
echo "error: neither 'docker compose' nor 'docker-compose' is installed." >&2
exit 1
fi
}
add_folder() {
ensure_config_exists
load_config
if [[ $# -eq 0 ]]; then
echo "usage: stack add .|foldername|/path/to/folder [more folders...]" >&2
exit 1
fi
local added=0
local arg target
for arg in "$@"; do
if [[ "$arg" == "." ]]; then
target="$PWD"
elif [[ "$arg" == /* ]]; then
target="$arg"
else
target="$PWD/$arg"
fi
target="$(resolve_path "$target")"
if [[ ! -d "$target" ]]; then
echo "error: folder does not exist: $target" >&2
continue
fi
if grep -Fxq -- "$target" "$CONFIG_FILE"; then
echo "already in stack.conf: $target"
continue
fi || true
printf '%s\n' "$target" >> "$CONFIG_FILE"
echo "added: $target"
added=1
done
[[ "$added" -eq 0 ]] && exit 1
}
start_stacks() {
ensure_config_exists
load_config
local cc
cc="$(compose_cmd)"
local any=0 dir file found
for dir in "${STACK_DIRS[@]}"; do
[[ -z "$dir" ]] && continue
if [[ ! -d "$dir" ]]; then
echo "skipping missing folder: $dir" >&2
continue
fi
found=0
for file in "${COMPOSE_CANDIDATES[@]}"; do
if [[ -f "$dir/$file" ]]; then
found=1
any=1
echo "starting: $dir/$file"
(cd "$dir" && $cc -f "$file" up -d)
fi
done
if [[ "$found" -eq 0 ]]; then
echo "no compose file found in: $dir" >&2
fi
done
if [[ "$any" -eq 0 ]]; then
echo "no compose files were started."
fi
}
update_stacks() {
ensure_config_exists
load_config
local cc
cc="$(compose_cmd)"
local any=0 dir file found
for dir in "${STACK_DIRS[@]}"; do
[[ -z "$dir" ]] && continue
if [[ ! -d "$dir" ]]; then
echo "skipping missing folder: $dir" >&2
continue
fi
found=0
for file in "${COMPOSE_CANDIDATES[@]}"; do
if [[ -f "$dir/$file" ]]; then
found=1
any=1
echo "updating: $dir/$file"
(
cd "$dir" && \
$cc -f "$file" pull && \
$cc -f "$file" up -d
)
fi
done
if [[ "$found" -eq 0 ]]; then
echo "no compose file in: $dir" >&2
fi
done
if [[ "$any" -eq 0 ]]; then
echo "no compose files updated."
fi
}
main() {
local cmd="${1:-}"
shift || true
case "$cmd" in
start)
start_stacks
;;
update)
update_stacks
;;
add)
add_folder "$@"
;;
""|-h|--help|help)
usage
;;
*)
echo "unknown command: $cmd" >&2
usage
exit 1
;;
esac
}
main "$@"