#!/usr/bin/env bash # Redirect each existing per-component Gitea repo into a branch on the # canonical RedBear-OS repo, then point the matching git submodule(s) at # that branch. After this, the per-component Gitea repos can be deleted # without breaking any submodule resolution. # # What this script does, for each per-component Gitea repo: # 1. Fetches the repo's HEAD into a temp clone. # 2. Pushes that HEAD as a `submodule/` branch on RedBear-OS. # 3. Rewrites `.gitmodules` so any submodule entry pointing at the # per-component URL now points at RedBear-OS with the new branch. # # What it does NOT do: # - It does not move source content between repositories (source already # lives in the per-component repo; we just push it under a new branch # name in the canonical repo). # - It does not delete the per-component Gitea repos. Use # delete-per-component-repos.sh afterwards. # - It does not touch recipe.toml files (none reference the per-component # URLs as far as the current tree shows). # # Token is read at runtime from $REDBEAR_GITEA_TOKEN (or ~/.netrc). It is # NEVER written to disk, logged, or echoed. set -euo pipefail GITEA_HOST="${GITEA_HOST:-https://gitea.redbearos.org}" GITEA_USER="${GITEA_USER:-vasilito}" CANONICAL_REPO="${CANONICAL_REPO:-RedBear-OS}" CANONICAL_URL="${CANONICAL_URL:-${GITEA_HOST}/${GITEA_USER}/${CANONICAL_REPO}.git}" # Per-component Gitea repos to redirect. The actual Gitea slug is # discovered at runtime via the API, so this list contains the canonical # component names only. DEFAULT_COMPONENTS=(base kernel installer redox-drm userutils libredox libpciaccess) DRY_RUN=0 SKIP_PUSH=0 COMPONENTS=() while [ $# -gt 0 ]; do case "$1" in --dry-run) DRY_RUN=1 ;; --skip-push) SKIP_PUSH=1 ;; -h|--help) sed -n '2,28p' "$0"; exit 0 ;; --) shift; while [ $# -gt 0 ]; do COMPONENTS+=("$1"); shift; done ;; -*) echo "ERROR: unknown arg: $1" >&2; exit 2 ;; *) COMPONENTS+=("$1") ;; esac shift done [ "${#COMPONENTS[@]}" -gt 0 ] || COMPONENTS=("${DEFAULT_COMPONENTS[@]}") log() { printf '[redirect-to-submodules] %s\n' "$*" >&2; } die() { log "FATAL: $*"; exit 1; } resolve_token() { if [ -n "${REDBEAR_GITEA_TOKEN:-}" ]; then printf '%s' "$REDBEAR_GITEA_TOKEN" return 0 fi if [ -r "$HOME/.netrc" ]; then awk -v host="gitea.redbearos.org" -v user="$GITEA_USER" ' $1=="machine" && $2==host { in_block=1; next } in_block && $1=="login" && $2==user { want=1; next } in_block && want && $1=="password" { print $2; exit } in_block && $1=="machine" { in_block=0 } ' "$HOME/.netrc" fi } TOKEN="$(resolve_token || true)" [ -n "$TOKEN" ] || die "no token found. Set REDBEAR_GITEA_TOKEN or configure ~/.netrc." command -v git >/dev/null || die "git not found in PATH" command -v jq >/dev/null || die "jq not found in PATH" git rev-parse --is-inside-work-tree >/dev/null 2>&1 || die "must be run from inside the ${CANONICAL_REPO} working tree" current_branch="$(git rev-parse --abbrev-ref HEAD)" log "Working tree : $(git rev-parse --show-toplevel)" log "Branch : ${current_branch}" log "Canonical URL: ${CANONICAL_URL}" if [ "$DRY_RUN" -eq 0 ] && [ "$SKIP_PUSH" -eq 0 ]; then log "" log "This script PUSHES branches to ${CANONICAL_URL} and modifies .gitmodules." read -r -p "Type 'redirect' to confirm: " confirm [ "$confirm" = "redirect" ] || { log "Aborted."; exit 1; } fi api_get() { curl -fsS -H "Authorization: token $TOKEN" \ -H "Accept: application/json" \ "$GITEA_HOST/api/v1$1" } log "Verifying Gitea credentials ..." api_get "/user" >/dev/null || die "token rejected by Gitea API" log "Fetching Gitea repo list ..." REPO_NAMES_API="$(api_get "/users/${GITEA_USER}/repos?limit=200" | jq -r '.[].name')" [ -n "${REPO_NAMES_API}" ] || die "no repos returned — check token permissions." find_slug() { local component="$1" # Try the legacy redbear-os- convention first, then the bare name. for candidate in "redbear-os-${component}" "${component}"; do if printf '%s\n' "${REPO_NAMES_API}" | grep -qx "${candidate}"; then printf '%s' "${candidate}" return 0 fi done return 1 } redirect_component() { local component="$1" local gitea_slug if ! gitea_slug="$(find_slug "${component}")"; then log "" log "=== ${component} ===" die "no Gitea repo found for component '${component}' (tried: redbear-os-${component}, ${component})" fi local branch="submodule/${component}" log "" log "=== ${component} ===" log " source Gitea repo : ${gitea_slug}" log " target branch : ${branch}" if [ "$DRY_RUN" -eq 1 ]; then log " [dry-run] would fetch HEAD, push as ${branch}, rewrite .gitmodules" return 0 fi local tmp tmp="$(mktemp -d)" trap 'rm -rf "$tmp"' EXIT log " cloning ${gitea_slug} ..." local src_url="https://${TOKEN}@${GITEA_HOST#https://}/${GITEA_USER}/${gitea_slug}.git" git clone --quiet "${src_url}" "${tmp}/src" \ || die "clone failed for ${gitea_slug}" local src_default src_default="$(git -C "${tmp}/src" symbolic-ref --short HEAD 2>/dev/null || echo "")" local src_commit_count src_commit_count="$(git -C "${tmp}/src" rev-list --all --count 2>/dev/null || echo 0)" if [ -z "${src_commit_count}" ] || [ "${src_commit_count}" = "0" ]; then log " source repo is empty (0 commits) — skipping push" rm -rf "${tmp}" trap - EXIT log " ✓ ${component} (no-op)" return 0 fi log " source default branch: ${src_default} (${src_commit_count} commits)" log " pushing ${branch} to ${CANONICAL_URL} ..." local push_url="https://${TOKEN}@${GITEA_HOST#https://}/${GITEA_USER}/${CANONICAL_REPO}.git" git -C "${tmp}/src" push --quiet "${push_url}" "refs/heads/${src_default}:refs/heads/${branch}" \ || die "push failed for ${branch}" log " rewriting .gitmodules ..." if grep -q "url = .*${gitea_slug}\.git" .gitmodules 2>/dev/null; then sed -i.bak "s|url = .*${gitea_slug}\.git|url = ${CANONICAL_URL}|" .gitmodules sed -i "s|^ branch = .*| branch = ${branch}|" .gitmodules rm -f .gitmodules.bak log " updated" else log " no .gitmodules entry references ${gitea_slug}; left untouched" fi rm -rf "${tmp}" trap - EXIT log " ✓ ${component} redirected" } for c in "${COMPONENTS[@]}"; do redirect_component "$c" done log "" log "Done. Verify with: git submodule status" log "Then run ./local/scripts/delete-per-component-repos.sh to delete the" log "now-unused per-component repos on Gitea."