# HG changeset patch # User Bryan O'Sullivan # Date 2012-11-30 23:55:07 # Node ID 74912fe3d7187cd945c520182d76ed4a0cbceb63 # Parent a39fe76c4c65c73d8824f7e3092dbbc049235422 dirstate: move file type filtering to its source This prepares us to move to a much faster statfiles implementation on Unix. diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py --- a/mercurial/dirstate.py +++ b/mercurial/dirstate.py @@ -697,9 +697,6 @@ class dirstate(object): if not skipstep3 and not exact: visit = sorted([f for f in dmap if f not in results and matchfn(f)]) for nf, st in zip(visit, util.statfiles([join(i) for i in visit])): - if (not st is None and - getkind(st.st_mode) not in (regkind, lnkkind)): - st = None results[nf] = st for s in subrepos: del results[s] diff --git a/mercurial/posix.py b/mercurial/posix.py --- a/mercurial/posix.py +++ b/mercurial/posix.py @@ -352,12 +352,18 @@ def findexe(command): def setsignalhandler(): pass +_wantedkinds = set([stat.S_IFREG, stat.S_IFLNK]) + def statfiles(files): - 'Stat each file in files and yield stat or None if file does not exist.' + '''Stat each file in files. Yield each stat, or None if a file does not + exist or has a type we don't care about.''' lstat = os.lstat + getkind = stat.S_IFMT for nf in files: try: st = lstat(nf) + if getkind(st.st_mode) not in _wantedkinds: + st = None except OSError, err: if err.errno not in (errno.ENOENT, errno.ENOTDIR): raise diff --git a/mercurial/windows.py b/mercurial/windows.py --- a/mercurial/windows.py +++ b/mercurial/windows.py @@ -7,7 +7,7 @@ from i18n import _ import osutil, encoding -import errno, msvcrt, os, re, sys, _winreg +import errno, msvcrt, os, re, stat, sys, _winreg import win32 executablepath = win32.executablepath @@ -213,10 +213,15 @@ def findexe(command): return executable return findexisting(os.path.expanduser(os.path.expandvars(command))) +_wantedkinds = set([stat.S_IFREG, stat.S_IFLNK]) + def statfiles(files): - '''Stat each file in files and yield stat or None if file does not exist. + '''Stat each file in files. Yield each stat, or None if a file + does not exist or has a type we don't care about. + Cluster and cache stat per directory to minimize number of OS stat calls.''' dircache = {} # dirname -> filename -> status | None if file does not exist + getkind = stat.S_IFMT for nf in files: nf = normcase(nf) dir, base = os.path.split(nf) @@ -226,7 +231,8 @@ def statfiles(files): if cache is None: try: dmap = dict([(normcase(n), s) - for n, k, s in osutil.listdir(dir, True)]) + for n, k, s in osutil.listdir(dir, True) + if getkind(s) in _wantedkinds]) except OSError, err: # handle directory not found in Python version prior to 2.5 # Python <= 2.4 returns native Windows code 3 in errno