14 import win32api |
14 import win32api |
15 |
15 |
16 from demandload import * |
16 from demandload import * |
17 from i18n import gettext as _ |
17 from i18n import gettext as _ |
18 demandload(globals(), 'errno os pywintypes win32con win32file win32process') |
18 demandload(globals(), 'errno os pywintypes win32con win32file win32process') |
19 demandload(globals(), 'winerror') |
19 demandload(globals(), 'cStringIO winerror') |
20 |
20 |
21 class WinError(OSError): |
21 class WinError: |
22 winerror_map = { |
22 winerror_map = { |
23 winerror.ERROR_ACCESS_DENIED: errno.EACCES, |
23 winerror.ERROR_ACCESS_DENIED: errno.EACCES, |
24 winerror.ERROR_ACCOUNT_DISABLED: errno.EACCES, |
24 winerror.ERROR_ACCOUNT_DISABLED: errno.EACCES, |
25 winerror.ERROR_ACCOUNT_RESTRICTION: errno.EACCES, |
25 winerror.ERROR_ACCOUNT_RESTRICTION: errno.EACCES, |
26 winerror.ERROR_ALREADY_ASSIGNED: errno.EBUSY, |
26 winerror.ERROR_ALREADY_ASSIGNED: errno.EBUSY, |
103 winerror.ERROR_OPEN_FILES: errno.EBUSY, |
103 winerror.ERROR_OPEN_FILES: errno.EBUSY, |
104 winerror.ERROR_OPERATION_ABORTED: errno.EINTR, |
104 winerror.ERROR_OPERATION_ABORTED: errno.EINTR, |
105 winerror.ERROR_OUTOFMEMORY: errno.ENOMEM, |
105 winerror.ERROR_OUTOFMEMORY: errno.ENOMEM, |
106 winerror.ERROR_PASSWORD_EXPIRED: errno.EACCES, |
106 winerror.ERROR_PASSWORD_EXPIRED: errno.EACCES, |
107 winerror.ERROR_PATH_BUSY: errno.EBUSY, |
107 winerror.ERROR_PATH_BUSY: errno.EBUSY, |
108 winerror.ERROR_PATH_NOT_FOUND: errno.ENOTDIR, |
108 winerror.ERROR_PATH_NOT_FOUND: errno.ENOENT, |
109 winerror.ERROR_PIPE_BUSY: errno.EBUSY, |
109 winerror.ERROR_PIPE_BUSY: errno.EBUSY, |
110 winerror.ERROR_PIPE_CONNECTED: errno.EPIPE, |
110 winerror.ERROR_PIPE_CONNECTED: errno.EPIPE, |
111 winerror.ERROR_PIPE_LISTENING: errno.EPIPE, |
111 winerror.ERROR_PIPE_LISTENING: errno.EPIPE, |
112 winerror.ERROR_PIPE_NOT_CONNECTED: errno.EPIPE, |
112 winerror.ERROR_PIPE_NOT_CONNECTED: errno.EPIPE, |
113 winerror.ERROR_PRIVILEGE_NOT_HELD: errno.EACCES, |
113 winerror.ERROR_PRIVILEGE_NOT_HELD: errno.EACCES, |
127 winerror.ERROR_WRITE_PROTECT: errno.EROFS, |
127 winerror.ERROR_WRITE_PROTECT: errno.EROFS, |
128 } |
128 } |
129 |
129 |
130 def __init__(self, err): |
130 def __init__(self, err): |
131 self.win_errno, self.win_function, self.win_strerror = err |
131 self.win_errno, self.win_function, self.win_strerror = err |
|
132 if self.win_strerror.endswith('.'): |
|
133 self.win_strerror = self.win_strerror[:-1] |
|
134 |
|
135 class WinIOError(WinError, IOError): |
|
136 def __init__(self, err, filename=None): |
|
137 WinError.__init__(self, err) |
|
138 IOError.__init__(self, self.winerror_map.get(self.win_errno, 0), |
|
139 self.win_strerror) |
|
140 self.filename = filename |
|
141 |
|
142 class WinOSError(WinError, OSError): |
|
143 def __init__(self, err): |
|
144 WinError.__init__(self, err) |
132 OSError.__init__(self, self.winerror_map.get(self.win_errno, 0), |
145 OSError.__init__(self, self.winerror_map.get(self.win_errno, 0), |
133 self.win_strerror) |
146 self.win_strerror) |
134 |
147 |
135 def os_link(src, dst): |
148 def os_link(src, dst): |
136 # NB will only succeed on NTFS |
149 # NB will only succeed on NTFS |
137 try: |
150 try: |
138 win32file.CreateHardLink(dst, src) |
151 win32file.CreateHardLink(dst, src) |
139 except pywintypes.error, details: |
152 except pywintypes.error, details: |
140 raise WinError(details) |
153 raise WinOSError(details) |
141 |
154 |
142 def nlinks(pathname): |
155 def nlinks(pathname): |
143 """Return number of hardlinks for the given file.""" |
156 """Return number of hardlinks for the given file.""" |
144 try: |
157 try: |
145 fh = win32file.CreateFile(pathname, |
158 fh = win32file.CreateFile(pathname, |
167 def system_rcpath_win32(): |
180 def system_rcpath_win32(): |
168 '''return default os-specific hgrc search path''' |
181 '''return default os-specific hgrc search path''' |
169 proc = win32api.GetCurrentProcess() |
182 proc = win32api.GetCurrentProcess() |
170 filename = win32process.GetModuleFileNameEx(proc, 0) |
183 filename = win32process.GetModuleFileNameEx(proc, 0) |
171 return [os.path.join(os.path.dirname(filename), 'mercurial.ini')] |
184 return [os.path.join(os.path.dirname(filename), 'mercurial.ini')] |
|
185 |
|
186 class posixfile(object): |
|
187 '''file object with posix-like semantics. on windows, normal |
|
188 files can not be deleted or renamed if they are open. must open |
|
189 with win32file.FILE_SHARE_DELETE. this flag does not exist on |
|
190 windows <= nt.''' |
|
191 |
|
192 # tried to use win32file._open_osfhandle to pass fd to os.fdopen, |
|
193 # but does not work at all. wrap win32 file api instead. |
|
194 |
|
195 def __init__(self, name, mode='rb'): |
|
196 access = 0 |
|
197 if 'r' in mode or '+' in mode: |
|
198 access |= win32file.GENERIC_READ |
|
199 if 'w' in mode or 'a' in mode: |
|
200 access |= win32file.GENERIC_WRITE |
|
201 if 'r' in mode: |
|
202 creation = win32file.OPEN_EXISTING |
|
203 elif 'a' in mode: |
|
204 creation = win32file.OPEN_ALWAYS |
|
205 else: |
|
206 creation = win32file.CREATE_ALWAYS |
|
207 try: |
|
208 self.handle = win32file.CreateFile(name, |
|
209 access, |
|
210 win32file.FILE_SHARE_READ | |
|
211 win32file.FILE_SHARE_WRITE | |
|
212 win32file.FILE_SHARE_DELETE, |
|
213 None, |
|
214 creation, |
|
215 win32file.FILE_ATTRIBUTE_NORMAL, |
|
216 0) |
|
217 except pywintypes.error, err: |
|
218 raise WinIOError(err, name) |
|
219 self.closed = False |
|
220 self.name = name |
|
221 self.mode = mode |
|
222 |
|
223 def read(self, count=-1): |
|
224 try: |
|
225 cs = cStringIO.StringIO() |
|
226 while count: |
|
227 wincount = int(count) |
|
228 if wincount == -1: |
|
229 wincount = 1048576 |
|
230 val, data = win32file.ReadFile(self.handle, wincount) |
|
231 if not data: break |
|
232 cs.write(data) |
|
233 if count != -1: |
|
234 count -= len(data) |
|
235 return cs.getvalue() |
|
236 except pywintypes.error, err: |
|
237 raise WinIOError(err) |
|
238 |
|
239 def write(self, data): |
|
240 try: |
|
241 if 'a' in self.mode: |
|
242 win32file.SetFilePointer(self.handle, 0, win32file.FILE_END) |
|
243 nwrit = 0 |
|
244 while nwrit < len(data): |
|
245 val, nwrit = win32file.WriteFile(self.handle, data) |
|
246 data = data[nwrit:] |
|
247 except pywintypes.error, err: |
|
248 raise WinIOError(err) |
|
249 |
|
250 def seek(self, pos, whence=0): |
|
251 try: |
|
252 win32file.SetFilePointer(self.handle, int(pos), whence) |
|
253 except pywintypes.error, err: |
|
254 raise WinIOError(err) |
|
255 |
|
256 def tell(self): |
|
257 try: |
|
258 return win32file.SetFilePointer(self.handle, 0, |
|
259 win32file.FILE_CURRENT) |
|
260 except pywintypes.error, err: |
|
261 raise WinIOError(err) |
|
262 |
|
263 def close(self): |
|
264 if not self.closed: |
|
265 self.handle = None |
|
266 self.closed = True |
|
267 |
|
268 def flush(self): |
|
269 try: |
|
270 win32file.FlushFileBuffers(self.handle) |
|
271 except pywintypes.error, err: |
|
272 raise WinIOError(err) |
|
273 |
|
274 def truncate(self, pos=0): |
|
275 try: |
|
276 win32file.SetFilePointer(self.handle, int(pos), |
|
277 win32file.FILE_BEGIN) |
|
278 win32file.SetEndOfFile(self.handle) |
|
279 except pywintypes.error, err: |
|
280 raise WinIOError(err) |