mirror of
https://github.com/borgmatic-collective/borgmatic.git
synced 2026-08-06 16:23:00 +02:00
Add Borg 1.4.1 features (#1078).
Reviewed-on: https://projects.torsion.org/borgmatic-collective/borgmatic/pulls/1081
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import logging
|
||||
|
||||
import borgmatic.config.paths
|
||||
from borgmatic.borg import environment, flags
|
||||
from borgmatic.borg import environment, feature, flags
|
||||
from borgmatic.execute import execute_command
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -37,11 +37,16 @@ def compact_segments(
|
||||
+ (('--threshold', str(threshold)) if threshold else ())
|
||||
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
|
||||
+ (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())
|
||||
+ (
|
||||
('--dry-run',)
|
||||
if dry_run and feature.available(feature.Feature.DRY_RUN_COMPACT, local_borg_version)
|
||||
else ()
|
||||
)
|
||||
+ (tuple(extra_borg_options.split(' ')) if extra_borg_options else ())
|
||||
+ flags.make_repository_flags(repository_path, local_borg_version)
|
||||
)
|
||||
|
||||
if dry_run:
|
||||
if dry_run and not feature.available(feature.Feature.DRY_RUN_COMPACT, local_borg_version):
|
||||
logging.info('Skipping compact (dry run)')
|
||||
return
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ OPTION_TO_ENVIRONMENT_VARIABLE = {
|
||||
DEFAULT_BOOL_OPTION_TO_DOWNCASE_ENVIRONMENT_VARIABLE = {
|
||||
'relocated_repo_access_is_ok': 'BORG_RELOCATED_REPO_ACCESS_IS_OK',
|
||||
'unknown_unencrypted_repo_access_is_ok': 'BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK',
|
||||
'use_chunks_archive': 'BORG_USE_CHUNKS_ARCHIVE',
|
||||
}
|
||||
|
||||
DEFAULT_BOOL_OPTION_TO_UPPERCASE_ENVIRONMENT_VARIABLE = {
|
||||
|
||||
@@ -18,6 +18,7 @@ class Feature(Enum):
|
||||
EXCLUDED_FILES_MINUS = 12
|
||||
ARCHIVE_SERIES = 13
|
||||
NO_PRUNE_STATS = 14
|
||||
DRY_RUN_COMPACT = 15
|
||||
|
||||
|
||||
FEATURE_TO_MINIMUM_BORG_VERSION = {
|
||||
@@ -35,6 +36,7 @@ FEATURE_TO_MINIMUM_BORG_VERSION = {
|
||||
Feature.EXCLUDED_FILES_MINUS: parse('2.0.0b5'), # --list --filter uses "-" for excludes
|
||||
Feature.ARCHIVE_SERIES: parse('2.0.0b11'), # identically named archives form a series
|
||||
Feature.NO_PRUNE_STATS: parse('2.0.0b10'), # prune --stats is not available
|
||||
Feature.DRY_RUN_COMPACT: parse('1.4.1'), # borg compact --dry-run support
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -389,6 +389,13 @@ properties:
|
||||
Path for Borg cache files. Defaults to
|
||||
$borg_base_directory/.cache/borg
|
||||
example: /path/to/base/cache
|
||||
use_chunks_archive:
|
||||
type: boolean
|
||||
description: |
|
||||
Enables or disables the use of chunks.archive.d for faster cache
|
||||
resyncs in Borg. If true, value is set to "yes" (default) else
|
||||
it's set to "no", reducing disk usage but slowing resyncs.
|
||||
example: true
|
||||
borg_files_cache_ttl:
|
||||
type: integer
|
||||
description: |
|
||||
@@ -558,6 +565,14 @@ properties:
|
||||
type: integer
|
||||
description: Number of yearly archives to keep.
|
||||
example: 1
|
||||
keep_13weekly:
|
||||
type: integer
|
||||
description: Number of quarterly archives to keep (13 week strategy).
|
||||
example: 13
|
||||
keep_3monthly:
|
||||
type: integer
|
||||
description: Number of quarterly archives to keep (3 month strategy).
|
||||
example: 3
|
||||
prefix:
|
||||
type: string
|
||||
description: |
|
||||
|
||||
@@ -68,8 +68,15 @@ def test_compact_segments_with_log_debug_calls_borg_with_debug_flag():
|
||||
)
|
||||
|
||||
|
||||
def test_compact_segments_with_dry_run_skips_borg_call():
|
||||
def test_compact_segments_with_dry_run_skips_borg_call_when_feature_unavailable():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.feature).should_receive('available').with_args(
|
||||
module.feature.Feature.DRY_RUN_COMPACT, '1.2.3'
|
||||
).and_return(False)
|
||||
flexmock(module.environment).should_receive('make_environment').never()
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').never()
|
||||
flexmock(module).should_receive('execute_command').never()
|
||||
flexmock(logging).should_receive('info').with_args('Skipping compact (dry run)').once()
|
||||
|
||||
module.compact_segments(
|
||||
repository_path='repo',
|
||||
@@ -80,6 +87,24 @@ def test_compact_segments_with_dry_run_skips_borg_call():
|
||||
)
|
||||
|
||||
|
||||
def test_compact_segments_with_dry_run_executes_borg_call_when_feature_available():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.feature).should_receive('available').with_args(
|
||||
module.feature.Feature.DRY_RUN_COMPACT, '1.4.1'
|
||||
).and_return(True)
|
||||
flexmock(module.environment).should_receive('make_environment').once()
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').once()
|
||||
flexmock(module).should_receive('execute_command').once()
|
||||
|
||||
module.compact_segments(
|
||||
repository_path='repo',
|
||||
config={},
|
||||
local_borg_version='1.4.1',
|
||||
global_arguments=flexmock(),
|
||||
dry_run=True,
|
||||
)
|
||||
|
||||
|
||||
def test_compact_segments_with_local_path_calls_borg_via_local_path():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg1',) + COMPACT_COMMAND[1:] + ('repo',), logging.INFO)
|
||||
|
||||
@@ -92,6 +92,7 @@ def test_make_environment_without_configuration_sets_certain_environment_variabl
|
||||
'BORG_EXIT_CODES': 'modern',
|
||||
'BORG_RELOCATED_REPO_ACCESS_IS_OK': 'no',
|
||||
'BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK': 'no',
|
||||
'BORG_USE_CHUNKS_ARCHIVE': 'no',
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +102,7 @@ def test_make_environment_without_configuration_passes_through_default_environme
|
||||
'USER': 'root',
|
||||
'BORG_RELOCATED_REPO_ACCESS_IS_OK': 'yup',
|
||||
'BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK': 'nah',
|
||||
'BORG_USE_CHUNKS_ARCHIVE': 'yup',
|
||||
}
|
||||
)
|
||||
flexmock(module.borgmatic.hooks.credential.parse).should_receive(
|
||||
@@ -113,6 +115,7 @@ def test_make_environment_without_configuration_passes_through_default_environme
|
||||
'USER': 'root',
|
||||
'BORG_RELOCATED_REPO_ACCESS_IS_OK': 'yup',
|
||||
'BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK': 'nah',
|
||||
'BORG_USE_CHUNKS_ARCHIVE': 'yup',
|
||||
'BORG_EXIT_CODES': 'modern',
|
||||
}
|
||||
|
||||
@@ -170,3 +173,17 @@ def test_make_environment_with_integer_variable_value():
|
||||
environment = module.make_environment({'borg_files_cache_ttl': 40})
|
||||
|
||||
assert environment.get('BORG_FILES_CACHE_TTL') == '40'
|
||||
|
||||
|
||||
def test_make_environment_with_use_chunks_archive_should_set_correct_environment_value():
|
||||
flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
|
||||
flexmock(module.borgmatic.hooks.credential.parse).should_receive(
|
||||
'resolve_credential'
|
||||
).and_return(None)
|
||||
flexmock(module.os).should_receive('pipe').never()
|
||||
|
||||
environment = module.make_environment({'use_chunks_archive': True})
|
||||
assert environment.get('BORG_USE_CHUNKS_ARCHIVE') == 'yes'
|
||||
|
||||
environment = module.make_environment({'use_chunks_archive': False})
|
||||
assert environment.get('BORG_USE_CHUNKS_ARCHIVE') == 'no'
|
||||
|
||||
@@ -43,6 +43,28 @@ def test_make_prune_flags_returns_flags_from_config():
|
||||
assert result == BASE_PRUNE_FLAGS
|
||||
|
||||
|
||||
def test_make_prune_flags_with_keep_13weekly_and_keep_3monthly():
|
||||
config = {
|
||||
'keep_13weekly': 4,
|
||||
'keep_3monthly': 5,
|
||||
}
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_match_archives_flags').and_return(())
|
||||
|
||||
result = module.make_prune_flags(
|
||||
config, flexmock(match_archives=None), local_borg_version='1.2.3'
|
||||
)
|
||||
|
||||
expected = (
|
||||
'--keep-13weekly',
|
||||
'4',
|
||||
'--keep-3monthly',
|
||||
'5',
|
||||
)
|
||||
|
||||
assert result == expected
|
||||
|
||||
|
||||
def test_make_prune_flags_accepts_prefix_with_placeholders():
|
||||
config = {
|
||||
'keep_daily': 1,
|
||||
|
||||
Reference in New Issue
Block a user