64 res += '|' |
64 res += '|' |
65 else: |
65 else: |
66 res += re.escape(c) |
66 res += re.escape(c) |
67 return head + res + tail |
67 return head + res + tail |
68 |
68 |
69 def matcher(cwd, pats, inc, exc, head = ''): |
69 _globchars = {'[': 1, '{': 1, '*': 1, '?': 1} |
|
70 |
|
71 def matcher(cwd, names, inc, exc, head = ''): |
|
72 def patlike(name): |
|
73 for prefix in 're:', 'glob:', 'path:': |
|
74 if name.startswith(prefix): return True |
|
75 for c in name: |
|
76 if c in _globchars: return True |
|
77 |
70 def regex(name, tail): |
78 def regex(name, tail): |
71 '''convert a pattern into a regular expression''' |
79 '''convert a pattern into a regular expression''' |
72 if name.startswith('re:'): |
80 if name.startswith('re:'): |
73 return name[3:] |
81 return name[3:] |
74 elif name.startswith('path:'): |
82 elif name.startswith('path:'): |
75 return '^' + re.escape(name[5:]) + '$' |
83 return '^' + re.escape(name[5:]) + '$' |
76 elif name.startswith('glob:'): |
84 elif name.startswith('glob:'): |
77 return head + globre(name[5:], '', tail) |
85 return head + globre(name[5:], '', tail) |
78 return head + globre(name, '', tail) |
86 return head + globre(name, '', tail) |
79 |
87 |
|
88 cwdsep = cwd + os.sep |
|
89 |
80 def under(fn): |
90 def under(fn): |
81 """check if fn is under our cwd""" |
91 """check if fn is under our cwd""" |
82 return not cwd or fn.startswith(cwdsep) |
92 return not cwd or fn.startswith(cwdsep) |
83 |
93 |
84 def matchfn(pats, tail): |
94 def matchfn(pats, tail): |
85 """build a matching function from a set of patterns""" |
95 """build a matching function from a set of patterns""" |
86 if pats: |
96 if pats: |
87 pat = '(?:%s)' % '|'.join([regex(p, tail) for p in pats]) |
97 pat = '(?:%s)' % '|'.join([regex(p, tail) for p in pats]) |
88 if cwd: |
98 if cwd: |
89 pat = re.escape(cwd + os.sep) + pat |
99 pat = re.escape(cwdsep) + pat |
90 return re.compile(pat).match |
100 return re.compile(pat).match |
91 |
101 |
92 cwdsep = cwd + os.sep |
102 pats = filter(patlike, names) |
93 patmatch = matchfn(pats, '$') or (lambda fn: True) |
103 files = [n for n in names if not patlike(n)] |
|
104 if pats: plain = [] |
|
105 elif cwd: plain = [cwdsep + f for f in files] |
|
106 else: plain = files |
|
107 |
|
108 patmatch = matchfn(pats, '$') |
|
109 filematch = matchfn(files, '(?:/|$)') |
94 incmatch = matchfn(inc, '(?:/|$)') or under |
110 incmatch = matchfn(inc, '(?:/|$)') or under |
95 excmatch = matchfn(exc, '(?:/|$)') or (lambda fn: False) |
111 excmatch = matchfn(exc, '(?:/|$)') or (lambda fn: False) |
96 |
112 |
97 return lambda fn: (incmatch(fn) and not excmatch(fn) and |
113 return plain, lambda fn: (incmatch(fn) and not excmatch(fn) and |
98 (fn.endswith('/') or patmatch(fn))) |
114 (fn.endswith('/') or |
|
115 (not pats and not files) or |
|
116 (pats and patmatch(fn)) or |
|
117 (files and filematch(fn)))) |
99 |
118 |
100 def system(cmd, errprefix=None): |
119 def system(cmd, errprefix=None): |
101 """execute a shell command that must succeed""" |
120 """execute a shell command that must succeed""" |
102 rc = os.system(cmd) |
121 rc = os.system(cmd) |
103 if rc: |
122 if rc: |