Dan Helfman 4 місяців тому
батько
коміт
b72b9aaf13

+ 5 - 5
borgmatic/hooks/data_source/btrfs.py

@@ -252,13 +252,13 @@ def dump_data_sources(
         snapshot_subvolume(btrfs_command, subvolume.path, snapshot_path)
         snapshot_subvolume(btrfs_command, subvolume.path, snapshot_path)
 
 
         for pattern in subvolume.contained_patterns:
         for pattern in subvolume.contained_patterns:
-            # Update the pattern in place, since pattern order matters to Borg.
+            snapshot_pattern = make_borg_snapshot_pattern(subvolume.path, pattern)
+
+            # Attempt to update the pattern in place, since pattern order matters to Borg.
             try:
             try:
-                patterns[patterns.index(pattern)] = make_borg_snapshot_pattern(
-                    subvolume.path, pattern
-                )
+                patterns[patterns.index(pattern)] = snapshot_pattern
             except ValueError:
             except ValueError:
-                pass
+                patterns.append(snapshot_pattern)
 
 
         patterns.append(make_snapshot_exclude_pattern(subvolume.path))
         patterns.append(make_snapshot_exclude_pattern(subvolume.path))
 
 

+ 5 - 6
borgmatic/hooks/data_source/lvm.py

@@ -228,14 +228,13 @@ def dump_data_sources(
         )
         )
 
 
         for pattern in logical_volume.contained_patterns:
         for pattern in logical_volume.contained_patterns:
-            # Update the pattern in place, since pattern order matters to Borg.
+            snapshot_pattern = make_borg_snapshot_pattern(pattern, normalized_runtime_directory)
+
+            # Attempt to update the pattern in place, since pattern order matters to Borg.
             try:
             try:
-                patterns[patterns.index(pattern)] = make_borg_snapshot_pattern(
-                    pattern,
-                    normalized_runtime_directory,
-                )
+                patterns[patterns.index(pattern)] = snapshot_pattern
             except ValueError:
             except ValueError:
-                pass
+                patterns.append(snapshot_pattern)
 
 
     return []
     return []
 
 

+ 5 - 6
borgmatic/hooks/data_source/zfs.py

@@ -250,14 +250,13 @@ def dump_data_sources(
         )
         )
 
 
         for pattern in dataset.contained_patterns:
         for pattern in dataset.contained_patterns:
-            # Update the pattern in place, since pattern order matters to Borg.
+            snapshot_pattern = make_borg_snapshot_pattern(pattern, normalized_runtime_directory)
+
+            # Attempt to update the pattern in place, since pattern order matters to Borg.
             try:
             try:
-                patterns[patterns.index(pattern)] = make_borg_snapshot_pattern(
-                    pattern,
-                    normalized_runtime_directory,
-                )
+                patterns[patterns.index(pattern)] = snapshot_pattern
             except ValueError:
             except ValueError:
-                pass
+                patterns.append(snapshot_pattern)
 
 
     return []
     return []
 
 

+ 133 - 89
tests/unit/hooks/data_source/test_btrfs.py

@@ -1,6 +1,7 @@
 import pytest
 import pytest
 from flexmock import flexmock
 from flexmock import flexmock
 
 
+from borgmatic.borg.pattern import Pattern, Pattern_type, Pattern_style
 from borgmatic.hooks.data_source import btrfs as module
 from borgmatic.hooks.data_source import btrfs as module
 
 
 
 
@@ -80,7 +81,7 @@ def test_get_subvolumes_for_filesystem_skips_empty_filesystem_mount_points():
     assert module.get_subvolumes_for_filesystem('btrfs', ' ') == ()
     assert module.get_subvolumes_for_filesystem('btrfs', ' ') == ()
 
 
 
 
-def test_get_subvolumes_collects_subvolumes_matching_source_directories_from_all_filesystems():
+def test_get_subvolumes_collects_subvolumes_matching_patterns_from_all_filesystems():
     flexmock(module).should_receive('get_filesystem_mount_points').and_return(('/mnt1', '/mnt2'))
     flexmock(module).should_receive('get_filesystem_mount_points').and_return(('/mnt1', '/mnt2'))
     flexmock(module).should_receive('get_subvolumes_for_filesystem').with_args(
     flexmock(module).should_receive('get_subvolumes_for_filesystem').with_args(
         'btrfs', '/mnt1'
         'btrfs', '/mnt1'
@@ -99,14 +100,21 @@ def test_get_subvolumes_collects_subvolumes_matching_source_directories_from_all
         ).with_args(path, object).and_return(())
         ).with_args(path, object).and_return(())
 
 
     assert module.get_subvolumes(
     assert module.get_subvolumes(
-        'btrfs', 'findmnt', source_directories=['/one', '/four', '/five', '/six', '/mnt2', '/mnt3']
+        'btrfs', 'findmnt', patterns=[
+            Pattern('/one'),
+            Pattern('/four'),
+            Pattern('/five'),
+            Pattern('/six'),
+            Pattern('/mnt2'),
+            Pattern('/mnt3'),
+        ]
     ) == (
     ) == (
-        module.Subvolume('/four', contained_source_directories=('/four',)),
-        module.Subvolume('/one', contained_source_directories=('/one',)),
+        module.Subvolume('/four', contained_patterns=(Pattern('/four'),)),
+        module.Subvolume('/one', contained_patterns=(Pattern('/one'),)),
     )
     )
 
 
 
 
-def test_get_subvolumes_without_source_directories_collects_all_subvolumes_from_all_filesystems():
+def test_get_subvolumes_without_patterns_collects_all_subvolumes_from_all_filesystems():
     flexmock(module).should_receive('get_filesystem_mount_points').and_return(('/mnt1', '/mnt2'))
     flexmock(module).should_receive('get_filesystem_mount_points').and_return(('/mnt1', '/mnt2'))
     flexmock(module).should_receive('get_subvolumes_for_filesystem').with_args(
     flexmock(module).should_receive('get_subvolumes_for_filesystem').with_args(
         'btrfs', '/mnt1'
         'btrfs', '/mnt1'
@@ -121,10 +129,10 @@ def test_get_subvolumes_without_source_directories_collects_all_subvolumes_from_
         ).with_args(path, object).and_return((path,))
         ).with_args(path, object).and_return((path,))
 
 
     assert module.get_subvolumes('btrfs', 'findmnt') == (
     assert module.get_subvolumes('btrfs', 'findmnt') == (
-        module.Subvolume('/four', contained_source_directories=('/four',)),
-        module.Subvolume('/one', contained_source_directories=('/one',)),
-        module.Subvolume('/three', contained_source_directories=('/three',)),
-        module.Subvolume('/two', contained_source_directories=('/two',)),
+        module.Subvolume('/four', contained_patterns=(Pattern('/four'),)),
+        module.Subvolume('/one', contained_patterns=(Pattern('/one'),)),
+        module.Subvolume('/three', contained_patterns=(Pattern('/three'),)),
+        module.Subvolume('/two', contained_patterns=(Pattern('/two'),)),
     )
     )
 
 
 
 
