Add script to init monorepo from proxmox .gitmodules (depth-first clones, optional Gitea)
Made-with: Cursor
This commit is contained in:
147
scripts/maintenance/init-monorepo-from-proxmox-gitmodules.sh
Executable file
147
scripts/maintenance/init-monorepo-from-proxmox-gitmodules.sh
Executable file
@@ -0,0 +1,147 @@
|
||||
#!/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/empty/dir ./scripts/maintenance/init-monorepo-from-proxmox-gitmodules.sh
|
||||
# GITEA_TOKEN=... GITEA_ORG=d-bis ./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 (default: $HOME/projects/complete-credential)
|
||||
# GITEA_URL — default https://gitea.d-bis.org
|
||||
# GITEA_ORG — default d-bis (this instance has no org slug "DBIS"; create it in Gitea or override)
|
||||
# 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/complete-credential}"
|
||||
GITEA_URL="${GITEA_URL:-https://gitea.d-bis.org}"
|
||||
GITEA_ORG="${GITEA_ORG:-d-bis}"
|
||||
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"
|
||||
Reference in New Issue
Block a user