A VCS repository archival tool
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

58 linhas
1.9 KiB

  1. import codearchiver.core
  2. import datetime
  3. import logging
  4. import os.path
  5. import shutil
  6. import subprocess
  7. logger = logging.getLogger(__name__)
  8. class Git(codearchiver.core.Module):
  9. @staticmethod
  10. def matches(inputUrl):
  11. return inputUrl.url.endswith('.git')
  12. def __init__(self, *args, extraBranches = {}, **kwargs):
  13. super().__init__(*args, **kwargs)
  14. self._extraBranches = extraBranches
  15. def process(self):
  16. directory = self._url.rsplit('/', 1)[1]
  17. if os.path.exists(directory):
  18. logger.fatal(f'{directory!r} already exists')
  19. return
  20. startTime = datetime.datetime.utcnow()
  21. if self._id is None:
  22. self._id = f'git_{self._url.replace("/", "_")}_{startTime:%Y%m%dT%H%M%SZ}'
  23. bundle = f'{self._id}.bundle'
  24. if os.path.exists(bundle):
  25. logger.fatal(f'{bundle!r} already exists')
  26. return
  27. logger.info(f'Cloning {self._url} into {directory}')
  28. subprocess.run(['git', 'clone', '--verbose', '--mirror', self._url, directory], check = True)
  29. if self._extraBranches:
  30. for branch, commit in self._extraBranches.items():
  31. logger.info(f'Fetching commit {commit} as {branch}')
  32. r = subprocess.run(['git', 'fetch', '--verbose', 'origin', commit], cwd = directory)
  33. if r.returncode == 0:
  34. r2 = subprocess.run(['git', 'update-ref', f'refs/codearchiver/{branch}', commit, ''], cwd = directory)
  35. if r2.returncode != 0:
  36. logger.error(f'Failed to update-ref refs/codearchiver/{branch} to {commit}')
  37. else:
  38. logger.error(f'Failed to fetch {commit}')
  39. logger.info(f'Bundling into {bundle}')
  40. subprocess.run(['git', 'bundle', 'create', f'../{bundle}', '--all'], cwd = directory, check = True)
  41. logger.info(f'Removing clone')
  42. shutil.rmtree(directory)
  43. return codearchiver.core.Result(id = self._id, files = [bundle])
  44. def __repr__(self):
  45. return f'{type(self).__module__}.{type(self).__name__}({self._inputUrl!r}, extraBranches = {self._extraBranches!r})'