diff --git a/NEWS b/NEWS index ce9f36b3..9e9ea40d 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +1.2.18 + * #147: Support for Borg create/extract --numeric-owner flag via "numeric_owner" option in + borgmatic's location section. + 1.2.17 * #140: List the files within an archive via --list --archive option. @@ -39,8 +43,8 @@ * #108: Support for Borg create --progress via borgmatic command-line flag. 1.2.10 - * #105: Support for Borg --chunker-params create option via "chunker_params" in borgmatic's storage - section. + * #105: Support for Borg --chunker-params create option via "chunker_params" option in borgmatic's + storage section. 1.2.9 * #102: Fix for syntax error that occurred in Python 3.5 and below. diff --git a/borgmatic/borg/create.py b/borgmatic/borg/create.py index 9fedbc25..62ecb8be 100644 --- a/borgmatic/borg/create.py +++ b/borgmatic/borg/create.py @@ -141,6 +141,7 @@ def create_archive( + (('--compression', compression) if compression else ()) + (('--remote-ratelimit', str(remote_rate_limit)) if remote_rate_limit else ()) + (('--one-file-system',) if location_config.get('one_file_system') else ()) + + (('--numeric-owner',) if location_config.get('numeric_owner') else ()) + (('--read-special',) if location_config.get('read_special') else ()) + (('--nobsdflags',) if location_config.get('bsd_flags') is False else ()) + (('--files-cache', files_cache) if files_cache else ()) diff --git a/borgmatic/borg/extract.py b/borgmatic/borg/extract.py index 078b3cfa..1b5bce80 100644 --- a/borgmatic/borg/extract.py +++ b/borgmatic/borg/extract.py @@ -57,6 +57,7 @@ def extract_archive( repository, archive, restore_paths, + location_config, storage_config, local_path='borg', remote_path=None, @@ -64,8 +65,8 @@ def extract_archive( ): ''' Given a dry-run flag, a local or remote repository path, an archive name, zero or more paths to - restore from the archive, and a storage configuration dict, extract the archive into the current - directory. + restore from the archive, and location/storage configuration dicts, extract the archive into the + current directory. ''' umask = storage_config.get('umask', None) lock_wait = storage_config.get('lock_wait', None) @@ -74,6 +75,7 @@ def extract_archive( (local_path, 'extract', '::'.join((repository, archive))) + (tuple(restore_paths) if restore_paths else ()) + (('--remote-path', remote_path) if remote_path else ()) + + (('--numeric-owner',) if location_config.get('numeric_owner') else ()) + (('--umask', str(umask)) if umask else ()) + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) diff --git a/borgmatic/commands/borgmatic.py b/borgmatic/commands/borgmatic.py index 2c1d9384..41ce4cec 100644 --- a/borgmatic/commands/borgmatic.py +++ b/borgmatic/commands/borgmatic.py @@ -367,6 +367,7 @@ def _run_commands_on_repository( repository, args.archive, args.restore_paths, + location, storage, local_path=local_path, remote_path=remote_path, diff --git a/borgmatic/config/schema.yaml b/borgmatic/config/schema.yaml index 85772f15..ce34f2a7 100644 --- a/borgmatic/config/schema.yaml +++ b/borgmatic/config/schema.yaml @@ -32,6 +32,10 @@ map: type: bool desc: Stay in same file system (do not cross mount points). Defaults to false. example: true + numeric_owner: + type: bool + desc: Only store/extract numeric user and group identifiers. Defaults to false. + example: true read_special: type: bool desc: | diff --git a/setup.py b/setup.py index 4496c3d2..ceda7a58 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from setuptools import setup, find_packages -VERSION = '1.2.17' +VERSION = '1.2.18' setup( diff --git a/tests/unit/borg/test_create.py b/tests/unit/borg/test_create.py index 8d69d3ed..e2ac7f11 100644 --- a/tests/unit/borg/test_create.py +++ b/tests/unit/borg/test_create.py @@ -425,7 +425,7 @@ def test_create_archive_with_remote_rate_limit_calls_borg_with_remote_ratelimit_ ) -def test_create_archive_with_one_file_system_calls_borg_with_one_file_system_parameters(): +def test_create_archive_with_one_file_system_calls_borg_with_one_file_system_parameter(): flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar')) flexmock(module).should_receive('_expand_home_directories').and_return(()) flexmock(module).should_receive('_write_pattern_file').and_return(None) @@ -446,6 +446,27 @@ def test_create_archive_with_one_file_system_calls_borg_with_one_file_system_par ) +def test_create_archive_with_numeric_owner_calls_borg_with_numeric_owner_parameter(): + flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar')) + flexmock(module).should_receive('_expand_home_directories').and_return(()) + flexmock(module).should_receive('_write_pattern_file').and_return(None) + flexmock(module).should_receive('_make_pattern_flags').and_return(()) + flexmock(module).should_receive('_make_exclude_flags').and_return(()) + insert_subprocess_mock(CREATE_COMMAND + ('--numeric-owner',)) + + module.create_archive( + dry_run=False, + repository='repo', + location_config={ + 'source_directories': ['foo', 'bar'], + 'repositories': ['repo'], + 'numeric_owner': True, + 'exclude_patterns': None, + }, + storage_config={}, + ) + + def test_create_archive_with_read_special_calls_borg_with_read_special_parameter(): flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar')) flexmock(module).should_receive('_expand_home_directories').and_return(()) diff --git a/tests/unit/borg/test_extract.py b/tests/unit/borg/test_extract.py index a36afb89..75b49357 100644 --- a/tests/unit/borg/test_extract.py +++ b/tests/unit/borg/test_extract.py @@ -111,6 +111,7 @@ def test_extract_archive_calls_borg_with_restore_path_parameters(): repository='repo', archive='archive', restore_paths=['path1', 'path2'], + location_config={}, storage_config={}, ) @@ -123,11 +124,25 @@ def test_extract_archive_calls_borg_with_remote_path_parameters(): repository='repo', archive='archive', restore_paths=None, + location_config={}, storage_config={}, remote_path='borg1', ) +def test_extract_archive_calls_borg_with_numeric_owner_parameter(): + insert_subprocess_mock(('borg', 'extract', 'repo::archive', '--numeric-owner')) + + module.extract_archive( + dry_run=False, + repository='repo', + archive='archive', + restore_paths=None, + location_config={'numeric_owner': True}, + storage_config={}, + ) + + def test_extract_archive_calls_borg_with_umask_parameters(): insert_subprocess_mock(('borg', 'extract', 'repo::archive', '--umask', '0770')) @@ -136,6 +151,7 @@ def test_extract_archive_calls_borg_with_umask_parameters(): repository='repo', archive='archive', restore_paths=None, + location_config={}, storage_config={'umask': '0770'}, ) @@ -148,6 +164,7 @@ def test_extract_archive_calls_borg_with_lock_wait_parameters(): repository='repo', archive='archive', restore_paths=None, + location_config={}, storage_config={'lock_wait': '5'}, ) @@ -157,7 +174,12 @@ def test_extract_archive_with_log_info_calls_borg_with_info_parameter(): insert_logging_mock(logging.INFO) module.extract_archive( - dry_run=False, repository='repo', archive='archive', restore_paths=None, storage_config={} + dry_run=False, + repository='repo', + archive='archive', + restore_paths=None, + location_config={}, + storage_config={}, ) @@ -166,7 +188,12 @@ def test_extract_archive_with_log_debug_calls_borg_with_debug_parameters(): insert_logging_mock(logging.DEBUG) module.extract_archive( - dry_run=False, repository='repo', archive='archive', restore_paths=None, storage_config={} + dry_run=False, + repository='repo', + archive='archive', + restore_paths=None, + location_config={}, + storage_config={}, ) @@ -174,7 +201,12 @@ def test_extract_archive_calls_borg_with_dry_run_parameter(): insert_subprocess_mock(('borg', 'extract', 'repo::archive', '--dry-run')) module.extract_archive( - dry_run=True, repository='repo', archive='archive', restore_paths=None, storage_config={} + dry_run=True, + repository='repo', + archive='archive', + restore_paths=None, + location_config={}, + storage_config={}, ) @@ -186,6 +218,7 @@ def test_extract_archive_calls_borg_with_progress_parameter(): repository='repo', archive='archive', restore_paths=None, + location_config={}, storage_config={}, progress=True, )