Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/util.py @ 812:b65af904d6d7
Reduce the amount of stat traffic generated by a walk.
When we switched to the new walk code for commands, we no longer passed a
list of specific files to the repo or dirstate walk or changes methods.
This meant that we always walked and attempted to match everything,
which was not efficient.
Now, if we are given any patterns to match, or nothing at all, we still
walk everything. But if we are given only file names that contain no
glob characters, we only walk those.
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Fri, 29 Jul 2005 12:30:12 -0800 |
parents | cdb9e95b2fab |
children | 0902ffece4b4 |
comparison
equal
deleted
inserted
replaced
811:fa9aaf3bbdd7 | 812:b65af904d6d7 |
---|---|
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: |