66 res += re.escape(c) |
67 res += re.escape(c) |
67 return head + res + tail |
68 return head + res + tail |
68 |
69 |
69 _globchars = {'[': 1, '{': 1, '*': 1, '?': 1} |
70 _globchars = {'[': 1, '{': 1, '*': 1, '?': 1} |
70 |
71 |
71 def matcher(cwd, names, inc, exc, head = ''): |
72 def canonpath(repo, cwd, myname): |
|
73 rootsep = repo.root + os.sep |
|
74 name = myname |
|
75 if not name.startswith(os.sep): |
|
76 name = os.path.join(repo.root, cwd, name) |
|
77 name = os.path.normpath(name) |
|
78 if name.startswith(rootsep): |
|
79 return name[len(rootsep):] |
|
80 elif name == repo.root: |
|
81 return '' |
|
82 else: |
|
83 raise Abort('%s not under repository root' % myname) |
|
84 |
|
85 def matcher(repo, cwd, names, inc, exc, head = ''): |
72 def patkind(name): |
86 def patkind(name): |
73 for prefix in 're:', 'glob:', 'path:': |
87 for prefix in 're:', 'glob:', 'path:': |
74 if name.startswith(prefix): return name.split(':', 1) |
88 if name.startswith(prefix): return name.split(':', 1) |
75 for c in name: |
89 for c in name: |
76 if c in _globchars: return 'glob', name |
90 if c in _globchars: return 'glob', name |
77 return 'relpath', name |
91 return 'relpath', name |
78 |
|
79 cwdsep = cwd + os.sep |
|
80 |
92 |
81 def regex(name, tail): |
93 def regex(name, tail): |
82 '''convert a pattern into a regular expression''' |
94 '''convert a pattern into a regular expression''' |
83 kind, name = patkind(name) |
95 kind, name = patkind(name) |
84 if kind == 're': |
96 if kind == 're': |
85 return name |
97 return name |
86 elif kind == 'path': |
98 elif kind == 'path': |
87 return '^' + re.escape(name) + '$' |
99 return '^' + re.escape(name) + '$' |
88 if cwd: name = os.path.join(cwdsep, name) |
|
89 name = os.path.normpath(name) |
|
90 if name == '.': name = '**' |
|
91 return head + globre(name, '', tail) |
100 return head + globre(name, '', tail) |
92 |
101 |
93 def matchfn(pats, tail): |
102 def matchfn(pats, tail): |
94 """build a matching function from a set of patterns""" |
103 """build a matching function from a set of patterns""" |
95 if pats: |
104 if pats: |
102 for p in pat.split(os.sep): |
111 for p in pat.split(os.sep): |
103 if patkind(p)[0] == 'glob': break |
112 if patkind(p)[0] == 'glob': break |
104 root.append(p) |
113 root.append(p) |
105 return os.sep.join(root) |
114 return os.sep.join(root) |
106 |
115 |
107 patkinds = map(patkind, names) |
116 pats = [] |
108 pats = [name for (kind, name) in patkinds if kind != 'relpath'] |
117 files = [] |
109 files = [name for (kind, name) in patkinds if kind == 'relpath'] |
118 roots = [] |
110 roots = filter(None, map(globprefix, pats)) + files |
119 for kind, name in map(patkind, names): |
111 if cwd: roots = [cwdsep + r for r in roots] |
120 if kind in ('glob', 'relpath'): |
|
121 name = canonpath(repo, cwd, name) |
|
122 if name == '': |
|
123 kind, name = 'glob', '**' |
|
124 if kind in ('glob', 're'): |
|
125 pats.append(name) |
|
126 if kind == 'glob': |
|
127 root = globprefix(name) |
|
128 if root: roots.append(root) |
|
129 elif kind == 'relpath': |
|
130 files.append(name) |
|
131 roots.append(name) |
112 |
132 |
113 patmatch = matchfn(pats, '$') or always |
133 patmatch = matchfn(pats, '$') or always |
114 filematch = matchfn(files, '(?:/|$)') or always |
134 filematch = matchfn(files, '(?:/|$)') or always |
115 incmatch = matchfn(inc, '(?:/|$)') or always |
135 incmatch = matchfn(inc, '(?:/|$)') or always |
116 excmatch = matchfn(exc, '(?:/|$)') or (lambda fn: False) |
136 excmatch = matchfn(exc, '(?:/|$)') or (lambda fn: False) |