attic.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. from datetime import datetime
  2. import os
  3. import platform
  4. import subprocess
  5. def create_archive(excludes_filename, verbose, source_directories, repository):
  6. '''
  7. Given an excludes filename, a vebosity flag, a space-separated list of source directories, and
  8. a local or remote repository path, create an attic archive.
  9. '''
  10. sources = tuple(source_directories.split(' '))
  11. command = (
  12. 'attic', 'create',
  13. '--exclude-from', excludes_filename,
  14. '{repo}::{hostname}-{timestamp}'.format(
  15. repo=repository,
  16. hostname=platform.node(),
  17. timestamp=datetime.now().isoformat(),
  18. ),
  19. ) + sources + (
  20. ('--verbose', '--stats') if verbose else ()
  21. )
  22. subprocess.check_call(command)
  23. def make_prune_flags(retention_config):
  24. '''
  25. Given a retention config dict mapping from option name to value, tranform it into an iterable of
  26. command-line name-value flag pairs.
  27. For example, given a retention config of:
  28. {'keep_weekly': 4, 'keep_monthly': 6}
  29. This will be returned as an iterable of:
  30. (
  31. ('--keep-weekly', '4'),
  32. ('--keep-monthly', '6'),
  33. )
  34. '''
  35. return (
  36. ('--' + option_name.replace('_', '-'), str(retention_config[option_name]))
  37. for option_name, value in retention_config.items()
  38. )
  39. def prune_archives(verbose, repository, retention_config):
  40. '''
  41. Given a verbosity flag, a local or remote repository path, and a retention config dict, prune
  42. attic archives according the the retention policy specified in that configuration.
  43. '''
  44. command = (
  45. 'attic', 'prune',
  46. repository,
  47. ) + tuple(
  48. element
  49. for pair in make_prune_flags(retention_config)
  50. for element in pair
  51. ) + (('--verbose',) if verbose else ())
  52. subprocess.check_call(command)
  53. def check_archives(verbose, repository):
  54. '''
  55. Given a verbosity flag and a local or remote repository path, check the contained attic archives
  56. for consistency.
  57. '''
  58. command = (
  59. 'attic', 'check',
  60. repository,
  61. ) + (('--verbose',) if verbose else ())
  62. # Attic's check command spews to stdout even without the verbose flag. Suppress it.
  63. stdout = None if verbose else open(os.devnull, 'w')
  64. subprocess.check_call(command, stdout=stdout)