#!/usr/bin/env bash set -euo pipefail # Migration script: Forgejo bare repos -> Radicle # # Usage: # 1. First rsync repos from helix: # rsync -avz git.sealight.xyz:/var/lib/gitea/repositories/aynish/ /tmp/forgejo-migration/ # # 2. Run this script: # sudo -u radicle ./migrate-forgejo-to-radicle.sh /tmp/forgejo-migration # # Or run as root: # ./migrate-forgejo-to-radicle.sh /tmp/forgejo-migration SOURCE_DIR="${1:-/tmp/forgejo-migration}" WORK_DIR="/var/lib/radicle/migration" LOG_FILE="/var/lib/radicle/migration.log" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' log() { echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"; } log_success() { log "${GREEN}✓ $1${NC}"; } log_warn() { log "${YELLOW}⚠ $1${NC}"; } log_error() { log "${RED}✗ $1${NC}"; } # Use rad directly with proper environment (rad-system can't access files outside sandbox) export RAD_HOME=/var/lib/radicle export HOME=/var/lib/radicle RAD_CMD="rad" # Ensure keys are in place (agenix stores them in /run/agenix/) if [[ -f /run/agenix/radicle-box-key ]] && [[ ! -s /var/lib/radicle/keys/radicle ]]; then log "Setting up radicle keys..." cp /run/agenix/radicle-box-key /var/lib/radicle/keys/radicle chmod 600 /var/lib/radicle/keys/radicle chown radicle:radicle /var/lib/radicle/keys/radicle fi # Get public key from the config if not present if [[ ! -s /var/lib/radicle/keys/radicle.pub ]]; then log "Generating public key..." ssh-keygen -y -f /var/lib/radicle/keys/radicle > /var/lib/radicle/keys/radicle.pub 2>/dev/null || true chown radicle:radicle /var/lib/radicle/keys/radicle.pub fi # Check source directory if [[ ! -d "$SOURCE_DIR" ]]; then log_error "Source directory not found: $SOURCE_DIR" echo "" echo "First rsync repos from helix:" echo " rsync -avz git.sealight.xyz:/var/lib/gitea/repositories/aynish/ /tmp/forgejo-migration/" exit 1 fi # Create work directory mkdir -p "$WORK_DIR" cd "$WORK_DIR" log "Starting Forgejo -> Radicle migration" log "Source: $SOURCE_DIR" log "Work dir: $WORK_DIR" log "Using: $RAD_CMD" # Count repos REPOS=$(find "$SOURCE_DIR" -maxdepth 1 -name "*.git" -type d | sort) TOTAL=$(echo "$REPOS" | grep -c . || echo 0) if [[ "$TOTAL" -eq 0 ]]; then log_error "No .git directories found in $SOURCE_DIR" exit 1 fi log "Found $TOTAL repositories to migrate" echo "" MIGRATED=0 SKIPPED=0 FAILED=0 for BARE_REPO in $REPOS; do # Extract repo name (remove .git suffix) REPO_NAME=$(basename "$BARE_REPO" .git) log "Processing: $REPO_NAME" CLONE_DIR="$WORK_DIR/$REPO_NAME" # Clone bare repo to working directory if [[ -d "$CLONE_DIR/.git" ]]; then log " Directory exists, skipping clone" else log " Cloning from bare repo..." if ! git clone --quiet "$BARE_REPO" "$CLONE_DIR" 2>>"$LOG_FILE"; then log_error " Failed to clone $REPO_NAME" ((FAILED++)) || true continue fi fi cd "$CLONE_DIR" # Check if already initialized in Radicle if $RAD_CMD . >/dev/null 2>&1; then log_warn " Already initialized in Radicle, skipping" cd "$WORK_DIR" ((SKIPPED++)) || true continue fi # Get current branch CURRENT_BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo "main") # Normalize to main if needed if [[ "$CURRENT_BRANCH" != "main" ]]; then log " Normalizing branch: $CURRENT_BRANCH -> main" git branch -m "$CURRENT_BRANCH" main 2>>"$LOG_FILE" || true fi # Get description from git config if available DESCRIPTION=$(git config --get gitweb.description 2>/dev/null || echo "Migrated from Forgejo") # Truncate description if too long if [[ ${#DESCRIPTION} -gt 255 ]]; then DESCRIPTION="${DESCRIPTION:0:252}..." fi # Initialize in Radicle log " Initializing in Radicle..." if $RAD_CMD init \ --name "$REPO_NAME" \ --description "$DESCRIPTION" \ --default-branch main \ --public 2>>"$LOG_FILE"; then # Push to radicle log " Pushing to Radicle..." if git push rad main 2>>"$LOG_FILE"; then RID=$($RAD_CMD . 2>/dev/null || echo "unknown") log_success " Migrated: $REPO_NAME -> $RID" ((MIGRATED++)) || true else log_error " Failed to push $REPO_NAME" ((FAILED++)) || true fi else log_error " Failed to init $REPO_NAME in Radicle" ((FAILED++)) || true fi cd "$WORK_DIR" done echo "" log "========================================" log "Migration Summary:" log " Total repos: $TOTAL" log " Migrated: $MIGRATED" log " Skipped: $SKIPPED" log " Failed: $FAILED" log "========================================" echo "" log "Verify with: $RAD_CMD ls" log "Configure helix to follow: rad-system follow --alias mossnet"