@@ -144,7 +152,7 @@ def test_make_snapshot_path_includes_stripped_subvolume_path(
 
 
 
 
 @pytest.mark.parametrize(
 @pytest.mark.parametrize(
-    'subvolume_path,source_directory_path,expected_path',
+    'subvolume_path,pattern_path,expected_path',
     (
     (
         ('/foo/bar', '/foo/bar/baz', '/foo/bar/.borgmatic-snapshot-1234/./foo/bar/baz'),
         ('/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/bar', '/foo/bar', '/foo/bar/.borgmatic-snapshot-1234/./foo/bar'),
@@ -152,24 +160,24 @@ def test_make_snapshot_path_includes_stripped_subvolume_path(
         ('/', '/', '/.borgmatic-snapshot-1234/./'),
         ('/', '/', '/.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
+def test_make_borg_snapshot_pattern_includes_slashdot_hack_and_stripped_pattern_path(
+    subvolume_path, pattern_path, expected_path
 ):
 ):
     flexmock(module.os).should_receive('getpid').and_return(1234)
     flexmock(module.os).should_receive('getpid').and_return(1234)
 
 
     assert (
     assert (
-        module.make_borg_source_directory_path(subvolume_path, source_directory_path)
-        == expected_path
+        module.make_borg_snapshot_pattern(subvolume_path, Pattern(pattern_path))
+        == Pattern(expected_path)
     )
     )
 
 
 
 
-def test_dump_data_sources_snapshots_each_subvolume_and_updates_source_directories():
-    source_directories = ['/foo', '/mnt/subvol1']
+def test_dump_data_sources_snapshots_each_subvolume_and_updates_patterns():
+    patterns = [Pattern('/foo'), Pattern('/mnt/subvol1')]
     config = {'btrfs': {}}
     config = {'btrfs': {}}
     flexmock(module).should_receive('get_subvolumes').and_return(
     flexmock(module).should_receive('get_subvolumes').and_return(
         (
         (
-            module.Subvolume('/mnt/subvol1', contained_source_directories=('/mnt/subvol1',)),
-            module.Subvolume('/mnt/subvol2', contained_source_directories=('/mnt/subvol2',)),
+            module.Subvolume('/mnt/subvol1', contained_patterns=(Pattern('/mnt/subvol1'),)),
+            module.Subvolume('/mnt/subvol2', contained_patterns=(Pattern('/mnt/subvol2'),)),
         )
         )
     )
     )
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
@@ -184,18 +192,30 @@ def test_dump_data_sources_snapshots_each_subvolume_and_updates_source_directori
     flexmock(module).should_receive('snapshot_subvolume').with_args(
     flexmock(module).should_receive('snapshot_subvolume').with_args(
         'btrfs', '/mnt/subvol2', '/mnt/subvol2/.borgmatic-1234/mnt/subvol2'
         'btrfs', '/mnt/subvol2', '/mnt/subvol2/.borgmatic-1234/mnt/subvol2'
     ).once()
     ).once()
-    flexmock(module).should_receive('make_snapshot_exclude_path').with_args(
+    flexmock(module).should_receive('make_snapshot_exclude_pattern').with_args(
         '/mnt/subvol1'
         '/mnt/subvol1'
-    ).and_return('/mnt/subvol1/.borgmatic-1234/mnt/subvol1/.borgmatic-1234')
-    flexmock(module).should_receive('make_snapshot_exclude_path').with_args(
+    ).and_return(
+        Pattern(
+            '/mnt/subvol1/.borgmatic-1234/mnt/subvol1/.borgmatic-1234',
+            Pattern_type.EXCLUDE,
+            Pattern_style.FNMATCH,
+        )
+    )
+    flexmock(module).should_receive('make_snapshot_exclude_pattern').with_args(
         '/mnt/subvol2'
         '/mnt/subvol2'
-    ).and_return('/mnt/subvol2/.borgmatic-1234/mnt/subvol2/.borgmatic-1234')
-    flexmock(module).should_receive('make_borg_source_directory_path').with_args(
+    ).and_return(
+        Pattern(
+            '/mnt/subvol2/.borgmatic-1234/mnt/subvol2/.borgmatic-1234',
+            Pattern_type.EXCLUDE,
+            Pattern_style.FNMATCH,
+        )
+    )
+    flexmock(module).should_receive('make_borg_snapshot_pattern').with_args(
         '/mnt/subvol1', object
         '/mnt/subvol1', object
-    ).and_return('/mnt/subvol1/.borgmatic-1234/mnt/subvol1')
-    flexmock(module).should_receive('make_borg_source_directory_path').with_args(
+    ).and_return(Pattern('/mnt/subvol1/.borgmatic-1234/mnt/subvol1'))
+    flexmock(module).should_receive('make_borg_snapshot_pattern').with_args(
         '/mnt/subvol2', object
         '/mnt/subvol2', object
-    ).and_return('/mnt/subvol2/.borgmatic-1234/mnt/subvol2')
+    ).and_return(Pattern('/mnt/subvol2/.borgmatic-1234/mnt/subvol2'))
 
 
     assert (
     assert (
         module.dump_data_sources(
         module.dump_data_sources(
@@ -204,16 +224,16 @@ def test_dump_data_sources_snapshots_each_subvolume_and_updates_source_directori
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == [
-        '/foo',
-        '/mnt/subvol1/.borgmatic-1234/mnt/subvol1',
-        '/mnt/subvol2/.borgmatic-1234/mnt/subvol2',
+    assert patterns == [
+        Pattern('/foo'),
+        Pattern('/mnt/subvol1/.borgmatic-1234/mnt/subvol1'),
+        Pattern('/mnt/subvol2/.borgmatic-1234/mnt/subvol2'),
     ]
     ]
     assert config == {
     assert config == {
         'btrfs': {},
         'btrfs': {},
@@ -225,10 +245,10 @@ def test_dump_data_sources_snapshots_each_subvolume_and_updates_source_directori
 
 
 
 
 def test_dump_data_sources_uses_custom_btrfs_command_in_commands():
 def test_dump_data_sources_uses_custom_btrfs_command_in_commands():
-    source_directories = ['/foo', '/mnt/subvol1']
+    patterns = [Pattern('/foo'), Pattern('/mnt/subvol1')]
     config = {'btrfs': {'btrfs_command': '/usr/local/bin/btrfs'}}
     config = {'btrfs': {'btrfs_command': '/usr/local/bin/btrfs'}}
     flexmock(module).should_receive('get_subvolumes').and_return(
     flexmock(module).should_receive('get_subvolumes').and_return(
-        (module.Subvolume('/mnt/subvol1', contained_source_directories=('/mnt/subvol1',)),)
+        (module.Subvolume('/mnt/subvol1', contained_patterns=(Pattern('/mnt/subvol1'),)),)
     )
     )
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
         '/mnt/subvol1/.borgmatic-1234/mnt/subvol1'
         '/mnt/subvol1/.borgmatic-1234/mnt/subvol1'
@@ -236,12 +256,18 @@ def test_dump_data_sources_uses_custom_btrfs_command_in_commands():
     flexmock(module).should_receive('snapshot_subvolume').with_args(
     flexmock(module).should_receive('snapshot_subvolume').with_args(
         '/usr/local/bin/btrfs', '/mnt/subvol1', '/mnt/subvol1/.borgmatic-1234/mnt/subvol1'
         '/usr/local/bin/btrfs', '/mnt/subvol1', '/mnt/subvol1/.borgmatic-1234/mnt/subvol1'
     ).once()
     ).once()
-    flexmock(module).should_receive('make_snapshot_exclude_path').with_args(
+    flexmock(module).should_receive('make_snapshot_exclude_pattern').with_args(
         '/mnt/subvol1'
         '/mnt/subvol1'
-    ).and_return('/mnt/subvol1/.borgmatic-1234/mnt/subvol1/.borgmatic-1234')
-    flexmock(module).should_receive('make_borg_source_directory_path').with_args(
+    ).and_return(
+        Pattern(
+            '/mnt/subvol1/.borgmatic-1234/mnt/subvol1/.borgmatic-1234',
+            Pattern_type.EXCLUDE,
+            Pattern_style.FNMATCH,
+        )
+    )
+    flexmock(module).should_receive('make_borg_snapshot_pattern').with_args(
         '/mnt/subvol1', object
         '/mnt/subvol1', object
-    ).and_return('/mnt/subvol1/.borgmatic-1234/mnt/subvol1')
+    ).and_return(Pattern('/mnt/subvol1/.borgmatic-1234/mnt/subvol1'))
 
 
     assert (
     assert (
         module.dump_data_sources(
         module.dump_data_sources(
@@ -250,15 +276,15 @@ def test_dump_data_sources_uses_custom_btrfs_command_in_commands():
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == [
-        '/foo',
-        '/mnt/subvol1/.borgmatic-1234/mnt/subvol1',
+    assert patterns == [
+        Pattern('/foo'),
+        Pattern('/mnt/subvol1/.borgmatic-1234/mnt/subvol1'),
     ]
     ]
     assert config == {
     assert config == {
         'btrfs': {
         'btrfs': {
@@ -271,12 +297,12 @@ def test_dump_data_sources_uses_custom_btrfs_command_in_commands():
 
 
 
 
 def test_dump_data_sources_uses_custom_findmnt_command_in_commands():
 def test_dump_data_sources_uses_custom_findmnt_command_in_commands():
-    source_directories = ['/foo', '/mnt/subvol1']
+    patterns = [Pattern('/foo'), Pattern('/mnt/subvol1')]
     config = {'btrfs': {'findmnt_command': '/usr/local/bin/findmnt'}}
     config = {'btrfs': {'findmnt_command': '/usr/local/bin/findmnt'}}
     flexmock(module).should_receive('get_subvolumes').with_args(
     flexmock(module).should_receive('get_subvolumes').with_args(
-        'btrfs', '/usr/local/bin/findmnt', source_directories
+        'btrfs', '/usr/local/bin/findmnt', patterns
     ).and_return(
     ).and_return(
-        (module.Subvolume('/mnt/subvol1', contained_source_directories=('/mnt/subvol1',)),)
+        (module.Subvolume('/mnt/subvol1', contained_patterns=(Pattern('/mnt/subvol1'),)),)
     ).once()
     ).once()
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
         '/mnt/subvol1/.borgmatic-1234/mnt/subvol1'
         '/mnt/subvol1/.borgmatic-1234/mnt/subvol1'
@@ -284,12 +310,18 @@ def test_dump_data_sources_uses_custom_findmnt_command_in_commands():
     flexmock(module).should_receive('snapshot_subvolume').with_args(
     flexmock(module).should_receive('snapshot_subvolume').with_args(
         'btrfs', '/mnt/subvol1', '/mnt/subvol1/.borgmatic-1234/mnt/subvol1'
         'btrfs', '/mnt/subvol1', '/mnt/subvol1/.borgmatic-1234/mnt/subvol1'
     ).once()
     ).once()
-    flexmock(module).should_receive('make_snapshot_exclude_path').with_args(
+    flexmock(module).should_receive('make_snapshot_exclude_pattern').with_args(
         '/mnt/subvol1'
         '/mnt/subvol1'
-    ).and_return('/mnt/subvol1/.borgmatic-1234/mnt/subvol1/.borgmatic-1234')
-    flexmock(module).should_receive('make_borg_source_directory_path').with_args(
+    ).and_return(
+        Pattern(
+            '/mnt/subvol1/.borgmatic-1234/mnt/subvol1/.borgmatic-1234',
+            Pattern_type.EXCLUDE,
+            Pattern_style.FNMATCH,
+        )
+    )
+    flexmock(module).should_receive('make_borg_snapshot_pattern').with_args(
         '/mnt/subvol1', object
         '/mnt/subvol1', object
-    ).and_return('/mnt/subvol1/.borgmatic-1234/mnt/subvol1')
+    ).and_return(Pattern('/mnt/subvol1/.borgmatic-1234/mnt/subvol1'))
 
 
     assert (
     assert (
         module.dump_data_sources(
         module.dump_data_sources(
@@ -298,15 +330,15 @@ def test_dump_data_sources_uses_custom_findmnt_command_in_commands():
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == [
-        '/foo',
-        '/mnt/subvol1/.borgmatic-1234/mnt/subvol1',
+    assert patterns == [
+        Pattern('/foo'),
+        Pattern('/mnt/subvol1/.borgmatic-1234/mnt/subvol1'),
     ]
     ]
     assert config == {
     assert config == {
         'btrfs': {
         'btrfs': {
@@ -318,17 +350,17 @@ def test_dump_data_sources_uses_custom_findmnt_command_in_commands():
     }
     }
 
 
 
 
-def test_dump_data_sources_with_dry_run_skips_snapshot_and_source_directories_update():
-    source_directories = ['/foo', '/mnt/subvol1']
+def test_dump_data_sources_with_dry_run_skips_snapshot_and_patterns_update():
+    patterns = [Pattern('/foo'), Pattern('/mnt/subvol1')]
     config = {'btrfs': {}}
     config = {'btrfs': {}}
     flexmock(module).should_receive('get_subvolumes').and_return(
     flexmock(module).should_receive('get_subvolumes').and_return(
-        (module.Subvolume('/mnt/subvol1', contained_source_directories=('/mnt/subvol1',)),)
+        (module.Subvolume('/mnt/subvol1', contained_patterns=(Pattern('/mnt/subvol1'),)),)
     )
     )
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
         '/mnt/subvol1/.borgmatic-1234/mnt/subvol1'
         '/mnt/subvol1/.borgmatic-1234/mnt/subvol1'
     )
     )
     flexmock(module).should_receive('snapshot_subvolume').never()
     flexmock(module).should_receive('snapshot_subvolume').never()
-    flexmock(module).should_receive('make_snapshot_exclude_path').never()
+    flexmock(module).should_receive('make_snapshot_exclude_pattern').never()
 
 
     assert (
     assert (
         module.dump_data_sources(
         module.dump_data_sources(
@@ -337,23 +369,23 @@ def test_dump_data_sources_with_dry_run_skips_snapshot_and_source_directories_up
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=True,
             dry_run=True,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == ['/foo', '/mnt/subvol1']
+    assert patterns == [Pattern('/foo'), Pattern('/mnt/subvol1')]
     assert config == {'btrfs': {}}
     assert config == {'btrfs': {}}
 
 
 
 
-def test_dump_data_sources_without_matching_subvolumes_skips_snapshot_and_source_directories_update():
-    source_directories = ['/foo', '/mnt/subvol1']
+def test_dump_data_sources_without_matching_subvolumes_skips_snapshot_and_patterns_update():
+    patterns = [Pattern('/foo'), Pattern('/mnt/subvol1')]
     config = {'btrfs': {}}
     config = {'btrfs': {}}
     flexmock(module).should_receive('get_subvolumes').and_return(())
     flexmock(module).should_receive('get_subvolumes').and_return(())
     flexmock(module).should_receive('make_snapshot_path').never()
     flexmock(module).should_receive('make_snapshot_path').never()
     flexmock(module).should_receive('snapshot_subvolume').never()
     flexmock(module).should_receive('snapshot_subvolume').never()
-    flexmock(module).should_receive('make_snapshot_exclude_path').never()
+    flexmock(module).should_receive('make_snapshot_exclude_pattern').never()
 
 
     assert (
     assert (
         module.dump_data_sources(
         module.dump_data_sources(
@@ -362,23 +394,23 @@ def test_dump_data_sources_without_matching_subvolumes_skips_snapshot_and_source
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == ['/foo', '/mnt/subvol1']
+    assert patterns == [Pattern('/foo'), Pattern('/mnt/subvol1')]
     assert config == {'btrfs': {}}
     assert config == {'btrfs': {}}
 
 
 
 
 def test_dump_data_sources_snapshots_adds_to_existing_exclude_patterns():
 def test_dump_data_sources_snapshots_adds_to_existing_exclude_patterns():
-    source_directories = ['/foo', '/mnt/subvol1']
+    patterns = [Pattern('/foo'), Pattern('/mnt/subvol1')]
     config = {'btrfs': {}, 'exclude_patterns': ['/bar']}
     config = {'btrfs': {}, 'exclude_patterns': ['/bar']}
     flexmock(module).should_receive('get_subvolumes').and_return(
     flexmock(module).should_receive('get_subvolumes').and_return(
         (
         (
-            module.Subvolume('/mnt/subvol1', contained_source_directories=('/mnt/subvol1',)),
-            module.Subvolume('/mnt/subvol2', contained_source_directories=('/mnt/subvol2',)),
+            module.Subvolume('/mnt/subvol1', contained_patterns=(Pattern('/mnt/subvol1'),)),
+            module.Subvolume('/mnt/subvol2', contained_patterns=(Pattern('/mnt/subvol2'),)),
         )
         )
     )
     )
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
@@ -393,18 +425,30 @@ def test_dump_data_sources_snapshots_adds_to_existing_exclude_patterns():
     flexmock(module).should_receive('snapshot_subvolume').with_args(
     flexmock(module).should_receive('snapshot_subvolume').with_args(
         'btrfs', '/mnt/subvol2', '/mnt/subvol2/.borgmatic-1234/mnt/subvol2'
         'btrfs', '/mnt/subvol2', '/mnt/subvol2/.borgmatic-1234/mnt/subvol2'
     ).once()
     ).once()
-    flexmock(module).should_receive('make_snapshot_exclude_path').with_args(
+    flexmock(module).should_receive('make_snapshot_exclude_pattern').with_args(
         '/mnt/subvol1'
         '/mnt/subvol1'
-    ).and_return('/mnt/subvol1/.borgmatic-1234/mnt/subvol1/.borgmatic-1234')
-    flexmock(module).should_receive('make_snapshot_exclude_path').with_args(
+    ).and_return(
+        Pattern(
+            '/mnt/subvol1/.borgmatic-1234/mnt/subvol1/.borgmatic-1234',
+            Pattern_type.EXCLUDE,
+            Pattern_style.FNMATCH,
+        )
+    )
+    flexmock(module).should_receive('make_snapshot_exclude_pattern').with_args(
         '/mnt/subvol2'
         '/mnt/subvol2'
-    ).and_return('/mnt/subvol2/.borgmatic-1234/mnt/subvol2/.borgmatic-1234')
-    flexmock(module).should_receive('make_borg_source_directory_path').with_args(
+    ).and_return(
+        Pattern(
+            '/mnt/subvol2/.borgmatic-1234/mnt/subvol2/.borgmatic-1234',
+            Pattern_type.EXCLUDE,
+            Pattern_style.FNMATCH,
+        )
+    )
+    flexmock(module).should_receive('make_borg_snapshot_pattern').with_args(
         '/mnt/subvol1', object
         '/mnt/subvol1', object
-    ).and_return('/mnt/subvol1/.borgmatic-1234/mnt/subvol1')
-    flexmock(module).should_receive('make_borg_source_directory_path').with_args(
+    ).and_return(Pattern('/mnt/subvol1/.borgmatic-1234/mnt/subvol1'))
+    flexmock(module).should_receive('make_borg_snapshot_pattern').with_args(
         '/mnt/subvol2', object
         '/mnt/subvol2', object
-    ).and_return('/mnt/subvol2/.borgmatic-1234/mnt/subvol2')
+    ).and_return(Pattern('/mnt/subvol2/.borgmatic-1234/mnt/subvol2'))
 
 
     assert (
     assert (
         module.dump_data_sources(
         module.dump_data_sources(
@@ -413,16 +457,16 @@ def test_dump_data_sources_snapshots_adds_to_existing_exclude_patterns():
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == [
-        '/foo',
-        '/mnt/subvol1/.borgmatic-1234/mnt/subvol1',
-        '/mnt/subvol2/.borgmatic-1234/mnt/subvol2',
+    assert patterns == [
+        Pattern('/foo'),
+        Pattern('/mnt/subvol1/.borgmatic-1234/mnt/subvol1'),
+        Pattern('/mnt/subvol2/.borgmatic-1234/mnt/subvol2'),
     ]
     ]
     assert config == {
     assert config == {
         'btrfs': {},
         'btrfs': {},
@@ -438,8 +482,8 @@ def test_remove_data_source_dumps_deletes_snapshots():
     config = {'btrfs': {}}
     config = {'btrfs': {}}
     flexmock(module).should_receive('get_subvolumes').and_return(
     flexmock(module).should_receive('get_subvolumes').and_return(
         (
         (
-            module.Subvolume('/mnt/subvol1', contained_source_directories=('/mnt/subvol1',)),
-            module.Subvolume('/mnt/subvol2', contained_source_directories=('/mnt/subvol2',)),
+            module.Subvolume('/mnt/subvol1', contained_patterns=(Pattern('/mnt/subvol1'),)),
+            module.Subvolume('/mnt/subvol2', contained_patterns=(Pattern('/mnt/subvol2'),)),
         )
         )
     )
     )
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
@@ -582,8 +626,8 @@ def test_remove_data_source_dumps_with_dry_run_skips_deletes():
     config = {'btrfs': {}}
     config = {'btrfs': {}}
     flexmock(module).should_receive('get_subvolumes').and_return(
     flexmock(module).should_receive('get_subvolumes').and_return(
         (
         (
-            module.Subvolume('/mnt/subvol1', contained_source_directories=('/mnt/subvol1',)),
-            module.Subvolume('/mnt/subvol2', contained_source_directories=('/mnt/subvol2',)),
+            module.Subvolume('/mnt/subvol1', contained_patterns=(Pattern('/mnt/subvol1'),)),
+            module.Subvolume('/mnt/subvol2', contained_patterns=(Pattern('/mnt/subvol2'),)),
         )
         )
     )
     )
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
@@ -665,8 +709,8 @@ def test_remove_data_source_without_snapshots_skips_deletes():
     config = {'btrfs': {}}
     config = {'btrfs': {}}
     flexmock(module).should_receive('get_subvolumes').and_return(
     flexmock(module).should_receive('get_subvolumes').and_return(
         (
         (
-            module.Subvolume('/mnt/subvol1', contained_source_directories=('/mnt/subvol1',)),
-            module.Subvolume('/mnt/subvol2', contained_source_directories=('/mnt/subvol2',)),
+            module.Subvolume('/mnt/subvol1', contained_patterns=(Pattern('/mnt/subvol1'),)),
+            module.Subvolume('/mnt/subvol2', contained_patterns=(Pattern('/mnt/subvol2'),)),
         )
         )
     )
     )
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
@@ -709,8 +753,8 @@ def test_remove_data_source_dumps_with_delete_snapshot_file_not_found_error_bail
     config = {'btrfs': {}}
     config = {'btrfs': {}}
     flexmock(module).should_receive('get_subvolumes').and_return(
     flexmock(module).should_receive('get_subvolumes').and_return(
         (
         (
-            module.Subvolume('/mnt/subvol1', contained_source_directories=('/mnt/subvol1',)),
-            module.Subvolume('/mnt/subvol2', contained_source_directories=('/mnt/subvol2',)),
+            module.Subvolume('/mnt/subvol1', contained_patterns=(Pattern('/mnt/subvol1'),)),
+            module.Subvolume('/mnt/subvol2', contained_patterns=(Pattern('/mnt/subvol2'),)),
         )
         )
     )
     )
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
@@ -773,8 +817,8 @@ def test_remove_data_source_dumps_with_delete_snapshot_called_process_error_bail
     config = {'btrfs': {}}
     config = {'btrfs': {}}
     flexmock(module).should_receive('get_subvolumes').and_return(
     flexmock(module).should_receive('get_subvolumes').and_return(
         (
         (
-            module.Subvolume('/mnt/subvol1', contained_source_directories=('/mnt/subvol1',)),
-            module.Subvolume('/mnt/subvol2', contained_source_directories=('/mnt/subvol2',)),
+            module.Subvolume('/mnt/subvol1', contained_patterns=(Pattern('/mnt/subvol1'),)),
+            module.Subvolume('/mnt/subvol2', contained_patterns=(Pattern('/mnt/subvol2'),)),
         )
         )
     )
     )
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(
     flexmock(module).should_receive('make_snapshot_path').with_args('/mnt/subvol1').and_return(

+ 81 - 80
tests/unit/hooks/data_source/test_lvm.py

@@ -1,10 +1,11 @@
 import pytest
 import pytest
 from flexmock import flexmock
 from flexmock import flexmock
 
 
+from borgmatic.borg.pattern import Pattern
 from borgmatic.hooks.data_source import lvm as module
 from borgmatic.hooks.data_source import lvm as module
 
 
 
 
-def test_get_logical_volumes_filters_by_source_directories():
+def test_get_logical_volumes_filters_by_patterns():
     flexmock(module.borgmatic.execute).should_receive(
     flexmock(module.borgmatic.execute).should_receive(
         'execute_command_and_capture_output'
         'execute_command_and_capture_output'
     ).and_return(
     ).and_return(
@@ -36,28 +37,28 @@ def test_get_logical_volumes_filters_by_source_directories():
         }
         }
         '''
         '''
     )
     )
-    contained = {'/mnt/lvolume', '/mnt/lvolume/subdir'}
+    contained = {Pattern('/mnt/lvolume'), Pattern('/mnt/lvolume/subdir')}
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
-        'get_contained_directories'
+        'get_contained_patterns'
     ).with_args(None, contained).never()
     ).with_args(None, contained).never()
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
-        'get_contained_directories'
-    ).with_args('/mnt/lvolume', contained).and_return(('/mnt/lvolume', '/mnt/lvolume/subdir'))
+        'get_contained_patterns'
+    ).with_args('/mnt/lvolume', contained).and_return((Pattern('/mnt/lvolume'), Pattern('/mnt/lvolume/subdir')))
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
-        'get_contained_directories'
+        'get_contained_patterns'
     ).with_args('/mnt/other', contained).and_return(())
     ).with_args('/mnt/other', contained).and_return(())
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
-        'get_contained_directories'
+        'get_contained_patterns'
     ).with_args('/mnt/notlvm', contained).never()
     ).with_args('/mnt/notlvm', contained).never()
 
 
     assert module.get_logical_volumes(
     assert module.get_logical_volumes(
-        'lsblk', source_directories=('/mnt/lvolume', '/mnt/lvolume/subdir')
+        'lsblk', patterns=(Pattern('/mnt/lvolume'), Pattern('/mnt/lvolume/subdir'))
     ) == (
     ) == (
         module.Logical_volume(
         module.Logical_volume(
-            'vgroup-lvolume',
-            '/dev/mapper/vgroup-lvolume',
-            '/mnt/lvolume',
-            ('/mnt/lvolume', '/mnt/lvolume/subdir'),
+            name='vgroup-lvolume',
+            device_path='/dev/mapper/vgroup-lvolume',
+            mount_point='/mnt/lvolume',
+            contained_patterns=(Pattern('/mnt/lvolume'), Pattern('/mnt/lvolume/subdir')),
         ),
         ),
     )
     )
 
 
@@ -68,12 +69,12 @@ def test_get_logical_volumes_with_invalid_lsblk_json_errors():
     ).and_return('{')
     ).and_return('{')
 
 
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
-        'get_contained_directories'
+        'get_contained_patterns'
     ).never()
     ).never()
 
 
     with pytest.raises(ValueError):
     with pytest.raises(ValueError):
         module.get_logical_volumes(
         module.get_logical_volumes(
-            'lsblk', source_directories=('/mnt/lvolume', '/mnt/lvolume/subdir')
+            'lsblk', patterns=(Pattern('/mnt/lvolume'), Pattern('/mnt/lvolume/subdir'))
         )
         )
 
 
 
 
@@ -83,12 +84,12 @@ def test_get_logical_volumes_with_lsblk_json_missing_keys_errors():
     ).and_return('{"block_devices": [{}]}')
     ).and_return('{"block_devices": [{}]}')
 
 
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
-        'get_contained_directories'
+        'get_contained_patterns'
     ).never()
     ).never()
 
 
     with pytest.raises(ValueError):
     with pytest.raises(ValueError):
         module.get_logical_volumes(
         module.get_logical_volumes(
-            'lsblk', source_directories=('/mnt/lvolume', '/mnt/lvolume/subdir')
+            'lsblk', patterns=(Pattern('/mnt/lvolume'), Pattern('/mnt/lvolume/subdir'))
         )
         )
 
 
 
 
@@ -130,22 +131,22 @@ def test_snapshot_logical_volume_with_non_percentage_snapshot_name_uses_lvcreate
     module.snapshot_logical_volume('lvcreate', 'snap', '/dev/snap', '10TB')
     module.snapshot_logical_volume('lvcreate', 'snap', '/dev/snap', '10TB')
 
 
 
 
-def test_dump_data_sources_snapshots_and_mounts_and_updates_source_directories():
+def test_dump_data_sources_snapshots_and_mounts_and_updates_patterns():
     config = {'lvm': {}}
     config = {'lvm': {}}
-    source_directories = ['/mnt/lvolume1/subdir', '/mnt/lvolume2']
+    patterns = [Pattern('/mnt/lvolume1/subdir'), Pattern('/mnt/lvolume2')]
     flexmock(module).should_receive('get_logical_volumes').and_return(
     flexmock(module).should_receive('get_logical_volumes').and_return(
         (
         (
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )
@@ -180,21 +181,21 @@ def test_dump_data_sources_snapshots_and_mounts_and_updates_source_directories()
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == [
-        '/run/borgmatic/lvm_snapshots/./mnt/lvolume1/subdir',
-        '/run/borgmatic/lvm_snapshots/./mnt/lvolume2',
+    assert patterns == [
+        Pattern('/run/borgmatic/lvm_snapshots/./mnt/lvolume1/subdir'),
+        Pattern('/run/borgmatic/lvm_snapshots/./mnt/lvolume2'),
     ]
     ]
 
 
 
 
 def test_dump_data_sources_with_no_logical_volumes_skips_snapshots():
 def test_dump_data_sources_with_no_logical_volumes_skips_snapshots():
     config = {'lvm': {}}
     config = {'lvm': {}}
-    source_directories = ['/mnt/lvolume1/subdir', '/mnt/lvolume2']
+    patterns = [Pattern('/mnt/lvolume1/subdir'), Pattern('/mnt/lvolume2')]
     flexmock(module).should_receive('get_logical_volumes').and_return(())
     flexmock(module).should_receive('get_logical_volumes').and_return(())
     flexmock(module).should_receive('snapshot_logical_volume').never()
     flexmock(module).should_receive('snapshot_logical_volume').never()
     flexmock(module).should_receive('mount_snapshot').never()
     flexmock(module).should_receive('mount_snapshot').never()
@@ -206,31 +207,31 @@ def test_dump_data_sources_with_no_logical_volumes_skips_snapshots():
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == ['/mnt/lvolume1/subdir', '/mnt/lvolume2']
+    assert patterns == [Pattern('/mnt/lvolume1/subdir'), Pattern('/mnt/lvolume2')]
 
 
 
 
 def test_dump_data_sources_uses_snapshot_size_for_snapshot():
 def test_dump_data_sources_uses_snapshot_size_for_snapshot():
     config = {'lvm': {'snapshot_size': '1000PB'}}
     config = {'lvm': {'snapshot_size': '1000PB'}}
-    source_directories = ['/mnt/lvolume1/subdir', '/mnt/lvolume2']
+    patterns = [Pattern('/mnt/lvolume1/subdir'), Pattern('/mnt/lvolume2')]
     flexmock(module).should_receive('get_logical_volumes').and_return(
     flexmock(module).should_receive('get_logical_volumes').and_return(
         (
         (
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )
@@ -271,15 +272,15 @@ def test_dump_data_sources_uses_snapshot_size_for_snapshot():
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == [
-        '/run/borgmatic/lvm_snapshots/./mnt/lvolume1/subdir',
-        '/run/borgmatic/lvm_snapshots/./mnt/lvolume2',
+    assert patterns == [
+        Pattern('/run/borgmatic/lvm_snapshots/./mnt/lvolume1/subdir'),
+        Pattern('/run/borgmatic/lvm_snapshots/./mnt/lvolume2'),
     ]
     ]
 
 
 
 
@@ -292,20 +293,20 @@ def test_dump_data_sources_uses_custom_commands():
             'mount_command': '/usr/local/bin/mount',
             'mount_command': '/usr/local/bin/mount',
         },
         },
     }
     }
-    source_directories = ['/mnt/lvolume1/subdir', '/mnt/lvolume2']
+    patterns = [Pattern('/mnt/lvolume1/subdir'), Pattern('/mnt/lvolume2')]
     flexmock(module).should_receive('get_logical_volumes').and_return(
     flexmock(module).should_receive('get_logical_volumes').and_return(
         (
         (
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )
@@ -346,34 +347,34 @@ def test_dump_data_sources_uses_custom_commands():
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == [
-        '/run/borgmatic/lvm_snapshots/./mnt/lvolume1/subdir',
-        '/run/borgmatic/lvm_snapshots/./mnt/lvolume2',
+    assert patterns == [
+        Pattern('/run/borgmatic/lvm_snapshots/./mnt/lvolume1/subdir'),
+        Pattern('/run/borgmatic/lvm_snapshots/./mnt/lvolume2'),
     ]
     ]
 
 
 
 
-def test_dump_data_sources_with_dry_run_skips_snapshots_and_does_not_touch_source_directories():
+def test_dump_data_sources_with_dry_run_skips_snapshots_and_does_not_touch_patterns():
     config = {'lvm': {}}
     config = {'lvm': {}}
-    source_directories = ['/mnt/lvolume1/subdir', '/mnt/lvolume2']
+    patterns = [Pattern('/mnt/lvolume1/subdir'), Pattern('/mnt/lvolume2')]
     flexmock(module).should_receive('get_logical_volumes').and_return(
     flexmock(module).should_receive('get_logical_volumes').and_return(
         (
         (
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )
@@ -398,34 +399,34 @@ def test_dump_data_sources_with_dry_run_skips_snapshots_and_does_not_touch_sourc
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=True,
             dry_run=True,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == [
-        '/mnt/lvolume1/subdir',
-        '/mnt/lvolume2',
+    assert patterns == [
+        Pattern('/mnt/lvolume1/subdir'),
+        Pattern('/mnt/lvolume2'),
     ]
     ]
 
 
 
 
-def test_dump_data_sources_ignores_mismatch_between_source_directories_and_contained_source_directories():
+def test_dump_data_sources_ignores_mismatch_between_given_patterns_and_contained_patterns():
     config = {'lvm': {}}
     config = {'lvm': {}}
-    source_directories = ['/hmm']
+    patterns = [Pattern('/hmm')]
     flexmock(module).should_receive('get_logical_volumes').and_return(
     flexmock(module).should_receive('get_logical_volumes').and_return(
         (
         (
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )
@@ -460,35 +461,35 @@ def test_dump_data_sources_ignores_mismatch_between_source_directories_and_conta
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == [
-        '/hmm',
-        '/run/borgmatic/lvm_snapshots/./mnt/lvolume1/subdir',
-        '/run/borgmatic/lvm_snapshots/./mnt/lvolume2',
+    assert patterns == [
+        Pattern('/hmm'),
+        Pattern('/run/borgmatic/lvm_snapshots/./mnt/lvolume1/subdir'),
+        Pattern('/run/borgmatic/lvm_snapshots/./mnt/lvolume2'),
     ]
     ]
 
 
 
 
 def test_dump_data_sources_with_missing_snapshot_errors():
 def test_dump_data_sources_with_missing_snapshot_errors():
     config = {'lvm': {}}
     config = {'lvm': {}}
-    source_directories = ['/mnt/lvolume1/subdir', '/mnt/lvolume2']
+    patterns = [Pattern('/mnt/lvolume1/subdir'), Pattern('/mnt/lvolume2')]
     flexmock(module).should_receive('get_logical_volumes').and_return(
     flexmock(module).should_receive('get_logical_volumes').and_return(
         (
         (
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )
@@ -514,7 +515,7 @@ def test_dump_data_sources_with_missing_snapshot_errors():
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
 
 
@@ -627,13 +628,13 @@ def test_remove_data_source_dumps_unmounts_and_remove_snapshots():
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )
@@ -736,13 +737,13 @@ def test_remove_data_source_dumps_with_missing_snapshot_directory_skips_unmount(
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )
@@ -781,13 +782,13 @@ def test_remove_data_source_dumps_with_missing_snapshot_mount_path_skips_unmount
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )
@@ -839,13 +840,13 @@ def test_remove_data_source_dumps_with_successful_mount_point_removal_skips_unmo
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )
@@ -897,13 +898,13 @@ def test_remove_data_source_dumps_bails_for_missing_umount_command():
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )
@@ -941,13 +942,13 @@ def test_remove_data_source_dumps_bails_for_umount_command_error():
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )
@@ -985,13 +986,13 @@ def test_remove_data_source_dumps_bails_for_missing_lvs_command():
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )
@@ -1029,13 +1030,13 @@ def test_remove_data_source_dumps_bails_for_lvs_command_error():
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )
@@ -1075,13 +1076,13 @@ def test_remove_data_source_with_dry_run_skips_snapshot_unmount_and_delete():
                 name='lvolume1',
                 name='lvolume1',
                 device_path='/dev/lvolume1',
                 device_path='/dev/lvolume1',
                 mount_point='/mnt/lvolume1',
                 mount_point='/mnt/lvolume1',
-                contained_source_directories=('/mnt/lvolume1/subdir',),
+                contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
             ),
             ),
             module.Logical_volume(
             module.Logical_volume(
                 name='lvolume2',
                 name='lvolume2',
                 device_path='/dev/lvolume2',
                 device_path='/dev/lvolume2',
                 mount_point='/mnt/lvolume2',
                 mount_point='/mnt/lvolume2',
-                contained_source_directories=('/mnt/lvolume2',),
+                contained_patterns=(Pattern('/mnt/lvolume2'),),
             ),
             ),
         )
         )
     )
     )

+ 6 - 6
tests/unit/hooks/data_source/test_mariadb.py

@@ -80,7 +80,7 @@ def test_dump_data_sources_dumps_each_database():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
         == processes
         == processes
@@ -111,7 +111,7 @@ def test_dump_data_sources_dumps_with_password():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=False,
         dry_run=False,
     ) == [process]
     ) == [process]
 
 
@@ -137,7 +137,7 @@ def test_dump_data_sources_dumps_all_databases_at_once():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=False,
         dry_run=False,
     ) == [process]
     ) == [process]
 
 
@@ -166,7 +166,7 @@ def test_dump_data_sources_dumps_all_databases_separately_when_format_configured
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
         == processes
         == processes
@@ -478,7 +478,7 @@ def test_dump_data_sources_errors_for_missing_all_databases():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
 
 
@@ -498,7 +498,7 @@ def test_dump_data_sources_does_not_error_for_missing_all_databases_with_dry_run
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=True,
             dry_run=True,
         )
         )
         == []
         == []

+ 7 - 7
tests/unit/hooks/data_source/test_mongodb.py

@@ -48,7 +48,7 @@ def test_dump_data_sources_runs_mongodump_for_each_database():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
         == processes
         == processes
@@ -71,7 +71,7 @@ def test_dump_data_sources_with_dry_run_skips_mongodump():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=True,
             dry_run=True,
         )
         )
         == []
         == []
@@ -110,7 +110,7 @@ def test_dump_data_sources_runs_mongodump_with_hostname_and_port():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=False,
         dry_run=False,
     ) == [process]
     ) == [process]
 
 
@@ -156,7 +156,7 @@ def test_dump_data_sources_runs_mongodump_with_username_and_password():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=False,
         dry_run=False,
     ) == [process]
     ) == [process]
 
 
@@ -182,7 +182,7 @@ def test_dump_data_sources_runs_mongodump_with_directory_format():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
@@ -218,7 +218,7 @@ def test_dump_data_sources_runs_mongodump_with_options():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=False,
         dry_run=False,
     ) == [process]
     ) == [process]
 
 
@@ -244,7 +244,7 @@ def test_dump_data_sources_runs_mongodumpall_for_all_databases():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=False,
         dry_run=False,
     ) == [process]
     ) == [process]
 
 

+ 6 - 6
tests/unit/hooks/data_source/test_mysql.py

@@ -80,7 +80,7 @@ def test_dump_data_sources_dumps_each_database():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
         == processes
         == processes
@@ -111,7 +111,7 @@ def test_dump_data_sources_dumps_with_password():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=False,
         dry_run=False,
     ) == [process]
     ) == [process]
 
 
@@ -137,7 +137,7 @@ def test_dump_data_sources_dumps_all_databases_at_once():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=False,
         dry_run=False,
     ) == [process]
     ) == [process]
 
 
@@ -166,7 +166,7 @@ def test_dump_data_sources_dumps_all_databases_separately_when_format_configured
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
         == processes
         == processes
@@ -476,7 +476,7 @@ def test_dump_data_sources_errors_for_missing_all_databases():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
 
 
@@ -496,7 +496,7 @@ def test_dump_data_sources_does_not_error_for_missing_all_databases_with_dry_run
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=True,
             dry_run=True,
         )
         )
         == []
         == []

+ 12 - 12
tests/unit/hooks/data_source/test_postgresql.py

@@ -258,7 +258,7 @@ def test_dump_data_sources_runs_pg_dump_for_each_database():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
         == processes
         == processes
@@ -278,7 +278,7 @@ def test_dump_data_sources_raises_when_no_database_names_to_dump():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
 
 
@@ -295,7 +295,7 @@ def test_dump_data_sources_does_not_raise_when_no_database_names_to_dump():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=True,
         dry_run=True,
     ) == []
     ) == []
 
 
