78 lines
1.9 KiB
Python
Executable File
78 lines
1.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import requests
|
|
import os
|
|
import os.path
|
|
import subprocess
|
|
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
|
|
def mirror_host(d, host, token):
|
|
|
|
for repo, url in get_repos(host, token):
|
|
p = os.path.join(d, repo)
|
|
if os.path.exists(os.path.join(p, 'config')):
|
|
logger.debug("Updating %s", repo)
|
|
cmd = ['git', '-C', p, 'fetch']
|
|
else:
|
|
logger.info("Cloning new repo: %s", repo)
|
|
os.makedirs(p, exist_ok=True)
|
|
cmd = ['git', 'clone', '--mirror', url, p]
|
|
try:
|
|
subprocess.run(cmd, check=True)
|
|
except subprocess.CalledProcessError:
|
|
logger.exception("Failed to process %s", repo)
|
|
|
|
|
|
def get_repos(host, token, pagesize=50):
|
|
|
|
page = 1
|
|
|
|
headers = {
|
|
'authorization': f"token {token}",
|
|
'accept': 'application/json'
|
|
}
|
|
|
|
while True:
|
|
|
|
r = requests.get(f"{host}/api/v1/user/repos?limit={pagesize}&page={page}",
|
|
headers=headers)
|
|
|
|
if r.status_code != 200:
|
|
r.raise_for_status()
|
|
|
|
data = r.json()
|
|
|
|
for repo in data:
|
|
yield repo['full_name'], repo['ssh_url']
|
|
|
|
if len(data) < pagesize:
|
|
break
|
|
page += 1
|
|
|
|
if __name__ == '__main__':
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument('instance',
|
|
help='Gitea instance')
|
|
parser.add_argument('target', default='.',
|
|
help='Target location')
|
|
parser.add_argument('--token', '-t',
|
|
help="Token (default GITEA_TOKEN)")
|
|
parser.add_argument('--level', '-l', default='info',
|
|
help='Logging level')
|
|
|
|
options = parser.parse_args()
|
|
|
|
logging.basicConfig(level=getattr(logging, options.level.upper(),
|
|
logging.INFO))
|
|
logger.debug(options)
|
|
|
|
token = options.token or os.ENVIRON['GITEA_TOKEN']
|
|
|
|
mirror_host(options.target, options.instance, token)
|
|
|