A VCS repository archival tool
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

61 行
2.0 KiB

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