@@ -321,7 +321,7 @@ def test_dump_data_sources_with_duplicate_dump_skips_pg_dump():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
@@ -349,7 +349,7 @@ def test_dump_data_sources_with_dry_run_skips_pg_dump():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=True,
             dry_run=True,
         )
         )
         == []
         == []
@@ -395,7 +395,7 @@ def test_dump_data_sources_runs_pg_dump_with_hostname_and_port():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=False,
         dry_run=False,
     ) == [process]
     ) == [process]
 
 
@@ -439,7 +439,7 @@ def test_dump_data_sources_runs_pg_dump_with_username_and_password():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=False,
         dry_run=False,
     ) == [process]
     ) == [process]
 
 
@@ -483,7 +483,7 @@ def test_dump_data_sources_with_username_injection_attack_gets_escaped():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=False,
         dry_run=False,
     ) == [process]
     ) == [process]
 
 
@@ -523,7 +523,7 @@ def test_dump_data_sources_runs_pg_dump_with_directory_format():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
@@ -566,7 +566,7 @@ def test_dump_data_sources_runs_pg_dump_with_options():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=False,
         dry_run=False,
     ) == [process]
     ) == [process]
 
 
@@ -596,7 +596,7 @@ def test_dump_data_sources_runs_pg_dumpall_for_all_databases():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=False,
         dry_run=False,
     ) == [process]
     ) == [process]
 
 
