Browse Source

Fix for an error when a blank line occurs in the configured patterns or excludes (#970).

Dan Helfman 4 months ago
parent
commit
e66df22a6e
4 changed files with 20 additions and 5 deletions
  1. 3 0
      NEWS
  2. 4 1
      borgmatic/actions/create.py
  3. 1 1
      pyproject.toml
  4. 12 3
      tests/unit/actions/test_create.py

+ 3 - 0
NEWS

@@ -1,3 +1,6 @@
+1.9.7
+ * #970: Fix for an error when a blank line occurs in the configured patterns or excludes.
+
 1.9.6
  * #959: Fix an error in the Btrfs hook when a subvolume mounted at "/" is configured in borgmatic's
    source directories.

+ 4 - 1
borgmatic/actions/create.py

@@ -23,7 +23,7 @@ def parse_pattern(pattern_line):
     try:
         (pattern_type, remainder) = pattern_line.split(' ', maxsplit=1)
     except ValueError:
-        raise ValueError('Invalid pattern:', pattern_line)
+        raise ValueError(f'Invalid pattern: {pattern_line}')
 
     try:
         (pattern_style, path) = remainder.split(':', maxsplit=1)
@@ -57,6 +57,7 @@ def collect_patterns(config):
                 parse_pattern(pattern_line.strip())
                 for pattern_line in config.get('patterns', ())
                 if not pattern_line.lstrip().startswith('#')
+                if pattern_line.strip()
             )
             + tuple(
                 borgmatic.borg.pattern.Pattern(
@@ -71,6 +72,7 @@ def collect_patterns(config):
                 for filename in config.get('patterns_from', ())
                 for pattern_line in open(filename).readlines()
                 if not pattern_line.lstrip().startswith('#')
+                if pattern_line.strip()
             )
             + tuple(
                 borgmatic.borg.pattern.Pattern(
@@ -81,6 +83,7 @@ def collect_patterns(config):
                 for filename in config.get('excludes_from', ())
                 for exclude_line in open(filename).readlines()
                 if not exclude_line.lstrip().startswith('#')
+                if exclude_line.strip()
             )
         )
     except (FileNotFoundError, OSError) as error:

+ 1 - 1
pyproject.toml

@@ -1,6 +1,6 @@
 [project]
 name = "borgmatic"
-version = "1.9.6"
+version = "1.9.7.dev0"
 authors = [
   { name="Dan Helfman", email="witten@torsion.org" },
 ]

+ 12 - 3
tests/unit/actions/test_create.py

@@ -36,9 +36,11 @@ def test_collect_patterns_converts_source_directories():
 def test_collect_patterns_parses_config_patterns():
     flexmock(module).should_receive('parse_pattern').with_args('R /foo').and_return(Pattern('/foo'))
     flexmock(module).should_receive('parse_pattern').with_args('# comment').never()
+    flexmock(module).should_receive('parse_pattern').with_args('').never()
+    flexmock(module).should_receive('parse_pattern').with_args('   ').never()
     flexmock(module).should_receive('parse_pattern').with_args('R /bar').and_return(Pattern('/bar'))
 
-    assert module.collect_patterns({'patterns': ['R /foo', '# comment', 'R /bar']}) == (
+    assert module.collect_patterns({'patterns': ['R /foo', '# comment', '', '   ', 'R /bar']}) == (
         Pattern('/foo'),
         Pattern('/bar'),
     )
@@ -55,10 +57,12 @@ def test_collect_patterns_reads_config_patterns_from_file():
     builtins = flexmock(sys.modules['builtins'])
     builtins.should_receive('open').with_args('file1.txt').and_return(io.StringIO('R /foo'))
     builtins.should_receive('open').with_args('file2.txt').and_return(
-        io.StringIO('R /bar\n# comment\nR /baz')
+        io.StringIO('R /bar\n# comment\n\n   \nR /baz')
     )
     flexmock(module).should_receive('parse_pattern').with_args('R /foo').and_return(Pattern('/foo'))
     flexmock(module).should_receive('parse_pattern').with_args('# comment').never()
+    flexmock(module).should_receive('parse_pattern').with_args('').never()
+    flexmock(module).should_receive('parse_pattern').with_args('   ').never()
     flexmock(module).should_receive('parse_pattern').with_args('R /bar').and_return(Pattern('/bar'))
     flexmock(module).should_receive('parse_pattern').with_args('R /baz').and_return(Pattern('/baz'))
 
@@ -82,8 +86,13 @@ def test_collect_patterns_reads_config_excludes_from_file():
     builtins = flexmock(sys.modules['builtins'])
     builtins.should_receive('open').with_args('file1.txt').and_return(io.StringIO('/foo'))
     builtins.should_receive('open').with_args('file2.txt').and_return(
-        io.StringIO('/bar\n# comment\n/baz')
+        io.StringIO('/bar\n# comment\n\n   \n/baz')
     )
+    flexmock(module).should_receive('parse_pattern').with_args('/bar').and_return(Pattern('/bar'))
+    flexmock(module).should_receive('parse_pattern').with_args('# comment').never()
+    flexmock(module).should_receive('parse_pattern').with_args('').never()
+    flexmock(module).should_receive('parse_pattern').with_args('   ').never()
+    flexmock(module).should_receive('parse_pattern').with_args('/baz').and_return(Pattern('/baz'))
 
     assert module.collect_patterns({'excludes_from': ['file1.txt', 'file2.txt']}) == (
         Pattern('/foo', Pattern_type.EXCLUDE, Pattern_style.FNMATCH),