diff --git a/README.md b/README.md index 1ed8f26..5e7d3a2 100644 --- a/README.md +++ b/README.md @@ -4,16 +4,11 @@ ## Install Master Layer -From `jarvis-brain` repo root: +From the standalone source repo: ```bash -bash scripts/agent/bootstrap-mosaic.sh -``` - -Or directly from this package source: - -```bash -bash userspace/mosaic/install.sh +git clone https://git.mosaicstack.dev/mosaic/bootstrap.git ~/src/mosaic-bootstrap +bash ~/src/mosaic-bootstrap/install.sh ``` ## What It Provides @@ -47,3 +42,17 @@ This creates/updates: - `.mosaic/` (repo-specific hook/config surface) - `scripts/agent/` (portable lifecycle scripts) - `AGENTS.md` (if missing) + +## Upgrade Existing Slave Repos + +Preview upgrades (dry-run): + +```bash +~/.mosaic/bin/mosaic-upgrade-slaves +``` + +Apply upgrades: + +```bash +~/.mosaic/bin/mosaic-upgrade-slaves --apply +``` diff --git a/bin/mosaic-upgrade-slaves b/bin/mosaic-upgrade-slaves new file mode 100755 index 0000000..7b75eef --- /dev/null +++ b/bin/mosaic-upgrade-slaves @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +set -euo pipefail + +MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.mosaic}" +BOOTSTRAP_CMD="$MOSAIC_HOME/bin/mosaic-bootstrap-repo" + +roots=("$HOME/src") +apply=0 + +usage() { + cat < Add a search root (repeatable). Default: $HOME/src + --apply Execute upgrades. Without this flag, script is dry-run. + -h, --help Show this help +USAGE +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --root) + [[ $# -lt 2 ]] && { echo "Missing value for --root" >&2; exit 1; } + roots+=("$2") + shift 2 + ;; + --apply) + apply=1 + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 1 + ;; + esac +done + +if [[ ! -x "$BOOTSTRAP_CMD" ]]; then + echo "[mosaic-upgrade] Missing bootstrap command: $BOOTSTRAP_CMD" >&2 + echo "[mosaic-upgrade] Install/refresh framework first: ~/.mosaic/install.sh" >&2 + exit 1 +fi + +# De-duplicate roots while preserving order. +uniq_roots=() +for r in "${roots[@]}"; do + skip=0 + for e in "${uniq_roots[@]}"; do + [[ "$r" == "$e" ]] && { skip=1; break; } + done + [[ $skip -eq 0 ]] && uniq_roots+=("$r") +done + +candidates=() +for root in "${uniq_roots[@]}"; do + [[ -d "$root" ]] || continue + + while IFS= read -r marker; do + repo_dir="$(dirname "$(dirname "$marker")")" + if [[ -d "$repo_dir/.git" ]]; then + candidates+=("$repo_dir") + fi + done < <(find "$root" -type f -path '*/.mosaic/README.md' 2>/dev/null) +done + +# De-duplicate repos while preserving order. +repos=() +for repo in "${candidates[@]}"; do + skip=0 + for existing in "${repos[@]}"; do + [[ "$repo" == "$existing" ]] && { skip=1; break; } + done + [[ $skip -eq 0 ]] && repos+=("$repo") +done + +count_total=${#repos[@]} +count_ok=0 +count_fail=0 + +mode="DRY-RUN" +[[ $apply -eq 1 ]] && mode="APPLY" + +echo "[mosaic-upgrade] Mode: $mode" +echo "[mosaic-upgrade] Roots: ${uniq_roots[*]}" +echo "[mosaic-upgrade] Linked repos found: $count_total" + +if [[ $count_total -eq 0 ]]; then + exit 0 +fi + +for repo in "${repos[@]}"; do + if [[ $apply -eq 1 ]]; then + if "$BOOTSTRAP_CMD" "$repo" --force >/dev/null; then + echo "[mosaic-upgrade] upgraded: $repo" + count_ok=$((count_ok + 1)) + else + echo "[mosaic-upgrade] FAILED: $repo" >&2 + count_fail=$((count_fail + 1)) + fi + else + echo "[mosaic-upgrade] would upgrade: $repo" + fi +done + +if [[ $apply -eq 1 ]]; then + echo "[mosaic-upgrade] complete: ok=$count_ok failed=$count_fail total=$count_total" + [[ $count_fail -gt 0 ]] && exit 1 +fi