test_extract.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. import logging
  2. import pytest
  3. from flexmock import flexmock
  4. from borgmatic.borg import extract as module
  5. from ..test_verbosity import insert_logging_mock
  6. def insert_execute_command_mock(command, working_directory=None):
  7. flexmock(module.environment).should_receive('make_environment')
  8. flexmock(module).should_receive('execute_command').with_args(
  9. command,
  10. working_directory=working_directory,
  11. extra_environment=None,
  12. ).once()
  13. def test_extract_last_archive_dry_run_calls_borg_with_last_archive():
  14. flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive')
  15. insert_execute_command_mock(('borg', 'extract', '--dry-run', 'repo::archive'))
  16. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  17. ('repo::archive',)
  18. )
  19. module.extract_last_archive_dry_run(
  20. config={},
  21. local_borg_version='1.2.3',
  22. global_arguments=flexmock(log_json=False),
  23. repository_path='repo',
  24. lock_wait=None,
  25. )
  26. def test_extract_last_archive_dry_run_without_any_archives_should_not_raise():
  27. flexmock(module.rlist).should_receive('resolve_archive_name').and_raise(ValueError)
  28. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(('repo',))
  29. module.extract_last_archive_dry_run(
  30. config={},
  31. local_borg_version='1.2.3',
  32. global_arguments=flexmock(log_json=False),
  33. repository_path='repo',
  34. lock_wait=None,
  35. )
  36. def test_extract_last_archive_dry_run_with_log_info_calls_borg_with_info_parameter():
  37. flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive')
  38. insert_execute_command_mock(('borg', 'extract', '--dry-run', '--info', 'repo::archive'))
  39. insert_logging_mock(logging.INFO)
  40. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  41. ('repo::archive',)
  42. )
  43. module.extract_last_archive_dry_run(
  44. config={},
  45. local_borg_version='1.2.3',
  46. global_arguments=flexmock(log_json=False),
  47. repository_path='repo',
  48. lock_wait=None,
  49. )
  50. def test_extract_last_archive_dry_run_with_log_debug_calls_borg_with_debug_parameter():
  51. flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive')
  52. insert_execute_command_mock(
  53. ('borg', 'extract', '--dry-run', '--debug', '--show-rc', '--list', 'repo::archive')
  54. )
  55. insert_logging_mock(logging.DEBUG)
  56. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  57. ('repo::archive',)
  58. )
  59. module.extract_last_archive_dry_run(
  60. config={},
  61. local_borg_version='1.2.3',
  62. global_arguments=flexmock(log_json=False),
  63. repository_path='repo',
  64. lock_wait=None,
  65. )
  66. def test_extract_last_archive_dry_run_calls_borg_via_local_path():
  67. flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive')
  68. insert_execute_command_mock(('borg1', 'extract', '--dry-run', 'repo::archive'))
  69. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  70. ('repo::archive',)
  71. )
  72. module.extract_last_archive_dry_run(
  73. config={},
  74. local_borg_version='1.2.3',
  75. global_arguments=flexmock(log_json=False),
  76. repository_path='repo',
  77. lock_wait=None,
  78. local_path='borg1',
  79. )
  80. def test_extract_last_archive_dry_run_calls_borg_with_remote_path_flags():
  81. flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive')
  82. insert_execute_command_mock(
  83. ('borg', 'extract', '--dry-run', '--remote-path', 'borg1', 'repo::archive')
  84. )
  85. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  86. ('repo::archive',)
  87. )
  88. module.extract_last_archive_dry_run(
  89. config={},
  90. local_borg_version='1.2.3',
  91. global_arguments=flexmock(log_json=False),
  92. repository_path='repo',
  93. lock_wait=None,
  94. remote_path='borg1',
  95. )
  96. def test_extract_last_archive_dry_run_calls_borg_with_log_json_flag():
  97. flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive')
  98. insert_execute_command_mock(('borg', 'extract', '--dry-run', '--log-json', 'repo::archive'))
  99. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  100. ('repo::archive',)
  101. )
  102. module.extract_last_archive_dry_run(
  103. config={},
  104. local_borg_version='1.2.3',
  105. global_arguments=flexmock(log_json=True),
  106. repository_path='repo',
  107. lock_wait=None,
  108. )
  109. def test_extract_last_archive_dry_run_calls_borg_with_lock_wait_flags():
  110. flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive')
  111. insert_execute_command_mock(
  112. ('borg', 'extract', '--dry-run', '--lock-wait', '5', 'repo::archive')
  113. )
  114. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  115. ('repo::archive',)
  116. )
  117. module.extract_last_archive_dry_run(
  118. config={},
  119. local_borg_version='1.2.3',
  120. global_arguments=flexmock(log_json=False),
  121. repository_path='repo',
  122. lock_wait=5,
  123. )
  124. def test_extract_archive_calls_borg_with_path_flags():
  125. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  126. insert_execute_command_mock(('borg', 'extract', 'repo::archive', 'path1', 'path2'))
  127. flexmock(module.feature).should_receive('available').and_return(True)
  128. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  129. ('repo::archive',)
  130. )
  131. flexmock(module.borgmatic.config.validate).should_receive(
  132. 'normalize_repository_path'
  133. ).and_return('repo')
  134. module.extract_archive(
  135. dry_run=False,
  136. repository='repo',
  137. archive='archive',
  138. paths=['path1', 'path2'],
  139. config={},
  140. local_borg_version='1.2.3',
  141. global_arguments=flexmock(log_json=False),
  142. )
  143. def test_extract_archive_calls_borg_with_remote_path_flags():
  144. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  145. insert_execute_command_mock(('borg', 'extract', '--remote-path', 'borg1', 'repo::archive'))
  146. flexmock(module.feature).should_receive('available').and_return(True)
  147. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  148. ('repo::archive',)
  149. )
  150. flexmock(module.borgmatic.config.validate).should_receive(
  151. 'normalize_repository_path'
  152. ).and_return('repo')
  153. module.extract_archive(
  154. dry_run=False,
  155. repository='repo',
  156. archive='archive',
  157. paths=None,
  158. config={},
  159. local_borg_version='1.2.3',
  160. global_arguments=flexmock(log_json=False),
  161. remote_path='borg1',
  162. )
  163. @pytest.mark.parametrize(
  164. 'feature_available,option_flag',
  165. (
  166. (True, '--numeric-ids'),
  167. (False, '--numeric-owner'),
  168. ),
  169. )
  170. def test_extract_archive_calls_borg_with_numeric_ids_parameter(feature_available, option_flag):
  171. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  172. insert_execute_command_mock(('borg', 'extract', option_flag, 'repo::archive'))
  173. flexmock(module.feature).should_receive('available').and_return(feature_available)
  174. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  175. ('repo::archive',)
  176. )
  177. flexmock(module.borgmatic.config.validate).should_receive(
  178. 'normalize_repository_path'
  179. ).and_return('repo')
  180. module.extract_archive(
  181. dry_run=False,
  182. repository='repo',
  183. archive='archive',
  184. paths=None,
  185. config={'numeric_ids': True},
  186. local_borg_version='1.2.3',
  187. global_arguments=flexmock(log_json=False),
  188. )
  189. def test_extract_archive_calls_borg_with_umask_flags():
  190. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  191. insert_execute_command_mock(('borg', 'extract', '--umask', '0770', 'repo::archive'))
  192. flexmock(module.feature).should_receive('available').and_return(True)
  193. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  194. ('repo::archive',)
  195. )
  196. flexmock(module.borgmatic.config.validate).should_receive(
  197. 'normalize_repository_path'
  198. ).and_return('repo')
  199. module.extract_archive(
  200. dry_run=False,
  201. repository='repo',
  202. archive='archive',
  203. paths=None,
  204. config={'umask': '0770'},
  205. local_borg_version='1.2.3',
  206. global_arguments=flexmock(log_json=False),
  207. )
  208. def test_extract_archive_calls_borg_with_log_json_flags():
  209. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  210. insert_execute_command_mock(('borg', 'extract', '--log-json', 'repo::archive'))
  211. flexmock(module.feature).should_receive('available').and_return(True)
  212. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  213. ('repo::archive',)
  214. )
  215. module.extract_archive(
  216. dry_run=False,
  217. repository='repo',
  218. archive='archive',
  219. paths=None,
  220. config={},
  221. local_borg_version='1.2.3',
  222. global_arguments=flexmock(log_json=True),
  223. )
  224. def test_extract_archive_calls_borg_with_lock_wait_flags():
  225. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  226. insert_execute_command_mock(('borg', 'extract', '--lock-wait', '5', 'repo::archive'))
  227. flexmock(module.feature).should_receive('available').and_return(True)
  228. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  229. ('repo::archive',)
  230. )
  231. flexmock(module.borgmatic.config.validate).should_receive(
  232. 'normalize_repository_path'
  233. ).and_return('repo')
  234. module.extract_archive(
  235. dry_run=False,
  236. repository='repo',
  237. archive='archive',
  238. paths=None,
  239. config={'lock_wait': '5'},
  240. local_borg_version='1.2.3',
  241. global_arguments=flexmock(log_json=False),
  242. )
  243. def test_extract_archive_with_log_info_calls_borg_with_info_parameter():
  244. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  245. insert_execute_command_mock(('borg', 'extract', '--info', 'repo::archive'))
  246. insert_logging_mock(logging.INFO)
  247. flexmock(module.feature).should_receive('available').and_return(True)
  248. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  249. ('repo::archive',)
  250. )
  251. flexmock(module.borgmatic.config.validate).should_receive(
  252. 'normalize_repository_path'
  253. ).and_return('repo')
  254. module.extract_archive(
  255. dry_run=False,
  256. repository='repo',
  257. archive='archive',
  258. paths=None,
  259. config={},
  260. local_borg_version='1.2.3',
  261. global_arguments=flexmock(log_json=False),
  262. )
  263. def test_extract_archive_with_log_debug_calls_borg_with_debug_flags():
  264. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  265. insert_execute_command_mock(
  266. ('borg', 'extract', '--debug', '--list', '--show-rc', 'repo::archive')
  267. )
  268. insert_logging_mock(logging.DEBUG)
  269. flexmock(module.feature).should_receive('available').and_return(True)
  270. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  271. ('repo::archive',)
  272. )
  273. flexmock(module.borgmatic.config.validate).should_receive(
  274. 'normalize_repository_path'
  275. ).and_return('repo')
  276. module.extract_archive(
  277. dry_run=False,
  278. repository='repo',
  279. archive='archive',
  280. paths=None,
  281. config={},
  282. local_borg_version='1.2.3',
  283. global_arguments=flexmock(log_json=False),
  284. )
  285. def test_extract_archive_calls_borg_with_dry_run_parameter():
  286. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  287. insert_execute_command_mock(('borg', 'extract', '--dry-run', 'repo::archive'))
  288. flexmock(module.feature).should_receive('available').and_return(True)
  289. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  290. ('repo::archive',)
  291. )
  292. flexmock(module.borgmatic.config.validate).should_receive(
  293. 'normalize_repository_path'
  294. ).and_return('repo')
  295. module.extract_archive(
  296. dry_run=True,
  297. repository='repo',
  298. archive='archive',
  299. paths=None,
  300. config={},
  301. local_borg_version='1.2.3',
  302. global_arguments=flexmock(log_json=False),
  303. )
  304. def test_extract_archive_calls_borg_with_destination_path():
  305. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  306. insert_execute_command_mock(('borg', 'extract', 'repo::archive'), working_directory='/dest')
  307. flexmock(module.feature).should_receive('available').and_return(True)
  308. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  309. ('repo::archive',)
  310. )
  311. flexmock(module.borgmatic.config.validate).should_receive(
  312. 'normalize_repository_path'
  313. ).and_return('repo')
  314. module.extract_archive(
  315. dry_run=False,
  316. repository='repo',
  317. archive='archive',
  318. paths=None,
  319. config={},
  320. local_borg_version='1.2.3',
  321. global_arguments=flexmock(log_json=False),
  322. destination_path='/dest',
  323. )
  324. def test_extract_archive_calls_borg_with_strip_components():
  325. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  326. insert_execute_command_mock(('borg', 'extract', '--strip-components', '5', 'repo::archive'))
  327. flexmock(module.feature).should_receive('available').and_return(True)
  328. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  329. ('repo::archive',)
  330. )
  331. flexmock(module.borgmatic.config.validate).should_receive(
  332. 'normalize_repository_path'
  333. ).and_return('repo')
  334. module.extract_archive(
  335. dry_run=False,
  336. repository='repo',
  337. archive='archive',
  338. paths=None,
  339. config={},
  340. local_borg_version='1.2.3',
  341. global_arguments=flexmock(log_json=False),
  342. strip_components=5,
  343. )
  344. def test_extract_archive_calls_borg_with_strip_components_calculated_from_all():
  345. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  346. insert_execute_command_mock(
  347. (
  348. 'borg',
  349. 'extract',
  350. '--strip-components',
  351. '2',
  352. 'repo::archive',
  353. 'foo/bar/baz.txt',
  354. 'foo/bar.txt',
  355. )
  356. )
  357. flexmock(module.feature).should_receive('available').and_return(True)
  358. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  359. ('repo::archive',)
  360. )
  361. flexmock(module.borgmatic.config.validate).should_receive(
  362. 'normalize_repository_path'
  363. ).and_return('repo')
  364. module.extract_archive(
  365. dry_run=False,
  366. repository='repo',
  367. archive='archive',
  368. paths=['foo/bar/baz.txt', 'foo/bar.txt'],
  369. config={},
  370. local_borg_version='1.2.3',
  371. global_arguments=flexmock(log_json=False),
  372. strip_components='all',
  373. )
  374. def test_extract_archive_with_strip_components_all_and_no_paths_raises():
  375. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  376. flexmock(module.feature).should_receive('available').and_return(True)
  377. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  378. ('repo::archive',)
  379. )
  380. flexmock(module.borgmatic.config.validate).should_receive(
  381. 'normalize_repository_path'
  382. ).and_return('repo')
  383. flexmock(module).should_receive('execute_command').never()
  384. with pytest.raises(ValueError):
  385. module.extract_archive(
  386. dry_run=False,
  387. repository='repo',
  388. archive='archive',
  389. paths=None,
  390. config={},
  391. local_borg_version='1.2.3',
  392. global_arguments=flexmock(log_json=False),
  393. strip_components='all',
  394. )
  395. def test_extract_archive_calls_borg_with_progress_parameter():
  396. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  397. flexmock(module.environment).should_receive('make_environment')
  398. flexmock(module).should_receive('execute_command').with_args(
  399. ('borg', 'extract', '--progress', 'repo::archive'),
  400. output_file=module.DO_NOT_CAPTURE,
  401. working_directory=None,
  402. extra_environment=None,
  403. ).once()
  404. flexmock(module.feature).should_receive('available').and_return(True)
  405. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  406. ('repo::archive',)
  407. )
  408. flexmock(module.borgmatic.config.validate).should_receive(
  409. 'normalize_repository_path'
  410. ).and_return('repo')
  411. module.extract_archive(
  412. dry_run=False,
  413. repository='repo',
  414. archive='archive',
  415. paths=None,
  416. config={},
  417. local_borg_version='1.2.3',
  418. global_arguments=flexmock(log_json=False),
  419. progress=True,
  420. )
  421. def test_extract_archive_with_progress_and_extract_to_stdout_raises():
  422. flexmock(module).should_receive('execute_command').never()
  423. with pytest.raises(ValueError):
  424. module.extract_archive(
  425. dry_run=False,
  426. repository='repo',
  427. archive='archive',
  428. paths=None,
  429. config={},
  430. local_borg_version='1.2.3',
  431. global_arguments=flexmock(log_json=False),
  432. progress=True,
  433. extract_to_stdout=True,
  434. )
  435. def test_extract_archive_calls_borg_with_stdout_parameter_and_returns_process():
  436. flexmock(module.os.path).should_receive('abspath').and_return('repo')
  437. process = flexmock()
  438. flexmock(module.environment).should_receive('make_environment')
  439. flexmock(module).should_receive('execute_command').with_args(
  440. ('borg', 'extract', '--stdout', 'repo::archive'),
  441. output_file=module.subprocess.PIPE,
  442. working_directory=None,
  443. run_to_completion=False,
  444. extra_environment=None,
  445. ).and_return(process).once()
  446. flexmock(module.feature).should_receive('available').and_return(True)
  447. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  448. ('repo::archive',)
  449. )
  450. flexmock(module.borgmatic.config.validate).should_receive(
  451. 'normalize_repository_path'
  452. ).and_return('repo')
  453. assert (
  454. module.extract_archive(
  455. dry_run=False,
  456. repository='repo',
  457. archive='archive',
  458. paths=None,
  459. config={},
  460. local_borg_version='1.2.3',
  461. global_arguments=flexmock(log_json=False),
  462. extract_to_stdout=True,
  463. )
  464. == process
  465. )
  466. def test_extract_archive_skips_abspath_for_remote_repository():
  467. flexmock(module.os.path).should_receive('abspath').never()
  468. flexmock(module.environment).should_receive('make_environment')
  469. flexmock(module).should_receive('execute_command').with_args(
  470. ('borg', 'extract', 'server:repo::archive'),
  471. working_directory=None,
  472. extra_environment=None,
  473. ).once()
  474. flexmock(module.feature).should_receive('available').and_return(True)
  475. flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
  476. ('server:repo::archive',)
  477. )
  478. flexmock(module.borgmatic.config.validate).should_receive(
  479. 'normalize_repository_path'
  480. ).and_return('repo')
  481. module.extract_archive(
  482. dry_run=False,
  483. repository='server:repo',
  484. archive='archive',
  485. paths=None,
  486. config={},
  487. local_borg_version='1.2.3',
  488. global_arguments=flexmock(log_json=False),
  489. )