@@ -638,7 +638,7 @@ def test_dump_data_sources_runs_non_default_pg_dump():
         'test.yaml',
         'test.yaml',
         config_paths=('test.yaml',),
         config_paths=('test.yaml',),
         borgmatic_runtime_directory='/run/borgmatic',
         borgmatic_runtime_directory='/run/borgmatic',
-        source_directories=[],
+        patterns=[],
         dry_run=False,
         dry_run=False,
     ) == [process]
     ) == [process]
 
 

+ 15 - 14
tests/unit/hooks/data_source/test_snapshot.py

@@ -1,26 +1,27 @@
+from borgmatic.borg.pattern import Pattern
 from borgmatic.hooks.data_source import snapshot as module
 from borgmatic.hooks.data_source import snapshot as module
 
 
 
 
-def test_get_contained_directories_without_candidates_returns_empty():
-    assert module.get_contained_directories('/mnt', {}) == ()
+def test_get_contained_patterns_without_candidates_returns_empty():
+    assert module.get_contained_patterns('/mnt', {}) == ()
 
 
 
 
-def test_get_contained_directories_with_self_candidate_returns_self():
-    candidates = {'/foo', '/mnt', '/bar'}
+def test_get_contained_patterns_with_self_candidate_returns_self():
+    candidates = {Pattern('/foo'), Pattern('/mnt'), Pattern('/bar')}
 
 
-    assert module.get_contained_directories('/mnt', candidates) == ('/mnt',)
-    assert candidates == {'/foo', '/bar'}
+    assert module.get_contained_patterns('/mnt', candidates) == (Pattern('/mnt'),)
+    assert candidates == {Pattern('/foo'), Pattern('/bar')}
 
 
 
 
-def test_get_contained_directories_with_child_candidate_returns_child():
-    candidates = {'/foo', '/mnt/subdir', '/bar'}
+def test_get_contained_patterns_with_child_candidate_returns_child():
+    candidates = {Pattern('/foo'), Pattern('/mnt/subdir'), Pattern('/bar')}
 
 
-    assert module.get_contained_directories('/mnt', candidates) == ('/mnt/subdir',)
-    assert candidates == {'/foo', '/bar'}
+    assert module.get_contained_patterns('/mnt', candidates) == (Pattern('/mnt/subdir'),)
+    assert candidates == {Pattern('/foo'), Pattern('/bar')}
 
 
 
 
-def test_get_contained_directories_with_grandchild_candidate_returns_child():
-    candidates = {'/foo', '/mnt/sub/dir', '/bar'}
+def test_get_contained_patterns_with_grandchild_candidate_returns_child():
+    candidates = {Pattern('/foo'), Pattern('/mnt/sub/dir'), Pattern('/bar')}
 
 
-    assert module.get_contained_directories('/mnt', candidates) == ('/mnt/sub/dir',)
-    assert candidates == {'/foo', '/bar'}
+    assert module.get_contained_patterns('/mnt', candidates) == (Pattern('/mnt/sub/dir'),)
+    assert candidates == {Pattern('/foo'), Pattern('/bar')}

+ 7 - 6
tests/unit/hooks/data_source/test_sqlite.py

@@ -2,6 +2,7 @@ import logging
 
 
 from flexmock import flexmock
 from flexmock import flexmock
 
 
+from borgmatic.borg.pattern import Pattern
 from borgmatic.hooks.data_source import sqlite as module
 from borgmatic.hooks.data_source import sqlite as module
 
 
 
 
@@ -33,7 +34,7 @@ def test_dump_data_sources_logs_and_skips_if_dump_already_exists():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
@@ -64,7 +65,7 @@ def test_dump_data_sources_dumps_each_database():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
         == processes
         == processes
@@ -102,7 +103,7 @@ def test_dump_data_sources_with_path_injection_attack_gets_escaped():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
         == processes
         == processes
@@ -131,7 +132,7 @@ def test_dump_data_sources_with_non_existent_path_warns_and_dumps_database():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
         == processes
         == processes
@@ -162,7 +163,7 @@ def test_dump_data_sources_with_name_all_warns_and_dumps_all_databases():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=False,
             dry_run=False,
         )
         )
         == processes
         == processes
@@ -187,7 +188,7 @@ def test_dump_data_sources_does_not_dump_if_dry_run():
             'test.yaml',
             'test.yaml',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=[],
+            patterns=[],
             dry_run=True,
             dry_run=True,
         )
         )
         == []
         == []

