#!/usr/bin/env bash set -euo pipefail usage() { cat <<'EOF' >&2 Usage: install hook for one repo: ./scripts/install-anythingllm-post-merge-hook.sh [] install hook for configured project clones: ./scripts/install-anythingllm-post-merge-hook.sh --all [--smart-ide-root ] ./scripts/install-anythingllm-post-merge-hook.sh --project [--smart-ide-root ] Notes: - Project clones are resolved from smart_ide `projects//conf.json` -> `project_path`. - The hook sources `${HOME}/.config/4nk/anythingllm-sync.env` if present. EOF } SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SMART_IDE_ROOT="" repo_paths=() mode="single" filter_project_id="" if [[ $# -ge 1 && "${1:-}" != --* ]]; then # Backward-compatible mode: [] repo_paths+=( "$1" ) SMART_IDE_ROOT="${2:-}" else while [[ $# -gt 0 ]]; do case "$1" in --smart-ide-root) SMART_IDE_ROOT="${2:-}" shift 2 ;; --all) mode="all" shift 1 ;; --project) filter_project_id="${2:-}" [[ -n "$filter_project_id" ]] || { echo "Missing value for --project" >&2; usage; exit 2; } mode="project" shift 2 ;; -h|--help) usage exit 0 ;; *) echo "Unknown arg: $1" >&2 usage exit 2 ;; esac done fi if [[ -z "$SMART_IDE_ROOT" ]]; then SMART_IDE_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" else SMART_IDE_ROOT="$(cd "$SMART_IDE_ROOT" && pwd)" fi SYNC_DIR="$SMART_IDE_ROOT/scripts/anythingllm-pull-sync" if [[ ! -f "$SYNC_DIR/sync.mjs" ]]; then echo "Missing $SYNC_DIR/sync.mjs" >&2 exit 1 fi install_one() { local repo_path="$1" local repo repo="$(cd "$repo_path" && pwd)" if [[ ! -d "$repo/.git" ]]; then echo "Not a git repository: $repo" >&2 return 1 fi local hook="$repo/.git/hooks/post-merge" mkdir -p "$(dirname "$hook")" cat >"$hook" </dev/null 2>&1 || { echo "jq not found; install jq." >&2 exit 1 } projects_dir="$SMART_IDE_ROOT/projects" if [[ ! -d "$projects_dir" ]]; then echo "Missing projects dir: $projects_dir" >&2 exit 1 fi count_ok=0 count_skip=0 count_err=0 for conf in "$projects_dir"/*/conf.json; do [[ -f "$conf" ]] || continue project_id="$(basename "$(dirname "$conf")")" if [[ "$mode" == "project" && "$project_id" != "$filter_project_id" ]]; then continue fi if [[ "$project_id" == "example" ]]; then echo "skip $project_id: template project" count_skip=$((count_skip + 1)) continue fi if ! project_path="$(jq -r '.project_path // empty' "$conf")"; then echo "err $project_id: failed to read project_path from $conf" >&2 count_err=$((count_err + 1)) continue fi if [[ -z "$project_path" || "$project_path" == "null" ]]; then echo "skip $project_id: empty project_path" count_skip=$((count_skip + 1)) continue fi if [[ "$project_path" != /* ]]; then project_path="$(cd "$SMART_IDE_ROOT" && realpath -m "$project_path" 2>/dev/null || echo "$SMART_IDE_ROOT/$project_path")" fi if [[ ! -d "$project_path" ]]; then echo "skip $project_id: not a directory: $project_path" count_skip=$((count_skip + 1)) continue fi if install_one "$project_path"; then count_ok=$((count_ok + 1)) else count_err=$((count_err + 1)) fi done echo "Done: ok=$count_ok skip=$count_skip err=$count_err" echo "Run: (cd $SYNC_DIR && npm install) if node_modules is missing." if [[ "$count_err" -gt 0 ]]; then exit 1 fi