##// END OF EJS Templates
util_win32: fix Windows version checking (issue1358)...
Patrick Mezard -
r7427:f21e3d0e default
parent child Browse files
Show More
@@ -1,373 +1,373 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 import errno, os, sys, pywintypes, win32con, win32file, win32process
16 import errno, os, sys, pywintypes, win32con, win32file, win32process
17 import cStringIO, winerror
17 import cStringIO, winerror
18 import osutil
18 import osutil
19 import util
19 import util
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 try:
150 try:
151 win32file.CreateHardLink(dst, src)
151 win32file.CreateHardLink(dst, src)
152 # CreateHardLink sometimes succeeds on mapped drives but
152 # CreateHardLink sometimes succeeds on mapped drives but
153 # following nlinks() returns 1. Check it now and bail out.
153 # following nlinks() returns 1. Check it now and bail out.
154 if nlinks(src) < 2:
154 if nlinks(src) < 2:
155 try:
155 try:
156 win32file.DeleteFile(dst)
156 win32file.DeleteFile(dst)
157 except:
157 except:
158 pass
158 pass
159 # Fake hardlinking error
159 # Fake hardlinking error
160 raise WinOSError((18, 'CreateHardLink', 'The system cannot '
160 raise WinOSError((18, 'CreateHardLink', 'The system cannot '
161 'move the file to a different disk drive'))
161 'move the file to a different disk drive'))
162 except pywintypes.error, details:
162 except pywintypes.error, details:
163 raise WinOSError(details)
163 raise WinOSError(details)
164
164
165 def nlinks(pathname):
165 def nlinks(pathname):
166 """Return number of hardlinks for the given file."""
166 """Return number of hardlinks for the given file."""
167 try:
167 try:
168 fh = win32file.CreateFile(pathname,
168 fh = win32file.CreateFile(pathname,
169 win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
169 win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
170 None, win32file.OPEN_EXISTING, 0, None)
170 None, win32file.OPEN_EXISTING, 0, None)
171 res = win32file.GetFileInformationByHandle(fh)
171 res = win32file.GetFileInformationByHandle(fh)
172 fh.Close()
172 fh.Close()
173 return res[7]
173 return res[7]
174 except pywintypes.error:
174 except pywintypes.error:
175 return os.lstat(pathname).st_nlink
175 return os.lstat(pathname).st_nlink
176
176
177 def testpid(pid):
177 def testpid(pid):
178 '''return True if pid is still running or unable to
178 '''return True if pid is still running or unable to
179 determine, False otherwise'''
179 determine, False otherwise'''
180 try:
180 try:
181 handle = win32api.OpenProcess(
181 handle = win32api.OpenProcess(
182 win32con.PROCESS_QUERY_INFORMATION, False, pid)
182 win32con.PROCESS_QUERY_INFORMATION, False, pid)
183 if handle:
183 if handle:
184 status = win32process.GetExitCodeProcess(handle)
184 status = win32process.GetExitCodeProcess(handle)
185 return status == win32con.STILL_ACTIVE
185 return status == win32con.STILL_ACTIVE
186 except pywintypes.error, details:
186 except pywintypes.error, details:
187 return details[0] != winerror.ERROR_INVALID_PARAMETER
187 return details[0] != winerror.ERROR_INVALID_PARAMETER
188 return True
188 return True
189
189
190 def lookup_reg(key, valname=None, scope=None):
190 def lookup_reg(key, valname=None, scope=None):
191 ''' Look up a key/value name in the Windows registry.
191 ''' Look up a key/value name in the Windows registry.
192
192
193 valname: value name. If unspecified, the default value for the key
193 valname: value name. If unspecified, the default value for the key
194 is used.
194 is used.
195 scope: optionally specify scope for registry lookup, this can be
195 scope: optionally specify scope for registry lookup, this can be
196 a sequence of scopes to look up in order. Default (CURRENT_USER,
196 a sequence of scopes to look up in order. Default (CURRENT_USER,
197 LOCAL_MACHINE).
197 LOCAL_MACHINE).
198 '''
198 '''
199 try:
199 try:
200 from _winreg import HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, \
200 from _winreg import HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, \
201 QueryValueEx, OpenKey
201 QueryValueEx, OpenKey
202 except ImportError:
202 except ImportError:
203 return None
203 return None
204
204
205 if scope is None:
205 if scope is None:
206 scope = (HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE)
206 scope = (HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE)
207 elif not isinstance(scope, (list, tuple)):
207 elif not isinstance(scope, (list, tuple)):
208 scope = (scope,)
208 scope = (scope,)
209 for s in scope:
209 for s in scope:
210 try:
210 try:
211 val = QueryValueEx(OpenKey(s, key), valname)[0]
211 val = QueryValueEx(OpenKey(s, key), valname)[0]
212 # never let a Unicode string escape into the wild
212 # never let a Unicode string escape into the wild
213 return util.tolocal(val.encode('UTF-8'))
213 return util.tolocal(val.encode('UTF-8'))
214 except EnvironmentError:
214 except EnvironmentError:
215 pass
215 pass
216
216
217 def system_rcpath_win32():
217 def system_rcpath_win32():
218 '''return default os-specific hgrc search path'''
218 '''return default os-specific hgrc search path'''
219 proc = win32api.GetCurrentProcess()
219 proc = win32api.GetCurrentProcess()
220 try:
220 try:
221 # This will fail on windows < NT
221 # This will fail on windows < NT
222 filename = win32process.GetModuleFileNameEx(proc, 0)
222 filename = win32process.GetModuleFileNameEx(proc, 0)
223 except:
223 except:
224 filename = win32api.GetModuleFileName(0)
224 filename = win32api.GetModuleFileName(0)
225 # Use mercurial.ini found in directory with hg.exe
225 # Use mercurial.ini found in directory with hg.exe
226 progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
226 progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
227 if os.path.isfile(progrc):
227 if os.path.isfile(progrc):
228 return [progrc]
228 return [progrc]
229 # else look for a system rcpath in the registry
229 # else look for a system rcpath in the registry
230 try:
230 try:
231 value = win32api.RegQueryValue(
231 value = win32api.RegQueryValue(
232 win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Mercurial')
232 win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Mercurial')
233 rcpath = []
233 rcpath = []
234 for p in value.split(os.pathsep):
234 for p in value.split(os.pathsep):
235 if p.lower().endswith('mercurial.ini'):
235 if p.lower().endswith('mercurial.ini'):
236 rcpath.append(p)
236 rcpath.append(p)
237 elif os.path.isdir(p):
237 elif os.path.isdir(p):
238 for f, kind in osutil.listdir(p):
238 for f, kind in osutil.listdir(p):
239 if f.endswith('.rc'):
239 if f.endswith('.rc'):
240 rcpath.append(os.path.join(p, f))
240 rcpath.append(os.path.join(p, f))
241 return rcpath
241 return rcpath
242 except pywintypes.error:
242 except pywintypes.error:
243 return []
243 return []
244
244
245 def user_rcpath_win32():
245 def user_rcpath_win32():
246 '''return os-specific hgrc search path to the user dir'''
246 '''return os-specific hgrc search path to the user dir'''
247 userdir = os.path.expanduser('~')
247 userdir = os.path.expanduser('~')
248 if sys.getwindowsversion() != 2 and userdir == '~':
248 if sys.getwindowsversion()[3] != 2 and userdir == '~':
249 # We are on win < nt: fetch the APPDATA directory location and use
249 # We are on win < nt: fetch the APPDATA directory location and use
250 # the parent directory as the user home dir.
250 # the parent directory as the user home dir.
251 appdir = shell.SHGetPathFromIDList(
251 appdir = shell.SHGetPathFromIDList(
252 shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
252 shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
253 userdir = os.path.dirname(appdir)
253 userdir = os.path.dirname(appdir)
254 return [os.path.join(userdir, 'mercurial.ini'),
254 return [os.path.join(userdir, 'mercurial.ini'),
255 os.path.join(userdir, '.hgrc')]
255 os.path.join(userdir, '.hgrc')]
256
256
257 class posixfile_nt(object):
257 class posixfile_nt(object):
258 '''file object with posix-like semantics. on windows, normal
258 '''file object with posix-like semantics. on windows, normal
259 files can not be deleted or renamed if they are open. must open
259 files can not be deleted or renamed if they are open. must open
260 with win32file.FILE_SHARE_DELETE. this flag does not exist on
260 with win32file.FILE_SHARE_DELETE. this flag does not exist on
261 windows < nt, so do not use this class there.'''
261 windows < nt, so do not use this class there.'''
262
262
263 # tried to use win32file._open_osfhandle to pass fd to os.fdopen,
263 # tried to use win32file._open_osfhandle to pass fd to os.fdopen,
264 # but does not work at all. wrap win32 file api instead.
264 # but does not work at all. wrap win32 file api instead.
265
265
266 def __init__(self, name, mode='rb'):
266 def __init__(self, name, mode='rb'):
267 self.closed = False
267 self.closed = False
268 self.name = name
268 self.name = name
269 self.mode = mode
269 self.mode = mode
270 access = 0
270 access = 0
271 if 'r' in mode or '+' in mode:
271 if 'r' in mode or '+' in mode:
272 access |= win32file.GENERIC_READ
272 access |= win32file.GENERIC_READ
273 if 'w' in mode or 'a' in mode or '+' in mode:
273 if 'w' in mode or 'a' in mode or '+' in mode:
274 access |= win32file.GENERIC_WRITE
274 access |= win32file.GENERIC_WRITE
275 if 'r' in mode:
275 if 'r' in mode:
276 creation = win32file.OPEN_EXISTING
276 creation = win32file.OPEN_EXISTING
277 elif 'a' in mode:
277 elif 'a' in mode:
278 creation = win32file.OPEN_ALWAYS
278 creation = win32file.OPEN_ALWAYS
279 else:
279 else:
280 creation = win32file.CREATE_ALWAYS
280 creation = win32file.CREATE_ALWAYS
281 try:
281 try:
282 self.handle = win32file.CreateFile(name,
282 self.handle = win32file.CreateFile(name,
283 access,
283 access,
284 win32file.FILE_SHARE_READ |
284 win32file.FILE_SHARE_READ |
285 win32file.FILE_SHARE_WRITE |
285 win32file.FILE_SHARE_WRITE |
286 win32file.FILE_SHARE_DELETE,
286 win32file.FILE_SHARE_DELETE,
287 None,
287 None,
288 creation,
288 creation,
289 win32file.FILE_ATTRIBUTE_NORMAL,
289 win32file.FILE_ATTRIBUTE_NORMAL,
290 0)
290 0)
291 except pywintypes.error, err:
291 except pywintypes.error, err:
292 raise WinIOError(err, name)
292 raise WinIOError(err, name)
293
293
294 def __iter__(self):
294 def __iter__(self):
295 for line in self.readlines():
295 for line in self.readlines():
296 yield line
296 yield line
297
297
298 def read(self, count=-1):
298 def read(self, count=-1):
299 try:
299 try:
300 cs = cStringIO.StringIO()
300 cs = cStringIO.StringIO()
301 while count:
301 while count:
302 wincount = int(count)
302 wincount = int(count)
303 if wincount == -1:
303 if wincount == -1:
304 wincount = 1048576
304 wincount = 1048576
305 val, data = win32file.ReadFile(self.handle, wincount)
305 val, data = win32file.ReadFile(self.handle, wincount)
306 if not data: break
306 if not data: break
307 cs.write(data)
307 cs.write(data)
308 if count != -1:
308 if count != -1:
309 count -= len(data)
309 count -= len(data)
310 return cs.getvalue()
310 return cs.getvalue()
311 except pywintypes.error, err:
311 except pywintypes.error, err:
312 raise WinIOError(err)
312 raise WinIOError(err)
313
313
314 def readlines(self, sizehint=None):
314 def readlines(self, sizehint=None):
315 # splitlines() splits on single '\r' while readlines()
315 # splitlines() splits on single '\r' while readlines()
316 # does not. cStringIO has a well behaving readlines() and is fast.
316 # does not. cStringIO has a well behaving readlines() and is fast.
317 return cStringIO.StringIO(self.read()).readlines()
317 return cStringIO.StringIO(self.read()).readlines()
318
318
319 def write(self, data):
319 def write(self, data):
320 try:
320 try:
321 if 'a' in self.mode:
321 if 'a' in self.mode:
322 win32file.SetFilePointer(self.handle, 0, win32file.FILE_END)
322 win32file.SetFilePointer(self.handle, 0, win32file.FILE_END)
323 nwrit = 0
323 nwrit = 0
324 while nwrit < len(data):
324 while nwrit < len(data):
325 val, nwrit = win32file.WriteFile(self.handle, data)
325 val, nwrit = win32file.WriteFile(self.handle, data)
326 data = data[nwrit:]
326 data = data[nwrit:]
327 except pywintypes.error, err:
327 except pywintypes.error, err:
328 raise WinIOError(err)
328 raise WinIOError(err)
329
329
330 def writelines(self, sequence):
330 def writelines(self, sequence):
331 for s in sequence:
331 for s in sequence:
332 self.write(s)
332 self.write(s)
333
333
334 def seek(self, pos, whence=0):
334 def seek(self, pos, whence=0):
335 try:
335 try:
336 win32file.SetFilePointer(self.handle, int(pos), whence)
336 win32file.SetFilePointer(self.handle, int(pos), whence)
337 except pywintypes.error, err:
337 except pywintypes.error, err:
338 raise WinIOError(err)
338 raise WinIOError(err)
339
339
340 def tell(self):
340 def tell(self):
341 try:
341 try:
342 return win32file.SetFilePointer(self.handle, 0,
342 return win32file.SetFilePointer(self.handle, 0,
343 win32file.FILE_CURRENT)
343 win32file.FILE_CURRENT)
344 except pywintypes.error, err:
344 except pywintypes.error, err:
345 raise WinIOError(err)
345 raise WinIOError(err)
346
346
347 def close(self):
347 def close(self):
348 if not self.closed:
348 if not self.closed:
349 self.handle = None
349 self.handle = None
350 self.closed = True
350 self.closed = True
351
351
352 def flush(self):
352 def flush(self):
353 # we have no application-level buffering
353 # we have no application-level buffering
354 pass
354 pass
355
355
356 def truncate(self, pos=0):
356 def truncate(self, pos=0):
357 try:
357 try:
358 win32file.SetFilePointer(self.handle, int(pos),
358 win32file.SetFilePointer(self.handle, int(pos),
359 win32file.FILE_BEGIN)
359 win32file.FILE_BEGIN)
360 win32file.SetEndOfFile(self.handle)
360 win32file.SetEndOfFile(self.handle)
361 except pywintypes.error, err:
361 except pywintypes.error, err:
362 raise WinIOError(err)
362 raise WinIOError(err)
363
363
364 getuser_fallback = win32api.GetUserName
364 getuser_fallback = win32api.GetUserName
365
365
366 def set_signal_handler_win32():
366 def set_signal_handler_win32():
367 """Register a termination handler for console events including
367 """Register a termination handler for console events including
368 CTRL+C. python signal handlers do not work well with socket
368 CTRL+C. python signal handlers do not work well with socket
369 operations.
369 operations.
370 """
370 """
371 def handler(event):
371 def handler(event):
372 win32process.ExitProcess(1)
372 win32process.ExitProcess(1)
373 win32api.SetConsoleCtrlHandler(handler)
373 win32api.SetConsoleCtrlHandler(handler)
General Comments 0
You need to be logged in to leave comments. Login now