Ignore archive filter parameters passed to list action when --archive is given (#557).
This commit is contained in:
parent
89d201c8ff
commit
b40e9b7da2
4 changed files with 177 additions and 47 deletions
7
NEWS
7
NEWS
|
@ -3,10 +3,9 @@
|
||||||
like "rcreate" (replaces "init"), "rlist" (list archives in repository), and "rinfo" (show
|
like "rcreate" (replaces "init"), "rlist" (list archives in repository), and "rinfo" (show
|
||||||
repository info). For the most part, borgmatic tries to smooth over differences between Borg 1
|
repository info). For the most part, borgmatic tries to smooth over differences between Borg 1
|
||||||
and 2 to make your upgrade process easier. However, there are still a few cases where Borg made
|
and 2 to make your upgrade process easier. However, there are still a few cases where Borg made
|
||||||
breaking changes, such as moving flags from "borg list" to "borg rlist". See the Borg 2.0
|
breaking changes. See the Borg 2.0 changelog for more information
|
||||||
changelog for more information (https://www.borgbackup.org/releases/borg-2.0.html). If you
|
(https://www.borgbackup.org/releases/borg-2.0.html). If you install Borg 2, you'll need to
|
||||||
install Borg 2, you'll need to manually "borg transfer" or "borgmatic transfer" your existing
|
manually "borg transfer" or "borgmatic transfer" your existing Borg 1 repositories before use.
|
||||||
Borg 1 repositories before use.
|
|
||||||
* #557: Rename several configuration options to match Borg 2: "remote_rate_limit" is now
|
* #557: Rename several configuration options to match Borg 2: "remote_rate_limit" is now
|
||||||
"upload_rate_limit", "numeric_owner" is "numeric_ids", and "bsd_flags" is "flags". borgmatic
|
"upload_rate_limit", "numeric_owner" is "numeric_ids", and "bsd_flags" is "flags". borgmatic
|
||||||
still works with the old options.
|
still works with the old options.
|
||||||
|
|
|
@ -9,7 +9,14 @@ from borgmatic.execute import execute_command
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
MAKE_FLAGS_EXCLUDES = ('repository', 'archive', 'successful', 'paths', 'find_paths')
|
ARCHIVE_FILTER_FLAGS_MOVED_TO_RLIST = ('prefix', 'glob_archives', 'sort_by', 'first', 'last')
|
||||||
|
MAKE_FLAGS_EXCLUDES = (
|
||||||
|
'repository',
|
||||||
|
'archive',
|
||||||
|
'successful',
|
||||||
|
'paths',
|
||||||
|
'find_paths',
|
||||||
|
) + ARCHIVE_FILTER_FLAGS_MOVED_TO_RLIST
|
||||||
|
|
||||||
|
|
||||||
def make_list_command(
|
def make_list_command(
|
||||||
|
@ -113,11 +120,11 @@ def list_archive(
|
||||||
repository, storage_config, local_borg_version, rlist_arguments, local_path, remote_path
|
repository, storage_config, local_borg_version, rlist_arguments, local_path, remote_path
|
||||||
)
|
)
|
||||||
|
|
||||||
if feature.available(feature.Feature.RLIST, local_borg_version):
|
if list_arguments.archive:
|
||||||
for flag_name in ('prefix', 'glob-archives', 'sort-by', 'first', 'last'):
|
for name in ARCHIVE_FILTER_FLAGS_MOVED_TO_RLIST:
|
||||||
if getattr(list_arguments, flag_name.replace('-', '_'), None):
|
if getattr(list_arguments, name, None):
|
||||||
raise ValueError(
|
logger.warning(
|
||||||
f'The --{flag_name} flag on the list action is not supported when using the --archive/--find flags and Borg 2.x+.'
|
f"The --{name.replace('_', '-')} flag on the list action is ignored when using the --archive flag."
|
||||||
)
|
)
|
||||||
|
|
||||||
if list_arguments.json:
|
if list_arguments.json:
|
||||||
|
@ -169,6 +176,12 @@ def list_archive(
|
||||||
|
|
||||||
archive_arguments = copy.copy(list_arguments)
|
archive_arguments = copy.copy(list_arguments)
|
||||||
archive_arguments.archive = archive
|
archive_arguments.archive = archive
|
||||||
|
|
||||||
|
# This list call is to show the files in a single archive, not list multiple archives. So
|
||||||
|
# blank out any archive filtering flags. They'll break anyway in Borg 2.
|
||||||
|
for name in ARCHIVE_FILTER_FLAGS_MOVED_TO_RLIST:
|
||||||
|
setattr(archive_arguments, name, None)
|
||||||
|
|
||||||
main_command = make_list_command(
|
main_command = make_list_command(
|
||||||
repository,
|
repository,
|
||||||
storage_config,
|
storage_config,
|
||||||
|
|
|
@ -204,6 +204,9 @@ Or, with Borg 2.x:
|
||||||
sudo borgmatic rcreate --encryption repokey-aes-ocb
|
sudo borgmatic rcreate --encryption repokey-aes-ocb
|
||||||
```
|
```
|
||||||
|
|
||||||
|
(Note that `repokey-chacha20-poly1305` may be faster than `repokey-aes-ocb` on
|
||||||
|
certain platforms like ARM64.)
|
||||||
|
|
||||||
This uses the borgmatic configuration file you created above to determine
|
This uses the borgmatic configuration file you created above to determine
|
||||||
which local or remote repository to create, and encrypts it with the
|
which local or remote repository to create, and encrypts it with the
|
||||||
encryption passphrase specified there if one is provided. Read about [Borg
|
encryption passphrase specified there if one is provided. Read about [Borg
|
||||||
|
|
|
@ -254,7 +254,17 @@ def test_make_find_paths_adds_globs_to_path_fragments():
|
||||||
|
|
||||||
|
|
||||||
def test_list_archive_calls_borg_with_parameters():
|
def test_list_archive_calls_borg_with_parameters():
|
||||||
list_arguments = argparse.Namespace(archive='archive', paths=None, json=False, find_paths=None)
|
list_arguments = argparse.Namespace(
|
||||||
|
archive='archive',
|
||||||
|
paths=None,
|
||||||
|
json=False,
|
||||||
|
find_paths=None,
|
||||||
|
prefix=None,
|
||||||
|
glob_archives=None,
|
||||||
|
sort_by=None,
|
||||||
|
first=None,
|
||||||
|
last=None,
|
||||||
|
)
|
||||||
|
|
||||||
flexmock(module.feature).should_receive('available').and_return(False)
|
flexmock(module.feature).should_receive('available').and_return(False)
|
||||||
flexmock(module).should_receive('make_list_command').with_args(
|
flexmock(module).should_receive('make_list_command').with_args(
|
||||||
|
@ -297,7 +307,17 @@ def test_list_archive_with_archive_and_json_errors():
|
||||||
|
|
||||||
|
|
||||||
def test_list_archive_calls_borg_with_local_path():
|
def test_list_archive_calls_borg_with_local_path():
|
||||||
list_arguments = argparse.Namespace(archive='archive', paths=None, json=False, find_paths=None)
|
list_arguments = argparse.Namespace(
|
||||||
|
archive='archive',
|
||||||
|
paths=None,
|
||||||
|
json=False,
|
||||||
|
find_paths=None,
|
||||||
|
prefix=None,
|
||||||
|
glob_archives=None,
|
||||||
|
sort_by=None,
|
||||||
|
first=None,
|
||||||
|
last=None,
|
||||||
|
)
|
||||||
|
|
||||||
flexmock(module.feature).should_receive('available').and_return(False)
|
flexmock(module.feature).should_receive('available').and_return(False)
|
||||||
flexmock(module).should_receive('make_list_command').with_args(
|
flexmock(module).should_receive('make_list_command').with_args(
|
||||||
|
@ -346,9 +366,7 @@ def test_list_archive_calls_borg_multiple_times_with_find_paths():
|
||||||
output_log_level=None,
|
output_log_level=None,
|
||||||
borg_local_path='borg',
|
borg_local_path='borg',
|
||||||
extra_environment=None,
|
extra_environment=None,
|
||||||
).and_return(
|
).and_return('archive1\narchive2').once()
|
||||||
'archive1 Sun, 2022-05-29 15:27:04 [abc]\narchive2 Mon, 2022-05-30 19:47:15 [xyz]'
|
|
||||||
).once()
|
|
||||||
flexmock(module).should_receive('make_list_command').and_return(
|
flexmock(module).should_receive('make_list_command').and_return(
|
||||||
('borg', 'list', 'repo::archive1')
|
('borg', 'list', 'repo::archive1')
|
||||||
).and_return(('borg', 'list', 'repo::archive2'))
|
).and_return(('borg', 'list', 'repo::archive2'))
|
||||||
|
@ -376,7 +394,17 @@ def test_list_archive_calls_borg_multiple_times_with_find_paths():
|
||||||
|
|
||||||
|
|
||||||
def test_list_archive_calls_borg_with_archive():
|
def test_list_archive_calls_borg_with_archive():
|
||||||
list_arguments = argparse.Namespace(archive='archive', paths=None, json=False, find_paths=None)
|
list_arguments = argparse.Namespace(
|
||||||
|
archive='archive',
|
||||||
|
paths=None,
|
||||||
|
json=False,
|
||||||
|
find_paths=None,
|
||||||
|
prefix=None,
|
||||||
|
glob_archives=None,
|
||||||
|
sort_by=None,
|
||||||
|
first=None,
|
||||||
|
last=None,
|
||||||
|
)
|
||||||
|
|
||||||
flexmock(module.feature).should_receive('available').and_return(False)
|
flexmock(module.feature).should_receive('available').and_return(False)
|
||||||
flexmock(module).should_receive('make_list_command').with_args(
|
flexmock(module).should_receive('make_list_command').with_args(
|
||||||
|
@ -461,35 +489,15 @@ def test_list_archive_with_borg_features_without_archive_delegates_to_list_repos
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'archive_filter_flag', ('prefix', 'glob_archives', 'sort_by', 'first', 'last',),
|
'archive_filter_flag', ('prefix', 'glob_archives', 'sort_by', 'first', 'last',),
|
||||||
)
|
)
|
||||||
def test_list_archive_with_archive_disallows_archive_filter_flag_if_rlist_feature_available(
|
def test_list_archive_with_archive_ignores_archive_filter_flag(archive_filter_flag,):
|
||||||
archive_filter_flag,
|
default_filter_flags = {
|
||||||
):
|
'prefix': None,
|
||||||
list_arguments = argparse.Namespace(
|
'glob_archives': None,
|
||||||
archive='archive', paths=None, json=False, find_paths=None, **{archive_filter_flag: 'foo'}
|
'sort_by': None,
|
||||||
)
|
'first': None,
|
||||||
|
'last': None,
|
||||||
flexmock(module.feature).should_receive('available').with_args(
|
}
|
||||||
module.feature.Feature.RLIST, '1.2.3'
|
altered_filter_flags = {**default_filter_flags, **{archive_filter_flag: 'foo'}}
|
||||||
).and_return(True)
|
|
||||||
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
module.list_archive(
|
|
||||||
repository='repo',
|
|
||||||
storage_config={},
|
|
||||||
local_borg_version='1.2.3',
|
|
||||||
list_arguments=list_arguments,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
'archive_filter_flag', ('prefix', 'glob_archives', 'sort_by', 'first', 'last',),
|
|
||||||
)
|
|
||||||
def test_list_archive_with_archive_allows_archive_filter_flag_if_rlist_feature_unavailable(
|
|
||||||
archive_filter_flag,
|
|
||||||
):
|
|
||||||
list_arguments = argparse.Namespace(
|
|
||||||
archive='archive', paths=None, json=False, find_paths=None, **{archive_filter_flag: 'foo'}
|
|
||||||
)
|
|
||||||
|
|
||||||
flexmock(module.feature).should_receive('available').with_args(
|
flexmock(module.feature).should_receive('available').with_args(
|
||||||
module.feature.Feature.RLIST, '1.2.3'
|
module.feature.Feature.RLIST, '1.2.3'
|
||||||
|
@ -498,7 +506,9 @@ def test_list_archive_with_archive_allows_archive_filter_flag_if_rlist_feature_u
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
local_borg_version='1.2.3',
|
local_borg_version='1.2.3',
|
||||||
list_arguments=list_arguments,
|
list_arguments=argparse.Namespace(
|
||||||
|
archive='archive', paths=None, json=False, find_paths=None, **default_filter_flags
|
||||||
|
),
|
||||||
local_path='borg',
|
local_path='borg',
|
||||||
remote_path=None,
|
remote_path=None,
|
||||||
).and_return(('borg', 'list', 'repo::archive'))
|
).and_return(('borg', 'list', 'repo::archive'))
|
||||||
|
@ -515,5 +525,110 @@ def test_list_archive_with_archive_allows_archive_filter_flag_if_rlist_feature_u
|
||||||
repository='repo',
|
repository='repo',
|
||||||
storage_config={},
|
storage_config={},
|
||||||
local_borg_version='1.2.3',
|
local_borg_version='1.2.3',
|
||||||
list_arguments=list_arguments,
|
list_arguments=argparse.Namespace(
|
||||||
|
archive='archive', paths=None, json=False, find_paths=None, **altered_filter_flags
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'archive_filter_flag', ('prefix', 'glob_archives', 'sort_by', 'first', 'last',),
|
||||||
|
)
|
||||||
|
def test_list_archive_with_find_paths_allows_archive_filter_flag_but_only_passes_it_to_rlist(
|
||||||
|
archive_filter_flag,
|
||||||
|
):
|
||||||
|
default_filter_flags = {
|
||||||
|
'prefix': None,
|
||||||
|
'glob_archives': None,
|
||||||
|
'sort_by': None,
|
||||||
|
'first': None,
|
||||||
|
'last': None,
|
||||||
|
}
|
||||||
|
altered_filter_flags = {**default_filter_flags, **{archive_filter_flag: 'foo'}}
|
||||||
|
glob_paths = ('**/*foo.txt*/**',)
|
||||||
|
flexmock(module.feature).should_receive('available').and_return(True)
|
||||||
|
|
||||||
|
flexmock(module.rlist).should_receive('make_rlist_command').with_args(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
rlist_arguments=argparse.Namespace(
|
||||||
|
repository='repo', short=True, format=None, json=None, **altered_filter_flags
|
||||||
|
),
|
||||||
|
local_path='borg',
|
||||||
|
remote_path=None,
|
||||||
|
).and_return(('borg', 'rlist', '--repo', 'repo'))
|
||||||
|
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'rlist', '--repo', 'repo'),
|
||||||
|
output_log_level=None,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
).and_return('archive1\narchive2').once()
|
||||||
|
|
||||||
|
flexmock(module).should_receive('make_list_command').with_args(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
list_arguments=argparse.Namespace(
|
||||||
|
repository='repo',
|
||||||
|
archive='archive1',
|
||||||
|
paths=None,
|
||||||
|
short=True,
|
||||||
|
format=None,
|
||||||
|
json=None,
|
||||||
|
find_paths=['foo.txt'],
|
||||||
|
**default_filter_flags,
|
||||||
|
),
|
||||||
|
local_path='borg',
|
||||||
|
remote_path=None,
|
||||||
|
).and_return(('borg', 'list', '--repo', 'repo', 'archive1'))
|
||||||
|
|
||||||
|
flexmock(module).should_receive('make_list_command').with_args(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
list_arguments=argparse.Namespace(
|
||||||
|
repository='repo',
|
||||||
|
archive='archive2',
|
||||||
|
paths=None,
|
||||||
|
short=True,
|
||||||
|
format=None,
|
||||||
|
json=None,
|
||||||
|
find_paths=['foo.txt'],
|
||||||
|
**default_filter_flags,
|
||||||
|
),
|
||||||
|
local_path='borg',
|
||||||
|
remote_path=None,
|
||||||
|
).and_return(('borg', 'list', '--repo', 'repo', 'archive2'))
|
||||||
|
|
||||||
|
flexmock(module).should_receive('make_find_paths').and_return(glob_paths)
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'list', '--repo', 'repo', 'archive1') + glob_paths,
|
||||||
|
output_log_level=logging.WARNING,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
).once()
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
('borg', 'list', '--repo', 'repo', 'archive2') + glob_paths,
|
||||||
|
output_log_level=logging.WARNING,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
).once()
|
||||||
|
|
||||||
|
module.list_archive(
|
||||||
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
list_arguments=argparse.Namespace(
|
||||||
|
repository='repo',
|
||||||
|
archive=None,
|
||||||
|
paths=None,
|
||||||
|
short=True,
|
||||||
|
format=None,
|
||||||
|
json=None,
|
||||||
|
find_paths=['foo.txt'],
|
||||||
|
**altered_filter_flags,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue