mirror of https://github.com/borgbackup/borg.git
66 lines
2.3 KiB
Python
66 lines
2.3 KiB
Python
import os
|
|
import re
|
|
|
|
|
|
def translate(pat, match_end=r"\Z"):
|
|
"""Translate a shell-style pattern to a regular expression.
|
|
|
|
The pattern may include ``**<sep>`` (<sep> stands for the platform-specific path separator; "/" on POSIX systems) for
|
|
matching zero or more directory levels and "*" for matching zero or more arbitrary characters with the exception of
|
|
any path separator. Wrap meta-characters in brackets for a literal match (i.e. "[?]" to match the literal character
|
|
"?").
|
|
|
|
Using match_end=regex one can give a regular expression that is used to match after the regex that is generated from
|
|
the pattern. The default is to match the end of the string.
|
|
|
|
This function is derived from the "fnmatch" module distributed with the Python standard library.
|
|
|
|
Copyright (C) 2001-2016 Python Software Foundation. All rights reserved.
|
|
|
|
TODO: support {alt1,alt2} shell-style alternatives
|
|
|
|
"""
|
|
sep = os.path.sep
|
|
n = len(pat)
|
|
i = 0
|
|
res = ""
|
|
|
|
while i < n:
|
|
c = pat[i]
|
|
i += 1
|
|
|
|
if c == "*":
|
|
if i + 1 < n and pat[i] == "*" and pat[i + 1] == sep:
|
|
# **/ == wildcard for 0+ full (relative) directory names with trailing slashes; the forward slash stands
|
|
# for the platform-specific path separator
|
|
res += rf"(?:[^\{sep}]*\{sep})*"
|
|
i += 2
|
|
else:
|
|
# * == wildcard for name parts (does not cross path separator)
|
|
res += r"[^\%s]*" % sep
|
|
elif c == "?":
|
|
# ? == any single character excluding path separator
|
|
res += r"[^\%s]" % sep
|
|
elif c == "[":
|
|
j = i
|
|
if j < n and pat[j] == "!":
|
|
j += 1
|
|
if j < n and pat[j] == "]":
|
|
j += 1
|
|
while j < n and pat[j] != "]":
|
|
j += 1
|
|
if j >= n:
|
|
res += "\\["
|
|
else:
|
|
stuff = pat[i:j].replace("\\", "\\\\")
|
|
i = j + 1
|
|
if stuff[0] == "!":
|
|
stuff = "^" + stuff[1:]
|
|
elif stuff[0] == "^":
|
|
stuff = "\\" + stuff
|
|
res += "[%s]" % stuff
|
|
else:
|
|
res += re.escape(c)
|
|
|
|
return "(?ms)" + res + match_end
|