mirror of
https://codeberg.org/gigirassy/stack.git
synced 2026-08-30 15:27:39 +00:00
Add stack
This commit is contained in:
@@ -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 "$@"
|
||||
Reference in New Issue
Block a user