4763.2.4
by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry. |
1 |
# Copyright (C) 2006, 2008, 2009, 2010 Canonical Ltd
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
2 |
#
|
3 |
# This program is free software; you can redistribute it and/or modify
|
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
7 |
#
|
|
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
#
|
|
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
4183.7.1
by Sabin Iacob
update FSF mailing address |
15 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
16 |
|
1739.2.7
by Robert Collins
Update readdir pyrex source files and usage in line with current practice. |
17 |
"""Wrapper for readdir which returns files ordered by inode."""
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
18 |
|
19 |
||
20 |
import os |
|
21 |
import sys |
|
22 |
||
3731.1.1
by Robert Collins
* The C extensions now build on python 2.4 (Robert Collins, #271939) |
23 |
#python2.4 support
|
24 |
cdef extern from "python-compat.h": |
|
25 |
pass
|
|
26 |
||
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
27 |
|
28 |
cdef extern from 'errno.h': |
|
29 |
int ENOENT |
|
1739.2.6
by Robert Collins
Merge bzr.dev |
30 |
int ENOTDIR |
31 |
int EAGAIN |
|
3766.1.5
by Martin Pool
add missing pyrex import |
32 |
int EINTR |
3766.1.6
by Martin Pool
We need a 'global' declaration to assign to errno; and fix comments |
33 |
char *strerror(int errno) |
34 |
# not necessarily a real variable, but this should be close enough
|
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
35 |
int errno |
36 |
||
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
37 |
cdef extern from 'unistd.h': |
38 |
int chdir(char *path) |
|
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
39 |
int close(int fd) |
40 |
int fchdir(int fd) |
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
41 |
char *getcwd(char *, int size) |
42 |
||
43 |
cdef extern from 'stdlib.h': |
|
44 |
void *malloc(int) |
|
45 |
void free(void *) |
|
46 |
||
3696.3.10
by Robert Collins
Review feedback. |
47 |
|
48 |
cdef extern from 'sys/types.h': |
|
49 |
ctypedef long ssize_t |
|
50 |
ctypedef unsigned long size_t |
|
51 |
ctypedef long time_t |
|
52 |
ctypedef unsigned long ino_t |
|
53 |
ctypedef unsigned long long off_t |
|
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
54 |
ctypedef int mode_t |
3696.3.10
by Robert Collins
Review feedback. |
55 |
|
56 |
||
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
57 |
cdef extern from 'sys/stat.h': |
58 |
cdef struct stat: |
|
59 |
int st_mode |
|
3696.3.10
by Robert Collins
Review feedback. |
60 |
off_t st_size |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
61 |
int st_dev |
3696.3.10
by Robert Collins
Review feedback. |
62 |
ino_t st_ino |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
63 |
int st_mtime |
64 |
int st_ctime |
|
65 |
int lstat(char *path, stat *buf) |
|
66 |
int S_ISDIR(int mode) |
|
67 |
int S_ISCHR(int mode) |
|
68 |
int S_ISBLK(int mode) |
|
69 |
int S_ISREG(int mode) |
|
70 |
int S_ISFIFO(int mode) |
|
71 |
int S_ISLNK(int mode) |
|
72 |
int S_ISSOCK(int mode) |
|
73 |
||
74 |
||
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
75 |
cdef extern from 'fcntl.h': |
76 |
int O_RDONLY |
|
77 |
int open(char *pathname, int flags, mode_t mode) |
|
78 |
||
79 |
||
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
80 |
cdef extern from 'Python.h': |
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
81 |
int PyErr_CheckSignals() except -1 |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
82 |
char * PyString_AS_STRING(object) |
83 |
ctypedef int Py_ssize_t # Required for older pyrex versions |
|
3696.3.7
by Robert Collins
Use PyString_Concat directly for another small boost. |
84 |
ctypedef struct PyObject: |
85 |
pass
|
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
86 |
Py_ssize_t PyString_Size(object s) |
87 |
object PyList_GetItem(object lst, Py_ssize_t index) |
|
88 |
void *PyList_GetItem_object_void "PyList_GET_ITEM" (object lst, int index) |
|
89 |
int PyList_Append(object lst, object item) except -1 |
|
90 |
void *PyTuple_GetItem_void_void "PyTuple_GET_ITEM" (void* tpl, int index) |
|
91 |
int PyTuple_SetItem(void *, Py_ssize_t pos, object item) except -1 |
|
3696.3.7
by Robert Collins
Use PyString_Concat directly for another small boost. |
92 |
int PyTuple_SetItem_obj "PyTuple_SetItem" (void *, Py_ssize_t pos, PyObject * item) except -1 |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
93 |
void Py_INCREF(object o) |
94 |
void Py_DECREF(object o) |
|
3696.3.7
by Robert Collins
Use PyString_Concat directly for another small boost. |
95 |
void PyString_Concat(PyObject **string, object newpart) |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
96 |
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
97 |
|
98 |
cdef extern from 'dirent.h': |
|
99 |
ctypedef struct dirent: |
|
100 |
char d_name[256] |
|
3696.3.6
by Robert Collins
Partial review feedback fixups. |
101 |
ino_t d_ino |
3766.1.6
by Martin Pool
We need a 'global' declaration to assign to errno; and fix comments |
102 |
# the opaque C library DIR type.
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
103 |
ctypedef struct DIR |
104 |
# should be DIR *, pyrex barfs.
|
|
1739.2.6
by Robert Collins
Merge bzr.dev |
105 |
DIR * opendir(char * name) |
106 |
int closedir(DIR * dir) |
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
107 |
dirent *readdir(DIR *dir) |
108 |
||
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
109 |
cdef object _directory |
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
110 |
_directory = 'directory' |
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
111 |
cdef object _chardev |
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
112 |
_chardev = 'chardev' |
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
113 |
cdef object _block |
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
114 |
_block = 'block' |
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
115 |
cdef object _file |
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
116 |
_file = 'file' |
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
117 |
cdef object _fifo |
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
118 |
_fifo = 'fifo' |
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
119 |
cdef object _symlink |
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
120 |
_symlink = 'symlink' |
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
121 |
cdef object _socket |
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
122 |
_socket = 'socket' |
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
123 |
cdef object _unknown |
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
124 |
_unknown = 'unknown' |
125 |
||
126 |
# add a typedef struct dirent dirent to workaround pyrex
|
|
127 |
cdef extern from 'readdir.h': |
|
128 |
pass
|
|
129 |
||
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
130 |
|
131 |
cdef class _Stat: |
|
132 |
"""Represent a 'stat' result."""
|
|
133 |
||
3696.3.8
by Robert Collins
Just embed a struct st in the python result object, avoids converting things we don't need converted, and copying values around always. |
134 |
cdef stat _st |
135 |
||
136 |
property st_dev: |
|
137 |
def __get__(self): |
|
138 |
return self._st.st_dev |
|
139 |
||
140 |
property st_ino: |
|
141 |
def __get__(self): |
|
142 |
return self._st.st_ino |
|
143 |
||
144 |
property st_mode: |
|
145 |
def __get__(self): |
|
146 |
return self._st.st_mode |
|
147 |
||
148 |
property st_ctime: |
|
149 |
def __get__(self): |
|
150 |
return self._st.st_ctime |
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
151 |
|
152 |
property st_mtime: |
|
153 |
def __get__(self): |
|
3696.3.8
by Robert Collins
Just embed a struct st in the python result object, avoids converting things we don't need converted, and copying values around always. |
154 |
return self._st.st_mtime |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
155 |
|
3696.3.8
by Robert Collins
Just embed a struct st in the python result object, avoids converting things we don't need converted, and copying values around always. |
156 |
property st_size: |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
157 |
def __get__(self): |
3696.3.8
by Robert Collins
Just embed a struct st in the python result object, avoids converting things we don't need converted, and copying values around always. |
158 |
return self._st.st_size |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
159 |
|
160 |
def __repr__(self): |
|
161 |
"""Repr is the same as a Stat object.
|
|
162 |
||
3696.3.6
by Robert Collins
Partial review feedback fixups. |
163 |
(mode, ino, dev, nlink, uid, gid, size, None(atime), mtime, ctime)
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
164 |
"""
|
165 |
return repr((self.st_mode, 0, 0, 0, 0, 0, self.st_size, None, |
|
4570.1.1
by Robert Collins
Fix repr() on Stat objects from the readdir C extension. |
166 |
self.st_mtime, self.st_ctime)) |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
167 |
|
168 |
||
169 |
from bzrlib import osutils |
|
170 |
||
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
171 |
cdef object _safe_utf8 |
172 |
_safe_utf8 = osutils.safe_utf8 |
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
173 |
|
174 |
cdef class UTF8DirReader: |
|
175 |
"""A dir reader for utf8 file systems."""
|
|
176 |
||
177 |
def kind_from_mode(self, int mode): |
|
178 |
"""Get the kind of a path from a mode status."""
|
|
179 |
return self._kind_from_mode(mode) |
|
180 |
||
181 |
cdef _kind_from_mode(self, int mode): |
|
3696.3.10
by Robert Collins
Review feedback. |
182 |
# Files and directories are the most common - check them first.
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
183 |
if S_ISREG(mode): |
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
184 |
return _file |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
185 |
if S_ISDIR(mode): |
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
186 |
return _directory |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
187 |
if S_ISCHR(mode): |
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
188 |
return _chardev |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
189 |
if S_ISBLK(mode): |
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
190 |
return _block |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
191 |
if S_ISLNK(mode): |
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
192 |
return _symlink |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
193 |
if S_ISFIFO(mode): |
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
194 |
return _fifo |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
195 |
if S_ISSOCK(mode): |
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
196 |
return _socket |
197 |
return _unknown |
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
198 |
|
199 |
def top_prefix_to_starting_dir(self, top, prefix=""): |
|
200 |
"""See DirReader.top_prefix_to_starting_dir."""
|
|
5243.2.1
by John Arbash Meinel
Change the object-level functions into module-level functions. |
201 |
return (_safe_utf8(prefix), None, None, None, _safe_utf8(top)) |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
202 |
|
203 |
def read_dir(self, prefix, top): |
|
204 |
"""Read a single directory from a utf8 file system.
|
|
205 |
||
206 |
All paths in and out are utf8.
|
|
207 |
||
208 |
This sub-function is called when we know the filesystem is already in utf8
|
|
209 |
encoding. So we don't need to transcode filenames.
|
|
210 |
||
211 |
See DirReader.read_dir for details.
|
|
212 |
"""
|
|
213 |
#cdef char *_prefix = prefix
|
|
214 |
#cdef char *_top = top
|
|
215 |
# Use C accelerated directory listing.
|
|
216 |
cdef object newval |
|
217 |
cdef int index |
|
218 |
cdef int length |
|
219 |
cdef void * atuple |
|
220 |
cdef object name |
|
3696.3.7
by Robert Collins
Use PyString_Concat directly for another small boost. |
221 |
cdef PyObject * new_val_obj |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
222 |
|
223 |
if PyString_Size(prefix): |
|
224 |
relprefix = prefix + '/' |
|
225 |
else: |
|
226 |
relprefix = '' |
|
227 |
top_slash = top + '/' |
|
228 |
||
229 |
# read_dir supplies in should-stat order.
|
|
230 |
# for _, name in sorted(_listdir(top)):
|
|
231 |
result = _read_dir(top) |
|
232 |
length = len(result) |
|
233 |
# result.sort()
|
|
234 |
for index from 0 <= index < length: |
|
235 |
atuple = PyList_GetItem_object_void(result, index) |
|
236 |
name = <object>PyTuple_GetItem_void_void(atuple, 1) |
|
3696.3.10
by Robert Collins
Review feedback. |
237 |
# We have a tuple with (inode, name, None, statvalue, None)
|
238 |
# Now edit it:
|
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
239 |
# inode -> path_from_top
|
3696.3.7
by Robert Collins
Use PyString_Concat directly for another small boost. |
240 |
# direct concat - faster than operator +.
|
241 |
new_val_obj = <PyObject *>relprefix |
|
242 |
Py_INCREF(relprefix) |
|
243 |
PyString_Concat(&new_val_obj, name) |
|
244 |
if NULL == new_val_obj: |
|
245 |
# PyString_Concat will have setup an exception, but how to get
|
|
246 |
# at it?
|
|
247 |
raise Exception("failed to strcat") |
|
248 |
PyTuple_SetItem_obj(atuple, 0, new_val_obj) |
|
3696.3.10
by Robert Collins
Review feedback. |
249 |
# 1st None -> kind
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
250 |
newval = self._kind_from_mode( |
251 |
(<_Stat>PyTuple_GetItem_void_void(atuple, 3)).st_mode) |
|
252 |
Py_INCREF(newval) |
|
253 |
PyTuple_SetItem(atuple, 2, newval) |
|
3696.3.10
by Robert Collins
Review feedback. |
254 |
# 2nd None -> abspath # for all - the caller may need to stat files
|
255 |
# etc.
|
|
3696.3.7
by Robert Collins
Use PyString_Concat directly for another small boost. |
256 |
# direct concat - faster than operator +.
|
257 |
new_val_obj = <PyObject *>top_slash |
|
258 |
Py_INCREF(top_slash) |
|
259 |
PyString_Concat(&new_val_obj, name) |
|
260 |
if NULL == new_val_obj: |
|
261 |
# PyString_Concat will have setup an exception, but how to get
|
|
262 |
# at it?
|
|
263 |
raise Exception("failed to strcat") |
|
264 |
PyTuple_SetItem_obj(atuple, 4, new_val_obj) |
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
265 |
return result |
266 |
||
267 |
||
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
268 |
cdef raise_os_error(int errnum, char *msg_prefix, path): |
269 |
if errnum == EINTR: |
|
270 |
PyErr_CheckSignals() |
|
271 |
raise OSError(errnum, msg_prefix + strerror(errnum), path) |
|
272 |
||
273 |
||
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
274 |
cdef _read_dir(path): |
1739.2.11
by Robert Collins
Docstring and copyright header update per Martin's review. |
275 |
"""Like os.listdir, this reads the contents of a directory.
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
276 |
|
277 |
:param path: the directory to list.
|
|
3696.3.10
by Robert Collins
Review feedback. |
278 |
:return: a list of single-owner (the list) tuples ready for editing into
|
279 |
the result tuples walkdirs needs to yield. They contain (inode, name,
|
|
280 |
None, statvalue, None).
|
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
281 |
"""
|
282 |
cdef DIR *the_dir |
|
283 |
# currently this needs a fixup - the C code says 'dirent' but should say
|
|
284 |
# 'struct dirent'
|
|
285 |
cdef dirent * entry |
|
1739.2.6
by Robert Collins
Merge bzr.dev |
286 |
cdef dirent sentinel |
287 |
cdef char *name |
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
288 |
cdef int stat_result |
289 |
cdef _Stat statvalue |
|
3766.1.6
by Martin Pool
We need a 'global' declaration to assign to errno; and fix comments |
290 |
global errno |
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
291 |
cdef int orig_dir_fd |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
292 |
|
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
293 |
# Avoid chdir('') because it causes problems on Sun OS, and avoid this if
|
294 |
# staying in .
|
|
295 |
if path != "" and path != '.': |
|
296 |
# we change into the requested directory before reading, and back at the
|
|
297 |
# end, because that turns out to make the stat calls measurably faster than
|
|
298 |
# passing full paths every time.
|
|
299 |
orig_dir_fd = open(".", O_RDONLY, 0) |
|
300 |
if orig_dir_fd == -1: |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
301 |
raise_os_error(errno, "open: ", ".") |
3841.1.2
by Martin Pool
Don't call chdir('') |
302 |
if -1 == chdir(path): |
4634.154.1
by John Arbash Meinel
Bug #583486, close the current-dir file descriptor |
303 |
# Ignore the return value, because we are already raising an
|
304 |
# exception
|
|
305 |
close(orig_dir_fd) |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
306 |
raise_os_error(errno, "chdir: ", path) |
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
307 |
else: |
308 |
orig_dir_fd = -1 |
|
309 |
||
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
310 |
try: |
3841.1.1
by Martin Pool
Fix try/finally block after chdir in readdir_pyx |
311 |
the_dir = opendir(".") |
312 |
if NULL == the_dir: |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
313 |
raise_os_error(errno, "opendir: ", path) |
3841.1.1
by Martin Pool
Fix try/finally block after chdir in readdir_pyx |
314 |
try: |
315 |
result = [] |
|
316 |
entry = &sentinel |
|
317 |
while entry != NULL: |
|
318 |
# Unlike most libc functions, readdir needs errno set to 0
|
|
319 |
# beforehand so that eof can be distinguished from errors. See
|
|
320 |
# <https://bugs.launchpad.net/bzr/+bug/279381>
|
|
321 |
while True: |
|
3841.1.5
by Martin Pool
Review cleanups on readdir |
322 |
errno = 0 |
3841.1.1
by Martin Pool
Fix try/finally block after chdir in readdir_pyx |
323 |
entry = readdir(the_dir) |
324 |
if entry == NULL and (errno == EAGAIN or errno == EINTR): |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
325 |
if errno == EINTR: |
326 |
PyErr_CheckSignals() |
|
3841.1.1
by Martin Pool
Fix try/finally block after chdir in readdir_pyx |
327 |
# try again
|
328 |
continue
|
|
329 |
else: |
|
330 |
break
|
|
331 |
if entry == NULL: |
|
332 |
if errno == ENOTDIR or errno == 0: |
|
333 |
# We see ENOTDIR at the end of a normal directory.
|
|
334 |
# As ENOTDIR for read_dir(file) is triggered on opendir,
|
|
335 |
# we consider ENOTDIR to be 'no error'.
|
|
336 |
continue
|
|
337 |
else: |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
338 |
raise_os_error(errno, "readdir: ", path) |
3841.1.1
by Martin Pool
Fix try/finally block after chdir in readdir_pyx |
339 |
name = entry.d_name |
340 |
if not (name[0] == c"." and ( |
|
341 |
(name[1] == 0) or |
|
342 |
(name[1] == c"." and name[2] == 0)) |
|
343 |
):
|
|
344 |
statvalue = _Stat() |
|
345 |
stat_result = lstat(entry.d_name, &statvalue._st) |
|
346 |
if stat_result != 0: |
|
347 |
if errno != ENOENT: |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
348 |
raise_os_error(errno, "lstat: ", |
4095.1.3
by Martin Pool
Add test for failures inside pyrex readdir |
349 |
path + "/" + entry.d_name) |
3841.1.1
by Martin Pool
Fix try/finally block after chdir in readdir_pyx |
350 |
else: |
4634.75.1
by Martin Pool
Cope with files disappearing between readdir and stat |
351 |
# the file seems to have disappeared after being
|
352 |
# seen by readdir - perhaps a transient temporary
|
|
353 |
# file. there's no point returning it.
|
|
354 |
continue
|
|
3841.1.1
by Martin Pool
Fix try/finally block after chdir in readdir_pyx |
355 |
# We append a 5-tuple that can be modified in-place by the C
|
356 |
# api:
|
|
357 |
# inode to sort on (to replace with top_path)
|
|
358 |
# name (to keep)
|
|
359 |
# kind (None, to set)
|
|
360 |
# statvalue (to keep)
|
|
361 |
# abspath (None, to set)
|
|
362 |
PyList_Append(result, (entry.d_ino, entry.d_name, None, |
|
363 |
statvalue, None)) |
|
364 |
finally: |
|
365 |
if -1 == closedir(the_dir): |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
366 |
raise_os_error(errno, "closedir: ", path) |
1739.2.6
by Robert Collins
Merge bzr.dev |
367 |
finally: |
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
368 |
if -1 != orig_dir_fd: |
3841.1.5
by Martin Pool
Review cleanups on readdir |
369 |
failed = False |
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
370 |
if -1 == fchdir(orig_dir_fd): |
3841.1.5
by Martin Pool
Review cleanups on readdir |
371 |
# try to close the original directory anyhow
|
372 |
failed = True |
|
373 |
if -1 == close(orig_dir_fd) or failed: |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
374 |
raise_os_error(errno, "return to orig_dir: ", "") |
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
375 |
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
376 |
return result |
1739.2.6
by Robert Collins
Merge bzr.dev |
377 |
|
378 |
||
379 |
# vim: tw=79 ai expandtab sw=4 sts=4
|