commit 27fd6926dcda08140be616c9e12807aacb3dbb02 Author: Tris Date: Fri Oct 16 17:45:56 2020 +1100 Initial import diff --git a/gitea-mirror.py b/gitea-mirror.py new file mode 100755 index 0000000..e4192ca --- /dev/null +++ b/gitea-mirror.py @@ -0,0 +1,74 @@ +#!/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] + subprocess.run(cmd, check=True) + + +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) +