565 lines
18 KiB
Bash
Executable File
565 lines
18 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# archeflow-init.sh — Initialize an ArcheFlow project from a template bundle, clone from
|
|
# another project, save the current setup as a template, or list available templates.
|
|
#
|
|
# Usage:
|
|
# archeflow-init.sh <bundle-name> [--set key=value ...] Init from named bundle
|
|
# archeflow-init.sh --from <project-path> Clone from another project
|
|
# archeflow-init.sh --list List available templates
|
|
# archeflow-init.sh --save <name> Save current setup as template
|
|
# archeflow-init.sh --share <name> <path> Export template to directory
|
|
#
|
|
# Examples:
|
|
# ./lib/archeflow-init.sh writing-short-story
|
|
# ./lib/archeflow-init.sh writing-short-story --set target_words=8000
|
|
# ./lib/archeflow-init.sh --from ../book.giesing-gschichten
|
|
# ./lib/archeflow-init.sh --save my-story-setup
|
|
# ./lib/archeflow-init.sh --list
|
|
|
|
set -euo pipefail
|
|
|
|
GLOBAL_TEMPLATES="${HOME}/.archeflow/templates"
|
|
LOCAL_TEMPLATES=".archeflow/templates"
|
|
|
|
# --- Helpers ----------------------------------------------------------------
|
|
|
|
die() { echo "ERROR: $*" >&2; exit 1; }
|
|
warn() { echo "WARNING: $*" >&2; }
|
|
info() { echo " $*"; }
|
|
|
|
# Parse YAML value (simple single-level extraction — no nested support).
|
|
# Falls back to grep+sed when yq is unavailable.
|
|
yaml_value() {
|
|
local file="$1" key="$2"
|
|
if command -v yq &>/dev/null; then
|
|
yq -r ".$key // empty" "$file" 2>/dev/null
|
|
else
|
|
grep -E "^${key}:" "$file" 2>/dev/null | sed 's/^[^:]*:[[:space:]]*//' | sed 's/^["'"'"']\(.*\)["'"'"']$/\1/'
|
|
fi
|
|
}
|
|
|
|
# Parse YAML list (simple — one item per "- " line under key).
|
|
yaml_list() {
|
|
local file="$1" key="$2"
|
|
if command -v yq &>/dev/null; then
|
|
yq -r ".$key[]? // empty" "$file" 2>/dev/null
|
|
else
|
|
sed -n "/^${key}:/,/^[^ -]/{ /^ *- /{ s/^ *- *//; s/^[\"']\(.*\)[\"']$/\1/; p; } }" "$file" 2>/dev/null
|
|
fi
|
|
}
|
|
|
|
# Check if a directory has files matching a glob (safe for empty results).
|
|
has_files() {
|
|
local dir="$1" pattern="${2:-*}"
|
|
# shellcheck disable=SC2086
|
|
compgen -G "${dir}/${pattern}" &>/dev/null
|
|
}
|
|
|
|
# Confirm overwrite if target exists and has files.
|
|
confirm_overwrite() {
|
|
local dir="$1" desc="$2"
|
|
if [[ -d "$dir" ]] && has_files "$dir"; then
|
|
warn "$desc already has files in $dir"
|
|
if [[ -t 0 ]]; then
|
|
read -r -p " Overwrite? [y/N] " answer
|
|
[[ "$answer" =~ ^[Yy]$ ]] || die "Aborted — will not overwrite existing files."
|
|
else
|
|
die "Non-interactive mode — will not overwrite existing files in $dir. Remove them first."
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# --- Commands ---------------------------------------------------------------
|
|
|
|
cmd_list() {
|
|
echo "ArcheFlow Templates"
|
|
echo "===================="
|
|
echo ""
|
|
|
|
# Bundles
|
|
local found_bundle=false
|
|
echo "Bundles:"
|
|
for base in "$LOCAL_TEMPLATES" "$GLOBAL_TEMPLATES"; do
|
|
local scope
|
|
[[ "$base" == "$LOCAL_TEMPLATES" ]] && scope="local" || scope="global"
|
|
if [[ -d "$base/bundles" ]]; then
|
|
for manifest in "$base"/bundles/*/manifest.yaml; do
|
|
[[ -f "$manifest" ]] || continue
|
|
found_bundle=true
|
|
local bname bdir desc
|
|
bdir="$(dirname "$manifest")"
|
|
bname="$(basename "$bdir")"
|
|
desc="$(yaml_value "$manifest" "description")"
|
|
printf " %-25s %-45s [%s]\n" "$bname" "${desc:-(no description)}" "$scope"
|
|
done
|
|
fi
|
|
done
|
|
$found_bundle || echo " (none)"
|
|
echo ""
|
|
|
|
# Individual templates
|
|
echo "Individual Templates:"
|
|
for category in workflows teams archetypes domains; do
|
|
local found=false
|
|
local label
|
|
label="$(echo "$category" | sed 's/^./\U&/')" # Capitalize
|
|
echo " ${label}:"
|
|
for base in "$LOCAL_TEMPLATES" "$GLOBAL_TEMPLATES"; do
|
|
local scope
|
|
[[ "$base" == "$LOCAL_TEMPLATES" ]] && scope="local" || scope="global"
|
|
if [[ -d "$base/$category" ]]; then
|
|
for f in "$base/$category"/*; do
|
|
[[ -f "$f" ]] || continue
|
|
found=true
|
|
printf " %-35s [%s]\n" "$(basename "$f")" "$scope"
|
|
done
|
|
fi
|
|
done
|
|
$found || echo " (none)"
|
|
done
|
|
}
|
|
|
|
cmd_init_bundle() {
|
|
local bundle_name="$1"
|
|
shift
|
|
local -A overrides=()
|
|
|
|
# Parse --set key=value arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--set)
|
|
shift
|
|
[[ $# -gt 0 ]] || die "--set requires a key=value argument"
|
|
local k="${1%%=*}" v="${1#*=}"
|
|
overrides["$k"]="$v"
|
|
shift
|
|
;;
|
|
*)
|
|
die "Unknown argument: $1"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Find the bundle
|
|
local bundle_dir=""
|
|
for base in "$LOCAL_TEMPLATES" "$GLOBAL_TEMPLATES"; do
|
|
if [[ -f "$base/bundles/${bundle_name}/manifest.yaml" ]]; then
|
|
bundle_dir="$base/bundles/${bundle_name}"
|
|
break
|
|
fi
|
|
done
|
|
[[ -n "$bundle_dir" ]] || die "Bundle not found: $bundle_name. Run '$0 --list' to see available templates."
|
|
|
|
local manifest="$bundle_dir/manifest.yaml"
|
|
echo "Initializing from bundle: $bundle_name"
|
|
echo " Source: $bundle_dir"
|
|
echo ""
|
|
|
|
# Check requires
|
|
local req
|
|
while IFS= read -r req; do
|
|
[[ -z "$req" ]] && continue
|
|
if [[ ! -e "$req" ]]; then
|
|
die "Required file not found: $req. This bundle requires it in the project root."
|
|
fi
|
|
info "Requirement satisfied: $req"
|
|
done < <(yaml_list "$manifest" "requires")
|
|
|
|
# Create target directories
|
|
mkdir -p .archeflow/teams .archeflow/workflows .archeflow/archetypes .archeflow/domains
|
|
|
|
# Copy team
|
|
local team_file
|
|
team_file="$(yaml_value "$manifest" "includes.team" 2>/dev/null || true)"
|
|
# Fallback for flat YAML parsing
|
|
if [[ -z "$team_file" ]] && command -v yq &>/dev/null; then
|
|
team_file="$(yq -r '.includes.team // empty' "$manifest" 2>/dev/null)"
|
|
fi
|
|
if [[ -n "$team_file" && -f "$bundle_dir/$team_file" ]]; then
|
|
confirm_overwrite ".archeflow/teams" "Teams directory"
|
|
cp "$bundle_dir/$team_file" ".archeflow/teams/$team_file"
|
|
info "Team: $team_file -> .archeflow/teams/"
|
|
elif [[ -n "$team_file" ]]; then
|
|
# team_file might just be the name, check without path
|
|
if [[ -f "$bundle_dir/team.yaml" ]]; then
|
|
confirm_overwrite ".archeflow/teams" "Teams directory"
|
|
cp "$bundle_dir/team.yaml" ".archeflow/teams/$team_file"
|
|
info "Team: $team_file -> .archeflow/teams/"
|
|
else
|
|
warn "Team file not found in bundle: $team_file"
|
|
fi
|
|
fi
|
|
|
|
# Copy workflow
|
|
local wf_file
|
|
wf_file="$(yaml_value "$manifest" "includes.workflow" 2>/dev/null || true)"
|
|
if [[ -z "$wf_file" ]] && command -v yq &>/dev/null; then
|
|
wf_file="$(yq -r '.includes.workflow // empty' "$manifest" 2>/dev/null)"
|
|
fi
|
|
if [[ -n "$wf_file" && -f "$bundle_dir/$wf_file" ]]; then
|
|
confirm_overwrite ".archeflow/workflows" "Workflows directory"
|
|
cp "$bundle_dir/$wf_file" ".archeflow/workflows/$wf_file"
|
|
info "Workflow: $wf_file -> .archeflow/workflows/"
|
|
elif [[ -n "$wf_file" && -f "$bundle_dir/workflow.yaml" ]]; then
|
|
confirm_overwrite ".archeflow/workflows" "Workflows directory"
|
|
cp "$bundle_dir/workflow.yaml" ".archeflow/workflows/$wf_file"
|
|
info "Workflow: $wf_file -> .archeflow/workflows/"
|
|
elif [[ -n "$wf_file" ]]; then
|
|
warn "Workflow file not found in bundle: $wf_file"
|
|
fi
|
|
|
|
# Copy archetypes
|
|
local arch_count=0
|
|
if [[ -d "$bundle_dir/archetypes" ]] && has_files "$bundle_dir/archetypes" "*.md"; then
|
|
confirm_overwrite ".archeflow/archetypes" "Archetypes directory"
|
|
for f in "$bundle_dir"/archetypes/*.md; do
|
|
[[ -f "$f" ]] || continue
|
|
cp "$f" ".archeflow/archetypes/$(basename "$f")"
|
|
arch_count=$((arch_count + 1))
|
|
done
|
|
info "Archetypes: $arch_count files -> .archeflow/archetypes/"
|
|
fi
|
|
|
|
# Copy domain
|
|
local domain_file
|
|
domain_file="$(yaml_value "$manifest" "includes.domain" 2>/dev/null || true)"
|
|
if [[ -z "$domain_file" ]] && command -v yq &>/dev/null; then
|
|
domain_file="$(yq -r '.includes.domain // empty' "$manifest" 2>/dev/null)"
|
|
fi
|
|
if [[ -n "$domain_file" && -f "$bundle_dir/$domain_file" ]]; then
|
|
confirm_overwrite ".archeflow/domains" "Domains directory"
|
|
cp "$bundle_dir/$domain_file" ".archeflow/domains/$domain_file"
|
|
info "Domain: $domain_file -> .archeflow/domains/"
|
|
elif [[ -n "$domain_file" && -f "$bundle_dir/domain.yaml" ]]; then
|
|
confirm_overwrite ".archeflow/domains" "Domains directory"
|
|
cp "$bundle_dir/domain.yaml" ".archeflow/domains/$domain_file"
|
|
info "Domain: $domain_file -> .archeflow/domains/"
|
|
elif [[ -n "$domain_file" ]]; then
|
|
warn "Domain file not found in bundle: $domain_file"
|
|
fi
|
|
|
|
# Copy hooks if present
|
|
if [[ -f "$bundle_dir/hooks.yaml" ]]; then
|
|
cp "$bundle_dir/hooks.yaml" ".archeflow/hooks.yaml"
|
|
info "Hooks: hooks.yaml -> .archeflow/"
|
|
fi
|
|
|
|
# Generate config.yaml with variables
|
|
local config_file=".archeflow/config.yaml"
|
|
{
|
|
echo "# Generated by archeflow init from bundle: $bundle_name"
|
|
echo "bundle: $bundle_name"
|
|
local version
|
|
version="$(yaml_value "$manifest" "version")"
|
|
echo "bundle_version: ${version:-1}"
|
|
echo "initialized: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
echo "variables:"
|
|
|
|
# Read default variables from manifest
|
|
local -A vars=()
|
|
if command -v yq &>/dev/null; then
|
|
while IFS='=' read -r k v; do
|
|
[[ -n "$k" ]] && vars["$k"]="$v"
|
|
done < <(yq -r '.variables // {} | to_entries[] | "\(.key)=\(.value)"' "$manifest" 2>/dev/null)
|
|
else
|
|
# Simple fallback: parse variables section
|
|
local in_vars=false
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ ^variables: ]]; then
|
|
in_vars=true; continue
|
|
fi
|
|
if $in_vars; then
|
|
if [[ "$line" =~ ^[[:space:]]+(.*):\ (.*) ]]; then
|
|
local vk="${BASH_REMATCH[1]}" vv="${BASH_REMATCH[2]}"
|
|
vk="$(echo "$vk" | xargs)"
|
|
vv="$(echo "$vv" | sed 's/#.*//' | xargs)"
|
|
[[ -n "$vk" ]] && vars["$vk"]="$vv"
|
|
elif [[ "$line" =~ ^[^[:space:]] ]]; then
|
|
break
|
|
fi
|
|
fi
|
|
done < "$manifest"
|
|
fi
|
|
|
|
# Apply overrides
|
|
for k in "${!overrides[@]}"; do
|
|
vars["$k"]="${overrides[$k]}"
|
|
done
|
|
|
|
# Write variables
|
|
if [[ ${#vars[@]} -eq 0 ]]; then
|
|
echo " # (no variables defined)"
|
|
else
|
|
for k in $(echo "${!vars[@]}" | tr ' ' '\n' | sort); do
|
|
echo " $k: ${vars[$k]}"
|
|
done
|
|
fi
|
|
} > "$config_file"
|
|
info "Config: $config_file"
|
|
|
|
echo ""
|
|
echo "ArcheFlow initialized from bundle: $bundle_name"
|
|
|
|
# Print variable summary
|
|
if [[ ${#vars[@]} -gt 0 ]]; then
|
|
local var_summary=""
|
|
for k in $(echo "${!vars[@]}" | tr ' ' '\n' | sort); do
|
|
[[ -n "$var_summary" ]] && var_summary+=", "
|
|
var_summary+="${k}=${vars[$k]}"
|
|
done
|
|
echo " Variables: $var_summary"
|
|
fi
|
|
|
|
echo ""
|
|
echo "Ready to run: archeflow:run"
|
|
}
|
|
|
|
cmd_init_from() {
|
|
local source_path="$1"
|
|
|
|
[[ -d "$source_path/.archeflow" ]] || die "No .archeflow/ directory found in $source_path"
|
|
|
|
echo "Cloning ArcheFlow setup from: $source_path"
|
|
echo ""
|
|
|
|
mkdir -p .archeflow
|
|
|
|
local copied=0
|
|
for subdir in teams workflows archetypes domains; do
|
|
if [[ -d "$source_path/.archeflow/$subdir" ]] && has_files "$source_path/.archeflow/$subdir"; then
|
|
confirm_overwrite ".archeflow/$subdir" "$subdir directory"
|
|
mkdir -p ".archeflow/$subdir"
|
|
cp "$source_path/.archeflow/$subdir"/* ".archeflow/$subdir/"
|
|
local count
|
|
count=$(find ".archeflow/$subdir" -maxdepth 1 -type f | wc -l)
|
|
info "$subdir/: $count files copied"
|
|
copied=$((copied + count))
|
|
fi
|
|
done
|
|
|
|
# Copy config.yaml if present
|
|
if [[ -f "$source_path/.archeflow/config.yaml" ]]; then
|
|
cp "$source_path/.archeflow/config.yaml" ".archeflow/config.yaml"
|
|
info "config.yaml copied"
|
|
copied=$((copied + 1))
|
|
fi
|
|
|
|
# Copy hooks.yaml if present
|
|
if [[ -f "$source_path/.archeflow/hooks.yaml" ]]; then
|
|
cp "$source_path/.archeflow/hooks.yaml" ".archeflow/hooks.yaml"
|
|
info "hooks.yaml copied"
|
|
copied=$((copied + 1))
|
|
fi
|
|
|
|
# Explicitly skip run-specific directories
|
|
for skip in events artifacts context templates; do
|
|
if [[ -d "$source_path/.archeflow/$skip" ]]; then
|
|
info "(skipped $skip/ — run-specific data)"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "Cloned $copied files from $source_path"
|
|
echo "Ready to run: archeflow:run"
|
|
}
|
|
|
|
cmd_save() {
|
|
local name="$1"
|
|
|
|
[[ -d ".archeflow" ]] || die "No .archeflow/ directory in current project. Nothing to save."
|
|
|
|
local bundle_dir="$GLOBAL_TEMPLATES/bundles/$name"
|
|
|
|
if [[ -d "$bundle_dir" ]]; then
|
|
warn "Template bundle already exists: $bundle_dir"
|
|
if [[ -t 0 ]]; then
|
|
read -r -p " Overwrite? [y/N] " answer
|
|
[[ "$answer" =~ ^[Yy]$ ]] || die "Aborted."
|
|
else
|
|
die "Non-interactive mode — will not overwrite existing bundle $name."
|
|
fi
|
|
rm -rf "$bundle_dir"
|
|
fi
|
|
|
|
mkdir -p "$bundle_dir"
|
|
echo "Saving current setup as template: $name"
|
|
echo ""
|
|
|
|
local team_file="" wf_file="" domain_file=""
|
|
local -a arch_files=()
|
|
local file_count=0
|
|
|
|
# Copy teams (take first .yaml file)
|
|
if [[ -d ".archeflow/teams" ]] && has_files ".archeflow/teams" "*.yaml"; then
|
|
team_file="$(ls .archeflow/teams/*.yaml 2>/dev/null | head -1)"
|
|
if [[ -n "$team_file" ]]; then
|
|
cp "$team_file" "$bundle_dir/$(basename "$team_file")"
|
|
team_file="$(basename "$team_file")"
|
|
info "Team: $team_file"
|
|
file_count=$((file_count + 1))
|
|
fi
|
|
fi
|
|
|
|
# Copy workflows (take first .yaml file)
|
|
if [[ -d ".archeflow/workflows" ]] && has_files ".archeflow/workflows" "*.yaml"; then
|
|
wf_file="$(ls .archeflow/workflows/*.yaml 2>/dev/null | head -1)"
|
|
if [[ -n "$wf_file" ]]; then
|
|
cp "$wf_file" "$bundle_dir/$(basename "$wf_file")"
|
|
wf_file="$(basename "$wf_file")"
|
|
info "Workflow: $wf_file"
|
|
file_count=$((file_count + 1))
|
|
fi
|
|
fi
|
|
|
|
# Copy archetypes
|
|
if [[ -d ".archeflow/archetypes" ]] && has_files ".archeflow/archetypes" "*.md"; then
|
|
mkdir -p "$bundle_dir/archetypes"
|
|
for f in .archeflow/archetypes/*.md; do
|
|
[[ -f "$f" ]] || continue
|
|
cp "$f" "$bundle_dir/archetypes/"
|
|
arch_files+=("$(basename "$f")")
|
|
file_count=$((file_count + 1))
|
|
done
|
|
info "Archetypes: ${#arch_files[@]} files"
|
|
fi
|
|
|
|
# Copy domain (take first .yaml file)
|
|
if [[ -d ".archeflow/domains" ]] && has_files ".archeflow/domains" "*.yaml"; then
|
|
domain_file="$(ls .archeflow/domains/*.yaml 2>/dev/null | head -1)"
|
|
if [[ -n "$domain_file" ]]; then
|
|
cp "$domain_file" "$bundle_dir/$(basename "$domain_file")"
|
|
domain_file="$(basename "$domain_file")"
|
|
info "Domain: $domain_file"
|
|
file_count=$((file_count + 1))
|
|
fi
|
|
fi
|
|
|
|
# Copy hooks if present
|
|
if [[ -f ".archeflow/hooks.yaml" ]]; then
|
|
cp ".archeflow/hooks.yaml" "$bundle_dir/hooks.yaml"
|
|
info "Hooks: hooks.yaml"
|
|
file_count=$((file_count + 1))
|
|
fi
|
|
|
|
# Detect domain name from domain file
|
|
local domain_name=""
|
|
if [[ -n "$domain_file" && -f "$bundle_dir/$domain_file" ]]; then
|
|
domain_name="$(yaml_value "$bundle_dir/$domain_file" "name")"
|
|
fi
|
|
|
|
# Read variables from config.yaml if present
|
|
local has_vars=false
|
|
local vars_yaml=""
|
|
if [[ -f ".archeflow/config.yaml" ]]; then
|
|
if command -v yq &>/dev/null; then
|
|
vars_yaml="$(yq -r '.variables // {} | to_entries[] | " \(.key): \(.value)"' ".archeflow/config.yaml" 2>/dev/null)"
|
|
[[ -n "$vars_yaml" ]] && has_vars=true
|
|
else
|
|
local in_vars=false
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ ^variables: ]]; then
|
|
in_vars=true; continue
|
|
fi
|
|
if $in_vars; then
|
|
if [[ "$line" =~ ^[[:space:]] ]]; then
|
|
vars_yaml+="$line"$'\n'
|
|
has_vars=true
|
|
else
|
|
break
|
|
fi
|
|
fi
|
|
done < ".archeflow/config.yaml"
|
|
fi
|
|
fi
|
|
|
|
# Generate manifest
|
|
local project_dir
|
|
project_dir="$(basename "$(pwd)")"
|
|
{
|
|
echo "name: $name"
|
|
echo "description: \"Saved from $project_dir\""
|
|
echo "version: 1"
|
|
[[ -n "$domain_name" ]] && echo "domain: $domain_name"
|
|
echo "includes:"
|
|
[[ -n "$team_file" ]] && echo " team: $team_file"
|
|
[[ -n "$wf_file" ]] && echo " workflow: $wf_file"
|
|
if [[ ${#arch_files[@]} -gt 0 ]]; then
|
|
echo " archetypes:"
|
|
for a in "${arch_files[@]}"; do
|
|
echo " - $a"
|
|
done
|
|
fi
|
|
[[ -n "$domain_file" ]] && echo " domain: $domain_file"
|
|
echo "requires: []"
|
|
if $has_vars; then
|
|
echo "variables:"
|
|
echo "$vars_yaml"
|
|
else
|
|
echo "variables: {}"
|
|
fi
|
|
} > "$bundle_dir/manifest.yaml"
|
|
|
|
file_count=$((file_count + 1)) # manifest itself
|
|
|
|
echo ""
|
|
echo "Template saved: $name"
|
|
echo " Location: $bundle_dir/"
|
|
echo " Files: $file_count"
|
|
echo " Use with: archeflow init $name"
|
|
}
|
|
|
|
cmd_share() {
|
|
local name="$1" target="$2"
|
|
|
|
local bundle_dir=""
|
|
for base in "$LOCAL_TEMPLATES" "$GLOBAL_TEMPLATES"; do
|
|
if [[ -d "$base/bundles/$name" ]]; then
|
|
bundle_dir="$base/bundles/$name"
|
|
break
|
|
fi
|
|
done
|
|
[[ -n "$bundle_dir" ]] || die "Bundle not found: $name. Run '$0 --list' to see available templates."
|
|
|
|
mkdir -p "$target"
|
|
cp -r "$bundle_dir" "$target/$name"
|
|
|
|
echo "Exported: $target/$name/"
|
|
echo "To import: cp -r $target/$name ~/.archeflow/templates/bundles/"
|
|
}
|
|
|
|
# --- Main -------------------------------------------------------------------
|
|
|
|
if [[ $# -eq 0 ]]; then
|
|
echo "Usage:"
|
|
echo " $0 <bundle-name> [--set key=value ...] Init from named bundle"
|
|
echo " $0 --from <project-path> Clone from another project"
|
|
echo " $0 --list List available templates"
|
|
echo " $0 --save <name> Save current setup as template"
|
|
echo " $0 --share <name> <path> Export template to directory"
|
|
exit 0
|
|
fi
|
|
|
|
case "$1" in
|
|
--list)
|
|
cmd_list
|
|
;;
|
|
--from)
|
|
[[ $# -ge 2 ]] || die "--from requires a project path"
|
|
cmd_init_from "$2"
|
|
;;
|
|
--save)
|
|
[[ $# -ge 2 ]] || die "--save requires a template name"
|
|
cmd_save "$2"
|
|
;;
|
|
--share)
|
|
[[ $# -ge 3 ]] || die "--share requires a name and a target path"
|
|
cmd_share "$2" "$3"
|
|
;;
|
|
-*)
|
|
die "Unknown option: $1"
|
|
;;
|
|
*)
|
|
cmd_init_bundle "$@"
|
|
;;
|
|
esac
|