##// END OF EJS Templates
win32: favor local mercurial.ini over registry key...
Steve Borho -
r5619:55d3e845 default
parent child Browse files
Show More
@@ -1,325 +1,329 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 proc = win32api.GetCurrentProcess()
184 try:
185 # This will fail on windows < NT
186 filename = win32process.GetModuleFileNameEx(proc, 0)
187 except:
188 filename = win32api.GetModuleFileName(0)
189 # Use mercurial.ini found in directory with hg.exe
190 progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
191 if os.path.isfile(progrc):
192 return [progrc]
193 # else look for a system rcpath in the registry
183 try:
194 try:
184 value = win32api.RegQueryValue(
195 value = win32api.RegQueryValue(
185 win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Mercurial')
196 win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Mercurial')
186 rcpath = []
197 rcpath = []
187 for p in value.split(os.pathsep):
198 for p in value.split(os.pathsep):
188 if p.lower().endswith('mercurial.ini'):
199 if p.lower().endswith('mercurial.ini'):
189 rcpath.append(p)
200 rcpath.append(p)
190 elif os.path.isdir(p):
201 elif os.path.isdir(p):
191 for f, kind in osutil.listdir(p):
202 for f, kind in osutil.listdir(p):
192 if f.endswith('.rc'):
203 if f.endswith('.rc'):
193 rcpath.append(os.path.join(p, f))
204 rcpath.append(os.path.join(p, f))
194 return rcpath
205 return rcpath
195 except pywintypes.error:
206 except pywintypes.error:
196 pass
207 return []
197 proc = win32api.GetCurrentProcess()
198 try:
199 # This will fail on windows < NT
200 filename = win32process.GetModuleFileNameEx(proc, 0)
201 except:
202 filename = win32api.GetModuleFileName(0)
203 return [os.path.join(os.path.dirname(filename), 'mercurial.ini')]
204
208
205 def user_rcpath_win32():
209 def user_rcpath_win32():
206 '''return os-specific hgrc search path to the user dir'''
210 '''return os-specific hgrc search path to the user dir'''
207 userdir = os.path.expanduser('~')
211 userdir = os.path.expanduser('~')
208 if sys.getwindowsversion() != 2 and userdir == '~':
212 if sys.getwindowsversion() != 2 and userdir == '~':
209 # We are on win < nt: fetch the APPDATA directory location and use
213 # We are on win < nt: fetch the APPDATA directory location and use
210 # the parent directory as the user home dir.
214 # the parent directory as the user home dir.
211 appdir = shell.SHGetPathFromIDList(
215 appdir = shell.SHGetPathFromIDList(
212 shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
216 shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
213 userdir = os.path.dirname(appdir)
217 userdir = os.path.dirname(appdir)
214 return os.path.join(userdir, 'mercurial.ini')
218 return os.path.join(userdir, 'mercurial.ini')
215
219
216 class posixfile_nt(object):
220 class posixfile_nt(object):
217 '''file object with posix-like semantics. on windows, normal
221 '''file object with posix-like semantics. on windows, normal
218 files can not be deleted or renamed if they are open. must open
222 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
223 with win32file.FILE_SHARE_DELETE. this flag does not exist on
220 windows < nt, so do not use this class there.'''
224 windows < nt, so do not use this class there.'''
221
225
222 # tried to use win32file._open_osfhandle to pass fd to os.fdopen,
226 # tried to use win32file._open_osfhandle to pass fd to os.fdopen,
223 # but does not work at all. wrap win32 file api instead.
227 # but does not work at all. wrap win32 file api instead.
224
228
225 def __init__(self, name, mode='rb'):
229 def __init__(self, name, mode='rb'):
226 access = 0
230 access = 0
227 if 'r' in mode or '+' in mode:
231 if 'r' in mode or '+' in mode:
228 access |= win32file.GENERIC_READ
232 access |= win32file.GENERIC_READ
229 if 'w' in mode or 'a' in mode or '+' in mode:
233 if 'w' in mode or 'a' in mode or '+' in mode:
230 access |= win32file.GENERIC_WRITE
234 access |= win32file.GENERIC_WRITE
231 if 'r' in mode:
235 if 'r' in mode:
232 creation = win32file.OPEN_EXISTING
236 creation = win32file.OPEN_EXISTING
233 elif 'a' in mode:
237 elif 'a' in mode:
234 creation = win32file.OPEN_ALWAYS
238 creation = win32file.OPEN_ALWAYS
235 else:
239 else:
236 creation = win32file.CREATE_ALWAYS
240 creation = win32file.CREATE_ALWAYS
237 try:
241 try:
238 self.handle = win32file.CreateFile(name,
242 self.handle = win32file.CreateFile(name,
239 access,
243 access,
240 win32file.FILE_SHARE_READ |
244 win32file.FILE_SHARE_READ |
241 win32file.FILE_SHARE_WRITE |
245 win32file.FILE_SHARE_WRITE |
242 win32file.FILE_SHARE_DELETE,
246 win32file.FILE_SHARE_DELETE,
243 None,
247 None,
244 creation,
248 creation,
245 win32file.FILE_ATTRIBUTE_NORMAL,
249 win32file.FILE_ATTRIBUTE_NORMAL,
246 0)
250 0)
247 except pywintypes.error, err:
251 except pywintypes.error, err:
248 raise WinIOError(err, name)
252 raise WinIOError(err, name)
249 self.closed = False
253 self.closed = False
250 self.name = name
254 self.name = name
251 self.mode = mode
255 self.mode = mode
252
256
253 def __iter__(self):
257 def __iter__(self):
254 for line in self.read().splitlines(True):
258 for line in self.read().splitlines(True):
255 yield line
259 yield line
256
260
257 def read(self, count=-1):
261 def read(self, count=-1):
258 try:
262 try:
259 cs = cStringIO.StringIO()
263 cs = cStringIO.StringIO()
260 while count:
264 while count:
261 wincount = int(count)
265 wincount = int(count)
262 if wincount == -1:
266 if wincount == -1:
263 wincount = 1048576
267 wincount = 1048576
264 val, data = win32file.ReadFile(self.handle, wincount)
268 val, data = win32file.ReadFile(self.handle, wincount)
265 if not data: break
269 if not data: break
266 cs.write(data)
270 cs.write(data)
267 if count != -1:
271 if count != -1:
268 count -= len(data)
272 count -= len(data)
269 return cs.getvalue()
273 return cs.getvalue()
270 except pywintypes.error, err:
274 except pywintypes.error, err:
271 raise WinIOError(err)
275 raise WinIOError(err)
272
276
273 def write(self, data):
277 def write(self, data):
274 try:
278 try:
275 if 'a' in self.mode:
279 if 'a' in self.mode:
276 win32file.SetFilePointer(self.handle, 0, win32file.FILE_END)
280 win32file.SetFilePointer(self.handle, 0, win32file.FILE_END)
277 nwrit = 0
281 nwrit = 0
278 while nwrit < len(data):
282 while nwrit < len(data):
279 val, nwrit = win32file.WriteFile(self.handle, data)
283 val, nwrit = win32file.WriteFile(self.handle, data)
280 data = data[nwrit:]
284 data = data[nwrit:]
281 except pywintypes.error, err:
285 except pywintypes.error, err:
282 raise WinIOError(err)
286 raise WinIOError(err)
283
287
284 def seek(self, pos, whence=0):
288 def seek(self, pos, whence=0):
285 try:
289 try:
286 win32file.SetFilePointer(self.handle, int(pos), whence)
290 win32file.SetFilePointer(self.handle, int(pos), whence)
287 except pywintypes.error, err:
291 except pywintypes.error, err:
288 raise WinIOError(err)
292 raise WinIOError(err)
289
293
290 def tell(self):
294 def tell(self):
291 try:
295 try:
292 return win32file.SetFilePointer(self.handle, 0,
296 return win32file.SetFilePointer(self.handle, 0,
293 win32file.FILE_CURRENT)
297 win32file.FILE_CURRENT)
294 except pywintypes.error, err:
298 except pywintypes.error, err:
295 raise WinIOError(err)
299 raise WinIOError(err)
296
300
297 def close(self):
301 def close(self):
298 if not self.closed:
302 if not self.closed:
299 self.handle = None
303 self.handle = None
300 self.closed = True
304 self.closed = True
301
305
302 def flush(self):
306 def flush(self):
303 try:
307 try:
304 win32file.FlushFileBuffers(self.handle)
308 win32file.FlushFileBuffers(self.handle)
305 except pywintypes.error, err:
309 except pywintypes.error, err:
306 raise WinIOError(err)
310 raise WinIOError(err)
307
311
308 def truncate(self, pos=0):
312 def truncate(self, pos=0):
309 try:
313 try:
310 win32file.SetFilePointer(self.handle, int(pos),
314 win32file.SetFilePointer(self.handle, int(pos),
311 win32file.FILE_BEGIN)
315 win32file.FILE_BEGIN)
312 win32file.SetEndOfFile(self.handle)
316 win32file.SetEndOfFile(self.handle)
313 except pywintypes.error, err:
317 except pywintypes.error, err:
314 raise WinIOError(err)
318 raise WinIOError(err)
315
319
316 getuser_fallback = win32api.GetUserName
320 getuser_fallback = win32api.GetUserName
317
321
318 def set_signal_handler_win32():
322 def set_signal_handler_win32():
319 """Register a termination handler for console events including
323 """Register a termination handler for console events including
320 CTRL+C. python signal handlers do not work well with socket
324 CTRL+C. python signal handlers do not work well with socket
321 operations.
325 operations.
322 """
326 """
323 def handler(event):
327 def handler(event):
324 win32process.ExitProcess(1)
328 win32process.ExitProcess(1)
325 win32api.SetConsoleCtrlHandler(handler)
329 win32api.SetConsoleCtrlHandler(handler)
General Comments 0
You need to be logged in to leave comments. Login now