comparison mercurial/pure/osutil.py @ 32512:0e8b0b9a7acc

cffi: split modules from pure The copyright lines are updated per change history. cffi/osutil.py isn't tested since I have no access to OS X machine right now, sorry.
author Yuya Nishihara <yuya@tcha.org>
date Tue, 02 May 2017 21:15:31 +0900
parents 2dcb3d52ef41
children 75979c8d4572
comparison
equal deleted inserted replaced
32511:2e431fb98c6b 32512:0e8b0b9a7acc
12 import os 12 import os
13 import socket 13 import socket
14 import stat as statmod 14 import stat as statmod
15 15
16 from .. import ( 16 from .. import (
17 policy,
18 pycompat, 17 pycompat,
19 ) 18 )
20
21 modulepolicy = policy.policy
22 policynocffi = policy.policynocffi
23 19
24 def _mode_to_kind(mode): 20 def _mode_to_kind(mode):
25 if statmod.S_ISREG(mode): 21 if statmod.S_ISREG(mode):
26 return statmod.S_IFREG 22 return statmod.S_IFREG
27 if statmod.S_ISDIR(mode): 23 if statmod.S_ISDIR(mode):
36 return statmod.S_IFIFO 32 return statmod.S_IFIFO
37 if statmod.S_ISSOCK(mode): 33 if statmod.S_ISSOCK(mode):
38 return statmod.S_IFSOCK 34 return statmod.S_IFSOCK
39 return mode 35 return mode
40 36
41 def listdirpure(path, stat=False, skip=None): 37 def listdir(path, stat=False, skip=None):
42 '''listdir(path, stat=False) -> list_of_tuples 38 '''listdir(path, stat=False) -> list_of_tuples
43 39
44 Return a sorted list containing information about the entries 40 Return a sorted list containing information about the entries
45 in the directory. 41 in the directory.
46 42
65 if stat: 61 if stat:
66 result.append((fn, _mode_to_kind(st.st_mode), st)) 62 result.append((fn, _mode_to_kind(st.st_mode), st))
67 else: 63 else:
68 result.append((fn, _mode_to_kind(st.st_mode))) 64 result.append((fn, _mode_to_kind(st.st_mode)))
69 return result 65 return result
70
71 ffi = None
72 if modulepolicy not in policynocffi and pycompat.sysplatform == 'darwin':
73 try:
74 from ..cffi._osutil import ffi, lib
75 except ImportError:
76 if modulepolicy == 'cffi': # strict cffi import
77 raise
78
79 if pycompat.sysplatform == 'darwin' and ffi is not None:
80 listdir_batch_size = 4096
81 # tweakable number, only affects performance, which chunks
82 # of bytes do we get back from getattrlistbulk
83
84 attrkinds = [None] * 20 # we need the max no for enum VXXX, 20 is plenty
85
86 attrkinds[lib.VREG] = statmod.S_IFREG
87 attrkinds[lib.VDIR] = statmod.S_IFDIR
88 attrkinds[lib.VLNK] = statmod.S_IFLNK
89 attrkinds[lib.VBLK] = statmod.S_IFBLK
90 attrkinds[lib.VCHR] = statmod.S_IFCHR
91 attrkinds[lib.VFIFO] = statmod.S_IFIFO
92 attrkinds[lib.VSOCK] = statmod.S_IFSOCK
93
94 class stat_res(object):
95 def __init__(self, st_mode, st_mtime, st_size):
96 self.st_mode = st_mode
97 self.st_mtime = st_mtime
98 self.st_size = st_size
99
100 tv_sec_ofs = ffi.offsetof("struct timespec", "tv_sec")
101 buf = ffi.new("char[]", listdir_batch_size)
102
103 def listdirinternal(dfd, req, stat, skip):
104 ret = []
105 while True:
106 r = lib.getattrlistbulk(dfd, req, buf, listdir_batch_size, 0)
107 if r == 0:
108 break
109 if r == -1:
110 raise OSError(ffi.errno, os.strerror(ffi.errno))
111 cur = ffi.cast("val_attrs_t*", buf)
112 for i in range(r):
113 lgt = cur.length
114 assert lgt == ffi.cast('uint32_t*', cur)[0]
115 ofs = cur.name_info.attr_dataoffset
116 str_lgt = cur.name_info.attr_length
117 base_ofs = ffi.offsetof('val_attrs_t', 'name_info')
118 name = str(ffi.buffer(ffi.cast("char*", cur) + base_ofs + ofs,
119 str_lgt - 1))
120 tp = attrkinds[cur.obj_type]
121 if name == "." or name == "..":
122 continue
123 if skip == name and tp == statmod.S_ISDIR:
124 return []
125 if stat:
126 mtime = cur.mtime.tv_sec
127 mode = (cur.accessmask & ~lib.S_IFMT)| tp
128 ret.append((name, tp, stat_res(st_mode=mode, st_mtime=mtime,
129 st_size=cur.datalength)))
130 else:
131 ret.append((name, tp))
132 cur = ffi.cast("val_attrs_t*", int(ffi.cast("intptr_t", cur))
133 + lgt)
134 return ret
135
136 def listdir(path, stat=False, skip=None):
137 req = ffi.new("struct attrlist*")
138 req.bitmapcount = lib.ATTR_BIT_MAP_COUNT
139 req.commonattr = (lib.ATTR_CMN_RETURNED_ATTRS |
140 lib.ATTR_CMN_NAME |
141 lib.ATTR_CMN_OBJTYPE |
142 lib.ATTR_CMN_ACCESSMASK |
143 lib.ATTR_CMN_MODTIME)
144 req.fileattr = lib.ATTR_FILE_DATALENGTH
145 dfd = lib.open(path, lib.O_RDONLY, 0)
146 if dfd == -1:
147 raise OSError(ffi.errno, os.strerror(ffi.errno))
148
149 try:
150 ret = listdirinternal(dfd, req, stat, skip)
151 finally:
152 try:
153 lib.close(dfd)
154 except BaseException:
155 pass # we ignore all the errors from closing, not
156 # much we can do about that
157 return ret
158 else:
159 listdir = listdirpure
160 66
161 if pycompat.osname != 'nt': 67 if pycompat.osname != 'nt':
162 posixfile = open 68 posixfile = open
163 69
164 _SCM_RIGHTS = 0x01 70 _SCM_RIGHTS = 0x01