Files
proxmox/scripts/maintenance/init-monorepo-from-proxmox-gitmodules.sh
defiQUG be14693184
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
init-monorepo script: default MONOREPO_ROOT to proxmox-submodules-mirror (not Complete Credential)
Made-with: Cursor
2026-03-21 17:24:31 -07:00

148 lines
5.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Initialize a single Git monorepo directory with the same tree layout as
# proxmox .gitmodules (clone each remote into path, drop nested .git).
#
# Optional: create empty repo on Gitea under an org and push (needs GITEA_TOKEN).
#
# Usage:
# MONOREPO_ROOT=/path/to/mirror/dir ./scripts/maintenance/init-monorepo-from-proxmox-gitmodules.sh
# GITEA_TOKEN=... GITEA_ORG=DBIS ./scripts/maintenance/init-monorepo-from-proxmox-gitmodules.sh --create-remote --push
#
# Env:
# PROXMOX_ROOT — repo with .gitmodules (default: parent of scripts/maintenance/../../)
# MONOREPO_ROOT — target directory (required, or default: $HOME/projects/proxmox-submodules-mirror — NOT Complete Credential product repo)
# GITEA_URL — default https://gitea.d-bis.org
# GITEA_ORG — default DBIS (override e.g. d-bis if needed)
# GITEA_TOKEN — for API create + HTTPS push
# SHALLOW — if 1, git clone --depth 1 (default 1)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROXMOX_ROOT="${PROXMOX_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
MONOREPO_ROOT="${MONOREPO_ROOT:-$HOME/projects/proxmox-submodules-mirror}"
GITEA_URL="${GITEA_URL:-https://gitea.d-bis.org}"
GITEA_ORG="${GITEA_ORG:-DBIS}"
SHALLOW="${SHALLOW:-1}"
CREATE_REMOTE=0
DO_PUSH=0
for arg in "$@"; do
case "$arg" in
--create-remote) CREATE_REMOTE=1 ;;
--push) DO_PUSH=1 ;;
-h|--help)
sed -n '1,25p' "$0"
exit 0
;;
esac
done
GITMODULES="${PROXMOX_ROOT}/.gitmodules"
[[ -f "$GITMODULES" ]] || { echo "ERROR: missing $GITMODULES" >&2; exit 1; }
mkdir -p "$MONOREPO_ROOT"
cd "$MONOREPO_ROOT"
if [[ -n "$(ls -A "$MONOREPO_ROOT" 2>/dev/null)" ]] && [[ ! -d "$MONOREPO_ROOT/.git" ]]; then
echo "ERROR: $MONOREPO_ROOT is not empty and not a git repo. Use an empty dir or rm -rf contents." >&2
exit 1
fi
manifest="$MONOREPO_ROOT/MONOREPO_SOURCES.txt"
: > "$manifest"
echo "# path<TAB>url — generated from $GITMODULES" >> "$manifest"
clone_one() {
local rel_path="$1" url="$2"
local dest="$MONOREPO_ROOT/$rel_path"
echo "[clone] $rel_path <= $url"
if [[ -e "$dest" ]]; then
# Parent repo may have created an empty placeholder (e.g. nested submodule path)
if [[ -z "$(find "$dest" -mindepth 1 -maxdepth 1 2>/dev/null | head -1)" ]]; then
rmdir "$dest" 2>/dev/null || rm -rf "$dest"
else
echo " skip: non-empty $dest"
printf '%s\t%s\n' "$rel_path" "$url" >> "$manifest"
return 0
fi
fi
mkdir -p "$(dirname "$dest")"
local depth_args=()
[[ "$SHALLOW" == "1" ]] && depth_args=(--depth 1)
GIT_TERMINAL_PROMPT=0 git clone "${depth_args[@]}" "$url" "$dest"
rm -rf "$dest/.git"
printf '%s\t%s\n' "$rel_path" "$url" >> "$manifest"
}
# Deepest paths first so nested submodule dirs (e.g. dbis_core/.../arbitrage) are not masked by parent clone.
pairs_tmp="$(mktemp)"
while read -r key path; do
[[ "$key" =~ ^submodule\.(.+)\.path$ ]] || continue
name="${BASH_REMATCH[1]}"
url="$(git config -f "$GITMODULES" --get "submodule.${name}.url" 2>/dev/null || true)"
[[ -n "$url" && -n "$path" ]] || continue
slashes="${path//[^\/]/}"
printf '%s\t%s\t%s\n' "${#slashes}" "$path" "$url"
done < <(git config -f "$GITMODULES" --get-regexp '^submodule\..*\.path$') | sort -t $'\t' -k1,1nr > "$pairs_tmp"
while IFS=$'\t' read -r _depth path url; do
clone_one "$path" "$url" || echo "WARN: clone failed for $path ($url)" >&2
done < "$pairs_tmp"
rm -f "$pairs_tmp"
if [[ ! -d "$MONOREPO_ROOT/.git" ]]; then
git init -b main "$MONOREPO_ROOT"
fi
cd "$MONOREPO_ROOT"
cat > README.md <<EOF
# DBIS workspace monorepo
Single repository mirroring paths from \`proxmox\` \`.gitmodules\` (no nested submodules).
Source list: \`MONOREPO_SOURCES.txt\`.
Regenerate tree: run \`scripts/maintenance/init-monorepo-from-proxmox-gitmodules.sh\` from the proxmox repo with \`MONOREPO_ROOT\` set to this directory.
EOF
git add -A
if git diff --cached --quiet 2>/dev/null; then
echo "Nothing new to commit."
else
git commit -m "Initial monorepo: import proxmox submodule remotes as directories"
fi
REPO_SLUG="$(basename "$MONOREPO_ROOT")"
if [[ "$CREATE_REMOTE" == "1" ]]; then
[[ -n "${GITEA_TOKEN:-}" ]] || { echo "ERROR: GITEA_TOKEN required for --create-remote" >&2; exit 1; }
api="$GITEA_URL/api/v1/orgs/${GITEA_ORG}/repos"
code="$(curl -sS -o /tmp/gitea-create-repo.json -w '%{http_code}' \
-H "Authorization: token ${GITEA_TOKEN}" \
-H 'Content-Type: application/json' \
-d "{\"name\":\"${REPO_SLUG}\",\"private\":true,\"description\":\"Monorepo from proxmox .gitmodules\"}" \
"$api")" || true
if [[ "$code" == "201" ]]; then
echo "Created Gitea repo ${GITEA_ORG}/${REPO_SLUG}"
elif [[ "$code" == "409" ]]; then
echo "Repo ${GITEA_ORG}/${REPO_SLUG} already exists (409). Continuing."
else
echo "Gitea API HTTP $code — body:" >&2
cat /tmp/gitea-create-repo.json >&2 || true
exit 1
fi
fi
if [[ "$DO_PUSH" == "1" ]]; then
[[ -n "${GITEA_TOKEN:-}" ]] || { echo "ERROR: GITEA_TOKEN required for --push (HTTPS)" >&2; exit 1; }
remote_url="${GITEA_URL}/${GITEA_ORG}/${REPO_SLUG}.git"
# embed token for one-shot push (user can switch to SSH later)
auth_url="$(echo "$remote_url" | sed "s#https://#https://oauth2:${GITEA_TOKEN}@#")"
git remote remove origin 2>/dev/null || true
git remote add origin "$remote_url"
git push -u "$auth_url" main
echo "Pushed to $remote_url (set credential helper or SSH remote for future pushes)."
fi
echo "Done. Monorepo at $MONOREPO_ROOT"