Files
gitea-mirror/gitea-mirror.py
T

103 lines
2.8 KiB
Python

import logging
import os.path
import sys
from os import makedirs
from src.config import Config, read_toml_config
from src.git import git_clone, git_pull, http_git_env, ssh_git_env
from src.gitea_api import GiteaApi
from src.log_fields import (
OPERATION,
PATH,
REPOSITORY,
REPOSITORY_COUNT,
REPOSITORY_URL,
)
from src.logging_config import setup_logging
from src.models import GiteaRepository
from src.repository_name import get_repository_name, is_valid_repository_names
BASE_PATH = "out"
FORMAT = "{owner}/{name}"
logger = logging.getLogger(__name__)
def get_fetch_params(config: Config, repo: GiteaRepository):
if config.fetch.ssh_key_path:
return repo.ssh_url, ssh_git_env(config.fetch.ssh_key_path)
return repo.clone_url, http_git_env(
user=config.fetch.user,
token=config.fetch.token,
)
def process_repo(config: Config, repo: GiteaRepository):
path = get_repository_name(name_format=config.repository_format, r=repo)
out_path = os.path.join(config.out_dir, path)
repository_url, git_env = get_fetch_params(config=config, repo=repo)
log_context = {
REPOSITORY: path,
PATH: out_path,
REPOSITORY_URL: repository_url,
}
makedirs(out_path, exist_ok=True)
if os.path.exists(os.path.join(out_path, ".git")):
logger.info(
"repository pull started",
extra=log_context | {OPERATION: "pull"},
)
git_pull(out_path, env=git_env)
return
logger.info(
"repository clone started",
extra=log_context | {OPERATION: "clone"},
)
git_clone(repository_url=repository_url, repository=out_path, env=git_env)
def main():
if len(sys.argv) < 2:
logging.basicConfig(
level=logging.ERROR,
format="%(levelname)s %(message)s",
)
logger.error("Usage: python gitea-mirror.py CONFIG_PATH")
sys.exit(1)
try:
config = read_toml_config(sys.argv[1])
except RuntimeError as err:
logging.basicConfig(
level=logging.ERROR,
format="%(levelname)s %(message)s",
)
logger.error("invalid config: %s", err)
sys.exit(1)
setup_logging(config.logging)
api = GiteaApi(
endpoint=config.endpoint,
api_token=config.api_token,
)
repos = api.get_repositories()
logger.info(
"repositories ready",
extra={OPERATION: "mirror", REPOSITORY_COUNT: len(repos)},
)
if not is_valid_repository_names(
name_format=config.repository_format,
repos=repos,
):
logger.error(
"repository name format creates duplicates",
extra={OPERATION: "validate_repository_names"},
)
sys.exit(1)
for repo in repos:
process_repo(config=config, repo=repo)
if __name__ == "__main__":
main()