148 lines
5.4 KiB
Bash
Executable File
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/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"
|