listdir: add support for aborting if a certain path is found
authorMatt Mackall <mpm@selenic.com>
Sat, 13 Sep 2008 10:46:47 -0500
changeset 7034 0d513661d6c2
parent 7033 892d27fb04a5
child 7039 aafe12bd7174
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.
mercurial/dirstate.py
mercurial/osutil.c
mercurial/osutil.py
--- a/mercurial/dirstate.py	Sat Sep 13 10:44:44 2008 -0500
+++ b/mercurial/dirstate.py	Sat Sep 13 10:46:47 2008 -0500
@@ -9,7 +9,7 @@
 
 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 @@
         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 @@
             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:
--- a/mercurial/osutil.c	Sat Sep 13 10:44:44 2008 -0500
+++ b/mercurial/osutil.c	Sat Sep 13 10:46:47 2008 -0500
@@ -114,17 +114,18 @@
 
 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 @@
 			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 @@
 		Py_DECREF(elem);
 	}
 
-	PyList_Sort(list);
 	ret = list;
 	Py_INCREF(ret);
 
--- a/mercurial/osutil.py	Sat Sep 13 10:44:44 2008 -0500
+++ b/mercurial/osutil.py	Sat Sep 13 10:46:47 2008 -0500
@@ -10,7 +10,7 @@
     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 @@
     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: