nix config
1#!/usr/bin/env bash
2set -euo pipefail
3
4# Migration script: Forgejo bare repos -> Radicle
5#
6# Usage:
7# 1. First rsync repos from helix:
8# rsync -avz git.sealight.xyz:/var/lib/gitea/repositories/aynish/ /tmp/forgejo-migration/
9#
10# 2. Run this script:
11# sudo -u radicle ./migrate-forgejo-to-radicle.sh /tmp/forgejo-migration
12#
13# Or run as root:
14# ./migrate-forgejo-to-radicle.sh /tmp/forgejo-migration
15
16SOURCE_DIR="${1:-/tmp/forgejo-migration}"
17WORK_DIR="/var/lib/radicle/migration"
18LOG_FILE="/var/lib/radicle/migration.log"
19
20# Colors
21RED='\033[0;31m'
22GREEN='\033[0;32m'
23YELLOW='\033[1;33m'
24NC='\033[0m'
25
26log() { echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"; }
27log_success() { log "${GREEN}✓ $1${NC}"; }
28log_warn() { log "${YELLOW}⚠ $1${NC}"; }
29log_error() { log "${RED}✗ $1${NC}"; }
30
31# Use rad directly with proper environment (rad-system can't access files outside sandbox)
32export RAD_HOME=/var/lib/radicle
33export HOME=/var/lib/radicle
34RAD_CMD="rad"
35
36# Ensure keys are in place (agenix stores them in /run/agenix/)
37if [[ -f /run/agenix/radicle-box-key ]] && [[ ! -s /var/lib/radicle/keys/radicle ]]; then
38 log "Setting up radicle keys..."
39 cp /run/agenix/radicle-box-key /var/lib/radicle/keys/radicle
40 chmod 600 /var/lib/radicle/keys/radicle
41 chown radicle:radicle /var/lib/radicle/keys/radicle
42fi
43
44# Get public key from the config if not present
45if [[ ! -s /var/lib/radicle/keys/radicle.pub ]]; then
46 log "Generating public key..."
47 ssh-keygen -y -f /var/lib/radicle/keys/radicle > /var/lib/radicle/keys/radicle.pub 2>/dev/null || true
48 chown radicle:radicle /var/lib/radicle/keys/radicle.pub
49fi
50
51# Check source directory
52if [[ ! -d "$SOURCE_DIR" ]]; then
53 log_error "Source directory not found: $SOURCE_DIR"
54 echo ""
55 echo "First rsync repos from helix:"
56 echo " rsync -avz git.sealight.xyz:/var/lib/gitea/repositories/aynish/ /tmp/forgejo-migration/"
57 exit 1
58fi
59
60# Create work directory
61mkdir -p "$WORK_DIR"
62cd "$WORK_DIR"
63
64log "Starting Forgejo -> Radicle migration"
65log "Source: $SOURCE_DIR"
66log "Work dir: $WORK_DIR"
67log "Using: $RAD_CMD"
68
69# Count repos
70REPOS=$(find "$SOURCE_DIR" -maxdepth 1 -name "*.git" -type d | sort)
71TOTAL=$(echo "$REPOS" | grep -c . || echo 0)
72
73if [[ "$TOTAL" -eq 0 ]]; then
74 log_error "No .git directories found in $SOURCE_DIR"
75 exit 1
76fi
77
78log "Found $TOTAL repositories to migrate"
79echo ""
80
81MIGRATED=0
82SKIPPED=0
83FAILED=0
84
85for BARE_REPO in $REPOS; do
86 # Extract repo name (remove .git suffix)
87 REPO_NAME=$(basename "$BARE_REPO" .git)
88
89 log "Processing: $REPO_NAME"
90
91 CLONE_DIR="$WORK_DIR/$REPO_NAME"
92
93 # Clone bare repo to working directory
94 if [[ -d "$CLONE_DIR/.git" ]]; then
95 log " Directory exists, skipping clone"
96 else
97 log " Cloning from bare repo..."
98 if ! git clone --quiet "$BARE_REPO" "$CLONE_DIR" 2>>"$LOG_FILE"; then
99 log_error " Failed to clone $REPO_NAME"
100 ((FAILED++)) || true
101 continue
102 fi
103 fi
104
105 cd "$CLONE_DIR"
106
107 # Check if already initialized in Radicle
108 if $RAD_CMD . >/dev/null 2>&1; then
109 log_warn " Already initialized in Radicle, skipping"
110 cd "$WORK_DIR"
111 ((SKIPPED++)) || true
112 continue
113 fi
114
115 # Get current branch
116 CURRENT_BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo "main")
117
118 # Normalize to main if needed
119 if [[ "$CURRENT_BRANCH" != "main" ]]; then
120 log " Normalizing branch: $CURRENT_BRANCH -> main"
121 git branch -m "$CURRENT_BRANCH" main 2>>"$LOG_FILE" || true
122 fi
123
124 # Get description from git config if available
125 DESCRIPTION=$(git config --get gitweb.description 2>/dev/null || echo "Migrated from Forgejo")
126
127 # Truncate description if too long
128 if [[ ${#DESCRIPTION} -gt 255 ]]; then
129 DESCRIPTION="${DESCRIPTION:0:252}..."
130 fi
131
132 # Initialize in Radicle
133 log " Initializing in Radicle..."
134 if $RAD_CMD init \
135 --name "$REPO_NAME" \
136 --description "$DESCRIPTION" \
137 --default-branch main \
138 --public 2>>"$LOG_FILE"; then
139
140 # Push to radicle
141 log " Pushing to Radicle..."
142 if git push rad main 2>>"$LOG_FILE"; then
143 RID=$($RAD_CMD . 2>/dev/null || echo "unknown")
144 log_success " Migrated: $REPO_NAME -> $RID"
145 ((MIGRATED++)) || true
146 else
147 log_error " Failed to push $REPO_NAME"
148 ((FAILED++)) || true
149 fi
150 else
151 log_error " Failed to init $REPO_NAME in Radicle"
152 ((FAILED++)) || true
153 fi
154
155 cd "$WORK_DIR"
156done
157
158echo ""
159log "========================================"
160log "Migration Summary:"
161log " Total repos: $TOTAL"
162log " Migrated: $MIGRATED"
163log " Skipped: $SKIPPED"
164log " Failed: $FAILED"
165log "========================================"
166echo ""
167log "Verify with: $RAD_CMD ls"
168log "Configure helix to follow: rad-system follow <box-nid> --alias mossnet"