From 8ccb918b47e348afbe8ccda6fceceb69284eb231 Mon Sep 17 00:00:00 2001 From: TheFlyingFool Date: Sat, 8 Feb 2025 20:13:56 -0600 Subject: [PATCH] New script added --- scripts/getgit.py | 120 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 scripts/getgit.py diff --git a/scripts/getgit.py b/scripts/getgit.py new file mode 100644 index 0000000..3e7205e --- /dev/null +++ b/scripts/getgit.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +""" +getgit.py - Pull or clone all of your Gitea user repositories. + +Usage: + ./getgit.py --server https://gitea.example.com --token YOUR_API_TOKEN +or, after setting the environment variable GITEA_TOKEN: + export GITEA_TOKEN=YOUR_API_TOKEN + ./getgit.py --server https://gitea.example.com + +By default the repositories will be placed under ~/repos. +If a repository directory already exists, a 'git pull' will be run; +otherwise, the repository will be cloned using its SSH URL. +""" + +import os +import sys +import argparse +import subprocess +import requests + +def get_repos(server, token, per_page=100): + """Fetch all repositories for the authenticated user from Gitea.""" + repos = [] + page = 1 + headers = { + "Authorization": f"token {token}", + "Accept": "application/json" + } + while True: + url = f"{server.rstrip('/')}/api/v1/user/repos?page={page}&limit={per_page}" + response = requests.get(url, headers=headers) + if response.status_code != 200: + print(f"Error fetching repositories (HTTP {response.status_code}): {response.text}") + sys.exit(1) + data = response.json() + if not data: + break + repos.extend(data) + if len(data) < per_page: + break + page += 1 + return repos + +def clone_or_pull_repo(repo, dest_dir): + """ + Given a repository object (as returned from the Gitea API), check if it exists locally. + If it exists, run 'git pull'; if not, run 'git clone' using the SSH URL. + """ + repo_name = repo.get('name') + ssh_url = repo.get('ssh_url') + if not repo_name or not ssh_url: + print(f"Skipping a repo entry with missing information: {repo}") + return + + repo_path = os.path.join(dest_dir, repo_name) + if os.path.exists(repo_path): + print(f"Updating repository '{repo_name}'...") + try: + subprocess.run(["git", "-C", repo_path, "pull"], check=True) + except subprocess.CalledProcessError: + print(f"Warning: Failed to update repository '{repo_name}'.") + else: + print(f"Cloning repository '{repo_name}'...") + try: + subprocess.run(["git", "clone", ssh_url, repo_path], check=True) + except subprocess.CalledProcessError: + print(f"Warning: Failed to clone repository '{repo_name}'.") + +def main(): + parser = argparse.ArgumentParser( + description="Clone or update all Gitea user repositories." + ) + parser.add_argument( + "--server", + type=str, + default="https://gitea.example.com", + help="Base URL of your Gitea server (e.g. https://gitea.example.com)" + ) + parser.add_argument( + "--dest", + type=str, + default=os.path.expanduser("~/repos"), + help="Local destination directory to clone repositories (default: ~/repos)" + ) + parser.add_argument( + "--token", + type=str, + help="Your Gitea API token. Alternatively, set the GITEA_TOKEN environment variable." + ) + parser.add_argument( + "--per-page", + type=int, + default=100, + help="Number of repositories to fetch per API page (default: 100)" + ) + args = parser.parse_args() + + # Retrieve the API token from argument or environment variable. + token = args.token or os.environ.get("GITEA_TOKEN") + if not token: + print("Error: No API token provided. Supply it via --token or set GITEA_TOKEN.") + sys.exit(1) + + # Ensure the destination directory exists. + dest_dir = os.path.expanduser(args.dest) + os.makedirs(dest_dir, exist_ok=True) + + print("Fetching repository list from Gitea...") + repos = get_repos(args.server, token, args.per_page) + if not repos: + print("No repositories found.") + sys.exit(0) + + print(f"Found {len(repos)} repositories. Processing each one...") + for repo in repos: + clone_or_pull_repo(repo, dest_dir) + +if __name__ == "__main__": + main()