mirror of
https://github.com/ArchiveBox/ArchiveBox.git
synced 2026-04-05 23:37:58 +10:00
199 lines
5.9 KiB
Bash
Executable File
199 lines
5.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
SCRIPT_REPO_ROOT="$(cd -- "$SCRIPT_DIR/.." && pwd)"
|
|
GITHUB_BASE="${GITHUB_BASE:-https://github.com/ArchiveBox}"
|
|
MONOREPO_REMOTE="${MONOREPO_REMOTE:-$GITHUB_BASE/monorepo.git}"
|
|
REPO_NAMES=(abxbus abx-pkg abx-plugins abx-dl archivebox)
|
|
|
|
is_member_repo() {
|
|
local repo_root="$1"
|
|
local repo_name
|
|
|
|
for repo_name in "${REPO_NAMES[@]}"; do
|
|
if [[ "$(basename "$repo_root")" == "$repo_name" ]]; then
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
monorepo_remote_matches() {
|
|
case "$1" in
|
|
git@github.com:ArchiveBox/monorepo.git | \
|
|
git+ssh://git@github.com/ArchiveBox/monorepo.git | \
|
|
https://github.com/ArchiveBox/monorepo.git)
|
|
return 0
|
|
;;
|
|
*)
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
warn() {
|
|
printf 'Warning: %s\n' "$1" >&2
|
|
}
|
|
|
|
have_ldap_build_deps() {
|
|
if command -v dpkg-query >/dev/null 2>&1; then
|
|
dpkg-query -W -f='${Status}' libldap2-dev 2>/dev/null | grep -q 'install ok installed' && return 0
|
|
fi
|
|
|
|
if command -v brew >/dev/null 2>&1; then
|
|
brew --prefix openldap >/dev/null 2>&1 && return 0
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
ensure_ldap_build_deps() {
|
|
if have_ldap_build_deps; then
|
|
return
|
|
fi
|
|
|
|
printf 'Ensuring LDAP build dependencies (best effort)\n'
|
|
|
|
if command -v apt >/dev/null 2>&1 && sudo -n apt install -y libldap2-dev >/dev/null 2>&1; then
|
|
return
|
|
fi
|
|
|
|
if command -v brew >/dev/null 2>&1 && brew install openldap >/dev/null 2>&1; then
|
|
return
|
|
fi
|
|
|
|
warn "Could not auto-install LDAP build dependencies; continuing. If you need archivebox[ldap], run: sudo apt install libldap2-dev || brew install openldap"
|
|
}
|
|
|
|
sync_workspace() {
|
|
if uv sync --all-packages --all-extras --no-cache --active; then
|
|
return
|
|
fi
|
|
|
|
warn "'uv sync --all-packages --all-extras --no-cache --active' failed; retrying without --all-extras"
|
|
uv sync --all-packages --no-cache --active
|
|
}
|
|
|
|
ensure_setup_link() {
|
|
local repo_name="$1"
|
|
local repo_dir="$ROOT_DIR/$repo_name"
|
|
local link_path="$repo_dir/bin/setup_monorepo.sh"
|
|
local source_path="$ROOT_DIR/bin/setup.sh"
|
|
|
|
mkdir -p "$repo_dir/bin"
|
|
|
|
if [[ -e "$link_path" ]] && [[ "$source_path" -ef "$link_path" ]]; then
|
|
return
|
|
fi
|
|
|
|
if [[ -d "$link_path" && ! -L "$link_path" ]]; then
|
|
printf 'Refusing to replace directory: %s\n' "$link_path" >&2
|
|
exit 1
|
|
fi
|
|
|
|
rm -f "$link_path"
|
|
ln "$source_path" "$link_path"
|
|
}
|
|
|
|
bootstrap_monorepo_root() {
|
|
local monorepo_root="$1"
|
|
local origin_url=""
|
|
|
|
if [[ -d "$monorepo_root/.git" ]]; then
|
|
origin_url="$(git -C "$monorepo_root" remote get-url origin 2>/dev/null || true)"
|
|
|
|
if [[ -n "$origin_url" ]] && ! monorepo_remote_matches "$origin_url"; then
|
|
printf 'Refusing to reuse existing git repo at %s (origin: %s)\n' "$monorepo_root" "$origin_url" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -z "$origin_url" ]]; then
|
|
git -C "$monorepo_root" remote add origin "$MONOREPO_REMOTE"
|
|
fi
|
|
|
|
printf 'Updating monorepo root: %s\n' "$monorepo_root"
|
|
if git -C "$monorepo_root" -c pull.rebase=false pull --ff-only --quiet >/dev/null 2>&1; then
|
|
printf 'Updated monorepo root\n'
|
|
else
|
|
printf 'Skipping monorepo pull (local changes, divergent branch, detached HEAD, or no upstream)\n' >&2
|
|
fi
|
|
return
|
|
fi
|
|
|
|
printf 'Bootstrapping monorepo root in %s\n' "$monorepo_root"
|
|
git -C "$monorepo_root" init -b main >/dev/null
|
|
git -C "$monorepo_root" remote add origin "$MONOREPO_REMOTE"
|
|
git -C "$monorepo_root" fetch --depth=1 origin main --quiet
|
|
|
|
if git -C "$monorepo_root" checkout -B main --track origin/main >/dev/null 2>&1; then
|
|
printf 'Initialized monorepo root\n'
|
|
else
|
|
printf 'Failed to materialize monorepo root in %s; existing files likely conflict with tracked monorepo files\n' "$monorepo_root" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
if is_member_repo "$SCRIPT_REPO_ROOT"; then
|
|
ROOT_DIR="$(cd -- "$SCRIPT_REPO_ROOT/.." && pwd)"
|
|
bootstrap_monorepo_root "$ROOT_DIR"
|
|
elif [[ -f "$SCRIPT_REPO_ROOT/pyproject.toml" ]]; then
|
|
ROOT_DIR="$SCRIPT_REPO_ROOT"
|
|
else
|
|
printf 'Unable to infer monorepo root from script location: %s\n' "$SCRIPT_DIR" >&2
|
|
exit 1
|
|
fi
|
|
|
|
ensure_member_repo() {
|
|
local repo_name="$1"
|
|
local repo_dir="$ROOT_DIR/$repo_name"
|
|
|
|
if [[ -d "$repo_dir/.git" ]]; then
|
|
printf 'Updating existing checkout: %s\n' "$repo_name"
|
|
if git -C "$repo_dir" -c pull.rebase=false pull --ff-only --quiet >/dev/null 2>&1; then
|
|
printf 'Updated: %s\n' "$repo_name"
|
|
else
|
|
printf 'Skipping pull for %s (local changes, divergent branch, detached HEAD, or no upstream)\n' "$repo_name" >&2
|
|
fi
|
|
return
|
|
fi
|
|
|
|
if [[ -e "$repo_dir" ]]; then
|
|
printf 'Refusing to overwrite existing path: %s\n' "$repo_dir" >&2
|
|
exit 1
|
|
fi
|
|
|
|
printf 'Cloning %s/%s.git -> %s\n' "$GITHUB_BASE" "$repo_name" "$repo_name"
|
|
git clone "$GITHUB_BASE/$repo_name.git" "$repo_dir"
|
|
}
|
|
|
|
for repo_name in "${REPO_NAMES[@]}"; do
|
|
ensure_member_repo "$repo_name"
|
|
done
|
|
|
|
for repo_name in "${REPO_NAMES[@]}"; do
|
|
ensure_setup_link "$repo_name"
|
|
done
|
|
|
|
cd "$ROOT_DIR"
|
|
deactivate || true
|
|
rm -Rf ./*/.venv # delete all sub-repo venvs, the monorepo venv needs to take precedence
|
|
|
|
uv venv --allow-existing "$ROOT_DIR/.venv"
|
|
# shellcheck disable=SC1091
|
|
source "$ROOT_DIR/.venv/bin/activate"
|
|
ensure_ldap_build_deps
|
|
sync_workspace
|
|
echo
|
|
echo
|
|
echo "[√] Monorepo setup complete, cloned and pulled: ${REPO_NAMES[*]}"
|
|
echo " MONOREPO_ROOT=$ROOT_DIR"
|
|
echo " VIRTUAL_ENV=$VIRTUAL_ENV"
|
|
echo " PYTHON_BIN=$VIRTUAL_ENV/bin/python"
|
|
echo " NODE_BIN=$(which node)"
|
|
echo
|
|
echo "TIPS:"
|
|
echo " - Always use 'uv run ...' within each subrepo, never in the root & never run 'python ...' directly"
|
|
echo " - Always read $ROOT_DIR/README.md into context before starting any work"
|