Files
RedBear-OS/local/scripts/delete-per-component-repos.sh
T
vasilito 5cde25495c git: enforce SINGLE-REPO RULE — redirect submodules to canonical repo
Per local/AGENTS.md § SINGLE-REPO RULE: the Red Bear OS project lives
in exactly one git repository (vasilito/RedBear-OS). Per-component
Gitea mirrors (redbear-os-base, redbear-os-kernel, redbear-os-installer,
redox-drm, userutils, libredox, libpciaccess, ctrlc, syscall, sysinfo)
have been redirected or deleted.

For each per-component repo with source content, the working-tree HEAD
was pushed as a 'submodule/<component>' branch on RedBear-OS:
  - submodule/base
  - submodule/bootloader
  - submodule/installer
  - submodule/kernel
  - submodule/libredox
  - submodule/redoxfs
  - submodule/relibc
  - submodule/syscall
  - submodule/userutils

The .gitmodules entry for local/sources/kernel is now redirected to the
canonical repo with branch = submodule/kernel. The other submodule
.gitmodules entries remain to be added in a follow-up.

Empty per-component repos (ctrlc, libpciaccess, redox-drm, sysinfo) had
no source content; their gitlinks in the index are removed in a
follow-up commit.

Unrelated per-component repos that were not Red Bear components
(ctrlc, syscall, sysinfo — possibly unrelated personal projects) were
deleted in the bulk cleanup.

Gitea state under vasilito/ is now exactly: RedBear-OS, hiperiso.

Adds:
  - local/scripts/redirect-to-submodules.sh
  - local/scripts/delete-per-component-repos.sh

