test_delete.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  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_includes_extra_borg_options():
  146. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  147. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
  148. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  149. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  150. ('repo',),
  151. )
  152. command = module.make_delete_command(
  153. repository={'path': 'repo'},
  154. config={'extra_borg_options': {'delete': '--extra "value with space"'}},
  155. local_borg_version='1.2.3',
  156. delete_arguments=flexmock(list_details=False, force=0, match_archives=None, archive=None),
  157. global_arguments=flexmock(dry_run=False),
  158. local_path='borg',
  159. remote_path=None,
  160. )
  161. assert command == ('borg', 'delete', '--extra', 'value with space', 'repo')
  162. def test_make_delete_command_with_list_config_calls_borg_with_list_flag():
  163. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  164. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').with_args(
  165. 'list',
  166. True,
  167. ).and_return(('--list',))
  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={'list_details': True},
  176. local_borg_version='1.2.3',
  177. delete_arguments=flexmock(list_details=None, force=0, 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', '--list', 'repo')
  183. def test_make_delete_command_includes_force():
  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=1, 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', 'repo')
  200. def test_make_delete_command_includes_force_twice():
  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. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  204. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  205. ('repo',),
  206. )
  207. command = module.make_delete_command(
  208. repository={'path': 'repo'},
  209. config={},
  210. local_borg_version='1.2.3',
  211. delete_arguments=flexmock(list_details=False, force=2, match_archives=None, archive=None),
  212. global_arguments=flexmock(dry_run=False),
  213. local_path='borg',
  214. remote_path=None,
  215. )
  216. assert command == ('borg', 'delete', '--force', '--force', 'repo')
  217. def test_make_delete_command_includes_archive():
  218. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  219. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(
  220. ('--match-archives', 'archive'),
  221. )
  222. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  223. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  224. ('repo',),
  225. )
  226. command = module.make_delete_command(
  227. repository={'path': 'repo'},
  228. config={},
  229. local_borg_version='1.2.3',
  230. delete_arguments=flexmock(
  231. list_details=False,
  232. force=0,
  233. match_archives=None,
  234. archive='archive',
  235. ),
  236. global_arguments=flexmock(dry_run=False),
  237. local_path='borg',
  238. remote_path=None,
  239. )
  240. assert command == ('borg', 'delete', '--match-archives', 'archive', 'repo')
  241. def test_make_delete_command_includes_match_archives():
  242. flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
  243. flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(
  244. ('--match-archives', 'sh:foo*'),
  245. )
  246. flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
  247. flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
  248. ('repo',),
  249. )
  250. command = module.make_delete_command(
  251. repository={'path': 'repo'},
  252. config={},
  253. local_borg_version='1.2.3',
  254. delete_arguments=flexmock(
  255. list_details=False,
  256. force=0,
  257. match_archives='sh:foo*',
  258. archive='archive',
  259. ),
  260. global_arguments=flexmock(dry_run=False),
  261. local_path='borg',
  262. remote_path=None,
  263. )
  264. assert command == ('borg', 'delete', '--match-archives', 'sh:foo*', 'repo')
  265. LOGGING_ANSWER = flexmock()
  266. def test_delete_archives_with_archive_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(archive='archive'),
  281. global_arguments=flexmock(),
  282. )
  283. def test_delete_archives_with_match_archives_calls_borg_delete():
  284. flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
  285. flexmock(module.logging).ANSWER = LOGGING_ANSWER
  286. flexmock(module.borgmatic.borg.repo_delete).should_receive('delete_repository').never()
  287. flexmock(module).should_receive('make_delete_command').and_return(flexmock())
  288. flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
  289. flexmock(),
  290. )
  291. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  292. flexmock(module.borgmatic.execute).should_receive('execute_command').once()
  293. module.delete_archives(
  294. repository={'path': 'repo'},
  295. config={},
  296. local_borg_version=flexmock(),
  297. delete_arguments=flexmock(match_archives='sh:foo*'),
  298. global_arguments=flexmock(),
  299. )
  300. @pytest.mark.parametrize('argument_name', module.ARCHIVE_RELATED_ARGUMENT_NAMES[2:])
  301. def test_delete_archives_with_archive_related_argument_calls_borg_delete(argument_name):
  302. flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
  303. flexmock(module.logging).ANSWER = LOGGING_ANSWER
  304. flexmock(module.borgmatic.borg.repo_delete).should_receive('delete_repository').never()
  305. flexmock(module).should_receive('make_delete_command').and_return(flexmock())
  306. flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
  307. flexmock(),
  308. )
  309. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  310. flexmock(module.borgmatic.execute).should_receive('execute_command').once()
  311. module.delete_archives(
  312. repository={'path': 'repo'},
  313. config={},
  314. local_borg_version=flexmock(),
  315. delete_arguments=flexmock(archive='archive', **{argument_name: 'value'}),
  316. global_arguments=flexmock(),
  317. )
  318. def test_delete_archives_without_archive_related_argument_calls_borg_repo_delete():
  319. flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
  320. flexmock(module.logging).ANSWER = LOGGING_ANSWER
  321. flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
  322. flexmock(module.borgmatic.borg.repo_delete).should_receive('delete_repository').once()
  323. flexmock(module).should_receive('make_delete_command').never()
  324. flexmock(module.borgmatic.borg.environment).should_receive('make_environment').never()
  325. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  326. flexmock(module.borgmatic.execute).should_receive('execute_command').never()
  327. module.delete_archives(
  328. repository={'path': 'repo'},
  329. config={},
  330. local_borg_version=flexmock(),
  331. delete_arguments=flexmock(
  332. list_details=True,
  333. force=False,
  334. cache_only=False,
  335. keep_security_info=False,
  336. ),
  337. global_arguments=flexmock(),
  338. )
  339. def test_delete_archives_calls_borg_delete_with_working_directory():
  340. flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
  341. flexmock(module.logging).ANSWER = LOGGING_ANSWER
  342. flexmock(module.borgmatic.borg.repo_delete).should_receive('delete_repository').never()
  343. command = flexmock()
  344. flexmock(module).should_receive('make_delete_command').and_return(command)
  345. environment = flexmock()
  346. flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
  347. environment,
  348. )
  349. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
  350. '/working/dir',
  351. )
  352. flexmock(module.borgmatic.execute).should_receive('execute_command').with_args(
  353. command,
  354. output_log_level=logging.ANSWER,
  355. environment=environment,
  356. working_directory='/working/dir',
  357. borg_local_path='borg',
  358. borg_exit_codes=None,
  359. ).once()
  360. module.delete_archives(
  361. repository={'path': 'repo'},
  362. config={'working_directory': '/working/dir'},
  363. local_borg_version=flexmock(),
  364. delete_arguments=flexmock(archive='archive'),
  365. global_arguments=flexmock(),
  366. )