121 lines
3.9 KiB
Python
121 lines
3.9 KiB
Python
#!/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()
|