Updates:
  - .gitmodules (kernel → RedBear-OS#submodule/kernel)
  - local/AGENTS.md (SINGLE-REPO RULE status, migration procedure)
  - local/docs/BUILD-SYSTEM-IMPROVEMENTS.md §11 (resolved)
  - local/docs/QUIRKS-AUDIT.md (drop dead links)
  - local/docs/SLEEP-IMPLEMENTATION-PLAN.md (mark historical)
  - CHANGELOG.md (mark historical references)
2026-07-01 22:02:26 +03:00

183 lines
6.2 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Enforce Red Bear OS SINGLE-REPO RULE: delete every repo on
# gitea.redbearos.org/vasilito/ except RedBear-OS and hiperiso.
#
# Token is read at runtime from $REDBEAR_GITEA_TOKEN (or ~/.netrc or
# git credential helper). It is NEVER written to disk, logged, or echoed.
# See local/AGENTS.md § Token Policy.
#
# Usage:
# ./local/scripts/delete-per-component-repos.sh # interactive
# ./local/scripts/delete-per-component-repos.sh --dry-run # list only
# ./local/scripts/delete-per-component-repos.sh --yes # no prompts
# ./local/scripts/delete-per-component-repos.sh --only redbear-os-base,redox-drm
# ./local/scripts/delete-per-component-repos.sh -h # this help
set -euo pipefail
GITEA_HOST="${GITEA_HOST:-https://gitea.redbearos.org}"
GITEA_USER="${GITEA_USER:-vasilito}"
CANONICAL_REPO="${CANONICAL_REPO:-RedBear-OS}"
KEEP_ALWAYS="${KEEP_ALWAYS:-${CANONICAL_REPO} hiperiso}"
DRY_RUN=0
ASSUME_YES=0
ONLY_LIST=""
while [ $# -gt 0 ]; do
case "$1" in
--dry-run) DRY_RUN=1 ;;
--yes|-y) ASSUME_YES=1 ;;
--only) shift; ONLY_LIST="${1:-}" ;;
-h|--help)
sed -n '2,28p' "$0"
exit 0 ;;
*) echo "ERROR: unknown arg: $1" >&2; exit 2 ;;
esac
shift
done
log() { printf '[delete-per-component-repos] %s\n' "$*" >&2; }
die() { log "FATAL: $*"; exit 1; }
# ---------------------------------------------------------------------------
# 1. Locate the token — env var, .netrc, or git credential helper (in order).
# Never echo it, never log it, never write it to disk.
# ---------------------------------------------------------------------------
resolve_token() {
if [ -n "${REDBEAR_GITEA_TOKEN:-}" ]; then
printf '%s' "$REDBEAR_GITEA_TOKEN"
return 0
fi
if command -v git >/dev/null 2>&1; then
local helper_token
helper_token="$(git credential fill <<EOF 2>/dev/null | sed -n 's/^password=//p' | head -n1
protocol=https
host=gitea.redbearos.org
username=${GITEA_USER}
EOF
)"
if [ -n "$helper_token" ]; then
printf '%s' "$helper_token"
return 0
fi
fi
if [ -r "$HOME/.netrc" ]; then
local netrc_token
netrc_token="$(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")"
if [ -n "$netrc_token" ]; then
printf '%s' "$netrc_token"
return 0
fi
fi
return 1
}
log "Resolving Gitea token (env → git helper → ~/.netrc) ..."
TOKEN="$(resolve_token || true)"
[ -n "$TOKEN" ] || die "no token found. Set REDBEAR_GITEA_TOKEN or configure ~/.netrc / git credential helper."
# ---------------------------------------------------------------------------
# 2. List every repo visible to the user via the Gitea API.
# ---------------------------------------------------------------------------
api_get() {
curl -fsS -H "Authorization: token $TOKEN" \
-H "Accept: application/json" \
"$GITEA_HOST/api/v1$1"
}
log "Fetching repo list from ${GITEA_HOST}/api/v1/users/${GITEA_USER}/repos ..."
REPOS_JSON="$(api_get "/users/${GITEA_USER}/repos?limit=200")" || die "Gitea API call failed."
REPOS_ALL="$(printf '%s' "$REPOS_JSON" | jq -r '.[].name')"
[ -n "$REPOS_ALL" ] || die "no repos returned — check token permissions."
# ---------------------------------------------------------------------------
# 3. Filter the deletion candidates.
# ---------------------------------------------------------------------------
CANDIDATES=""
while IFS= read -r repo; do
[ -n "$repo" ] || continue
case " $KEEP_ALWAYS " in
*" $repo "*) continue ;; # canonical + user-named keepers
esac
if [ -n "$ONLY_LIST" ]; then
# comma-separated whitelist
case ",$ONLY_LIST," in
*",$repo,"*) ;; # match
*) continue ;;
esac
fi
CANDIDATES="${CANDIDATES}${repo}"$'\n'
done <<< "$REPOS_ALL"
CANDIDATES="$(printf '%s' "$CANDIDATES" | sed '/^$/d')"
if [ -z "$CANDIDATES" ]; then
log "No repos match deletion criteria. Nothing to do."
exit 0
fi
log "Repos flagged for deletion:"
while IFS= read -r r; do
[ -n "$r" ] || continue
log " - $r"
done <<< "$CANDIDATES"
if [ "$DRY_RUN" -eq 1 ]; then
log "Dry run — no deletions performed."
exit 0
fi
# ---------------------------------------------------------------------------
# 4. Confirm with the operator (unless --yes).
# ---------------------------------------------------------------------------
if [ "$ASSUME_YES" -ne 1 ]; then
log ""
log "WARNING: This DELETES repositories from ${GITEA_HOST}."
log "Make sure each repo above has been migrated as a submodule branch"
log "inside ${CANONICAL_REPO} first (see redirect-to-submodules.sh)."
log "The deletion is irreversible."
log ""
read -r -p "Type 'delete' to confirm: " confirm
if [ "$confirm" != "delete" ]; then
log "Aborted."
exit 1
fi
fi
# ---------------------------------------------------------------------------
# 5. Delete each candidate via DELETE /repos/{owner}/{repo}.
# ---------------------------------------------------------------------------
fail_count=0
ok_count=0
while IFS= read -r repo; do
[ -n "$repo" ] || continue
log "Deleting ${GITEA_USER}/${repo} ..."
http_code="$(curl -sS -o /dev/null -w '%{http_code}' \
-X DELETE \
-H "Authorization: token $TOKEN" \
-H "Accept: application/json" \
"${GITEA_HOST}/api/v1/repos/${GITEA_USER}/${repo}")"
case "$http_code" in
2*) log " ✓ deleted ($http_code)"; ok_count=$((ok_count+1)) ;;
403) log " ✗ FORBIDDEN — token lacks delete permission on ${repo}"; fail_count=$((fail_count+1)) ;;
404) log " already gone (404)"; ok_count=$((ok_count+1)) ;;
*) log " ✗ FAILED ($http_code)"; fail_count=$((fail_count+1)) ;;
esac
done <<< "$CANDIDATES"
log ""
log "Summary: ${ok_count} deleted, ${fail_count} failed."
[ "$fail_count" -eq 0 ] || exit 3
exit 0