+ 48 - 40
tests/unit/hooks/data_source/test_zfs.py

@@ -3,27 +3,35 @@ import os
 import pytest
 import pytest
 from flexmock import flexmock
 from flexmock import flexmock
 
 
+from borgmatic.borg.pattern import Pattern
 from borgmatic.hooks.data_source import zfs as module
 from borgmatic.hooks.data_source import zfs as module
 
 
 
 
-def test_get_datasets_to_backup_filters_datasets_by_source_directories():
+def test_get_datasets_to_backup_filters_datasets_by_patterns():
     flexmock(module.borgmatic.execute).should_receive(
     flexmock(module.borgmatic.execute).should_receive(
         'execute_command_and_capture_output'
         'execute_command_and_capture_output'
     ).and_return(
     ).and_return(
         'dataset\t/dataset\t-\nother\t/other\t-',
         'dataset\t/dataset\t-\nother\t/other\t-',
     )
     )
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
-        'get_contained_directories'
-    ).with_args('/dataset', object).and_return(('/dataset',))
+        'get_contained_patterns'
+    ).with_args('/dataset', object).and_return((Pattern('/dataset'),))
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
-        'get_contained_directories'
+        'get_contained_patterns'
     ).with_args('/other', object).and_return(())
     ).with_args('/other', object).and_return(())
 
 
     assert module.get_datasets_to_backup(
     assert module.get_datasets_to_backup(
-        'zfs', source_directories=('/foo', '/dataset', '/bar')
+        'zfs',
+        patterns=(
+            Pattern('/foo'),
+            Pattern('/dataset'),
+            Pattern('/bar'),
+        ),
     ) == (
     ) == (
         module.Dataset(
         module.Dataset(
-            name='dataset', mount_point='/dataset', contained_source_directories=('/dataset',)
+            name='dataset',
+            mount_point='/dataset',
+            contained_patterns=(Pattern('/dataset'),),
         ),
         ),
     )
     )
 
 
