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

67 行
1.7 KiB

  1. import abc
  2. import codearchiver.core
  3. import contextlib
  4. import logging
  5. import os.path
  6. import shutil
  7. import typing
  8. _logger = logging.getLogger(__name__)
  9. class Storage(abc.ABC):
  10. def __init__(self):
  11. self._queue = []
  12. def queue(self, filename: str):
  13. '''Queue a local file for putting into storage. Note that nothing is written to storage until `put_queue` is called.'''
  14. _logger.debug(f'Queueing {filename}')
  15. self._queue.append(filename)
  16. def queue_result(self, result: codearchiver.core.Result):
  17. for fn in result.files:
  18. self.queue(fn)
  19. for _, subresult in result.submoduleResults:
  20. self.queue_result(subresult)
  21. @property
  22. def queued_files(self) -> typing.List[str]:
  23. return self._queue[:]
  24. @abc.abstractmethod
  25. def put_queue(self):
  26. '''Put all queued files into storage. If an error occurs, partial copies may remain in storage. If it completes, the local input copy is removed.'''
  27. @abc.abstractmethod
  28. @contextlib.contextmanager
  29. def open(self, filename: str) -> typing.Iterator[typing.BinaryIO]:
  30. '''Open a file from storage.'''
  31. class DirectoryStorage(Storage):
  32. def __init__(self, directory):
  33. super().__init__()
  34. self._directory = directory
  35. def _check_directory(self):
  36. exists = os.path.exists(self._directory)
  37. if exists and not os.path.isdir(self._directory):
  38. raise NotADirectoryError(self._directory)
  39. return exists
  40. def _ensure_directory(self):
  41. if not self._check_directory():
  42. os.makedirs(self._directory)
  43. def put_queue(self):
  44. self._ensure_directory()
  45. for fn in self.queued_files:
  46. _logger.info(f'Moving {fn} to {self._directory}')
  47. shutil.move(fn, self._directory)
  48. @contextlib.contextmanager
  49. def open(self, filename):
  50. with open(filename, 'rb') as fp:
  51. yield fp