test_delete.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. import logging
  2. import pytest
  3. from flexmock import flexmock
  4. from borgmatic.borg import delete as module
  5. from ..test_verbosity import insert_logging_mock
  6. def test_make_delete_command_includes_log_info():
  7. insert_logging_mock(logging.INFO)
  8. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  9. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
  10. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  11. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  12. ('repo',),
  13. )
  14. command = module.make_delete_command(
  15. repository={'path': 'repo'},
  16. config={},
  17. local_borg_version='1.2.3',
  18. delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
  19. global_arguments=flexmock(dry_run=False),
  20. local_path='borg',
  21. remote_path=None,
  22. )
  23. assert command == ('borg', 'delete', '--info', 'repo')
  24. def test_make_delete_command_includes_log_debug():
  25. insert_logging_mock(logging.DEBUG)
  26. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  27. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
  28. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  29. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  30. ('repo',),
  31. )
  32. command = module.make_delete_command(
  33. repository={'path': 'repo'},
  34. config={},
  35. local_borg_version='1.2.3',
  36. delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
  37. global_arguments=flexmock(dry_run=False),
  38. local_path='borg',
  39. remote_path=None,
  40. )
  41. assert command == ('borg', 'delete', '--debug', '--show-rc', 'repo')
  42. def test_make_delete_command_includes_dry_run():
  43. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  44. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').with_args(
  45. 'dry-run',
  46. True,
  47. ).and_return(('--dry-run',))
  48. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
  49. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  50. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  51. ('repo',),
  52. )
  53. command = module.make_delete_command(
  54. repository={'path': 'repo'},
  55. config={},
  56. local_borg_version='1.2.3',
  57. delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
  58. global_arguments=flexmock(dry_run=True),
  59. local_path='borg',
  60. remote_path=None,
  61. )
  62. assert command == ('borg', 'delete', '--dry-run', 'repo')
  63. def test_make_delete_command_includes_remote_path():
  64. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  65. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').with_args(
  66. 'remote-path',
  67. 'borg1',
  68. ).and_return(('--remote-path', 'borg1'))
  69. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
  70. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  71. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  72. ('repo',),
  73. )
  74. command = module.make_delete_command(
  75. repository={'path': 'repo'},
  76. config={},
  77. local_borg_version='1.2.3',
  78. delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
  79. global_arguments=flexmock(dry_run=False),
  80. local_path='borg',
  81. remote_path='borg1',
  82. )
  83. assert command == ('borg', 'delete', '--remote-path', 'borg1', 'repo')
  84. def test_make_delete_command_includes_umask():
  85. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').replace_with(
  86. lambda name, value: (f'--{name}', value) if value else (),
  87. )
  88. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
  89. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  90. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  91. ('repo',),
  92. )
  93. command = module.make_delete_command(
  94. repository={'path': 'repo'},
  95. config={'umask': '077'},
  96. local_borg_version='1.2.3',
  97. delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
  98. global_arguments=flexmock(dry_run=False),
  99. local_path='borg',
  100. remote_path=None,
  101. )
  102. assert command == ('borg', 'delete', '--umask', '077', 'repo')
  103. def test_make_delete_command_includes_log_json():
  104. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  105. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').with_args(
  106. 'log-json',
  107. True,
  108. ).and_return(('--log-json',))
  109. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
  110. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  111. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  112. ('repo',),
  113. )
  114. command = module.make_delete_command(
  115. repository={'path': 'repo'},
  116. config={'log_json': True},
  117. local_borg_version='1.2.3',
  118. delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
  119. global_arguments=flexmock(dry_run=False),
  120. local_path='borg',
  121. remote_path=None,
  122. )
  123. assert command == ('borg', 'delete', '--log-json', 'repo')
  124. def test_make_delete_command_includes_lock_wait():
  125. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  126. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').with_args(
  127. 'lock-wait',
  128. 5,
  129. ).and_return(('--lock-wait', '5'))
  130. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
  131. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  132. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  133. ('repo',),
  134. )
  135. command = module.make_delete_command(
  136. repository={'path': 'repo'},
  137. config={'lock_wait': 5},
  138. local_borg_version='1.2.3',
  139. delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
  140. global_arguments=flexmock(dry_run=False),
  141. local_path='borg',
  142. remote_path=None,
  143. )
  144. assert command == ('borg', 'delete', '--lock-wait', '5', 'repo')
  145. def test_make_delete_command_with_list_config_calls_borg_with_list_flag():
  146. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  147. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').with_args(
  148. 'list',
  149. True,
  150. ).and_return(('--list',))
  151. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
  152. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  153. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  154. ('repo',),
  155. )
  156. command = module.make_delete_command(
  157. repository={'path': 'repo'},
  158. config={'list_details': True},
  159. local_borg_version='1.2.3',
  160. delete_arguments=flexmock(list_details=None, force=0, match_archives=None, archive=None),
  161. global_arguments=flexmock(dry_run=False),
  162. local_path='borg',
  163. remote_path=None,
  164. )
  165. assert command == ('borg', 'delete', '--list', 'repo')
  166. def test_make_delete_command_includes_force():
  167. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  168. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
  169. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  170. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  171. ('repo',),
  172. )
  173. command = module.make_delete_command(
  174. repository={'path': 'repo'},
  175. config={},
  176. local_borg_version='1.2.3',
  177. delete_arguments=flexmock(list_details=False, force=1, match_archives=None, archive=None),
  178. global_arguments=flexmock(dry_run=False),
  179. local_path='borg',
  180. remote_path=None,
  181. )
  182. assert command == ('borg', 'delete', '--force', 'repo')
  183. def test_make_delete_command_includes_force_twice():
  184. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  185. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
  186. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  187. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  188. ('repo',),
  189. )
  190. command = module.make_delete_command(
  191. repository={'path': 'repo'},
  192. config={},
  193. local_borg_version='1.2.3',
  194. delete_arguments=flexmock(list_details=False, force=2, match_archives=None, archive=None),
  195. global_arguments=flexmock(dry_run=False),
  196. local_path='borg',
  197. remote_path=None,
  198. )
  199. assert command == ('borg', 'delete', '--force', '--force', 'repo')
  200. def test_make_delete_command_includes_archive():
  201. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  202. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(
  203. ('--match-archives', 'archive'),
  204. )
  205. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  206. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  207. ('repo',),
  208. )
  209. command = module.make_delete_command(
  210. repository={'path': 'repo'},
  211. config={},
  212. local_borg_version='1.2.3',
  213. delete_arguments=flexmock(
  214. list_details=False,
  215. force=0,
  216. match_archives=None,
  217. archive='archive',
  218. ),
  219. global_arguments=flexmock(dry_run=False),
  220. local_path='borg',
  221. remote_path=None,
  222. )
  223. assert command == ('borg', 'delete', '--match-archives', 'archive', 'repo')
  224. def test_make_delete_command_includes_match_archives():
  225. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  226. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(
  227. ('--match-archives', 'sh:foo*'),
  228. )
  229. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  230. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  231. ('repo',),
  232. )
  233. command = module.make_delete_command(
  234. repository={'path': 'repo'},
  235. config={},
  236. local_borg_version='1.2.3',
  237. delete_arguments=flexmock(
  238. list_details=False,
  239. force=0,
  240. match_archives='sh:foo*',
  241. archive='archive',
  242. ),
  243. global_arguments=flexmock(dry_run=False),
  244. local_path='borg',
  245. remote_path=None,
  246. )
  247. assert command == ('borg', 'delete', '--match-archives', 'sh:foo*', 'repo')
  248. LOGGING_ANSWER = flexmock()
  249. def test_delete_archives_with_archive_calls_borg_delete():
  250. flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
  251. flexmock(module.logging).ANSWER = LOGGING_ANSWER
  252. flexmock(module.borgmatic.borg.repo_delete).should_receive('delete_repository').never()
  253. flexmock(module).should_receive('make_delete_command').and_return(flexmock())
  254. flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
  255. flexmock(),
  256. )
  257. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  258. flexmock(module.borgmatic.execute).should_receive('execute_command').once()
  259. module.delete_archives(
  260. repository={'path': 'repo'},
  261. config={},
  262. local_borg_version=flexmock(),
  263. delete_arguments=flexmock(archive='archive'),
  264. global_arguments=flexmock(),
  265. )
  266. def test_delete_archives_with_match_archives_calls_borg_delete():
  267. flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
  268. flexmock(module.logging).ANSWER = LOGGING_ANSWER
  269. flexmock(module.borgmatic.borg.repo_delete).should_receive('delete_repository').never()
  270. flexmock(module).should_receive('make_delete_command').and_return(flexmock())
  271. flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
  272. flexmock(),
  273. )
  274. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  275. flexmock(module.borgmatic.execute).should_receive('execute_command').once()
  276. module.delete_archives(
  277. repository={'path': 'repo'},
  278. config={},
  279. local_borg_version=flexmock(),
  280. delete_arguments=flexmock(match_archives='sh:foo*'),
  281. global_arguments=flexmock(),
  282. )
  283. @pytest.mark.parametrize('argument_name', module.ARCHIVE_RELATED_ARGUMENT_NAMES[2:])
  284. def test_delete_archives_with_archive_related_argument_calls_borg_delete(argument_name):
  285. flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
  286. flexmock(module.logging).ANSWER = LOGGING_ANSWER
  287. flexmock(module.borgmatic.borg.repo_delete).should_receive('delete_repository').never()
  288. flexmock(module).should_receive('make_delete_command').and_return(flexmock())
  289. flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
  290. flexmock(),
  291. )
  292. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  293. flexmock(module.borgmatic.execute).should_receive('execute_command').once()
  294. module.delete_archives(
  295. repository={'path': 'repo'},
  296. config={},
  297. local_borg_version=flexmock(),
  298. delete_arguments=flexmock(archive='archive', **{argument_name: 'value'}),
  299. global_arguments=flexmock(),
  300. )
  301. def test_delete_archives_without_archive_related_argument_calls_borg_repo_delete():
  302. flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
  303. flexmock(module.logging).ANSWER = LOGGING_ANSWER
  304. flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
  305. flexmock(module.borgmatic.borg.repo_delete).should_receive('delete_repository').once()
  306. flexmock(module).should_receive('make_delete_command').never()
  307. flexmock(module.borgmatic.borg.environment).should_receive('make_environment').never()
  308. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  309. flexmock(module.borgmatic.execute).should_receive('execute_command').never()
  310. module.delete_archives(
  311. repository={'path': 'repo'},
  312. config={},
  313. local_borg_version=flexmock(),
  314. delete_arguments=flexmock(
  315. list_details=True,
  316. force=False,
  317. cache_only=False,
  318. keep_security_info=False,
  319. ),
  320. global_arguments=flexmock(),
  321. )
  322. def test_delete_archives_calls_borg_delete_with_working_directory():
  323. flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
  324. flexmock(module.logging).ANSWER = LOGGING_ANSWER
  325. flexmock(module.borgmatic.borg.repo_delete).should_receive('delete_repository').never()
  326. command = flexmock()
  327. flexmock(module).should_receive('make_delete_command').and_return(command)
  328. environment = flexmock()
  329. flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
  330. environment,
  331. )
  332. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
  333. '/working/dir',
  334. )
  335. flexmock(module.borgmatic.execute).should_receive('execute_command').with_args(
  336. command,
  337. output_log_level=logging.ANSWER,
  338. environment=environment,
  339. working_directory='/working/dir',
  340. borg_local_path='borg',
  341. borg_exit_codes=None,
  342. ).once()
  343. module.delete_archives(
  344. repository={'path': 'repo'},
  345. config={'working_directory': '/working/dir'},
  346. local_borg_version=flexmock(),
  347. delete_arguments=flexmock(archive='archive'),
  348. global_arguments=flexmock(),
  349. )