Explorar el Código

Fix snapshotting in the ZFS, Btrfs, and LVM hooks to play nicely with the Borg 1.4+ "slashdot" hack within source directory paths (#1151).

Dan Helfman hace 2 meses
padre
commit
1192451718

+ 2 - 0
NEWS

@@ -3,6 +3,8 @@
    service.
  * #1149: Add support for Python 3.14.
  * #1149: Include automated tests in the source dist tarball uploaded to PyPI.
+ * #1151: Fix snapshotting in the ZFS, Btrfs, and LVM hooks to play nicely with the Borg 1.4+
+   "slashdot" hack within source directory paths.
 
 2.0.8
  * #1114: Document systemd configuration changes for the ZFS filesystem hook.

+ 4 - 1
borgmatic/hooks/data_source/btrfs.py

@@ -265,7 +265,10 @@ def make_borg_snapshot_pattern(subvolume_path, pattern):
     rewritten_path = initial_caret + os.path.join(
         subvolume_path,
         f'{BORGMATIC_SNAPSHOT_PREFIX}{os.getpid()}',
-        '.',  # Borg 1.4+ "slashdot" hack.
+        # Use the Borg 1.4+ "slashdot" hack to prevent the snapshot path prefix from getting
+        # included in the archive—but only if there's not already a slashdot hack present in the
+        # pattern.
+        ('' if f'{os.path.sep}.{os.path.sep}' in pattern.path else '.'),
         # Included so that the source directory ends up in the Borg archive at its "original" path.
         pattern.path.lstrip('^').lstrip(os.path.sep),
     )

+ 4 - 1
borgmatic/hooks/data_source/lvm.py

@@ -166,7 +166,10 @@ def make_borg_snapshot_pattern(pattern, logical_volume, normalized_runtime_direc
         hashlib.shake_256(logical_volume.mount_point.encode('utf-8')).hexdigest(
             MOUNT_POINT_HASH_LENGTH,
         ),
-        '.',  # Borg 1.4+ "slashdot" hack.
+        # Use the Borg 1.4+ "slashdot" hack to prevent the snapshot path prefix from getting
+        # included in the archive—but only if there's not already a slashdot hack present in the
+        # pattern.
+        ('' if f'{os.path.sep}.{os.path.sep}' in pattern.path else '.'),
         # Included so that the source directory ends up in the Borg archive at its "original" path.
         pattern.path.lstrip('^').lstrip(os.path.sep),
     )

+ 4 - 1
borgmatic/hooks/data_source/zfs.py

@@ -214,7 +214,10 @@ def make_borg_snapshot_pattern(pattern, dataset, normalized_runtime_directory):
         # For instance, without this, snapshotting a dataset at /var and another at /var/spool would
         # result in overlapping snapshot patterns and therefore colliding mount attempts.
         hashlib.shake_256(dataset.mount_point.encode('utf-8')).hexdigest(MOUNT_POINT_HASH_LENGTH),
-        '.',  # Borg 1.4+ "slashdot" hack.
+        # Use the Borg 1.4+ "slashdot" hack to prevent the snapshot path prefix from getting
+        # included in the archive—but only if there's not already a slashdot hack present in the
+        # pattern.
+        ('' if f'{os.path.sep}.{os.path.sep}' in pattern.path else '.'),
         # Included so that the source directory ends up in the Borg archive at its "original" path.
         pattern.path.lstrip('^').lstrip(os.path.sep),
     )

+ 5 - 0
tests/unit/hooks/data_source/test_btrfs.py

@@ -326,6 +326,11 @@ def test_make_snapshot_path_includes_stripped_subvolume_path(
         ),
         ('/', Pattern('/foo'), Pattern('/.borgmatic-snapshot-1234/./foo')),
         ('/', Pattern('/'), Pattern('/.borgmatic-snapshot-1234/./')),
+        (
+            '/foo/bar',
+            Pattern('/foo/bar/./baz'),
+            Pattern('/foo/bar/.borgmatic-snapshot-1234/foo/bar/./baz'),
+        ),
     ),
 )
 def test_make_borg_snapshot_pattern_includes_slashdot_hack_and_stripped_pattern_path(

+ 4 - 0
tests/unit/hooks/data_source/test_lvm.py

@@ -270,6 +270,10 @@ def test_snapshot_logical_volume_with_non_percentage_snapshot_name_uses_lvcreate
         ),
         (Pattern('/foo'), Pattern('/run/borgmatic/lvm_snapshots/b33f/./foo')),
         (Pattern('/'), Pattern('/run/borgmatic/lvm_snapshots/b33f/./')),
+        (
+            Pattern('/foo/./bar/baz'),
+            Pattern('/run/borgmatic/lvm_snapshots/b33f/foo/./bar/baz'),
+        ),
     ),
 )
 def test_make_borg_snapshot_pattern_includes_slashdot_hack_and_stripped_pattern_path(

+ 4 - 0
tests/unit/hooks/data_source/test_zfs.py

@@ -278,6 +278,10 @@ def test_get_all_dataset_mount_points_omits_duplicates():
         ),
         (Pattern('/foo'), Pattern('/run/borgmatic/zfs_snapshots/b33f/./foo')),
         (Pattern('/'), Pattern('/run/borgmatic/zfs_snapshots/b33f/./')),
+        (
+            Pattern('/foo/./bar/baz'),
+            Pattern('/run/borgmatic/zfs_snapshots/b33f/foo/./bar/baz'),
+        ),
     ),
 )
 def test_make_borg_snapshot_pattern_includes_slashdot_hack_and_stripped_pattern_path(