import codearchiver.core import datetime import logging import os.path import shutil import subprocess logger = logging.getLogger(__name__) class Git(codearchiver.core.Module): @staticmethod def matches(inputUrl): return inputUrl.url.endswith('.git') def __init__(self, inputUrl, extraBranches = {}): self._inputUrl = inputUrl self._url = inputUrl.url self._extraBranches = extraBranches def process(self): directory = self._url.rsplit('/', 1)[1] if os.path.exists(directory): logger.fatal(f'{directory!r} already exists') return startTime = datetime.datetime.utcnow() bundle = f'{self._url.replace("/", "_")}.{startTime:%Y%m%dT%H%M%SZ}.bundle' if os.path.exists(bundle): logger.fatal(f'{bundle!r} already exists') return logger.info(f'Cloning {self._url} into {directory}') subprocess.run(['git', 'clone', '--verbose', '--mirror', self._url, directory], check = True) if self._extraBranches: for branch, commit in self._extraBranches.items(): logger.info(f'Fetching commit {commit} as {branch}') r = subprocess.run(['git', 'fetch', '--verbose', 'origin', commit], cwd = directory) if r.returncode == 0: r2 = subprocess.run(['git', 'update-ref', f'refs/codearchiver/{branch}', commit, ''], cwd = directory) if r2.returncode != 0: logger.error(f'Failed to update-ref refs/codearchiver/{branch} to {commit}') else: logger.error(f'Failed to fetch {commit}') logger.info(f'Bundling into {bundle}') subprocess.run(['git', 'bundle', 'create', f'../{bundle}', '--all'], cwd = directory, check = True) logger.info(f'Removing clone') shutil.rmtree(directory) return codearchiver.core.Result(id = f'git-{bundle[:-7]}', files = [bundle])