From e3dd545345908304833440d803fb3a8a48119a6f Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Fri, 1 Nov 2019 10:00:26 -0700 Subject: [PATCH] Extract files to a particular directory via "borgmatic extract --destination" flag. Also rename "--restore-path" to "--path" to reduce confusion. --- NEWS | 5 +++++ borgmatic/borg/extract.py | 4 ++-- borgmatic/commands/arguments.py | 11 +++++++++-- borgmatic/commands/borgmatic.py | 4 ++-- docs/how-to/extract-a-backup.md | 19 ++++++++++++++++--- setup.py | 2 +- tests/integration/commands/test_arguments.py | 4 ++-- tests/unit/borg/test_extract.py | 20 ++++++++++---------- 8 files changed, 47 insertions(+), 22 deletions(-) diff --git a/NEWS b/NEWS index 379278623..bc5dbbf54 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +1.4.2 + * Extract files to a particular directory via "borgmatic extract --destination" flag. + * Rename "borgmatic extract --restore-path" flag to "--path" to reduce confusion with the separate + "borgmatic restore" action. Any uses of "--restore-path" will continue working. + 1.4.1 * #229: Restore backed up PostgreSQL databases via "borgmatic restore" action. See the documentation for more information: diff --git a/borgmatic/borg/extract.py b/borgmatic/borg/extract.py index 94e1e2ab6..f365942fd 100644 --- a/borgmatic/borg/extract.py +++ b/borgmatic/borg/extract.py @@ -55,7 +55,7 @@ def extract_archive( dry_run, repository, archive, - restore_paths, + paths, location_config, storage_config, local_path='borg', @@ -83,7 +83,7 @@ def extract_archive( + (('--dry-run',) if dry_run else ()) + (('--progress',) if progress else ()) + ('::'.join((os.path.abspath(repository), archive)),) - + (tuple(restore_paths) if restore_paths else ()) + + (tuple(paths) if paths else ()) ) # The progress output isn't compatible with captured and logged output, as progress messes with diff --git a/borgmatic/commands/arguments.py b/borgmatic/commands/arguments.py index 857ba1e82..361c473fe 100644 --- a/borgmatic/commands/arguments.py +++ b/borgmatic/commands/arguments.py @@ -275,11 +275,18 @@ def parse_arguments(*unparsed_arguments): ) extract_group.add_argument('--archive', help='Name of archive to operate on', required=True) extract_group.add_argument( + '--path', '--restore-path', metavar='PATH', nargs='+', - dest='restore_paths', - help='Paths to restore from archive, defaults to the entire archive', + dest='paths', + help='Paths to extract from archive, defaults to the entire archive', + ) + extract_group.add_argument( + '--destination', + metavar='PATH', + dest='destination', + help='Directory to extract files into, defaults to the current directory', ) extract_group.add_argument( '--progress', diff --git a/borgmatic/commands/borgmatic.py b/borgmatic/commands/borgmatic.py index 3d0f1a698..fce102ccd 100644 --- a/borgmatic/commands/borgmatic.py +++ b/borgmatic/commands/borgmatic.py @@ -215,12 +215,12 @@ def run_actions( global_arguments.dry_run, repository, arguments['extract'].archive, - arguments['extract'].restore_paths, + arguments['extract'].paths, location, storage, local_path=local_path, remote_path=remote_path, - destination_path=None, + destination_path=arguments['extract'].destination, progress=arguments['extract'].progress, ) if 'restore' in arguments: diff --git a/docs/how-to/extract-a-backup.md b/docs/how-to/extract-a-backup.md index 7888b1298..554bf7252 100644 --- a/docs/how-to/extract-a-backup.md +++ b/docs/how-to/extract-a-backup.md @@ -51,11 +51,11 @@ borgmatic extract --repository repo.borg --archive host-2019-... ## Extract particular files Sometimes, you want to extract a single deleted file, rather than extracting -everything from an archive. To do that, tack on one or more `--restore-path` -values. For instance: +everything from an archive. To do that, tack on one or more `--path` values. +For instance: ```bash -borgmatic extract --archive host-2019-... --restore-path path/1 path/2 +borgmatic extract --archive host-2019-... --path path/1 path/2 ``` Note that the specified restore paths should not have a leading slash. Like a @@ -63,6 +63,19 @@ whole-archive extract, this also extracts into the current directory. So for example, if you happen to be in the directory `/var` and you run the `extract` command above, borgmatic will extract `/var/path/1` and `/var/path/2`. +## Extract to a particular destination + +By default, borgmatic extracts files into the current directory. To instead +extract files to a particular destination directory, use the `--destination` +flag: + +```bash +borgmatic extract --archive host-2019-... --destination /tmp +``` + +When using the `--destination` flag, be careful not to overwrite your system's +files with extracted files unless that is your intent. + ## Database restoration diff --git a/setup.py b/setup.py index 79a8211fd..8610ef43f 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import find_packages, setup -VERSION = '1.4.1' +VERSION = '1.4.2' setup( diff --git a/tests/integration/commands/test_arguments.py b/tests/integration/commands/test_arguments.py index 6e3b11e6d..527da05ff 100644 --- a/tests/integration/commands/test_arguments.py +++ b/tests/integration/commands/test_arguments.py @@ -267,11 +267,11 @@ def test_parse_arguments_disallows_archive_without_extract_restore_or_list(): module.parse_arguments('--config', 'myconfig', '--archive', 'test') -def test_parse_arguments_disallows_restore_paths_without_extract(): +def test_parse_arguments_disallows_paths_without_extract(): flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default']) with pytest.raises(SystemExit): - module.parse_arguments('--config', 'myconfig', '--restore-path', 'test') + module.parse_arguments('--config', 'myconfig', '--path', 'test') def test_parse_arguments_allows_archive_with_extract(): diff --git a/tests/unit/borg/test_extract.py b/tests/unit/borg/test_extract.py index 2db8c8505..1459d53a1 100644 --- a/tests/unit/borg/test_extract.py +++ b/tests/unit/borg/test_extract.py @@ -95,7 +95,7 @@ def test_extract_archive_calls_borg_with_restore_path_parameters(): dry_run=False, repository='repo', archive='archive', - restore_paths=['path1', 'path2'], + paths=['path1', 'path2'], location_config={}, storage_config={}, ) @@ -109,7 +109,7 @@ def test_extract_archive_calls_borg_with_remote_path_parameters(): dry_run=False, repository='repo', archive='archive', - restore_paths=None, + paths=None, location_config={}, storage_config={}, remote_path='borg1', @@ -124,7 +124,7 @@ def test_extract_archive_calls_borg_with_numeric_owner_parameter(): dry_run=False, repository='repo', archive='archive', - restore_paths=None, + paths=None, location_config={'numeric_owner': True}, storage_config={}, ) @@ -138,7 +138,7 @@ def test_extract_archive_calls_borg_with_umask_parameters(): dry_run=False, repository='repo', archive='archive', - restore_paths=None, + paths=None, location_config={}, storage_config={'umask': '0770'}, ) @@ -152,7 +152,7 @@ def test_extract_archive_calls_borg_with_lock_wait_parameters(): dry_run=False, repository='repo', archive='archive', - restore_paths=None, + paths=None, location_config={}, storage_config={'lock_wait': '5'}, ) @@ -167,7 +167,7 @@ def test_extract_archive_with_log_info_calls_borg_with_info_parameter(): dry_run=False, repository='repo', archive='archive', - restore_paths=None, + paths=None, location_config={}, storage_config={}, ) @@ -184,7 +184,7 @@ def test_extract_archive_with_log_debug_calls_borg_with_debug_parameters(): dry_run=False, repository='repo', archive='archive', - restore_paths=None, + paths=None, location_config={}, storage_config={}, ) @@ -198,7 +198,7 @@ def test_extract_archive_calls_borg_with_dry_run_parameter(): dry_run=True, repository='repo', archive='archive', - restore_paths=None, + paths=None, location_config={}, storage_config={}, ) @@ -212,7 +212,7 @@ def test_extract_archive_calls_borg_with_destination_path(): dry_run=False, repository='repo', archive='archive', - restore_paths=None, + paths=None, location_config={}, storage_config={}, destination_path='/dest', @@ -231,7 +231,7 @@ def test_extract_archive_calls_borg_with_progress_parameter(): dry_run=False, repository='repo', archive='archive', - restore_paths=None, + paths=None, location_config={}, storage_config={}, progress=True,