mirror-gitea-github/mirror-contribution-graph.py

79 lines
2.5 KiB
Python

import subprocess
import os
import logging
from datetime import datetime
# ---------------- CONFIG ----------------
GITHUB_USER = ""
GITHUB_EMAIL = ""
GITHUB_TOKEN = ""
# Folder where mirrored bare repos from Gitea exist
REPOS_DIR = "./gitea_repos" # your folder with bare clones
# ---------------- Logging Setup ----------------
log_filename = f"heatmap_update_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[
logging.FileHandler(log_filename),
logging.StreamHandler()
]
)
# ---------------- FUNCTIONS ----------------
def list_local_repos():
"""Return a list of folder names in REPOS_DIR (bare git repos)"""
repos = []
for entry in os.listdir(REPOS_DIR):
full_path = os.path.join(REPOS_DIR, entry)
if os.path.isdir(full_path):
# Treat folder as bare git repo if it has HEAD file
if os.path.exists(os.path.join(full_path, "HEAD")):
repos.append(entry)
return repos
def process_repo(repo_name):
local_path = os.path.join(REPOS_DIR, repo_name)
github_url = f"https://{GITHUB_TOKEN}@github.com/{GITHUB_USER}/{repo_name}.git"
try:
logging.info(f"Fetching latest commits for {repo_name}...")
subprocess.run(["git", "--git-dir", local_path, "fetch", "--all"], check=True)
# Rewrite commits to GitHub email (preserves dates)
logging.info(f"Rewriting commits in {repo_name} to GitHub email...")
subprocess.run([
"git", "--git-dir", local_path, "filter-repo",
"--email-callback", f'return b"{GITHUB_EMAIL}"',
"--force"
], check=True)
# Push to GitHub
logging.info(f"Pushing {repo_name} to GitHub...")
subprocess.run(["git", "--git-dir", local_path, "push", "--mirror", github_url], check=True)
logging.info(f"✅ Finished processing {repo_name}")
except subprocess.CalledProcessError as e:
logging.error(f"❌ Error processing {repo_name}: {e}")
# ---------------- MAIN ----------------
def main():
logging.info(f"Starting heatmap update for GitHub user: {GITHUB_USER}")
existing_repos = list_local_repos()
if not existing_repos:
logging.info(f"No repos found in {REPOS_DIR}. Nothing to process.")
return
for repo_name in existing_repos:
logging.info(f"Processing repo: {repo_name}")
process_repo(repo_name)
logging.info(f"All done! Log saved to {log_filename}")
if __name__ == "__main__":
main()