@@ -35,18 +43,18 @@ def test_get_datasets_to_backup_filters_datasets_by_user_property():
         'dataset\t/dataset\tauto\nother\t/other\t-',
         'dataset\t/dataset\tauto\nother\t/other\t-',
     )
     )
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
-        'get_contained_directories'
-    ).with_args('/dataset', object).never()
+        'get_contained_patterns'
+    ).with_args('/dataset', object).and_return(())
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
-        'get_contained_directories'
+        'get_contained_patterns'
     ).with_args('/other', object).and_return(())
     ).with_args('/other', object).and_return(())
 
 
-    assert module.get_datasets_to_backup('zfs', source_directories=('/foo', '/bar')) == (
+    assert module.get_datasets_to_backup('zfs', patterns=(Pattern('/foo'), Pattern('/bar'))) == (
         module.Dataset(
         module.Dataset(
             name='dataset',
             name='dataset',
             mount_point='/dataset',
             mount_point='/dataset',
             auto_backup=True,
             auto_backup=True,
-            contained_source_directories=('/dataset',),
+            contained_patterns=(Pattern('/dataset'),),
         ),
         ),
     )
     )
 
 
@@ -58,11 +66,11 @@ def test_get_datasets_to_backup_with_invalid_list_output_raises():
         'dataset',
         'dataset',
     )
     )
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
-        'get_contained_directories'
+        'get_contained_patterns'
     ).never()
     ).never()
 
 
     with pytest.raises(ValueError, match='zfs'):
     with pytest.raises(ValueError, match='zfs'):
-        module.get_datasets_to_backup('zfs', source_directories=('/foo', '/bar'))
+        module.get_datasets_to_backup('zfs', patterns=(Pattern('/foo'), Pattern('/bar')))
 
 
 
 
 def test_get_all_dataset_mount_points_does_not_filter_datasets():
 def test_get_all_dataset_mount_points_does_not_filter_datasets():
