A VCS repository archival tool
Você não pode selecionar mais de 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.

55 linhas
1.5 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. @abc.abstractmethod
  11. def put(self, filename: str):
  12. '''Put a local file into storage. If an error occurs, a partial copy may remain in storage. If it completes, the local input file is removed.'''
  13. def put_result(self, result: codearchiver.core.Result):
  14. '''Put a module's Result into storage. The semantics are as for `put`, and the exact behaviour regarding partial copies and leftover files on errors is undefined.'''
  15. for fn in result.files:
  16. self.put(fn)
  17. for _, subresult in result.submoduleResults:
  18. self.put_result(subresult)
  19. @abc.abstractmethod
  20. @contextlib.contextmanager
  21. def open(self, filename: str) -> typing.Iterator[typing.BinaryIO]:
  22. '''Open a file from storage.'''
  23. class DirectoryStorage(Storage):
  24. def __init__(self, directory):
  25. super().__init__()
  26. self._directory = directory
  27. def _check_directory(self):
  28. exists = os.path.exists(self._directory)
  29. if exists and not os.path.isdir(self._directory):
  30. raise NotADirectoryError(self._directory)
  31. return exists
  32. def _ensure_directory(self):
  33. if not self._check_directory():
  34. os.makedirs(self._directory)
  35. def put(self, filename):
  36. self._ensure_directory()
  37. _logger.info(f'Moving {filename} to {self._directory}')
  38. shutil.move(filename, self._directory)
  39. @contextlib.contextmanager
  40. def open(self, filename):
  41. with open(filename, 'rb') as fp:
  42. yield fp