When using the "bsd_flags" option, tailor the flags passed to Borg depending on the Borg version (#394).
This commit is contained in:
parent
4b5af2770d
commit
6bf6ac310b
6 changed files with 65 additions and 16 deletions
3
NEWS
3
NEWS
|
@ -2,7 +2,8 @@
|
||||||
* #394: Compact repository segments and free space with new "borgmatic compact" action. Borg 1.2+
|
* #394: Compact repository segments and free space with new "borgmatic compact" action. Borg 1.2+
|
||||||
only. Also run "compact" by default when no actions are specified, as "prune" in Borg 1.2 no
|
only. Also run "compact" by default when no actions are specified, as "prune" in Borg 1.2 no
|
||||||
longer frees up space unless "compact" is run.
|
longer frees up space unless "compact" is run.
|
||||||
* #394: When the "atime" option is used, tailor the flags passed to Borg depending on version.
|
* #394: When using the "atime" or "bsd_flags" options, tailor the flags passed to Borg depending on
|
||||||
|
the Borg version.
|
||||||
* #480, #482: Fix traceback when a YAML validation error occurs.
|
* #480, #482: Fix traceback when a YAML validation error occurs.
|
||||||
|
|
||||||
1.5.22
|
1.5.22
|
||||||
|
|
|
@ -227,12 +227,16 @@ def create_archive(
|
||||||
archive_name_format = storage_config.get('archive_name_format', DEFAULT_ARCHIVE_NAME_FORMAT)
|
archive_name_format = storage_config.get('archive_name_format', DEFAULT_ARCHIVE_NAME_FORMAT)
|
||||||
extra_borg_options = storage_config.get('extra_borg_options', {}).get('create', '')
|
extra_borg_options = storage_config.get('extra_borg_options', {}).get('create', '')
|
||||||
|
|
||||||
atime_feature_available = feature.available(feature.Feature.ATIME, local_borg_version)
|
if feature.available(feature.Feature.ATIME, local_borg_version):
|
||||||
if atime_feature_available:
|
|
||||||
atime_flags = ('--atime',) if location_config.get('atime') is True else ()
|
atime_flags = ('--atime',) if location_config.get('atime') is True else ()
|
||||||
else:
|
else:
|
||||||
atime_flags = ('--noatime',) if location_config.get('atime') is False else ()
|
atime_flags = ('--noatime',) if location_config.get('atime') is False else ()
|
||||||
|
|
||||||
|
if feature.available(feature.Feature.NOFLAGS, local_borg_version):
|
||||||
|
noflags_flags = ('--noflags',) if location_config.get('bsd_flags') is False else ()
|
||||||
|
else:
|
||||||
|
noflags_flags = ('--nobsdflags',) if location_config.get('bsd_flags') is False else ()
|
||||||
|
|
||||||
full_command = (
|
full_command = (
|
||||||
tuple(local_path.split(' '))
|
tuple(local_path.split(' '))
|
||||||
+ ('create',)
|
+ ('create',)
|
||||||
|
@ -252,7 +256,7 @@ def create_archive(
|
||||||
+ (('--noctime',) if location_config.get('ctime') is False else ())
|
+ (('--noctime',) if location_config.get('ctime') is False else ())
|
||||||
+ (('--nobirthtime',) if location_config.get('birthtime') is False else ())
|
+ (('--nobirthtime',) if location_config.get('birthtime') is False else ())
|
||||||
+ (('--read-special',) if (location_config.get('read_special') or stream_processes) else ())
|
+ (('--read-special',) if (location_config.get('read_special') or stream_processes) else ())
|
||||||
+ (('--nobsdflags',) if location_config.get('bsd_flags') is False else ())
|
+ noflags_flags
|
||||||
+ (('--files-cache', files_cache) if files_cache else ())
|
+ (('--files-cache', files_cache) if files_cache else ())
|
||||||
+ (('--remote-path', remote_path) if remote_path else ())
|
+ (('--remote-path', remote_path) if remote_path else ())
|
||||||
+ (('--umask', str(umask)) if umask else ())
|
+ (('--umask', str(umask)) if umask else ())
|
||||||
|
|
|
@ -6,11 +6,13 @@ from pkg_resources import parse_version
|
||||||
class Feature(Enum):
|
class Feature(Enum):
|
||||||
COMPACT = 1
|
COMPACT = 1
|
||||||
ATIME = 2
|
ATIME = 2
|
||||||
|
NOFLAGS = 3
|
||||||
|
|
||||||
|
|
||||||
FEATURE_TO_MINIMUM_BORG_VERSION = {
|
FEATURE_TO_MINIMUM_BORG_VERSION = {
|
||||||
Feature.COMPACT: parse_version('1.2.0a2'),
|
Feature.COMPACT: parse_version('1.2.0a2'), # borg compact
|
||||||
Feature.ATIME: parse_version('1.2.0a7'),
|
Feature.ATIME: parse_version('1.2.0a7'), # borg create --atime
|
||||||
|
Feature.NOFLAGS: parse_version('1.2.0a8'), # borg create --noflags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -111,10 +111,10 @@ properties:
|
||||||
type: string
|
type: string
|
||||||
description: |
|
description: |
|
||||||
Any paths matching these patterns are included/excluded from
|
Any paths matching these patterns are included/excluded from
|
||||||
backups. Globs are expanded. (Tildes are not.) Note that
|
backups. Globs are expanded. (Tildes are not.) See the
|
||||||
Borg considers this option experimental. See the output of
|
output of "borg help patterns" for more details. Quote any
|
||||||
"borg help patterns" for more details. Quote any value if it
|
value if it contains leading punctuation, so it parses
|
||||||
contains leading punctuation, so it parses correctly.
|
correctly.
|
||||||
example:
|
example:
|
||||||
- 'R /'
|
- 'R /'
|
||||||
- '- /home/*/.cache'
|
- '- /home/*/.cache'
|
||||||
|
|
|
@ -38,7 +38,7 @@ for sub_command in prune create check list info; do
|
||||||
| grep -v '^--json$' \
|
| grep -v '^--json$' \
|
||||||
| grep -v '^--keep-last$' \
|
| grep -v '^--keep-last$' \
|
||||||
| grep -v '^--list$' \
|
| grep -v '^--list$' \
|
||||||
| grep -v '^--nobsdflags$' \
|
| grep -v '^--bsdflags$' \
|
||||||
| grep -v '^--pattern$' \
|
| grep -v '^--pattern$' \
|
||||||
| grep -v '^--progress$' \
|
| grep -v '^--progress$' \
|
||||||
| grep -v '^--stats$' \
|
| grep -v '^--stats$' \
|
||||||
|
|
|
@ -768,11 +768,9 @@ def test_create_archive_with_read_special_calls_borg_with_read_special_parameter
|
||||||
('ctime', False),
|
('ctime', False),
|
||||||
('birthtime', True),
|
('birthtime', True),
|
||||||
('birthtime', False),
|
('birthtime', False),
|
||||||
('bsd_flags', True),
|
|
||||||
('bsd_flags', False),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
def test_create_archive_with_option_calls_borg_without_corresponding_parameter(
|
def test_create_archive_with_basic_option_calls_borg_with_corresponding_parameter(
|
||||||
option_name, option_value
|
option_name, option_value
|
||||||
):
|
):
|
||||||
option_flag = '--no' + option_name.replace('_', '') if option_value is False else None
|
option_flag = '--no' + option_name.replace('_', '') if option_value is False else None
|
||||||
|
@ -815,7 +813,7 @@ def test_create_archive_with_option_calls_borg_without_corresponding_parameter(
|
||||||
(False, False, '--noatime'),
|
(False, False, '--noatime'),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
def test_create_archive_with_atime_option_calls_borg_without_corresponding_parameter(
|
def test_create_archive_with_atime_option_calls_borg_with_corresponding_parameter(
|
||||||
option_value, feature_available, option_flag
|
option_value, feature_available, option_flag
|
||||||
):
|
):
|
||||||
flexmock(module).should_receive('borgmatic_source_directories').and_return([])
|
flexmock(module).should_receive('borgmatic_source_directories').and_return([])
|
||||||
|
@ -824,7 +822,8 @@ def test_create_archive_with_atime_option_calls_borg_without_corresponding_param
|
||||||
flexmock(module).should_receive('_expand_directories').and_return(())
|
flexmock(module).should_receive('_expand_directories').and_return(())
|
||||||
flexmock(module).should_receive('_expand_home_directories').and_return(())
|
flexmock(module).should_receive('_expand_home_directories').and_return(())
|
||||||
flexmock(module).should_receive('_write_pattern_file').and_return(None)
|
flexmock(module).should_receive('_write_pattern_file').and_return(None)
|
||||||
flexmock(module.feature).should_receive('available').and_return(feature_available)
|
flexmock(module.feature).should_receive('available').with_args(module.feature.Feature.ATIME, '1.2.3').and_return(feature_available)
|
||||||
|
flexmock(module.feature).should_receive('available').with_args(module.feature.Feature.NOFLAGS, '1.2.3').and_return(True)
|
||||||
flexmock(module).should_receive('_make_pattern_flags').and_return(())
|
flexmock(module).should_receive('_make_pattern_flags').and_return(())
|
||||||
flexmock(module).should_receive('_make_exclude_flags').and_return(())
|
flexmock(module).should_receive('_make_exclude_flags').and_return(())
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
@ -848,6 +847,49 @@ def test_create_archive_with_atime_option_calls_borg_without_corresponding_param
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'option_value,feature_available,option_flag',
|
||||||
|
(
|
||||||
|
(True, True, None),
|
||||||
|
(True, False, None),
|
||||||
|
(False, True, '--noflags'),
|
||||||
|
(False, False, '--nobsdflags'),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_create_archive_with_bsd_flags_option_calls_borg_with_corresponding_parameter(
|
||||||
|
option_value, feature_available, option_flag
|
||||||
|
):
|
||||||
|
flexmock(module).should_receive('borgmatic_source_directories').and_return([])
|
||||||
|
flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar'))
|
||||||
|
flexmock(module).should_receive('map_directories_to_devices').and_return({})
|
||||||
|
flexmock(module).should_receive('_expand_directories').and_return(())
|
||||||
|
flexmock(module).should_receive('_expand_home_directories').and_return(())
|
||||||
|
flexmock(module).should_receive('_write_pattern_file').and_return(None)
|
||||||
|
flexmock(module.feature).should_receive('available').with_args(module.feature.Feature.ATIME, '1.2.3').and_return(True)
|
||||||
|
flexmock(module.feature).should_receive('available').with_args(module.feature.Feature.NOFLAGS, '1.2.3').and_return(feature_available)
|
||||||
|
flexmock(module).should_receive('_make_pattern_flags').and_return(())
|
||||||
|
flexmock(module).should_receive('_make_exclude_flags').and_return(())
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'create') + ((option_flag,) if option_flag else ()) + ARCHIVE_WITH_PATHS,
|
||||||
|
output_log_level=logging.INFO,
|
||||||
|
output_file=None,
|
||||||
|
borg_local_path='borg',
|
||||||
|
)
|
||||||
|
|
||||||
|
module.create_archive(
|
||||||
|
dry_run=False,
|
||||||
|
repository='repo',
|
||||||
|
location_config={
|
||||||
|
'source_directories': ['foo', 'bar'],
|
||||||
|
'repositories': ['repo'],
|
||||||
|
'bsd_flags': option_value,
|
||||||
|
'exclude_patterns': None,
|
||||||
|
},
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_create_archive_with_files_cache_calls_borg_with_files_cache_parameters():
|
def test_create_archive_with_files_cache_calls_borg_with_files_cache_parameters():
|
||||||
flexmock(module).should_receive('borgmatic_source_directories').and_return([])
|
flexmock(module).should_receive('borgmatic_source_directories').and_return([])
|
||||||
flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar'))
|
flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar'))
|
||||||
|
|
Loading…
Reference in a new issue