@@ -72,8 +80,8 @@ def test_get_all_dataset_mount_points_does_not_filter_datasets():
         '/dataset\n/other',
         '/dataset\n/other',
     )
     )
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
     flexmock(module.borgmatic.hooks.data_source.snapshot).should_receive(
-        'get_contained_directories'
-    ).and_return(('/dataset',))
+        'get_contained_patterns'
+    ).and_return((Pattern('/dataset'),))
 
 
     assert module.get_all_dataset_mount_points('zfs') == (
     assert module.get_all_dataset_mount_points('zfs') == (
         ('/dataset'),
         ('/dataset'),
@@ -81,13 +89,13 @@ def test_get_all_dataset_mount_points_does_not_filter_datasets():
     )
     )
 
 
 
 
-def test_dump_data_sources_snapshots_and_mounts_and_updates_source_directories():
+def test_dump_data_sources_snapshots_and_mounts_and_updates_patterns():
     flexmock(module).should_receive('get_datasets_to_backup').and_return(
     flexmock(module).should_receive('get_datasets_to_backup').and_return(
         (
         (
             flexmock(
             flexmock(
                 name='dataset',
                 name='dataset',
                 mount_point='/mnt/dataset',
                 mount_point='/mnt/dataset',
-                contained_source_directories=('/mnt/dataset/subdir',),
+                contained_patterns=(Pattern('/mnt/dataset/subdir'),),
             )
             )
         )
         )
     )
     )
@@ -103,7 +111,7 @@ def test_dump_data_sources_snapshots_and_mounts_and_updates_source_directories()
         full_snapshot_name,
         full_snapshot_name,
         module.os.path.normpath(snapshot_mount_path),
         module.os.path.normpath(snapshot_mount_path),
     ).once()
     ).once()
-    source_directories = ['/mnt/dataset/subdir']
+    patterns = [Pattern('/mnt/dataset/subdir')]
 
 
     assert (
     assert (
         module.dump_data_sources(
         module.dump_data_sources(
@@ -112,13 +120,13 @@ def test_dump_data_sources_snapshots_and_mounts_and_updates_source_directories()
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == [os.path.join(snapshot_mount_path, 'subdir')]
+    assert patterns == [Pattern(os.path.join(snapshot_mount_path, 'subdir'))]
 
 
 
 
 def test_dump_data_sources_with_no_datasets_skips_snapshots():
 def test_dump_data_sources_with_no_datasets_skips_snapshots():
@@ -126,22 +134,22 @@ def test_dump_data_sources_with_no_datasets_skips_snapshots():
     flexmock(module.os).should_receive('getpid').and_return(1234)
     flexmock(module.os).should_receive('getpid').and_return(1234)
     flexmock(module).should_receive('snapshot_dataset').never()
     flexmock(module).should_receive('snapshot_dataset').never()
     flexmock(module).should_receive('mount_snapshot').never()
     flexmock(module).should_receive('mount_snapshot').never()
-    source_directories = ['/mnt/dataset']
+    patterns = [Pattern('/mnt/dataset')]
 
 
     assert (
     assert (
         module.dump_data_sources(
         module.dump_data_sources(
             hook_config={},
             hook_config={},
-            config={'source_directories': '/mnt/dataset', 'zfs': {}},
+            config={'patterns': flexmock(), 'zfs': {}},
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == ['/mnt/dataset']
+    assert patterns == [Pattern('/mnt/dataset')]
 
 
 
 
 def test_dump_data_sources_uses_custom_commands():
 def test_dump_data_sources_uses_custom_commands():
@@ -150,7 +158,7 @@ def test_dump_data_sources_uses_custom_commands():
             flexmock(
             flexmock(
                 name='dataset',
                 name='dataset',
                 mount_point='/mnt/dataset',
                 mount_point='/mnt/dataset',
-                contained_source_directories=('/mnt/dataset/subdir',),
+                contained_patterns=(Pattern('/mnt/dataset/subdir'),),
             )
             )
         )
         )
     )
     )
@@ -166,7 +174,7 @@ def test_dump_data_sources_uses_custom_commands():
         full_snapshot_name,
         full_snapshot_name,
         module.os.path.normpath(snapshot_mount_path),
         module.os.path.normpath(snapshot_mount_path),
     ).once()
     ).once()
-    source_directories = ['/mnt/dataset/subdir']
+    patterns = [Pattern('/mnt/dataset/subdir')]
     hook_config = {
     hook_config = {
         'zfs_command': '/usr/local/bin/zfs',
         'zfs_command': '/usr/local/bin/zfs',
         'mount_command': '/usr/local/bin/mount',
         'mount_command': '/usr/local/bin/mount',
@@ -176,53 +184,53 @@ def test_dump_data_sources_uses_custom_commands():
         module.dump_data_sources(
         module.dump_data_sources(
             hook_config=hook_config,
             hook_config=hook_config,
             config={
             config={
-                'source_directories': source_directories,
+                'patterns': flexmock(),
                 'zfs': hook_config,
                 'zfs': hook_config,
             },
             },
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == [os.path.join(snapshot_mount_path, 'subdir')]
+    assert patterns == [Pattern(os.path.join(snapshot_mount_path, 'subdir'))]
 
 
 
 
-def test_dump_data_sources_with_dry_run_skips_commands_and_does_not_touch_source_directories():
+def test_dump_data_sources_with_dry_run_skips_commands_and_does_not_touch_patterns():
     flexmock(module).should_receive('get_datasets_to_backup').and_return(
     flexmock(module).should_receive('get_datasets_to_backup').and_return(
         (flexmock(name='dataset', mount_point='/mnt/dataset'),)
         (flexmock(name='dataset', mount_point='/mnt/dataset'),)
     )
     )
     flexmock(module.os).should_receive('getpid').and_return(1234)
     flexmock(module.os).should_receive('getpid').and_return(1234)
     flexmock(module).should_receive('snapshot_dataset').never()
     flexmock(module).should_receive('snapshot_dataset').never()
     flexmock(module).should_receive('mount_snapshot').never()
     flexmock(module).should_receive('mount_snapshot').never()
-    source_directories = ['/mnt/dataset']
+    patterns = [Pattern('/mnt/dataset')]
 
 
     assert (
     assert (
         module.dump_data_sources(
         module.dump_data_sources(
             hook_config={},
             hook_config={},
-            config={'source_directories': '/mnt/dataset', 'zfs': {}},
+            config={'patterns': ('R /mnt/dataset',), 'zfs': {}},
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=True,
             dry_run=True,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == ['/mnt/dataset']
+    assert patterns == [Pattern('/mnt/dataset')]
 
 
 
 
-def test_dump_data_sources_ignores_mismatch_between_source_directories_and_contained_source_directories():
+def test_dump_data_sources_ignores_mismatch_between_given_patterns_and_contained_patterns():
     flexmock(module).should_receive('get_datasets_to_backup').and_return(
     flexmock(module).should_receive('get_datasets_to_backup').and_return(
         (
         (
             flexmock(
             flexmock(
                 name='dataset',
                 name='dataset',
                 mount_point='/mnt/dataset',
                 mount_point='/mnt/dataset',
-                contained_source_directories=('/mnt/dataset/subdir',),
+                contained_patterns=(Pattern('/mnt/dataset/subdir'),),
             )
             )
         )
         )
     )
     )
@@ -238,22 +246,22 @@ def test_dump_data_sources_ignores_mismatch_between_source_directories_and_conta
         full_snapshot_name,
         full_snapshot_name,
         module.os.path.normpath(snapshot_mount_path),
         module.os.path.normpath(snapshot_mount_path),
     ).once()
     ).once()
-    source_directories = ['/hmm']
+    patterns = [Pattern('/hmm'),]
 
 
     assert (
     assert (
         module.dump_data_sources(
         module.dump_data_sources(
             hook_config={},
             hook_config={},
-            config={'source_directories': '/mnt/dataset', 'zfs': {}},
+            config={'patterns': ('R /mnt/dataset',), 'zfs': {}},
             log_prefix='test',
             log_prefix='test',
             config_paths=('test.yaml',),
             config_paths=('test.yaml',),
             borgmatic_runtime_directory='/run/borgmatic',
             borgmatic_runtime_directory='/run/borgmatic',
-            source_directories=source_directories,
+            patterns=patterns,
             dry_run=False,
             dry_run=False,
         )
         )
         == []
         == []
     )
     )
 
 
-    assert source_directories == ['/hmm', os.path.join(snapshot_mount_path, 'subdir')]
+    assert patterns == [Pattern('/hmm'), Pattern(os.path.join(snapshot_mount_path, 'subdir'))]
 
 
 
 
 def test_get_all_snapshots_parses_list_output():
 def test_get_all_snapshots_parses_list_output():