# HG changeset patch # User mpm@selenic.com # Date 1121966493 18000 # Node ID 092937de2ad79bbb32641aedf7a6c91c0d96beda # Parent 156dc2f3be7f3e763f7714ea4eb8d489a864ce9f Refactor matchpats and walk Move core match function code to util Add some comments and whitespace Simplify options Use lambdas instead of always and never diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -39,40 +39,16 @@ def relpath(repo, args): for x in args] return args -def matchpats(ui, cwd, pats = [], opts = {}, emptyok = True): - if not pats and not emptyok: - raise Abort('at least one file name or pattern required') - head = '' - if opts.get('rootless'): head = '(?:.*/|)' - def reify(name, tail): - if name.startswith('re:'): - return name[3:] - elif name.startswith('glob:'): - return head + util.globre(name[5:], '', tail) - elif name.startswith('path:'): - return '^' + re.escape(name[5:]) + '$' - return head + util.globre(name, '', tail) - cwdsep = cwd + os.sep - def under(fn): - if not cwd or fn.startswith(cwdsep): return True - def matchfn(pats, tail, ifempty = util.always): - if not pats: return ifempty - pat = '(?:%s)' % '|'.join([reify(p, tail) for p in pats]) - if cwd: pat = re.escape(cwd + os.sep) + pat - ui.debug('regexp: %s\n' % pat) - return re.compile(pat).match - patmatch = matchfn(pats, '$') - incmatch = matchfn(opts.get('include'), '(?:/|$)', under) - excmatch = matchfn(opts.get('exclude'), '(?:/|$)', util.never) - return lambda fn: (incmatch(fn) and not excmatch(fn) and - (fn.endswith('/') or patmatch(fn))) +def matchpats(cwd, pats = [], opts = {}, head = ''): + return util.matcher(cwd, pats, opts.get('include'), + opts.get('exclude'), head) -def walk(repo, pats, opts, emptyok = True): +def walk(repo, pats, opts, head = ''): cwd = repo.getcwd() + c = 0 if cwd: c = len(cwd) + 1 - for src, fn in repo.walk(match = matchpats(repo.ui, cwd, pats, opts, emptyok)): - if cwd: yield src, fn, fn[c:] - else: yield src, fn, fn + for src, fn in repo.walk(match = matchpats(cwd, pats, opts, head)): + yield src, fn, fn[c:] revrangesep = ':' @@ -709,10 +685,10 @@ def init(ui, source=None): def locate(ui, repo, *pats, **opts): """locate files matching specific patterns""" + end = '\n' if opts['print0']: end = '\0' - else: end = '\n' - opts['rootless'] = True - for src, abs, rel in walk(repo, pats, opts): + + for src, abs, rel in walk(repo, pats, opts, '(?:.*/|)'): if repo.dirstate.state(abs) == '?': continue if opts['fullpath']: ui.write(os.path.join(repo.root, abs), end) @@ -998,8 +974,7 @@ def status(ui, repo, *pats, **opts): R = removed ? = not tracked''' - (c, a, d, u) = repo.changes(match = matchpats(ui, repo.getcwd(), - pats, opts)) + (c, a, d, u) = repo.changes(match = matchpats(repo.getcwd(), pats, opts)) (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u)) for f in c: diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -79,6 +79,37 @@ def globre(pat, head = '^', tail = '$'): res += re.escape(c) return head + res + tail +def matcher(cwd, pats, inc, exc, head = ''): + def regex(name, tail): + '''convert a pattern into a regular expression''' + if name.startswith('re:'): + return name[3:] + elif name.startswith('path:'): + return '^' + re.escape(name[5:]) + '$' + elif name.startswith('glob:'): + return head + globre(name[5:], '', tail) + return head + globre(name, '', tail) + + def under(fn): + """check if fn is under our cwd""" + return not cwd or fn.startswith(cwdsep) + + def matchfn(pats, tail): + """build a matching function from a set of patterns""" + if pats: + pat = '(?:%s)' % '|'.join([regex(p, tail) for p in pats]) + if cwd: + pat = re.escape(cwd + os.sep) + pat + return re.compile(pat).match + + cwdsep = cwd + os.sep + patmatch = matchfn(pats, '$') or (lambda fn: True) + incmatch = matchfn(inc, '(?:/|$)') or under + excmatch = matchfn(exc, '(?:/|$)') or (lambda fn: False) + + return lambda fn: (incmatch(fn) and not excmatch(fn) and + (fn.endswith('/') or patmatch(fn))) + def system(cmd, errprefix=None): """execute a shell command that must succeed""" rc = os.system(cmd)