##// END OF EJS Templates
Merge with crew-stable
Patrick Mezard -
r5612:7c976bb0 merge default
parent child Browse files
Show More
@@ -1,325 +1,325 b''
1 # util_win32.py - utility functions that use win32 API
1 # util_win32.py - utility functions that use win32 API
2 #
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of
6 # This software may be used and distributed according to the terms of
7 # the GNU General Public License, incorporated herein by reference.
7 # the GNU General Public License, incorporated herein by reference.
8
8
9 # Mark Hammond's win32all package allows better functionality on
9 # Mark Hammond's win32all package allows better functionality on
10 # Windows. this module overrides definitions in util.py. if not
10 # Windows. this module overrides definitions in util.py. if not
11 # available, import of this module will fail, and generic code will be
11 # available, import of this module will fail, and generic code will be
12 # used.
12 # used.
13
13
14 import win32api
14 import win32api
15
15
16 from i18n import _
16 from i18n import _
17 import errno, os, pywintypes, win32con, win32file, win32process
17 import errno, os, pywintypes, win32con, win32file, win32process
18 import cStringIO, winerror
18 import cStringIO, winerror
19 import osutil
19 import osutil
20 from win32com.shell import shell,shellcon
20 from win32com.shell import shell,shellcon
21
21
22 class WinError:
22 class WinError:
23 winerror_map = {
23 winerror_map = {
24 winerror.ERROR_ACCESS_DENIED: errno.EACCES,
24 winerror.ERROR_ACCESS_DENIED: errno.EACCES,
25 winerror.ERROR_ACCOUNT_DISABLED: errno.EACCES,
25 winerror.ERROR_ACCOUNT_DISABLED: errno.EACCES,
26 winerror.ERROR_ACCOUNT_RESTRICTION: errno.EACCES,
26 winerror.ERROR_ACCOUNT_RESTRICTION: errno.EACCES,
27 winerror.ERROR_ALREADY_ASSIGNED: errno.EBUSY,
27 winerror.ERROR_ALREADY_ASSIGNED: errno.EBUSY,
28 winerror.ERROR_ALREADY_EXISTS: errno.EEXIST,
28 winerror.ERROR_ALREADY_EXISTS: errno.EEXIST,
29 winerror.ERROR_ARITHMETIC_OVERFLOW: errno.ERANGE,
29 winerror.ERROR_ARITHMETIC_OVERFLOW: errno.ERANGE,
30 winerror.ERROR_BAD_COMMAND: errno.EIO,
30 winerror.ERROR_BAD_COMMAND: errno.EIO,
31 winerror.ERROR_BAD_DEVICE: errno.ENODEV,
31 winerror.ERROR_BAD_DEVICE: errno.ENODEV,
32 winerror.ERROR_BAD_DRIVER_LEVEL: errno.ENXIO,
32 winerror.ERROR_BAD_DRIVER_LEVEL: errno.ENXIO,
33 winerror.ERROR_BAD_EXE_FORMAT: errno.ENOEXEC,
33 winerror.ERROR_BAD_EXE_FORMAT: errno.ENOEXEC,
34 winerror.ERROR_BAD_FORMAT: errno.ENOEXEC,
34 winerror.ERROR_BAD_FORMAT: errno.ENOEXEC,
35 winerror.ERROR_BAD_LENGTH: errno.EINVAL,
35 winerror.ERROR_BAD_LENGTH: errno.EINVAL,
36 winerror.ERROR_BAD_PATHNAME: errno.ENOENT,
36 winerror.ERROR_BAD_PATHNAME: errno.ENOENT,
37 winerror.ERROR_BAD_PIPE: errno.EPIPE,
37 winerror.ERROR_BAD_PIPE: errno.EPIPE,
38 winerror.ERROR_BAD_UNIT: errno.ENODEV,
38 winerror.ERROR_BAD_UNIT: errno.ENODEV,
39 winerror.ERROR_BAD_USERNAME: errno.EINVAL,
39 winerror.ERROR_BAD_USERNAME: errno.EINVAL,
40 winerror.ERROR_BROKEN_PIPE: errno.EPIPE,
40 winerror.ERROR_BROKEN_PIPE: errno.EPIPE,
41 winerror.ERROR_BUFFER_OVERFLOW: errno.ENAMETOOLONG,
41 winerror.ERROR_BUFFER_OVERFLOW: errno.ENAMETOOLONG,
42 winerror.ERROR_BUSY: errno.EBUSY,
42 winerror.ERROR_BUSY: errno.EBUSY,
43 winerror.ERROR_BUSY_DRIVE: errno.EBUSY,
43 winerror.ERROR_BUSY_DRIVE: errno.EBUSY,
44 winerror.ERROR_CALL_NOT_IMPLEMENTED: errno.ENOSYS,
44 winerror.ERROR_CALL_NOT_IMPLEMENTED: errno.ENOSYS,
45 winerror.ERROR_CANNOT_MAKE: errno.EACCES,
45 winerror.ERROR_CANNOT_MAKE: errno.EACCES,
46 winerror.ERROR_CANTOPEN: errno.EIO,
46 winerror.ERROR_CANTOPEN: errno.EIO,
47 winerror.ERROR_CANTREAD: errno.EIO,
47 winerror.ERROR_CANTREAD: errno.EIO,
48 winerror.ERROR_CANTWRITE: errno.EIO,
48 winerror.ERROR_CANTWRITE: errno.EIO,
49 winerror.ERROR_CRC: errno.EIO,
49 winerror.ERROR_CRC: errno.EIO,
50 winerror.ERROR_CURRENT_DIRECTORY: errno.EACCES,
50 winerror.ERROR_CURRENT_DIRECTORY: errno.EACCES,
51 winerror.ERROR_DEVICE_IN_USE: errno.EBUSY,
51 winerror.ERROR_DEVICE_IN_USE: errno.EBUSY,
52 winerror.ERROR_DEV_NOT_EXIST: errno.ENODEV,
52 winerror.ERROR_DEV_NOT_EXIST: errno.ENODEV,
53 winerror.ERROR_DIRECTORY: errno.EINVAL,
53 winerror.ERROR_DIRECTORY: errno.EINVAL,
54 winerror.ERROR_DIR_NOT_EMPTY: errno.ENOTEMPTY,
54 winerror.ERROR_DIR_NOT_EMPTY: errno.ENOTEMPTY,
55 winerror.ERROR_DISK_CHANGE: errno.EIO,
55 winerror.ERROR_DISK_CHANGE: errno.EIO,
56 winerror.ERROR_DISK_FULL: errno.ENOSPC,
56 winerror.ERROR_DISK_FULL: errno.ENOSPC,
57 winerror.ERROR_DRIVE_LOCKED: errno.EBUSY,
57 winerror.ERROR_DRIVE_LOCKED: errno.EBUSY,
58 winerror.ERROR_ENVVAR_NOT_FOUND: errno.EINVAL,
58 winerror.ERROR_ENVVAR_NOT_FOUND: errno.EINVAL,
59 winerror.ERROR_EXE_MARKED_INVALID: errno.ENOEXEC,
59 winerror.ERROR_EXE_MARKED_INVALID: errno.ENOEXEC,
60 winerror.ERROR_FILENAME_EXCED_RANGE: errno.ENAMETOOLONG,
60 winerror.ERROR_FILENAME_EXCED_RANGE: errno.ENAMETOOLONG,
61 winerror.ERROR_FILE_EXISTS: errno.EEXIST,
61 winerror.ERROR_FILE_EXISTS: errno.EEXIST,
62 winerror.ERROR_FILE_INVALID: errno.ENODEV,
62 winerror.ERROR_FILE_INVALID: errno.ENODEV,
63 winerror.ERROR_FILE_NOT_FOUND: errno.ENOENT,
63 winerror.ERROR_FILE_NOT_FOUND: errno.ENOENT,
64 winerror.ERROR_GEN_FAILURE: errno.EIO,
64 winerror.ERROR_GEN_FAILURE: errno.EIO,
65 winerror.ERROR_HANDLE_DISK_FULL: errno.ENOSPC,
65 winerror.ERROR_HANDLE_DISK_FULL: errno.ENOSPC,
66 winerror.ERROR_INSUFFICIENT_BUFFER: errno.ENOMEM,
66 winerror.ERROR_INSUFFICIENT_BUFFER: errno.ENOMEM,
67 winerror.ERROR_INVALID_ACCESS: errno.EACCES,
67 winerror.ERROR_INVALID_ACCESS: errno.EACCES,
68 winerror.ERROR_INVALID_ADDRESS: errno.EFAULT,
68 winerror.ERROR_INVALID_ADDRESS: errno.EFAULT,
69 winerror.ERROR_INVALID_BLOCK: errno.EFAULT,
69 winerror.ERROR_INVALID_BLOCK: errno.EFAULT,
70 winerror.ERROR_INVALID_DATA: errno.EINVAL,
70 winerror.ERROR_INVALID_DATA: errno.EINVAL,
71 winerror.ERROR_INVALID_DRIVE: errno.ENODEV,
71 winerror.ERROR_INVALID_DRIVE: errno.ENODEV,
72 winerror.ERROR_INVALID_EXE_SIGNATURE: errno.ENOEXEC,
72 winerror.ERROR_INVALID_EXE_SIGNATURE: errno.ENOEXEC,
73 winerror.ERROR_INVALID_FLAGS: errno.EINVAL,
73 winerror.ERROR_INVALID_FLAGS: errno.EINVAL,
74 winerror.ERROR_INVALID_FUNCTION: errno.ENOSYS,
74 winerror.ERROR_INVALID_FUNCTION: errno.ENOSYS,
75 winerror.ERROR_INVALID_HANDLE: errno.EBADF,
75 winerror.ERROR_INVALID_HANDLE: errno.EBADF,
76 winerror.ERROR_INVALID_LOGON_HOURS: errno.EACCES,
76 winerror.ERROR_INVALID_LOGON_HOURS: errno.EACCES,
77 winerror.ERROR_INVALID_NAME: errno.EINVAL,
77 winerror.ERROR_INVALID_NAME: errno.EINVAL,
78 winerror.ERROR_INVALID_OWNER: errno.EINVAL,
78 winerror.ERROR_INVALID_OWNER: errno.EINVAL,
79 winerror.ERROR_INVALID_PARAMETER: errno.EINVAL,
79 winerror.ERROR_INVALID_PARAMETER: errno.EINVAL,
80 winerror.ERROR_INVALID_PASSWORD: errno.EPERM,
80 winerror.ERROR_INVALID_PASSWORD: errno.EPERM,
81 winerror.ERROR_INVALID_PRIMARY_GROUP: errno.EINVAL,
81 winerror.ERROR_INVALID_PRIMARY_GROUP: errno.EINVAL,
82 winerror.ERROR_INVALID_SIGNAL_NUMBER: errno.EINVAL,
82 winerror.ERROR_INVALID_SIGNAL_NUMBER: errno.EINVAL,
83 winerror.ERROR_INVALID_TARGET_HANDLE: errno.EIO,
83 winerror.ERROR_INVALID_TARGET_HANDLE: errno.EIO,
84 winerror.ERROR_INVALID_WORKSTATION: errno.EACCES,
84 winerror.ERROR_INVALID_WORKSTATION: errno.EACCES,
85 winerror.ERROR_IO_DEVICE: errno.EIO,
85 winerror.ERROR_IO_DEVICE: errno.EIO,
86 winerror.ERROR_IO_INCOMPLETE: errno.EINTR,
86 winerror.ERROR_IO_INCOMPLETE: errno.EINTR,
87 winerror.ERROR_LOCKED: errno.EBUSY,
87 winerror.ERROR_LOCKED: errno.EBUSY,
88 winerror.ERROR_LOCK_VIOLATION: errno.EACCES,
88 winerror.ERROR_LOCK_VIOLATION: errno.EACCES,
89 winerror.ERROR_LOGON_FAILURE: errno.EACCES,
89 winerror.ERROR_LOGON_FAILURE: errno.EACCES,
90 winerror.ERROR_MAPPED_ALIGNMENT: errno.EINVAL,
90 winerror.ERROR_MAPPED_ALIGNMENT: errno.EINVAL,
91 winerror.ERROR_META_EXPANSION_TOO_LONG: errno.E2BIG,
91 winerror.ERROR_META_EXPANSION_TOO_LONG: errno.E2BIG,
92 winerror.ERROR_MORE_DATA: errno.EPIPE,
92 winerror.ERROR_MORE_DATA: errno.EPIPE,
93 winerror.ERROR_NEGATIVE_SEEK: errno.ESPIPE,
93 winerror.ERROR_NEGATIVE_SEEK: errno.ESPIPE,
94 winerror.ERROR_NOACCESS: errno.EFAULT,
94 winerror.ERROR_NOACCESS: errno.EFAULT,
95 winerror.ERROR_NONE_MAPPED: errno.EINVAL,
95 winerror.ERROR_NONE_MAPPED: errno.EINVAL,
96 winerror.ERROR_NOT_ENOUGH_MEMORY: errno.ENOMEM,
96 winerror.ERROR_NOT_ENOUGH_MEMORY: errno.ENOMEM,
97 winerror.ERROR_NOT_READY: errno.EAGAIN,
97 winerror.ERROR_NOT_READY: errno.EAGAIN,
98 winerror.ERROR_NOT_SAME_DEVICE: errno.EXDEV,
98 winerror.ERROR_NOT_SAME_DEVICE: errno.EXDEV,
99 winerror.ERROR_NO_DATA: errno.EPIPE,
99 winerror.ERROR_NO_DATA: errno.EPIPE,
100 winerror.ERROR_NO_MORE_SEARCH_HANDLES: errno.EIO,
100 winerror.ERROR_NO_MORE_SEARCH_HANDLES: errno.EIO,
101 winerror.ERROR_NO_PROC_SLOTS: errno.EAGAIN,
101 winerror.ERROR_NO_PROC_SLOTS: errno.EAGAIN,
102 winerror.ERROR_NO_SUCH_PRIVILEGE: errno.EACCES,
102 winerror.ERROR_NO_SUCH_PRIVILEGE: errno.EACCES,
103 winerror.ERROR_OPEN_FAILED: errno.EIO,
103 winerror.ERROR_OPEN_FAILED: errno.EIO,
104 winerror.ERROR_OPEN_FILES: errno.EBUSY,
104 winerror.ERROR_OPEN_FILES: errno.EBUSY,
105 winerror.ERROR_OPERATION_ABORTED: errno.EINTR,
105 winerror.ERROR_OPERATION_ABORTED: errno.EINTR,
106 winerror.ERROR_OUTOFMEMORY: errno.ENOMEM,
106 winerror.ERROR_OUTOFMEMORY: errno.ENOMEM,
107 winerror.ERROR_PASSWORD_EXPIRED: errno.EACCES,
107 winerror.ERROR_PASSWORD_EXPIRED: errno.EACCES,
108 winerror.ERROR_PATH_BUSY: errno.EBUSY,
108 winerror.ERROR_PATH_BUSY: errno.EBUSY,
109 winerror.ERROR_PATH_NOT_FOUND: errno.ENOENT,
109 winerror.ERROR_PATH_NOT_FOUND: errno.ENOENT,
110 winerror.ERROR_PIPE_BUSY: errno.EBUSY,
110 winerror.ERROR_PIPE_BUSY: errno.EBUSY,
111 winerror.ERROR_PIPE_CONNECTED: errno.EPIPE,
111 winerror.ERROR_PIPE_CONNECTED: errno.EPIPE,
112 winerror.ERROR_PIPE_LISTENING: errno.EPIPE,
112 winerror.ERROR_PIPE_LISTENING: errno.EPIPE,
113 winerror.ERROR_PIPE_NOT_CONNECTED: errno.EPIPE,
113 winerror.ERROR_PIPE_NOT_CONNECTED: errno.EPIPE,
114 winerror.ERROR_PRIVILEGE_NOT_HELD: errno.EACCES,
114 winerror.ERROR_PRIVILEGE_NOT_HELD: errno.EACCES,
115 winerror.ERROR_READ_FAULT: errno.EIO,
115 winerror.ERROR_READ_FAULT: errno.EIO,
116 winerror.ERROR_SEEK: errno.EIO,
116 winerror.ERROR_SEEK: errno.EIO,
117 winerror.ERROR_SEEK_ON_DEVICE: errno.ESPIPE,
117 winerror.ERROR_SEEK_ON_DEVICE: errno.ESPIPE,
118 winerror.ERROR_SHARING_BUFFER_EXCEEDED: errno.ENFILE,
118 winerror.ERROR_SHARING_BUFFER_EXCEEDED: errno.ENFILE,
119 winerror.ERROR_SHARING_VIOLATION: errno.EACCES,
119 winerror.ERROR_SHARING_VIOLATION: errno.EACCES,
120 winerror.ERROR_STACK_OVERFLOW: errno.ENOMEM,
120 winerror.ERROR_STACK_OVERFLOW: errno.ENOMEM,
121 winerror.ERROR_SWAPERROR: errno.ENOENT,
121 winerror.ERROR_SWAPERROR: errno.ENOENT,
122 winerror.ERROR_TOO_MANY_MODULES: errno.EMFILE,
122 winerror.ERROR_TOO_MANY_MODULES: errno.EMFILE,
123 winerror.ERROR_TOO_MANY_OPEN_FILES: errno.EMFILE,
123 winerror.ERROR_TOO_MANY_OPEN_FILES: errno.EMFILE,
124 winerror.ERROR_UNRECOGNIZED_MEDIA: errno.ENXIO,
124 winerror.ERROR_UNRECOGNIZED_MEDIA: errno.ENXIO,
125 winerror.ERROR_UNRECOGNIZED_VOLUME: errno.ENODEV,
125 winerror.ERROR_UNRECOGNIZED_VOLUME: errno.ENODEV,
126 winerror.ERROR_WAIT_NO_CHILDREN: errno.ECHILD,
126 winerror.ERROR_WAIT_NO_CHILDREN: errno.ECHILD,
127 winerror.ERROR_WRITE_FAULT: errno.EIO,
127 winerror.ERROR_WRITE_FAULT: errno.EIO,
128 winerror.ERROR_WRITE_PROTECT: errno.EROFS,
128 winerror.ERROR_WRITE_PROTECT: errno.EROFS,
129 }
129 }
130
130
131 def __init__(self, err):
131 def __init__(self, err):
132 self.win_errno, self.win_function, self.win_strerror = err
132 self.win_errno, self.win_function, self.win_strerror = err
133 if self.win_strerror.endswith('.'):
133 if self.win_strerror.endswith('.'):
134 self.win_strerror = self.win_strerror[:-1]
134 self.win_strerror = self.win_strerror[:-1]
135
135
136 class WinIOError(WinError, IOError):
136 class WinIOError(WinError, IOError):
137 def __init__(self, err, filename=None):
137 def __init__(self, err, filename=None):
138 WinError.__init__(self, err)
138 WinError.__init__(self, err)
139 IOError.__init__(self, self.winerror_map.get(self.win_errno, 0),
139 IOError.__init__(self, self.winerror_map.get(self.win_errno, 0),
140 self.win_strerror)
140 self.win_strerror)
141 self.filename = filename
141 self.filename = filename
142
142
143 class WinOSError(WinError, OSError):
143 class WinOSError(WinError, OSError):
144 def __init__(self, err):
144 def __init__(self, err):
145 WinError.__init__(self, err)
145 WinError.__init__(self, err)
146 OSError.__init__(self, self.winerror_map.get(self.win_errno, 0),
146 OSError.__init__(self, self.winerror_map.get(self.win_errno, 0),
147 self.win_strerror)
147 self.win_strerror)
148
148
149 def os_link(src, dst):
149 def os_link(src, dst):
150 # NB will only succeed on NTFS
150 # NB will only succeed on NTFS
151 try:
151 try:
152 win32file.CreateHardLink(dst, src)
152 win32file.CreateHardLink(dst, src)
153 except pywintypes.error, details:
153 except pywintypes.error, details:
154 raise WinOSError(details)
154 raise WinOSError(details)
155
155
156 def nlinks(pathname):
156 def nlinks(pathname):
157 """Return number of hardlinks for the given file."""
157 """Return number of hardlinks for the given file."""
158 try:
158 try:
159 fh = win32file.CreateFile(pathname,
159 fh = win32file.CreateFile(pathname,
160 win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
160 win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
161 None, win32file.OPEN_EXISTING, 0, None)
161 None, win32file.OPEN_EXISTING, 0, None)
162 res = win32file.GetFileInformationByHandle(fh)
162 res = win32file.GetFileInformationByHandle(fh)
163 fh.Close()
163 fh.Close()
164 return res[7]
164 return res[7]
165 except pywintypes.error:
165 except pywintypes.error:
166 return os.lstat(pathname).st_nlink
166 return os.lstat(pathname).st_nlink
167
167
168 def testpid(pid):
168 def testpid(pid):
169 '''return True if pid is still running or unable to
169 '''return True if pid is still running or unable to
170 determine, False otherwise'''
170 determine, False otherwise'''
171 try:
171 try:
172 handle = win32api.OpenProcess(
172 handle = win32api.OpenProcess(
173 win32con.PROCESS_QUERY_INFORMATION, False, pid)
173 win32con.PROCESS_QUERY_INFORMATION, False, pid)
174 if handle:
174 if handle:
175 status = win32process.GetExitCodeProcess(handle)
175 status = win32process.GetExitCodeProcess(handle)
176 return status == win32con.STILL_ACTIVE
176 return status == win32con.STILL_ACTIVE
177 except pywintypes.error, details:
177 except pywintypes.error, details:
178 return details[0] != winerror.ERROR_INVALID_PARAMETER
178 return details[0] != winerror.ERROR_INVALID_PARAMETER
179 return True
179 return True
180
180
181 def system_rcpath_win32():
181 def system_rcpath_win32():
182 '''return default os-specific hgrc search path'''
182 '''return default os-specific hgrc search path'''
183 try:
183 try:
184 value = win32api.RegQueryValue(
184 value = win32api.RegQueryValue(
185 win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Mercurial')
185 win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Mercurial')
186 rcpath = []
186 rcpath = []
187 for p in value.split(os.pathsep):
187 for p in value.split(os.pathsep):
188 if p.lower().endswith('mercurial.ini'):
188 if p.lower().endswith('mercurial.ini'):
189 rcpath.append(p)
189 rcpath.append(p)
190 elif os.path.isdir(p):
190 elif os.path.isdir(p):
191 for f, kind in osutil.listdir(p):
191 for f, kind in osutil.listdir(p):
192 if f.endswith('.rc'):
192 if f.endswith('.rc'):
193 rcpath.append(os.path.join(p, f))
193 rcpath.append(os.path.join(p, f))
194 return rcpath
194 return rcpath
195 except pywintypes.error:
195 except pywintypes.error:
196 pass
196 pass
197 proc = win32api.GetCurrentProcess()
197 proc = win32api.GetCurrentProcess()
198 try:
198 try:
199 # This will fail on windows < NT
199 # This will fail on windows < NT
200 filename = win32process.GetModuleFileNameEx(proc, 0)
200 filename = win32process.GetModuleFileNameEx(proc, 0)
201 except:
201 except:
202 filename = win32api.GetModuleFileName(0)
202 filename = win32api.GetModuleFileName(0)
203 return [os.path.join(os.path.dirname(filename), 'mercurial.ini')]
203 return [os.path.join(os.path.dirname(filename), 'mercurial.ini')]
204
204
205 def user_rcpath_win32():
205 def user_rcpath_win32():
206 '''return os-specific hgrc search path to the user dir'''
206 '''return os-specific hgrc search path to the user dir'''
207 userdir = os.path.expanduser('~')
207 userdir = os.path.expanduser('~')
208 if userdir == '~':
208 if sys.getwindowsversion() != 2 and userdir == '~':
209 # We are on win < nt: fetch the APPDATA directory location and use
209 # We are on win < nt: fetch the APPDATA directory location and use
210 # the parent directory as the user home dir.
210 # the parent directory as the user home dir.
211 appdir = shell.SHGetPathFromIDList(
211 appdir = shell.SHGetPathFromIDList(
212 shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
212 shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
213 userdir = os.path.dirname(appdir)
213 userdir = os.path.dirname(appdir)
214 return os.path.join(userdir, 'mercurial.ini')
214 return os.path.join(userdir, 'mercurial.ini')
215
215
216 class posixfile_nt(object):
216 class posixfile_nt(object):
217 '''file object with posix-like semantics. on windows, normal
217 '''file object with posix-like semantics. on windows, normal
218 files can not be deleted or renamed if they are open. must open
218 files can not be deleted or renamed if they are open. must open
219 with win32file.FILE_SHARE_DELETE. this flag does not exist on
219 with win32file.FILE_SHARE_DELETE. this flag does not exist on
220 windows < nt, so do not use this class there.'''
220 windows < nt, so do not use this class there.'''
221
221
222 # tried to use win32file._open_osfhandle to pass fd to os.fdopen,
222 # tried to use win32file._open_osfhandle to pass fd to os.fdopen,
223 # but does not work at all. wrap win32 file api instead.
223 # but does not work at all. wrap win32 file api instead.
224
224
225 def __init__(self, name, mode='rb'):
225 def __init__(self, name, mode='rb'):
226 access = 0
226 access = 0
227 if 'r' in mode or '+' in mode:
227 if 'r' in mode or '+' in mode:
228 access |= win32file.GENERIC_READ
228 access |= win32file.GENERIC_READ
229 if 'w' in mode or 'a' in mode or '+' in mode:
229 if 'w' in mode or 'a' in mode or '+' in mode:
230 access |= win32file.GENERIC_WRITE
230 access |= win32file.GENERIC_WRITE
231 if 'r' in mode:
231 if 'r' in mode:
232 creation = win32file.OPEN_EXISTING
232 creation = win32file.OPEN_EXISTING
233 elif 'a' in mode:
233 elif 'a' in mode:
234 creation = win32file.OPEN_ALWAYS
234 creation = win32file.OPEN_ALWAYS
235 else:
235 else:
236 creation = win32file.CREATE_ALWAYS
236 creation = win32file.CREATE_ALWAYS
237 try:
237 try:
238 self.handle = win32file.CreateFile(name,
238 self.handle = win32file.CreateFile(name,
239 access,
239 access,
240 win32file.FILE_SHARE_READ |
240 win32file.FILE_SHARE_READ |
241 win32file.FILE_SHARE_WRITE |
241 win32file.FILE_SHARE_WRITE |
242 win32file.FILE_SHARE_DELETE,
242 win32file.FILE_SHARE_DELETE,
243 None,
243 None,
244 creation,
244 creation,
245 win32file.FILE_ATTRIBUTE_NORMAL,
245 win32file.FILE_ATTRIBUTE_NORMAL,
246 0)
246 0)
247 except pywintypes.error, err:
247 except pywintypes.error, err:
248 raise WinIOError(err, name)
248 raise WinIOError(err, name)
249 self.closed = False
249 self.closed = False
250 self.name = name
250 self.name = name
251 self.mode = mode
251 self.mode = mode
252
252
253 def __iter__(self):
253 def __iter__(self):
254 for line in self.read().splitlines(True):
254 for line in self.read().splitlines(True):
255 yield line
255 yield line
256
256
257 def read(self, count=-1):
257 def read(self, count=-1):
258 try:
258 try:
259 cs = cStringIO.StringIO()
259 cs = cStringIO.StringIO()
260 while count:
260 while count:
261 wincount = int(count)
261 wincount = int(count)
262 if wincount == -1:
262 if wincount == -1:
263 wincount = 1048576
263 wincount = 1048576
264 val, data = win32file.ReadFile(self.handle, wincount)
264 val, data = win32file.ReadFile(self.handle, wincount)
265 if not data: break
265 if not data: break
266 cs.write(data)
266 cs.write(data)
267 if count != -1:
267 if count != -1:
268 count -= len(data)
268 count -= len(data)
269 return cs.getvalue()
269 return cs.getvalue()
270 except pywintypes.error, err:
270 except pywintypes.error, err:
271 raise WinIOError(err)
271 raise WinIOError(err)
272
272
273 def write(self, data):
273 def write(self, data):
274 try:
274 try:
275 if 'a' in self.mode:
275 if 'a' in self.mode:
276 win32file.SetFilePointer(self.handle, 0, win32file.FILE_END)
276 win32file.SetFilePointer(self.handle, 0, win32file.FILE_END)
277 nwrit = 0
277 nwrit = 0
278 while nwrit < len(data):
278 while nwrit < len(data):
279 val, nwrit = win32file.WriteFile(self.handle, data)
279 val, nwrit = win32file.WriteFile(self.handle, data)
280 data = data[nwrit:]
280 data = data[nwrit:]
281 except pywintypes.error, err:
281 except pywintypes.error, err:
282 raise WinIOError(err)
282 raise WinIOError(err)
283
283
284 def seek(self, pos, whence=0):
284 def seek(self, pos, whence=0):
285 try:
285 try:
286 win32file.SetFilePointer(self.handle, int(pos), whence)
286 win32file.SetFilePointer(self.handle, int(pos), whence)
287 except pywintypes.error, err:
287 except pywintypes.error, err:
288 raise WinIOError(err)
288 raise WinIOError(err)
289
289
290 def tell(self):
290 def tell(self):
291 try:
291 try:
292 return win32file.SetFilePointer(self.handle, 0,
292 return win32file.SetFilePointer(self.handle, 0,
293 win32file.FILE_CURRENT)
293 win32file.FILE_CURRENT)
294 except pywintypes.error, err:
294 except pywintypes.error, err:
295 raise WinIOError(err)
295 raise WinIOError(err)
296
296
297 def close(self):
297 def close(self):
298 if not self.closed:
298 if not self.closed:
299 self.handle = None
299 self.handle = None
300 self.closed = True
300 self.closed = True
301
301
302 def flush(self):
302 def flush(self):
303 try:
303 try:
304 win32file.FlushFileBuffers(self.handle)
304 win32file.FlushFileBuffers(self.handle)
305 except pywintypes.error, err:
305 except pywintypes.error, err:
306 raise WinIOError(err)
306 raise WinIOError(err)
307
307
308 def truncate(self, pos=0):
308 def truncate(self, pos=0):
309 try:
309 try:
310 win32file.SetFilePointer(self.handle, int(pos),
310 win32file.SetFilePointer(self.handle, int(pos),
311 win32file.FILE_BEGIN)
311 win32file.FILE_BEGIN)
312 win32file.SetEndOfFile(self.handle)
312 win32file.SetEndOfFile(self.handle)
313 except pywintypes.error, err:
313 except pywintypes.error, err:
314 raise WinIOError(err)
314 raise WinIOError(err)
315
315
316 getuser_fallback = win32api.GetUserName
316 getuser_fallback = win32api.GetUserName
317
317
318 def set_signal_handler_win32():
318 def set_signal_handler_win32():
319 """Register a termination handler for console events including
319 """Register a termination handler for console events including
320 CTRL+C. python signal handlers do not work well with socket
320 CTRL+C. python signal handlers do not work well with socket
321 operations.
321 operations.
322 """
322 """
323 def handler(event):
323 def handler(event):
324 win32process.ExitProcess(1)
324 win32process.ExitProcess(1)
325 win32api.SetConsoleCtrlHandler(handler)
325 win32api.SetConsoleCtrlHandler(handler)
General Comments 0
You need to be logged in to leave comments. Login now