##// END OF EJS Templates
py3: use pycompat.getcwd instead of os.getcwd
Pulkit Goyal -
r30667:5861bdbe default
parent child Browse files
Show More
@@ -1,505 +1,508
1 # win32.py - utility functions that use win32 API
1 # win32.py - utility functions that use win32 API
2 #
2 #
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import ctypes
10 import ctypes
11 import errno
11 import errno
12 import msvcrt
12 import msvcrt
13 import os
13 import os
14 import random
14 import random
15 import subprocess
15 import subprocess
16
16
17 from . import encoding
17 from . import (
18 encoding,
19 pycompat,
20 )
18
21
19 _kernel32 = ctypes.windll.kernel32
22 _kernel32 = ctypes.windll.kernel32
20 _advapi32 = ctypes.windll.advapi32
23 _advapi32 = ctypes.windll.advapi32
21 _user32 = ctypes.windll.user32
24 _user32 = ctypes.windll.user32
22
25
23 _BOOL = ctypes.c_long
26 _BOOL = ctypes.c_long
24 _WORD = ctypes.c_ushort
27 _WORD = ctypes.c_ushort
25 _DWORD = ctypes.c_ulong
28 _DWORD = ctypes.c_ulong
26 _UINT = ctypes.c_uint
29 _UINT = ctypes.c_uint
27 _LONG = ctypes.c_long
30 _LONG = ctypes.c_long
28 _LPCSTR = _LPSTR = ctypes.c_char_p
31 _LPCSTR = _LPSTR = ctypes.c_char_p
29 _HANDLE = ctypes.c_void_p
32 _HANDLE = ctypes.c_void_p
30 _HWND = _HANDLE
33 _HWND = _HANDLE
31
34
32 _INVALID_HANDLE_VALUE = _HANDLE(-1).value
35 _INVALID_HANDLE_VALUE = _HANDLE(-1).value
33
36
34 # GetLastError
37 # GetLastError
35 _ERROR_SUCCESS = 0
38 _ERROR_SUCCESS = 0
36 _ERROR_NO_MORE_FILES = 18
39 _ERROR_NO_MORE_FILES = 18
37 _ERROR_INVALID_PARAMETER = 87
40 _ERROR_INVALID_PARAMETER = 87
38 _ERROR_BROKEN_PIPE = 109
41 _ERROR_BROKEN_PIPE = 109
39 _ERROR_INSUFFICIENT_BUFFER = 122
42 _ERROR_INSUFFICIENT_BUFFER = 122
40
43
41 # WPARAM is defined as UINT_PTR (unsigned type)
44 # WPARAM is defined as UINT_PTR (unsigned type)
42 # LPARAM is defined as LONG_PTR (signed type)
45 # LPARAM is defined as LONG_PTR (signed type)
43 if ctypes.sizeof(ctypes.c_long) == ctypes.sizeof(ctypes.c_void_p):
46 if ctypes.sizeof(ctypes.c_long) == ctypes.sizeof(ctypes.c_void_p):
44 _WPARAM = ctypes.c_ulong
47 _WPARAM = ctypes.c_ulong
45 _LPARAM = ctypes.c_long
48 _LPARAM = ctypes.c_long
46 elif ctypes.sizeof(ctypes.c_longlong) == ctypes.sizeof(ctypes.c_void_p):
49 elif ctypes.sizeof(ctypes.c_longlong) == ctypes.sizeof(ctypes.c_void_p):
47 _WPARAM = ctypes.c_ulonglong
50 _WPARAM = ctypes.c_ulonglong
48 _LPARAM = ctypes.c_longlong
51 _LPARAM = ctypes.c_longlong
49
52
50 class _FILETIME(ctypes.Structure):
53 class _FILETIME(ctypes.Structure):
51 _fields_ = [('dwLowDateTime', _DWORD),
54 _fields_ = [('dwLowDateTime', _DWORD),
52 ('dwHighDateTime', _DWORD)]
55 ('dwHighDateTime', _DWORD)]
53
56
54 class _BY_HANDLE_FILE_INFORMATION(ctypes.Structure):
57 class _BY_HANDLE_FILE_INFORMATION(ctypes.Structure):
55 _fields_ = [('dwFileAttributes', _DWORD),
58 _fields_ = [('dwFileAttributes', _DWORD),
56 ('ftCreationTime', _FILETIME),
59 ('ftCreationTime', _FILETIME),
57 ('ftLastAccessTime', _FILETIME),
60 ('ftLastAccessTime', _FILETIME),
58 ('ftLastWriteTime', _FILETIME),
61 ('ftLastWriteTime', _FILETIME),
59 ('dwVolumeSerialNumber', _DWORD),
62 ('dwVolumeSerialNumber', _DWORD),
60 ('nFileSizeHigh', _DWORD),
63 ('nFileSizeHigh', _DWORD),
61 ('nFileSizeLow', _DWORD),
64 ('nFileSizeLow', _DWORD),
62 ('nNumberOfLinks', _DWORD),
65 ('nNumberOfLinks', _DWORD),
63 ('nFileIndexHigh', _DWORD),
66 ('nFileIndexHigh', _DWORD),
64 ('nFileIndexLow', _DWORD)]
67 ('nFileIndexLow', _DWORD)]
65
68
66 # CreateFile
69 # CreateFile
67 _FILE_SHARE_READ = 0x00000001
70 _FILE_SHARE_READ = 0x00000001
68 _FILE_SHARE_WRITE = 0x00000002
71 _FILE_SHARE_WRITE = 0x00000002
69 _FILE_SHARE_DELETE = 0x00000004
72 _FILE_SHARE_DELETE = 0x00000004
70
73
71 _OPEN_EXISTING = 3
74 _OPEN_EXISTING = 3
72
75
73 _FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
76 _FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
74
77
75 # SetFileAttributes
78 # SetFileAttributes
76 _FILE_ATTRIBUTE_NORMAL = 0x80
79 _FILE_ATTRIBUTE_NORMAL = 0x80
77 _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000
80 _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000
78
81
79 # Process Security and Access Rights
82 # Process Security and Access Rights
80 _PROCESS_QUERY_INFORMATION = 0x0400
83 _PROCESS_QUERY_INFORMATION = 0x0400
81
84
82 # GetExitCodeProcess
85 # GetExitCodeProcess
83 _STILL_ACTIVE = 259
86 _STILL_ACTIVE = 259
84
87
85 class _STARTUPINFO(ctypes.Structure):
88 class _STARTUPINFO(ctypes.Structure):
86 _fields_ = [('cb', _DWORD),
89 _fields_ = [('cb', _DWORD),
87 ('lpReserved', _LPSTR),
90 ('lpReserved', _LPSTR),
88 ('lpDesktop', _LPSTR),
91 ('lpDesktop', _LPSTR),
89 ('lpTitle', _LPSTR),
92 ('lpTitle', _LPSTR),
90 ('dwX', _DWORD),
93 ('dwX', _DWORD),
91 ('dwY', _DWORD),
94 ('dwY', _DWORD),
92 ('dwXSize', _DWORD),
95 ('dwXSize', _DWORD),
93 ('dwYSize', _DWORD),
96 ('dwYSize', _DWORD),
94 ('dwXCountChars', _DWORD),
97 ('dwXCountChars', _DWORD),
95 ('dwYCountChars', _DWORD),
98 ('dwYCountChars', _DWORD),
96 ('dwFillAttribute', _DWORD),
99 ('dwFillAttribute', _DWORD),
97 ('dwFlags', _DWORD),
100 ('dwFlags', _DWORD),
98 ('wShowWindow', _WORD),
101 ('wShowWindow', _WORD),
99 ('cbReserved2', _WORD),
102 ('cbReserved2', _WORD),
100 ('lpReserved2', ctypes.c_char_p),
103 ('lpReserved2', ctypes.c_char_p),
101 ('hStdInput', _HANDLE),
104 ('hStdInput', _HANDLE),
102 ('hStdOutput', _HANDLE),
105 ('hStdOutput', _HANDLE),
103 ('hStdError', _HANDLE)]
106 ('hStdError', _HANDLE)]
104
107
105 class _PROCESS_INFORMATION(ctypes.Structure):
108 class _PROCESS_INFORMATION(ctypes.Structure):
106 _fields_ = [('hProcess', _HANDLE),
109 _fields_ = [('hProcess', _HANDLE),
107 ('hThread', _HANDLE),
110 ('hThread', _HANDLE),
108 ('dwProcessId', _DWORD),
111 ('dwProcessId', _DWORD),
109 ('dwThreadId', _DWORD)]
112 ('dwThreadId', _DWORD)]
110
113
111 _CREATE_NO_WINDOW = 0x08000000
114 _CREATE_NO_WINDOW = 0x08000000
112 _SW_HIDE = 0
115 _SW_HIDE = 0
113
116
114 class _COORD(ctypes.Structure):
117 class _COORD(ctypes.Structure):
115 _fields_ = [('X', ctypes.c_short),
118 _fields_ = [('X', ctypes.c_short),
116 ('Y', ctypes.c_short)]
119 ('Y', ctypes.c_short)]
117
120
118 class _SMALL_RECT(ctypes.Structure):
121 class _SMALL_RECT(ctypes.Structure):
119 _fields_ = [('Left', ctypes.c_short),
122 _fields_ = [('Left', ctypes.c_short),
120 ('Top', ctypes.c_short),
123 ('Top', ctypes.c_short),
121 ('Right', ctypes.c_short),
124 ('Right', ctypes.c_short),
122 ('Bottom', ctypes.c_short)]
125 ('Bottom', ctypes.c_short)]
123
126
124 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
127 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
125 _fields_ = [('dwSize', _COORD),
128 _fields_ = [('dwSize', _COORD),
126 ('dwCursorPosition', _COORD),
129 ('dwCursorPosition', _COORD),
127 ('wAttributes', _WORD),
130 ('wAttributes', _WORD),
128 ('srWindow', _SMALL_RECT),
131 ('srWindow', _SMALL_RECT),
129 ('dwMaximumWindowSize', _COORD)]
132 ('dwMaximumWindowSize', _COORD)]
130
133
131 _STD_ERROR_HANDLE = _DWORD(-12).value
134 _STD_ERROR_HANDLE = _DWORD(-12).value
132
135
133 # CreateToolhelp32Snapshot, Process32First, Process32Next
136 # CreateToolhelp32Snapshot, Process32First, Process32Next
134 _TH32CS_SNAPPROCESS = 0x00000002
137 _TH32CS_SNAPPROCESS = 0x00000002
135 _MAX_PATH = 260
138 _MAX_PATH = 260
136
139
137 class _tagPROCESSENTRY32(ctypes.Structure):
140 class _tagPROCESSENTRY32(ctypes.Structure):
138 _fields_ = [('dwsize', _DWORD),
141 _fields_ = [('dwsize', _DWORD),
139 ('cntUsage', _DWORD),
142 ('cntUsage', _DWORD),
140 ('th32ProcessID', _DWORD),
143 ('th32ProcessID', _DWORD),
141 ('th32DefaultHeapID', ctypes.c_void_p),
144 ('th32DefaultHeapID', ctypes.c_void_p),
142 ('th32ModuleID', _DWORD),
145 ('th32ModuleID', _DWORD),
143 ('cntThreads', _DWORD),
146 ('cntThreads', _DWORD),
144 ('th32ParentProcessID', _DWORD),
147 ('th32ParentProcessID', _DWORD),
145 ('pcPriClassBase', _LONG),
148 ('pcPriClassBase', _LONG),
146 ('dwFlags', _DWORD),
149 ('dwFlags', _DWORD),
147 ('szExeFile', ctypes.c_char * _MAX_PATH)]
150 ('szExeFile', ctypes.c_char * _MAX_PATH)]
148
151
149 def __init__(self):
152 def __init__(self):
150 super(_tagPROCESSENTRY32, self).__init__()
153 super(_tagPROCESSENTRY32, self).__init__()
151 self.dwsize = ctypes.sizeof(self)
154 self.dwsize = ctypes.sizeof(self)
152
155
153
156
154 # types of parameters of C functions used (required by pypy)
157 # types of parameters of C functions used (required by pypy)
155
158
156 _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p,
159 _kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p,
157 _DWORD, _DWORD, _HANDLE]
160 _DWORD, _DWORD, _HANDLE]
158 _kernel32.CreateFileA.restype = _HANDLE
161 _kernel32.CreateFileA.restype = _HANDLE
159
162
160 _kernel32.GetFileInformationByHandle.argtypes = [_HANDLE, ctypes.c_void_p]
163 _kernel32.GetFileInformationByHandle.argtypes = [_HANDLE, ctypes.c_void_p]
161 _kernel32.GetFileInformationByHandle.restype = _BOOL
164 _kernel32.GetFileInformationByHandle.restype = _BOOL
162
165
163 _kernel32.CloseHandle.argtypes = [_HANDLE]
166 _kernel32.CloseHandle.argtypes = [_HANDLE]
164 _kernel32.CloseHandle.restype = _BOOL
167 _kernel32.CloseHandle.restype = _BOOL
165
168
166 try:
169 try:
167 _kernel32.CreateHardLinkA.argtypes = [_LPCSTR, _LPCSTR, ctypes.c_void_p]
170 _kernel32.CreateHardLinkA.argtypes = [_LPCSTR, _LPCSTR, ctypes.c_void_p]
168 _kernel32.CreateHardLinkA.restype = _BOOL
171 _kernel32.CreateHardLinkA.restype = _BOOL
169 except AttributeError:
172 except AttributeError:
170 pass
173 pass
171
174
172 _kernel32.SetFileAttributesA.argtypes = [_LPCSTR, _DWORD]
175 _kernel32.SetFileAttributesA.argtypes = [_LPCSTR, _DWORD]
173 _kernel32.SetFileAttributesA.restype = _BOOL
176 _kernel32.SetFileAttributesA.restype = _BOOL
174
177
175 _kernel32.OpenProcess.argtypes = [_DWORD, _BOOL, _DWORD]
178 _kernel32.OpenProcess.argtypes = [_DWORD, _BOOL, _DWORD]
176 _kernel32.OpenProcess.restype = _HANDLE
179 _kernel32.OpenProcess.restype = _HANDLE
177
180
178 _kernel32.GetExitCodeProcess.argtypes = [_HANDLE, ctypes.c_void_p]
181 _kernel32.GetExitCodeProcess.argtypes = [_HANDLE, ctypes.c_void_p]
179 _kernel32.GetExitCodeProcess.restype = _BOOL
182 _kernel32.GetExitCodeProcess.restype = _BOOL
180
183
181 _kernel32.GetLastError.argtypes = []
184 _kernel32.GetLastError.argtypes = []
182 _kernel32.GetLastError.restype = _DWORD
185 _kernel32.GetLastError.restype = _DWORD
183
186
184 _kernel32.GetModuleFileNameA.argtypes = [_HANDLE, ctypes.c_void_p, _DWORD]
187 _kernel32.GetModuleFileNameA.argtypes = [_HANDLE, ctypes.c_void_p, _DWORD]
185 _kernel32.GetModuleFileNameA.restype = _DWORD
188 _kernel32.GetModuleFileNameA.restype = _DWORD
186
189
187 _kernel32.CreateProcessA.argtypes = [_LPCSTR, _LPCSTR, ctypes.c_void_p,
190 _kernel32.CreateProcessA.argtypes = [_LPCSTR, _LPCSTR, ctypes.c_void_p,
188 ctypes.c_void_p, _BOOL, _DWORD, ctypes.c_void_p, _LPCSTR, ctypes.c_void_p,
191 ctypes.c_void_p, _BOOL, _DWORD, ctypes.c_void_p, _LPCSTR, ctypes.c_void_p,
189 ctypes.c_void_p]
192 ctypes.c_void_p]
190 _kernel32.CreateProcessA.restype = _BOOL
193 _kernel32.CreateProcessA.restype = _BOOL
191
194
192 _kernel32.ExitProcess.argtypes = [_UINT]
195 _kernel32.ExitProcess.argtypes = [_UINT]
193 _kernel32.ExitProcess.restype = None
196 _kernel32.ExitProcess.restype = None
194
197
195 _kernel32.GetCurrentProcessId.argtypes = []
198 _kernel32.GetCurrentProcessId.argtypes = []
196 _kernel32.GetCurrentProcessId.restype = _DWORD
199 _kernel32.GetCurrentProcessId.restype = _DWORD
197
200
198 _SIGNAL_HANDLER = ctypes.WINFUNCTYPE(_BOOL, _DWORD)
201 _SIGNAL_HANDLER = ctypes.WINFUNCTYPE(_BOOL, _DWORD)
199 _kernel32.SetConsoleCtrlHandler.argtypes = [_SIGNAL_HANDLER, _BOOL]
202 _kernel32.SetConsoleCtrlHandler.argtypes = [_SIGNAL_HANDLER, _BOOL]
200 _kernel32.SetConsoleCtrlHandler.restype = _BOOL
203 _kernel32.SetConsoleCtrlHandler.restype = _BOOL
201
204
202 _kernel32.GetStdHandle.argtypes = [_DWORD]
205 _kernel32.GetStdHandle.argtypes = [_DWORD]
203 _kernel32.GetStdHandle.restype = _HANDLE
206 _kernel32.GetStdHandle.restype = _HANDLE
204
207
205 _kernel32.GetConsoleScreenBufferInfo.argtypes = [_HANDLE, ctypes.c_void_p]
208 _kernel32.GetConsoleScreenBufferInfo.argtypes = [_HANDLE, ctypes.c_void_p]
206 _kernel32.GetConsoleScreenBufferInfo.restype = _BOOL
209 _kernel32.GetConsoleScreenBufferInfo.restype = _BOOL
207
210
208 _advapi32.GetUserNameA.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
211 _advapi32.GetUserNameA.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
209 _advapi32.GetUserNameA.restype = _BOOL
212 _advapi32.GetUserNameA.restype = _BOOL
210
213
211 _user32.GetWindowThreadProcessId.argtypes = [_HANDLE, ctypes.c_void_p]
214 _user32.GetWindowThreadProcessId.argtypes = [_HANDLE, ctypes.c_void_p]
212 _user32.GetWindowThreadProcessId.restype = _DWORD
215 _user32.GetWindowThreadProcessId.restype = _DWORD
213
216
214 _user32.ShowWindow.argtypes = [_HANDLE, ctypes.c_int]
217 _user32.ShowWindow.argtypes = [_HANDLE, ctypes.c_int]
215 _user32.ShowWindow.restype = _BOOL
218 _user32.ShowWindow.restype = _BOOL
216
219
217 _WNDENUMPROC = ctypes.WINFUNCTYPE(_BOOL, _HWND, _LPARAM)
220 _WNDENUMPROC = ctypes.WINFUNCTYPE(_BOOL, _HWND, _LPARAM)
218 _user32.EnumWindows.argtypes = [_WNDENUMPROC, _LPARAM]
221 _user32.EnumWindows.argtypes = [_WNDENUMPROC, _LPARAM]
219 _user32.EnumWindows.restype = _BOOL
222 _user32.EnumWindows.restype = _BOOL
220
223
221 _kernel32.CreateToolhelp32Snapshot.argtypes = [_DWORD, _DWORD]
224 _kernel32.CreateToolhelp32Snapshot.argtypes = [_DWORD, _DWORD]
222 _kernel32.CreateToolhelp32Snapshot.restype = _BOOL
225 _kernel32.CreateToolhelp32Snapshot.restype = _BOOL
223
226
224 _kernel32.PeekNamedPipe.argtypes = [_HANDLE, ctypes.c_void_p, _DWORD,
227 _kernel32.PeekNamedPipe.argtypes = [_HANDLE, ctypes.c_void_p, _DWORD,
225 ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
228 ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
226 _kernel32.PeekNamedPipe.restype = _BOOL
229 _kernel32.PeekNamedPipe.restype = _BOOL
227
230
228 _kernel32.Process32First.argtypes = [_HANDLE, ctypes.c_void_p]
231 _kernel32.Process32First.argtypes = [_HANDLE, ctypes.c_void_p]
229 _kernel32.Process32First.restype = _BOOL
232 _kernel32.Process32First.restype = _BOOL
230
233
231 _kernel32.Process32Next.argtypes = [_HANDLE, ctypes.c_void_p]
234 _kernel32.Process32Next.argtypes = [_HANDLE, ctypes.c_void_p]
232 _kernel32.Process32Next.restype = _BOOL
235 _kernel32.Process32Next.restype = _BOOL
233
236
234 def _raiseoserror(name):
237 def _raiseoserror(name):
235 err = ctypes.WinError()
238 err = ctypes.WinError()
236 raise OSError(err.errno, '%s: %s' % (name, err.strerror))
239 raise OSError(err.errno, '%s: %s' % (name, err.strerror))
237
240
238 def _getfileinfo(name):
241 def _getfileinfo(name):
239 fh = _kernel32.CreateFileA(name, 0,
242 fh = _kernel32.CreateFileA(name, 0,
240 _FILE_SHARE_READ | _FILE_SHARE_WRITE | _FILE_SHARE_DELETE,
243 _FILE_SHARE_READ | _FILE_SHARE_WRITE | _FILE_SHARE_DELETE,
241 None, _OPEN_EXISTING, _FILE_FLAG_BACKUP_SEMANTICS, None)
244 None, _OPEN_EXISTING, _FILE_FLAG_BACKUP_SEMANTICS, None)
242 if fh == _INVALID_HANDLE_VALUE:
245 if fh == _INVALID_HANDLE_VALUE:
243 _raiseoserror(name)
246 _raiseoserror(name)
244 try:
247 try:
245 fi = _BY_HANDLE_FILE_INFORMATION()
248 fi = _BY_HANDLE_FILE_INFORMATION()
246 if not _kernel32.GetFileInformationByHandle(fh, ctypes.byref(fi)):
249 if not _kernel32.GetFileInformationByHandle(fh, ctypes.byref(fi)):
247 _raiseoserror(name)
250 _raiseoserror(name)
248 return fi
251 return fi
249 finally:
252 finally:
250 _kernel32.CloseHandle(fh)
253 _kernel32.CloseHandle(fh)
251
254
252 def oslink(src, dst):
255 def oslink(src, dst):
253 try:
256 try:
254 if not _kernel32.CreateHardLinkA(dst, src, None):
257 if not _kernel32.CreateHardLinkA(dst, src, None):
255 _raiseoserror(src)
258 _raiseoserror(src)
256 except AttributeError: # Wine doesn't support this function
259 except AttributeError: # Wine doesn't support this function
257 _raiseoserror(src)
260 _raiseoserror(src)
258
261
259 def nlinks(name):
262 def nlinks(name):
260 '''return number of hardlinks for the given file'''
263 '''return number of hardlinks for the given file'''
261 return _getfileinfo(name).nNumberOfLinks
264 return _getfileinfo(name).nNumberOfLinks
262
265
263 def samefile(path1, path2):
266 def samefile(path1, path2):
264 '''Returns whether path1 and path2 refer to the same file or directory.'''
267 '''Returns whether path1 and path2 refer to the same file or directory.'''
265 res1 = _getfileinfo(path1)
268 res1 = _getfileinfo(path1)
266 res2 = _getfileinfo(path2)
269 res2 = _getfileinfo(path2)
267 return (res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
270 return (res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
268 and res1.nFileIndexHigh == res2.nFileIndexHigh
271 and res1.nFileIndexHigh == res2.nFileIndexHigh
269 and res1.nFileIndexLow == res2.nFileIndexLow)
272 and res1.nFileIndexLow == res2.nFileIndexLow)
270
273
271 def samedevice(path1, path2):
274 def samedevice(path1, path2):
272 '''Returns whether path1 and path2 are on the same device.'''
275 '''Returns whether path1 and path2 are on the same device.'''
273 res1 = _getfileinfo(path1)
276 res1 = _getfileinfo(path1)
274 res2 = _getfileinfo(path2)
277 res2 = _getfileinfo(path2)
275 return res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
278 return res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
276
279
277 def peekpipe(pipe):
280 def peekpipe(pipe):
278 handle = msvcrt.get_osfhandle(pipe.fileno())
281 handle = msvcrt.get_osfhandle(pipe.fileno())
279 avail = _DWORD()
282 avail = _DWORD()
280
283
281 if not _kernel32.PeekNamedPipe(handle, None, 0, None, ctypes.byref(avail),
284 if not _kernel32.PeekNamedPipe(handle, None, 0, None, ctypes.byref(avail),
282 None):
285 None):
283 err = _kernel32.GetLastError()
286 err = _kernel32.GetLastError()
284 if err == _ERROR_BROKEN_PIPE:
287 if err == _ERROR_BROKEN_PIPE:
285 return 0
288 return 0
286 raise ctypes.WinError(err)
289 raise ctypes.WinError(err)
287
290
288 return avail.value
291 return avail.value
289
292
290 def testpid(pid):
293 def testpid(pid):
291 '''return True if pid is still running or unable to
294 '''return True if pid is still running or unable to
292 determine, False otherwise'''
295 determine, False otherwise'''
293 h = _kernel32.OpenProcess(_PROCESS_QUERY_INFORMATION, False, pid)
296 h = _kernel32.OpenProcess(_PROCESS_QUERY_INFORMATION, False, pid)
294 if h:
297 if h:
295 try:
298 try:
296 status = _DWORD()
299 status = _DWORD()
297 if _kernel32.GetExitCodeProcess(h, ctypes.byref(status)):
300 if _kernel32.GetExitCodeProcess(h, ctypes.byref(status)):
298 return status.value == _STILL_ACTIVE
301 return status.value == _STILL_ACTIVE
299 finally:
302 finally:
300 _kernel32.CloseHandle(h)
303 _kernel32.CloseHandle(h)
301 return _kernel32.GetLastError() != _ERROR_INVALID_PARAMETER
304 return _kernel32.GetLastError() != _ERROR_INVALID_PARAMETER
302
305
303 def executablepath():
306 def executablepath():
304 '''return full path of hg.exe'''
307 '''return full path of hg.exe'''
305 size = 600
308 size = 600
306 buf = ctypes.create_string_buffer(size + 1)
309 buf = ctypes.create_string_buffer(size + 1)
307 len = _kernel32.GetModuleFileNameA(None, ctypes.byref(buf), size)
310 len = _kernel32.GetModuleFileNameA(None, ctypes.byref(buf), size)
308 if len == 0:
311 if len == 0:
309 raise ctypes.WinError() # Note: WinError is a function
312 raise ctypes.WinError() # Note: WinError is a function
310 elif len == size:
313 elif len == size:
311 raise ctypes.WinError(_ERROR_INSUFFICIENT_BUFFER)
314 raise ctypes.WinError(_ERROR_INSUFFICIENT_BUFFER)
312 return buf.value
315 return buf.value
313
316
314 def getuser():
317 def getuser():
315 '''return name of current user'''
318 '''return name of current user'''
316 size = _DWORD(300)
319 size = _DWORD(300)
317 buf = ctypes.create_string_buffer(size.value + 1)
320 buf = ctypes.create_string_buffer(size.value + 1)
318 if not _advapi32.GetUserNameA(ctypes.byref(buf), ctypes.byref(size)):
321 if not _advapi32.GetUserNameA(ctypes.byref(buf), ctypes.byref(size)):
319 raise ctypes.WinError()
322 raise ctypes.WinError()
320 return buf.value
323 return buf.value
321
324
322 _signalhandler = []
325 _signalhandler = []
323
326
324 def setsignalhandler():
327 def setsignalhandler():
325 '''Register a termination handler for console events including
328 '''Register a termination handler for console events including
326 CTRL+C. python signal handlers do not work well with socket
329 CTRL+C. python signal handlers do not work well with socket
327 operations.
330 operations.
328 '''
331 '''
329 def handler(event):
332 def handler(event):
330 _kernel32.ExitProcess(1)
333 _kernel32.ExitProcess(1)
331
334
332 if _signalhandler:
335 if _signalhandler:
333 return # already registered
336 return # already registered
334 h = _SIGNAL_HANDLER(handler)
337 h = _SIGNAL_HANDLER(handler)
335 _signalhandler.append(h) # needed to prevent garbage collection
338 _signalhandler.append(h) # needed to prevent garbage collection
336 if not _kernel32.SetConsoleCtrlHandler(h, True):
339 if not _kernel32.SetConsoleCtrlHandler(h, True):
337 raise ctypes.WinError()
340 raise ctypes.WinError()
338
341
339 def hidewindow():
342 def hidewindow():
340
343
341 def callback(hwnd, pid):
344 def callback(hwnd, pid):
342 wpid = _DWORD()
345 wpid = _DWORD()
343 _user32.GetWindowThreadProcessId(hwnd, ctypes.byref(wpid))
346 _user32.GetWindowThreadProcessId(hwnd, ctypes.byref(wpid))
344 if pid == wpid.value:
347 if pid == wpid.value:
345 _user32.ShowWindow(hwnd, _SW_HIDE)
348 _user32.ShowWindow(hwnd, _SW_HIDE)
346 return False # stop enumerating windows
349 return False # stop enumerating windows
347 return True
350 return True
348
351
349 pid = _kernel32.GetCurrentProcessId()
352 pid = _kernel32.GetCurrentProcessId()
350 _user32.EnumWindows(_WNDENUMPROC(callback), pid)
353 _user32.EnumWindows(_WNDENUMPROC(callback), pid)
351
354
352 def termsize():
355 def termsize():
353 # cmd.exe does not handle CR like a unix console, the CR is
356 # cmd.exe does not handle CR like a unix console, the CR is
354 # counted in the line length. On 80 columns consoles, if 80
357 # counted in the line length. On 80 columns consoles, if 80
355 # characters are written, the following CR won't apply on the
358 # characters are written, the following CR won't apply on the
356 # current line but on the new one. Keep room for it.
359 # current line but on the new one. Keep room for it.
357 width = 80 - 1
360 width = 80 - 1
358 height = 25
361 height = 25
359 # Query stderr to avoid problems with redirections
362 # Query stderr to avoid problems with redirections
360 screenbuf = _kernel32.GetStdHandle(
363 screenbuf = _kernel32.GetStdHandle(
361 _STD_ERROR_HANDLE) # don't close the handle returned
364 _STD_ERROR_HANDLE) # don't close the handle returned
362 if screenbuf is None or screenbuf == _INVALID_HANDLE_VALUE:
365 if screenbuf is None or screenbuf == _INVALID_HANDLE_VALUE:
363 return width, height
366 return width, height
364 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
367 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
365 if not _kernel32.GetConsoleScreenBufferInfo(
368 if not _kernel32.GetConsoleScreenBufferInfo(
366 screenbuf, ctypes.byref(csbi)):
369 screenbuf, ctypes.byref(csbi)):
367 return width, height
370 return width, height
368 width = csbi.srWindow.Right - csbi.srWindow.Left # don't '+ 1'
371 width = csbi.srWindow.Right - csbi.srWindow.Left # don't '+ 1'
369 height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1
372 height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1
370 return width, height
373 return width, height
371
374
372 def _1stchild(pid):
375 def _1stchild(pid):
373 '''return the 1st found child of the given pid
376 '''return the 1st found child of the given pid
374
377
375 None is returned when no child is found'''
378 None is returned when no child is found'''
376 pe = _tagPROCESSENTRY32()
379 pe = _tagPROCESSENTRY32()
377
380
378 # create handle to list all processes
381 # create handle to list all processes
379 ph = _kernel32.CreateToolhelp32Snapshot(_TH32CS_SNAPPROCESS, 0)
382 ph = _kernel32.CreateToolhelp32Snapshot(_TH32CS_SNAPPROCESS, 0)
380 if ph == _INVALID_HANDLE_VALUE:
383 if ph == _INVALID_HANDLE_VALUE:
381 raise ctypes.WinError()
384 raise ctypes.WinError()
382 try:
385 try:
383 r = _kernel32.Process32First(ph, ctypes.byref(pe))
386 r = _kernel32.Process32First(ph, ctypes.byref(pe))
384 # loop over all processes
387 # loop over all processes
385 while r:
388 while r:
386 if pe.th32ParentProcessID == pid:
389 if pe.th32ParentProcessID == pid:
387 # return first child found
390 # return first child found
388 return pe.th32ProcessID
391 return pe.th32ProcessID
389 r = _kernel32.Process32Next(ph, ctypes.byref(pe))
392 r = _kernel32.Process32Next(ph, ctypes.byref(pe))
390 finally:
393 finally:
391 _kernel32.CloseHandle(ph)
394 _kernel32.CloseHandle(ph)
392 if _kernel32.GetLastError() != _ERROR_NO_MORE_FILES:
395 if _kernel32.GetLastError() != _ERROR_NO_MORE_FILES:
393 raise ctypes.WinError()
396 raise ctypes.WinError()
394 return None # no child found
397 return None # no child found
395
398
396 class _tochildpid(int): # pid is _DWORD, which always matches in an int
399 class _tochildpid(int): # pid is _DWORD, which always matches in an int
397 '''helper for spawndetached, returns the child pid on conversion to string
400 '''helper for spawndetached, returns the child pid on conversion to string
398
401
399 Does not resolve the child pid immediately because the child may not yet be
402 Does not resolve the child pid immediately because the child may not yet be
400 started.
403 started.
401 '''
404 '''
402 def childpid(self):
405 def childpid(self):
403 '''returns the child pid of the first found child of the process
406 '''returns the child pid of the first found child of the process
404 with this pid'''
407 with this pid'''
405 return _1stchild(self)
408 return _1stchild(self)
406 def __str__(self):
409 def __str__(self):
407 # run when the pid is written to the file
410 # run when the pid is written to the file
408 ppid = self.childpid()
411 ppid = self.childpid()
409 if ppid is None:
412 if ppid is None:
410 # race, child has exited since check
413 # race, child has exited since check
411 # fall back to this pid. Its process will also have disappeared,
414 # fall back to this pid. Its process will also have disappeared,
412 # raising the same error type later as when the child pid would
415 # raising the same error type later as when the child pid would
413 # be returned.
416 # be returned.
414 return " %d" % self
417 return " %d" % self
415 return str(ppid)
418 return str(ppid)
416
419
417 def spawndetached(args):
420 def spawndetached(args):
418 # No standard library function really spawns a fully detached
421 # No standard library function really spawns a fully detached
419 # process under win32 because they allocate pipes or other objects
422 # process under win32 because they allocate pipes or other objects
420 # to handle standard streams communications. Passing these objects
423 # to handle standard streams communications. Passing these objects
421 # to the child process requires handle inheritance to be enabled
424 # to the child process requires handle inheritance to be enabled
422 # which makes really detached processes impossible.
425 # which makes really detached processes impossible.
423 si = _STARTUPINFO()
426 si = _STARTUPINFO()
424 si.cb = ctypes.sizeof(_STARTUPINFO)
427 si.cb = ctypes.sizeof(_STARTUPINFO)
425
428
426 pi = _PROCESS_INFORMATION()
429 pi = _PROCESS_INFORMATION()
427
430
428 env = ''
431 env = ''
429 for k in encoding.environ:
432 for k in encoding.environ:
430 env += "%s=%s\0" % (k, encoding.environ[k])
433 env += "%s=%s\0" % (k, encoding.environ[k])
431 if not env:
434 if not env:
432 env = '\0'
435 env = '\0'
433 env += '\0'
436 env += '\0'
434
437
435 args = subprocess.list2cmdline(args)
438 args = subprocess.list2cmdline(args)
436 # Not running the command in shell mode makes Python 2.6 hang when
439 # Not running the command in shell mode makes Python 2.6 hang when
437 # writing to hgweb output socket.
440 # writing to hgweb output socket.
438 comspec = encoding.environ.get("COMSPEC", "cmd.exe")
441 comspec = encoding.environ.get("COMSPEC", "cmd.exe")
439 args = comspec + " /c " + args
442 args = comspec + " /c " + args
440
443
441 res = _kernel32.CreateProcessA(
444 res = _kernel32.CreateProcessA(
442 None, args, None, None, False, _CREATE_NO_WINDOW,
445 None, args, None, None, False, _CREATE_NO_WINDOW,
443 env, os.getcwd(), ctypes.byref(si), ctypes.byref(pi))
446 env, pycompat.getcwd(), ctypes.byref(si), ctypes.byref(pi))
444 if not res:
447 if not res:
445 raise ctypes.WinError()
448 raise ctypes.WinError()
446
449
447 # _tochildpid because the process is the child of COMSPEC
450 # _tochildpid because the process is the child of COMSPEC
448 return _tochildpid(pi.dwProcessId)
451 return _tochildpid(pi.dwProcessId)
449
452
450 def unlink(f):
453 def unlink(f):
451 '''try to implement POSIX' unlink semantics on Windows'''
454 '''try to implement POSIX' unlink semantics on Windows'''
452
455
453 if os.path.isdir(f):
456 if os.path.isdir(f):
454 # use EPERM because it is POSIX prescribed value, even though
457 # use EPERM because it is POSIX prescribed value, even though
455 # unlink(2) on directories returns EISDIR on Linux
458 # unlink(2) on directories returns EISDIR on Linux
456 raise IOError(errno.EPERM,
459 raise IOError(errno.EPERM,
457 "Unlinking directory not permitted: '%s'" % f)
460 "Unlinking directory not permitted: '%s'" % f)
458
461
459 # POSIX allows to unlink and rename open files. Windows has serious
462 # POSIX allows to unlink and rename open files. Windows has serious
460 # problems with doing that:
463 # problems with doing that:
461 # - Calling os.unlink (or os.rename) on a file f fails if f or any
464 # - Calling os.unlink (or os.rename) on a file f fails if f or any
462 # hardlinked copy of f has been opened with Python's open(). There is no
465 # hardlinked copy of f has been opened with Python's open(). There is no
463 # way such a file can be deleted or renamed on Windows (other than
466 # way such a file can be deleted or renamed on Windows (other than
464 # scheduling the delete or rename for the next reboot).
467 # scheduling the delete or rename for the next reboot).
465 # - Calling os.unlink on a file that has been opened with Mercurial's
468 # - Calling os.unlink on a file that has been opened with Mercurial's
466 # posixfile (or comparable methods) will delay the actual deletion of
469 # posixfile (or comparable methods) will delay the actual deletion of
467 # the file for as long as the file is held open. The filename is blocked
470 # the file for as long as the file is held open. The filename is blocked
468 # during that time and cannot be used for recreating a new file under
471 # during that time and cannot be used for recreating a new file under
469 # that same name ("zombie file"). Directories containing such zombie files
472 # that same name ("zombie file"). Directories containing such zombie files
470 # cannot be removed or moved.
473 # cannot be removed or moved.
471 # A file that has been opened with posixfile can be renamed, so we rename
474 # A file that has been opened with posixfile can be renamed, so we rename
472 # f to a random temporary name before calling os.unlink on it. This allows
475 # f to a random temporary name before calling os.unlink on it. This allows
473 # callers to recreate f immediately while having other readers do their
476 # callers to recreate f immediately while having other readers do their
474 # implicit zombie filename blocking on a temporary name.
477 # implicit zombie filename blocking on a temporary name.
475
478
476 for tries in xrange(10):
479 for tries in xrange(10):
477 temp = '%s-%08x' % (f, random.randint(0, 0xffffffff))
480 temp = '%s-%08x' % (f, random.randint(0, 0xffffffff))
478 try:
481 try:
479 os.rename(f, temp) # raises OSError EEXIST if temp exists
482 os.rename(f, temp) # raises OSError EEXIST if temp exists
480 break
483 break
481 except OSError as e:
484 except OSError as e:
482 if e.errno != errno.EEXIST:
485 if e.errno != errno.EEXIST:
483 raise
486 raise
484 else:
487 else:
485 raise IOError(errno.EEXIST, "No usable temporary filename found")
488 raise IOError(errno.EEXIST, "No usable temporary filename found")
486
489
487 try:
490 try:
488 os.unlink(temp)
491 os.unlink(temp)
489 except OSError:
492 except OSError:
490 # The unlink might have failed because the READONLY attribute may heave
493 # The unlink might have failed because the READONLY attribute may heave
491 # been set on the original file. Rename works fine with READONLY set,
494 # been set on the original file. Rename works fine with READONLY set,
492 # but not os.unlink. Reset all attributes and try again.
495 # but not os.unlink. Reset all attributes and try again.
493 _kernel32.SetFileAttributesA(temp, _FILE_ATTRIBUTE_NORMAL)
496 _kernel32.SetFileAttributesA(temp, _FILE_ATTRIBUTE_NORMAL)
494 try:
497 try:
495 os.unlink(temp)
498 os.unlink(temp)
496 except OSError:
499 except OSError:
497 # The unlink might have failed due to some very rude AV-Scanners.
500 # The unlink might have failed due to some very rude AV-Scanners.
498 # Leaking a tempfile is the lesser evil than aborting here and
501 # Leaking a tempfile is the lesser evil than aborting here and
499 # leaving some potentially serious inconsistencies.
502 # leaving some potentially serious inconsistencies.
500 pass
503 pass
501
504
502 def makedir(path, notindexed):
505 def makedir(path, notindexed):
503 os.mkdir(path)
506 os.mkdir(path)
504 if notindexed:
507 if notindexed:
505 _kernel32.SetFileAttributesA(path, _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
508 _kernel32.SetFileAttributesA(path, _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
@@ -1,53 +1,50
1 #require test-repo
1 #require test-repo
2
2
3 $ . "$TESTDIR/helpers-testrepo.sh"
3 $ . "$TESTDIR/helpers-testrepo.sh"
4 $ check_code="$TESTDIR"/../contrib/check-code.py
4 $ check_code="$TESTDIR"/../contrib/check-code.py
5 $ cd "$TESTDIR"/..
5 $ cd "$TESTDIR"/..
6
6
7 New errors are not allowed. Warnings are strongly discouraged.
7 New errors are not allowed. Warnings are strongly discouraged.
8 (The writing "no-che?k-code" is for not skipping this file when checking.)
8 (The writing "no-che?k-code" is for not skipping this file when checking.)
9
9
10 $ hg locate -X contrib/python-zstandard -X hgext/fsmonitor/pywatchman |
10 $ hg locate -X contrib/python-zstandard -X hgext/fsmonitor/pywatchman |
11 > sed 's-\\-/-g' | xargs "$check_code" --warnings --per-file=0 || false
11 > sed 's-\\-/-g' | xargs "$check_code" --warnings --per-file=0 || false
12 Skipping i18n/polib.py it has no-che?k-code (glob)
12 Skipping i18n/polib.py it has no-che?k-code (glob)
13 mercurial/demandimport.py:309:
13 mercurial/demandimport.py:309:
14 > if os.environ.get('HGDEMANDIMPORT') != 'disable':
14 > if os.environ.get('HGDEMANDIMPORT') != 'disable':
15 use encoding.environ instead (py3)
15 use encoding.environ instead (py3)
16 mercurial/encoding.py:54:
16 mercurial/encoding.py:54:
17 > environ = os.environ
17 > environ = os.environ
18 use encoding.environ instead (py3)
18 use encoding.environ instead (py3)
19 mercurial/encoding.py:56:
19 mercurial/encoding.py:56:
20 > environ = os.environb
20 > environ = os.environb
21 use encoding.environ instead (py3)
21 use encoding.environ instead (py3)
22 mercurial/encoding.py:61:
22 mercurial/encoding.py:61:
23 > for k, v in os.environ.items())
23 > for k, v in os.environ.items())
24 use encoding.environ instead (py3)
24 use encoding.environ instead (py3)
25 mercurial/encoding.py:203:
25 mercurial/encoding.py:203:
26 > for k, v in os.environ.items())
26 > for k, v in os.environ.items())
27 use encoding.environ instead (py3)
27 use encoding.environ instead (py3)
28 Skipping mercurial/httpclient/__init__.py it has no-che?k-code (glob)
28 Skipping mercurial/httpclient/__init__.py it has no-che?k-code (glob)
29 Skipping mercurial/httpclient/_readers.py it has no-che?k-code (glob)
29 Skipping mercurial/httpclient/_readers.py it has no-che?k-code (glob)
30 mercurial/policy.py:45:
30 mercurial/policy.py:45:
31 > policy = os.environ.get('HGMODULEPOLICY', policy)
31 > policy = os.environ.get('HGMODULEPOLICY', policy)
32 use encoding.environ instead (py3)
32 use encoding.environ instead (py3)
33 Skipping mercurial/statprof.py it has no-che?k-code (glob)
33 Skipping mercurial/statprof.py it has no-che?k-code (glob)
34 mercurial/win32.py:443:
35 > env, os.getcwd(), ctypes.byref(si), ctypes.byref(pi))
36 use pycompat.getcwd instead (py3)
37 [1]
34 [1]
38
35
39 @commands in debugcommands.py should be in alphabetical order.
36 @commands in debugcommands.py should be in alphabetical order.
40
37
41 >>> import re
38 >>> import re
42 >>> commands = []
39 >>> commands = []
43 >>> with open('mercurial/debugcommands.py', 'rb') as fh:
40 >>> with open('mercurial/debugcommands.py', 'rb') as fh:
44 ... for line in fh:
41 ... for line in fh:
45 ... m = re.match("^@command\('([a-z]+)", line)
42 ... m = re.match("^@command\('([a-z]+)", line)
46 ... if m:
43 ... if m:
47 ... commands.append(m.group(1))
44 ... commands.append(m.group(1))
48 >>> scommands = list(sorted(commands))
45 >>> scommands = list(sorted(commands))
49 >>> for i, command in enumerate(scommands):
46 >>> for i, command in enumerate(scommands):
50 ... if command != commands[i]:
47 ... if command != commands[i]:
51 ... print('commands in debugcommands.py not sorted; first differing '
48 ... print('commands in debugcommands.py not sorted; first differing '
52 ... 'command is %s; expected %s' % (commands[i], command))
49 ... 'command is %s; expected %s' % (commands[i], command))
53 ... break
50 ... break
General Comments 0
You need to be logged in to leave comments. Login now