# HG changeset patch # User Matt Mackall # Date 2008-09-13 15:46:47 # Node ID 0d513661d6c280fae68a96aea16231702959bfb6 # Parent 892d27fb04a5d50fc01bdaf11be16ccd3c5f2573 listdir: add support for aborting if a certain path is found This lets us bail out early if we find '.hg', letting us skip sorting and bisecting for it. diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py --- a/mercurial/dirstate.py +++ b/mercurial/dirstate.py @@ -9,7 +9,7 @@ of the GNU General Public License, incor from node import nullid from i18n import _ -import struct, os, bisect, stat, util, errno, ignore +import struct, os, stat, util, errno, ignore import cStringIO, osutil, sys _unknown = ('?', 0, 0, 0) @@ -458,7 +458,6 @@ class dirstate(object): normalize = self.normalize listdir = osutil.listdir lstat = os.lstat - bisect_left = bisect.bisect_left pconvert = util.pconvert getkind = stat.S_IFMT dirkind = stat.S_IFDIR @@ -510,17 +509,11 @@ class dirstate(object): nd = work.pop() if hasattr(match, 'dir'): match.dir(nd) - entries = listdir(join(nd), stat=True) if nd == '.': nd = '' + entries = listdir(join(nd), stat=True) else: - # do not recurse into a repo contained in this - # one. use bisect to find .hg directory so speed - # is good on big directory. - hg = bisect_left(entries, ('.hg')) - if hg < len(entries) and entries[hg][0] == '.hg' \ - and entries[hg][1] == dirkind: - continue + entries = listdir(join(nd), stat=True, skip ='.hg') for f, kind, st in entries: nf = normalize(nd and (nd + "/" + f) or f) if nf not in results: diff --git a/mercurial/osutil.c b/mercurial/osutil.c --- a/mercurial/osutil.c +++ b/mercurial/osutil.c @@ -114,17 +114,18 @@ int entkind(struct dirent *ent) static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs) { - static char *kwlist[] = { "path", "stat", NULL }; + static char *kwlist[] = { "path", "stat", "skip", NULL }; PyObject *statflag = NULL, *list, *elem, *stat, *ret = NULL; - char fullpath[PATH_MAX + 10], *path; + char fullpath[PATH_MAX + 10], *path, *skip = NULL; int pathlen, keepstat, kind, dfd = -1, err; struct stat st; struct dirent *ent; DIR *dir; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|O:listdir", kwlist, - &path, &pathlen, &statflag)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|Os:listdir", kwlist, + &path, &pathlen, &statflag, &skip)) goto error_parse; + if (pathlen >= PATH_MAX) goto error_parse; @@ -177,6 +178,12 @@ static PyObject *listdir(PyObject *self, kind = st.st_mode & S_IFMT; } + /* quit early? */ + if (skip && kind == S_IFDIR && !strcmp(ent->d_name, skip)) { + ret = PyList_New(0); + goto error; + } + if (keepstat) { stat = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL); if (!stat) @@ -192,7 +199,6 @@ static PyObject *listdir(PyObject *self, Py_DECREF(elem); } - PyList_Sort(list); ret = list; Py_INCREF(ret); diff --git a/mercurial/osutil.py b/mercurial/osutil.py --- a/mercurial/osutil.py +++ b/mercurial/osutil.py @@ -10,7 +10,7 @@ def _mode_to_kind(mode): if stat.S_ISSOCK(mode): return stat.S_IFSOCK return mode -def listdir(path, stat=False): +def listdir(path, stat=False, skip=None): '''listdir(path, stat=False) -> list_of_tuples Return a sorted list containing information about the entries @@ -30,6 +30,8 @@ def listdir(path, stat=False): names.sort() for fn in names: st = os.lstat(prefix + fn) + if fn == skip and stat.S_ISDIR(st.st_mode): + return [] if stat: result.append((fn, _mode_to_kind(st.st_mode), st)) else: