Fix an error in the Btrfs hook when a "/" subvolume is configured in borgmatic's source directories (#959).

This commit is contained in:
Dan Helfman
2024-12-28 09:57:33 -08:00
parent 87e77ff2b7
commit d3409df84c
4 changed files with 45 additions and 8 deletions
+4
View File
@@ -1,3 +1,7 @@
1.9.6.dev0
* #959: Fix an error in the Btrfs hook when a "/" subvolume is configured in borgmatic's source
directories.
1.9.5
* #418: Backup and restore databases that have the same name but with different ports, hostnames,
or hooks.
+5 -7
View File
@@ -115,17 +115,15 @@ def get_subvolumes(btrfs_command, findmnt_command, source_directories=None):
BORGMATIC_SNAPSHOT_PREFIX = '.borgmatic-snapshot-'
def make_snapshot_path(subvolume_path): # pragma: no cover
def make_snapshot_path(subvolume_path):
'''
Given the path to a subvolume, make a corresponding snapshot path for it.
'''
return os.path.join(
subvolume_path,
f'{BORGMATIC_SNAPSHOT_PREFIX}{os.getpid()}',
# Included so that the snapshot ends up in the Borg archive at the "original" subvolume
# path.
subvolume_path.lstrip(os.path.sep),
)
# Included so that the snapshot ends up in the Borg archive at the "original" subvolume path.
) + subvolume_path.rstrip(os.path.sep)
def make_snapshot_exclude_path(subvolume_path): # pragma: no cover
@@ -155,7 +153,7 @@ def make_snapshot_exclude_path(subvolume_path): # pragma: no cover
)
def make_borg_source_directory_path(subvolume_path, source_directory): # pragma: no cover
def make_borg_source_directory_path(subvolume_path, source_directory):
'''
Given the path to a subvolume and a source directory inside it, make a corresponding path for
the source directory within a snapshot path intended for giving to Borg.
@@ -181,7 +179,7 @@ def snapshot_subvolume(btrfs_command, subvolume_path, snapshot_path): # pragma:
+ (
'subvolume',
'snapshot',
'-r', # Read-only,
'-r', # Read-only.
subvolume_path,
snapshot_path,
),
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "borgmatic"
version = "1.9.5"
version = "1.9.6.dev0"
authors = [
{ name="Dan Helfman", email="witten@torsion.org" },
]
@@ -128,6 +128,41 @@ def test_get_subvolumes_without_source_directories_collects_all_subvolumes_from_
)
@pytest.mark.parametrize(
'subvolume_path,expected_snapshot_path',
(
('/foo/bar', '/foo/bar/.borgmatic-snapshot-1234/foo/bar'),
('/', '/.borgmatic-snapshot-1234'),
),
)
def test_make_snapshot_path_includes_stripped_subvolume_path(
subvolume_path, expected_snapshot_path
):
flexmock(module.os).should_receive('getpid').and_return(1234)
assert module.make_snapshot_path(subvolume_path) == expected_snapshot_path
@pytest.mark.parametrize(
'subvolume_path,source_directory_path,expected_path',
(
('/foo/bar', '/foo/bar/baz', '/foo/bar/.borgmatic-snapshot-1234/./foo/bar/baz'),
('/foo/bar', '/foo/bar', '/foo/bar/.borgmatic-snapshot-1234/./foo/bar'),
('/', '/foo', '/.borgmatic-snapshot-1234/./foo'),
('/', '/', '/.borgmatic-snapshot-1234/./'),
),
)
def test_make_borg_source_directory_path_includes_slashdot_hack_and_stripped_source_directory_path(
subvolume_path, source_directory_path, expected_path
):
flexmock(module.os).should_receive('getpid').and_return(1234)
assert (
module.make_borg_source_directory_path(subvolume_path, source_directory_path)
== expected_path
)
def test_dump_data_sources_snapshots_each_subvolume_and_updates_source_directories():
source_directories = ['/foo', '/mnt/subvol1']
config = {'btrfs': {}}