Browse Source

backup: use decorated paths for matching patterns

By ensuring that directory names end in '/', the behavior of
"match only directories if the pattern ends with /" comes for
free based on how wcmatch.glob works, so we don't need to run
the regex match twice.
Jim Paris 7 months ago
1 changed files with 9 additions and 9 deletions
  1. +9

+ 9
- 9 View File

@@ -81,12 +81,7 @@ class Config:
[ re.compile(x) for x in b ])

def match_re(self, re: tuple[list[typing.Pattern],
path: bytes, is_dir: bool):
# If it's a directory, try matching against a trailing slash
# first.
if is_dir and self.match_re(re, path + b'/', False):
return True
list[typing.Pattern]], path: bytes):
# Path matches if it matches at least one regex in
# re[0] and no regex in re[1].
for a in re[0]:
@@ -146,10 +141,15 @@ class Backup:
is_dir = stat.S_ISDIR(st.st_mode)
is_reg = stat.S_ISREG(st.st_mode)

# Decorated path ends with a '/' if it's a directory.
decorated_path = path
if is_dir and not decorated_path.endswith(b'/'):
decorated_path += b'/'

# See if there's a reason to exclude it
exclude_reason = None

if self.config.match_re(self.config.exclude_re, relpath, is_dir):
if self.config.match_re(self.config.exclude_re, decorated_path):
# Config file says to exclude
exclude_reason = ('I', f"skipping, excluded by config file")

@@ -173,8 +173,8 @@ class Backup:

# If we have a reason to exclude it, stop now unless it's
# force-included
force = self.config.match_re(
self.config.force_include_re, relpath, is_dir)
force = self.config.match_re(self.config.force_include_re,
if exclude_reason and not force:
f"{exclude_reason[1]}: {pstr(path)}")