##// END OF EJS Templates
port win32.py to using the Python ctypes library...
Adrian Buehlmann -
r13375:f1fa8f48 default
parent child Browse files
Show More
@@ -16,23 +16,14 b''
16 <File Name="mercurial.parsers.pyd" />
16 <File Name="mercurial.parsers.pyd" />
17 <File Name="pyexpat.pyd" />
17 <File Name="pyexpat.pyd" />
18 <File Name="python26.dll" />
18 <File Name="python26.dll" />
19 <File Name="pythoncom26.dll" />
20 <File Name="pywintypes26.dll" />
21 <File Name="bz2.pyd" />
19 <File Name="bz2.pyd" />
22 <File Name="select.pyd" />
20 <File Name="select.pyd" />
23 <File Name="unicodedata.pyd" />
21 <File Name="unicodedata.pyd" />
24 <File Name="win32api.pyd" />
22 <File Name="_ctypes.pyd" />
25 <File Name="win32com.shell.shell.pyd" />
26 <File Name="win32console.pyd" />
27 <File Name="win32file.pyd" />
28 <File Name="win32gui.pyd" />
29 <File Name="win32pipe.pyd" />
30 <File Name="win32process.pyd" />
31 <File Name="_elementtree.pyd" />
23 <File Name="_elementtree.pyd" />
32 <File Name="_hashlib.pyd" />
24 <File Name="_hashlib.pyd" />
33 <File Name="_socket.pyd" />
25 <File Name="_socket.pyd" />
34 <File Name="_ssl.pyd" />
26 <File Name="_ssl.pyd" />
35 <File Name="_win32sysloader.pyd" />
36 </Component>
27 </Component>
37 </DirectoryRef>
28 </DirectoryRef>
38 </Fragment>
29 </Fragment>
@@ -9,7 +9,7 b''
9 <?define contrib.vim.guid = {BB04903A-652D-4C4F-9590-2BD07A2304F2} ?>
9 <?define contrib.vim.guid = {BB04903A-652D-4C4F-9590-2BD07A2304F2} ?>
10
10
11 <!-- dist.wxs -->
11 <!-- dist.wxs -->
12 <?define dist.guid = {0F63D160-0740-4BAF-BF25-0C6930310F51} ?>
12 <?define dist.guid = {C3B634A4-1B05-4A40-94A9-38EE853CF693} ?>
13
13
14 <!-- doc.wxs -->
14 <!-- doc.wxs -->
15 <?define doc.hg.1.html.guid = {AAAA3FDA-EDC5-4220-B59D-D342722358A2} ?>
15 <?define doc.hg.1.html.guid = {AAAA3FDA-EDC5-4220-B59D-D342722358A2} ?>
@@ -13,6 +13,7 b' posixfile = open'
13 nulldev = '/dev/null'
13 nulldev = '/dev/null'
14 normpath = os.path.normpath
14 normpath = os.path.normpath
15 samestat = os.path.samestat
15 samestat = os.path.samestat
16 os_link = os.link
16 unlink = os.unlink
17 unlink = os.unlink
17 rename = os.rename
18 rename = os.rename
18 expandglobs = False
19 expandglobs = False
@@ -24,6 +25,10 b' def openhardlinks():'
24 '''return true if it is safe to hold open file handles to hardlinks'''
25 '''return true if it is safe to hold open file handles to hardlinks'''
25 return True
26 return True
26
27
28 def nlinks(name):
29 '''return number of hardlinks for the given file'''
30 return os.lstat(name).st_nlink
31
27 def rcfiles(path):
32 def rcfiles(path):
28 rcs = [os.path.join(path, 'hgrc')]
33 rcs = [os.path.join(path, 'hgrc')]
29 rcdir = os.path.join(path, 'hgrc.d')
34 rcdir = os.path.join(path, 'hgrc.d')
@@ -554,16 +554,6 b' class path_auditor(object):'
554 # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
554 # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
555 self.auditeddir.update(prefixes)
555 self.auditeddir.update(prefixes)
556
556
557 def nlinks(pathname):
558 """Return number of hardlinks for the given file."""
559 return os.lstat(pathname).st_nlink
560
561 if hasattr(os, 'link'):
562 os_link = os.link
563 else:
564 def os_link(src, dst):
565 raise OSError(0, _("Hardlinks not supported"))
566
567 def lookup_reg(key, name=None, scope=None):
557 def lookup_reg(key, name=None, scope=None):
568 return None
558 return None
569
559
@@ -5,74 +5,173 b''
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 """Utility functions that use win32 API.
8 import osutil, encoding
9 import ctypes, errno, os, struct, subprocess
10
11 _kernel32 = ctypes.windll.kernel32
12
13 _BOOL = ctypes.c_long
14 _WORD = ctypes.c_ushort
15 _DWORD = ctypes.c_ulong
16 _LPCSTR = _LPSTR = ctypes.c_char_p
17 _HANDLE = ctypes.c_void_p
18 _HWND = _HANDLE
19
20 _INVALID_HANDLE_VALUE = -1
21
22 # GetLastError
23 _ERROR_SUCCESS = 0
24 _ERROR_INVALID_PARAMETER = 87
25 _ERROR_INSUFFICIENT_BUFFER = 122
26
27 # WPARAM is defined as UINT_PTR (unsigned type)
28 # LPARAM is defined as LONG_PTR (signed type)
29 if ctypes.sizeof(ctypes.c_long) == ctypes.sizeof(ctypes.c_void_p):
30 _WPARAM = ctypes.c_ulong
31 _LPARAM = ctypes.c_long
32 elif ctypes.sizeof(ctypes.c_longlong) == ctypes.sizeof(ctypes.c_void_p):
33 _WPARAM = ctypes.c_ulonglong
34 _LPARAM = ctypes.c_longlong
35
36 class _FILETIME(ctypes.Structure):
37 _fields_ = [('dwLowDateTime', _DWORD),
38 ('dwHighDateTime', _DWORD)]
39
40 class _BY_HANDLE_FILE_INFORMATION(ctypes.Structure):
41 _fields_ = [('dwFileAttributes', _DWORD),
42 ('ftCreationTime', _FILETIME),
43 ('ftLastAccessTime', _FILETIME),
44 ('ftLastWriteTime', _FILETIME),
45 ('dwVolumeSerialNumber', _DWORD),
46 ('nFileSizeHigh', _DWORD),
47 ('nFileSizeLow', _DWORD),
48 ('nNumberOfLinks', _DWORD),
49 ('nFileIndexHigh', _DWORD),
50 ('nFileIndexLow', _DWORD)]
51
52 # CreateFile
53 _FILE_SHARE_READ = 0x00000001
54 _FILE_SHARE_WRITE = 0x00000002
55 _FILE_SHARE_DELETE = 0x00000004
56
57 _OPEN_EXISTING = 3
58
59 # Process Security and Access Rights
60 _PROCESS_QUERY_INFORMATION = 0x0400
61
62 # GetExitCodeProcess
63 _STILL_ACTIVE = 259
64
65 # registry
66 _HKEY_CURRENT_USER = 0x80000001L
67 _HKEY_LOCAL_MACHINE = 0x80000002L
68 _KEY_READ = 0x20019
69 _REG_SZ = 1
70 _REG_DWORD = 4
9
71
10 Mark Hammond's win32all package allows better functionality on
72 class _STARTUPINFO(ctypes.Structure):
11 Windows. This module overrides definitions in util.py. If not
73 _fields_ = [('cb', _DWORD),
12 available, import of this module will fail, and generic code will be
74 ('lpReserved', _LPSTR),
13 used.
75 ('lpDesktop', _LPSTR),
14 """
76 ('lpTitle', _LPSTR),
77 ('dwX', _DWORD),
78 ('dwY', _DWORD),
79 ('dwXSize', _DWORD),
80 ('dwYSize', _DWORD),
81 ('dwXCountChars', _DWORD),
82 ('dwYCountChars', _DWORD),
83 ('dwFillAttribute', _DWORD),
84 ('dwFlags', _DWORD),
85 ('wShowWindow', _WORD),
86 ('cbReserved2', _WORD),
87 ('lpReserved2', ctypes.c_char_p),
88 ('hStdInput', _HANDLE),
89 ('hStdOutput', _HANDLE),
90 ('hStdError', _HANDLE)]
91
92 class _PROCESS_INFORMATION(ctypes.Structure):
93 _fields_ = [('hProcess', _HANDLE),
94 ('hThread', _HANDLE),
95 ('dwProcessId', _DWORD),
96 ('dwThreadId', _DWORD)]
97
98 _DETACHED_PROCESS = 0x00000008
99 _STARTF_USESHOWWINDOW = 0x00000001
100 _SW_HIDE = 0
15
101
16 import win32api
102 class _COORD(ctypes.Structure):
103 _fields_ = [('X', ctypes.c_short),
104 ('Y', ctypes.c_short)]
105
106 class _SMALL_RECT(ctypes.Structure):
107 _fields_ = [('Left', ctypes.c_short),
108 ('Top', ctypes.c_short),
109 ('Right', ctypes.c_short),
110 ('Bottom', ctypes.c_short)]
111
112 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
113 _fields_ = [('dwSize', _COORD),
114 ('dwCursorPosition', _COORD),
115 ('wAttributes', _WORD),
116 ('srWindow', _SMALL_RECT),
117 ('dwMaximumWindowSize', _COORD)]
17
118
18 import errno, os, sys, pywintypes, win32con, win32file, win32process
119 _STD_ERROR_HANDLE = 0xfffffff4L # (DWORD)-12
19 import winerror, win32gui, win32console
120
20 import osutil, encoding
121 def _raiseoserror(name):
21 from win32com.shell import shell, shellcon
122 err = ctypes.WinError()
123 raise OSError(err.errno, '%s: %s' % (name, err.strerror))
124
125 def _getfileinfo(name):
126 fh = _kernel32.CreateFileA(name, 0,
127 _FILE_SHARE_READ | _FILE_SHARE_WRITE | _FILE_SHARE_DELETE,
128 None, _OPEN_EXISTING, 0, None)
129 if fh == _INVALID_HANDLE_VALUE:
130 _raiseoserror(name)
131 try:
132 fi = _BY_HANDLE_FILE_INFORMATION()
133 if not _kernel32.GetFileInformationByHandle(fh, ctypes.byref(fi)):
134 _raiseoserror(name)
135 return fi
136 finally:
137 _kernel32.CloseHandle(fh)
22
138
23 def os_link(src, dst):
139 def os_link(src, dst):
24 try:
140 if not _kernel32.CreateHardLinkA(dst, src, None):
25 win32file.CreateHardLink(dst, src)
141 _raiseoserror(src)
26 except pywintypes.error:
27 raise OSError(errno.EINVAL, 'target implements hardlinks improperly')
28 except NotImplementedError: # Another fake error win Win98
29 raise OSError(errno.EINVAL, 'Hardlinking not supported')
30
142
31 def _getfileinfo(pathname):
143 def nlinks(name):
32 """Return number of hardlinks for the given file."""
144 '''return number of hardlinks for the given file'''
33 try:
145 return _getfileinfo(name).nNumberOfLinks
34 fh = win32file.CreateFile(pathname, 0,
35 win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE |
36 win32file.FILE_SHARE_DELETE,
37 None, win32file.OPEN_EXISTING, 0, None)
38 except pywintypes.error:
39 raise OSError(errno.ENOENT, 'The system cannot find the file specified')
40 try:
41 return win32file.GetFileInformationByHandle(fh)
42 finally:
43 fh.Close()
44
45 def nlinks(pathname):
46 """Return number of hardlinks for the given file."""
47 return _getfileinfo(pathname)[7]
48
146
49 def samefile(fpath1, fpath2):
147 def samefile(fpath1, fpath2):
50 """Returns whether fpath1 and fpath2 refer to the same file. This is only
148 '''Returns whether fpath1 and fpath2 refer to the same file. This is only
51 guaranteed to work for files, not directories."""
149 guaranteed to work for files, not directories.'''
52 res1 = _getfileinfo(fpath1)
150 res1 = _getfileinfo(fpath1)
53 res2 = _getfileinfo(fpath2)
151 res2 = _getfileinfo(fpath2)
54 # Index 4 is the volume serial number, and 8 and 9 contain the file ID
152 return (res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
55 return res1[4] == res2[4] and res1[8] == res2[8] and res1[9] == res2[9]
153 and res1.nFileIndexHigh == res2.nFileIndexHigh
154 and res1.nFileIndexLow == res2.nFileIndexLow)
56
155
57 def samedevice(fpath1, fpath2):
156 def samedevice(fpath1, fpath2):
58 """Returns whether fpath1 and fpath2 are on the same device. This is only
157 '''Returns whether fpath1 and fpath2 are on the same device. This is only
59 guaranteed to work for files, not directories."""
158 guaranteed to work for files, not directories.'''
60 res1 = _getfileinfo(fpath1)
159 res1 = _getfileinfo(fpath1)
61 res2 = _getfileinfo(fpath2)
160 res2 = _getfileinfo(fpath2)
62 return res1[4] == res2[4]
161 return res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
63
162
64 def testpid(pid):
163 def testpid(pid):
65 '''return True if pid is still running or unable to
164 '''return True if pid is still running or unable to
66 determine, False otherwise'''
165 determine, False otherwise'''
67 try:
166 h = _kernel32.OpenProcess(_PROCESS_QUERY_INFORMATION, False, pid)
68 handle = win32api.OpenProcess(
167 if h:
69 win32con.PROCESS_QUERY_INFORMATION, False, pid)
168 try:
70 if handle:
169 status = _DWORD()
71 status = win32process.GetExitCodeProcess(handle)
170 if _kernel32.GetExitCodeProcess(h, ctypes.byref(status)):
72 return status == win32con.STILL_ACTIVE
171 return status.value == _STILL_ACTIVE
73 except pywintypes.error, details:
172 finally:
74 return details[0] != winerror.ERROR_INVALID_PARAMETER
173 _kernel32.CloseHandle(h)
75 return True
174 return _kernel32.GetLastError() != _ERROR_INVALID_PARAMETER
76
175
77 def lookup_reg(key, valname=None, scope=None):
176 def lookup_reg(key, valname=None, scope=None):
78 ''' Look up a key/value name in the Windows registry.
177 ''' Look up a key/value name in the Windows registry.
@@ -83,101 +182,169 b' def lookup_reg(key, valname=None, scope='
83 a sequence of scopes to look up in order. Default (CURRENT_USER,
182 a sequence of scopes to look up in order. Default (CURRENT_USER,
84 LOCAL_MACHINE).
183 LOCAL_MACHINE).
85 '''
184 '''
86 try:
185 adv = ctypes.windll.advapi32
87 from _winreg import HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, \
186 byref = ctypes.byref
88 QueryValueEx, OpenKey
89 except ImportError:
90 return None
91
92 if scope is None:
187 if scope is None:
93 scope = (HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE)
188 scope = (_HKEY_CURRENT_USER, _HKEY_LOCAL_MACHINE)
94 elif not isinstance(scope, (list, tuple)):
189 elif not isinstance(scope, (list, tuple)):
95 scope = (scope,)
190 scope = (scope,)
96 for s in scope:
191 for s in scope:
192 kh = _HANDLE()
193 res = adv.RegOpenKeyExA(s, key, 0, _KEY_READ, ctypes.byref(kh))
194 if res != _ERROR_SUCCESS:
195 continue
97 try:
196 try:
98 val = QueryValueEx(OpenKey(s, key), valname)[0]
197 size = _DWORD(600)
99 # never let a Unicode string escape into the wild
198 type = _DWORD()
100 return encoding.tolocal(val.encode('UTF-8'))
199 buf = ctypes.create_string_buffer(size.value + 1)
101 except EnvironmentError:
200 res = adv.RegQueryValueExA(kh.value, valname, None,
102 pass
201 byref(type), buf, byref(size))
202 if res != _ERROR_SUCCESS:
203 continue
204 if type.value == _REG_SZ:
205 # never let a Unicode string escape into the wild
206 return encoding.tolocal(buf.value.encode('UTF-8'))
207 elif type.value == _REG_DWORD:
208 fmt = '<L'
209 s = ctypes.string_at(byref(buf), struct.calcsize(fmt))
210 return struct.unpack(fmt, s)[0]
211 finally:
212 adv.RegCloseKey(kh.value)
103
213
104 def system_rcpath_win32():
214 def system_rcpath_win32():
105 '''return default os-specific hgrc search path'''
215 '''return default os-specific hgrc search path'''
106 filename = win32api.GetModuleFileName(0)
216 rcpath = []
217 size = 600
218 buf = ctypes.create_string_buffer(size + 1)
219 len = _kernel32.GetModuleFileNameA(None, ctypes.byref(buf), size)
220 if len == 0:
221 raise ctypes.WinError()
222 elif len == size:
223 raise ctypes.WinError(_ERROR_INSUFFICIENT_BUFFER)
224 filename = buf.value
107 # Use mercurial.ini found in directory with hg.exe
225 # Use mercurial.ini found in directory with hg.exe
108 progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
226 progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
109 if os.path.isfile(progrc):
227 if os.path.isfile(progrc):
110 return [progrc]
228 rcpath.append(progrc)
229 return rcpath
111 # Use hgrc.d found in directory with hg.exe
230 # Use hgrc.d found in directory with hg.exe
112 progrcd = os.path.join(os.path.dirname(filename), 'hgrc.d')
231 progrcd = os.path.join(os.path.dirname(filename), 'hgrc.d')
113 if os.path.isdir(progrcd):
232 if os.path.isdir(progrcd):
114 rcpath = []
115 for f, kind in osutil.listdir(progrcd):
233 for f, kind in osutil.listdir(progrcd):
116 if f.endswith('.rc'):
234 if f.endswith('.rc'):
117 rcpath.append(os.path.join(progrcd, f))
235 rcpath.append(os.path.join(progrcd, f))
118 return rcpath
236 return rcpath
119 # else look for a system rcpath in the registry
237 # else look for a system rcpath in the registry
120 try:
238 value = lookup_reg('SOFTWARE\\Mercurial', None, _HKEY_LOCAL_MACHINE)
121 value = win32api.RegQueryValue(
239 if not isinstance(value, str) or not value:
122 win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Mercurial')
123 rcpath = []
124 for p in value.split(os.pathsep):
125 if p.lower().endswith('mercurial.ini'):
126 rcpath.append(p)
127 elif os.path.isdir(p):
128 for f, kind in osutil.listdir(p):
129 if f.endswith('.rc'):
130 rcpath.append(os.path.join(p, f))
131 return rcpath
240 return rcpath
132 except pywintypes.error:
241 value = value.replace('/', os.sep)
133 return []
242 for p in value.split(os.pathsep):
243 if p.lower().endswith('mercurial.ini'):
244 rcpath.append(p)
245 elif os.path.isdir(p):
246 for f, kind in osutil.listdir(p):
247 if f.endswith('.rc'):
248 rcpath.append(os.path.join(p, f))
249 return rcpath
134
250
135 def user_rcpath_win32():
251 def user_rcpath_win32():
136 '''return os-specific hgrc search path to the user dir'''
252 '''return os-specific hgrc search path to the user dir'''
137 userdir = os.path.expanduser('~')
253 userdir = os.path.expanduser('~')
138 if sys.getwindowsversion()[3] != 2 and userdir == '~':
139 # We are on win < nt: fetch the APPDATA directory location and use
140 # the parent directory as the user home dir.
141 appdir = shell.SHGetPathFromIDList(
142 shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
143 userdir = os.path.dirname(appdir)
144 return [os.path.join(userdir, 'mercurial.ini'),
254 return [os.path.join(userdir, 'mercurial.ini'),
145 os.path.join(userdir, '.hgrc')]
255 os.path.join(userdir, '.hgrc')]
146
256
147 def getuser():
257 def getuser():
148 '''return name of current user'''
258 '''return name of current user'''
149 return win32api.GetUserName()
259 adv = ctypes.windll.advapi32
260 size = _DWORD(300)
261 buf = ctypes.create_string_buffer(size.value + 1)
262 if not adv.GetUserNameA(ctypes.byref(buf), ctypes.byref(size)):
263 raise ctypes.WinError()
264 return buf.value
150
265
151 def set_signal_handler_win32():
266 _SIGNAL_HANDLER = ctypes.WINFUNCTYPE(_BOOL, _DWORD)
152 """Register a termination handler for console events including
267 _signal_handler = []
268
269 def set_signal_handler():
270 '''Register a termination handler for console events including
153 CTRL+C. python signal handlers do not work well with socket
271 CTRL+C. python signal handlers do not work well with socket
154 operations.
272 operations.
155 """
273 '''
156 def handler(event):
274 def handler(event):
157 win32process.ExitProcess(1)
275 _kernel32.ExitProcess(1)
158 win32api.SetConsoleCtrlHandler(handler)
276
277 if _signal_handler:
278 return # already registered
279 h = _SIGNAL_HANDLER(handler)
280 _signal_handler.append(h) # needed to prevent garbage collection
281 if not _kernel32.SetConsoleCtrlHandler(h, True):
282 raise ctypes.WinError()
283
284 _WNDENUMPROC = ctypes.WINFUNCTYPE(_BOOL, _HWND, _LPARAM)
159
285
160 def hidewindow():
286 def hidewindow():
161 def callback(*args, **kwargs):
287 user32 = ctypes.windll.user32
162 hwnd, pid = args
163 wpid = win32process.GetWindowThreadProcessId(hwnd)[1]
164 if pid == wpid:
165 win32gui.ShowWindow(hwnd, win32con.SW_HIDE)
166
288
167 pid = win32process.GetCurrentProcessId()
289 def callback(hwnd, pid):
168 win32gui.EnumWindows(callback, pid)
290 wpid = _DWORD()
291 user32.GetWindowThreadProcessId(hwnd, ctypes.byref(wpid))
292 if pid == wpid.value:
293 user32.ShowWindow(hwnd, _SW_HIDE)
294 return False # stop enumerating windows
295 return True
296
297 pid = _kernel32.GetCurrentProcessId()
298 user32.EnumWindows(_WNDENUMPROC(callback), pid)
169
299
170 def termwidth():
300 def termwidth():
171 try:
301 # cmd.exe does not handle CR like a unix console, the CR is
172 # Query stderr to avoid problems with redirections
302 # counted in the line length. On 80 columns consoles, if 80
173 screenbuf = win32console.GetStdHandle(win32console.STD_ERROR_HANDLE)
303 # characters are written, the following CR won't apply on the
174 if screenbuf is None:
304 # current line but on the new one. Keep room for it.
175 return 79
305 width = 79
176 try:
306 # Query stderr to avoid problems with redirections
177 window = screenbuf.GetConsoleScreenBufferInfo()['Window']
307 screenbuf = _kernel32.GetStdHandle(
178 width = window.Right - window.Left
308 _STD_ERROR_HANDLE) # don't close the handle returned
179 return width
309 if screenbuf is None or screenbuf == _INVALID_HANDLE_VALUE:
180 finally:
310 return width
181 screenbuf.Detach()
311 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
182 except pywintypes.error:
312 if not _kernel32.GetConsoleScreenBufferInfo(
183 return 79
313 screenbuf, ctypes.byref(csbi)):
314 return width
315 width = csbi.srWindow.Right - csbi.srWindow.Left
316 return width
317
318 def spawndetached(args):
319 # No standard library function really spawns a fully detached
320 # process under win32 because they allocate pipes or other objects
321 # to handle standard streams communications. Passing these objects
322 # to the child process requires handle inheritance to be enabled
323 # which makes really detached processes impossible.
324 si = _STARTUPINFO()
325 si.cb = ctypes.sizeof(_STARTUPINFO)
326 si.dwFlags = _STARTF_USESHOWWINDOW
327 si.wShowWindow = _SW_HIDE
328
329 pi = _PROCESS_INFORMATION()
330
331 env = ''
332 for k in os.environ:
333 env += "%s=%s\0" % (k, os.environ[k])
334 if not env:
335 env = '\0'
336 env += '\0'
337
338 args = subprocess.list2cmdline(args)
339 # Not running the command in shell mode makes python26 hang when
340 # writing to hgweb output socket.
341 comspec = os.environ.get("COMSPEC", "cmd.exe")
342 args = comspec + " /c " + args
343
344 res = _kernel32.CreateProcessA(
345 None, args, None, None, False, _DETACHED_PROCESS,
346 env, os.getcwd(), ctypes.byref(si), ctypes.byref(pi))
347 if not res:
348 raise ctypes.WinError()
349
350 return pi.dwProcessId
@@ -71,7 +71,7 b' def _is_win_9x():'
71 return 'command' in os.environ.get('comspec', '')
71 return 'command' in os.environ.get('comspec', '')
72
72
73 def openhardlinks():
73 def openhardlinks():
74 return not _is_win_9x() and "win32api" in globals()
74 return not _is_win_9x()
75
75
76 def system_rcpath():
76 def system_rcpath():
77 try:
77 try:
@@ -106,10 +106,6 b' def sshargs(sshcmd, host, user, port):'
106 args = user and ("%s@%s" % (user, host)) or host
106 args = user and ("%s@%s" % (user, host)) or host
107 return port and ("%s %s %s" % (args, pflag, port)) or args
107 return port and ("%s %s %s" % (args, pflag, port)) or args
108
108
109 def testpid(pid):
110 '''return False if pid dead, True if running or not known'''
111 return True
112
113 def set_flags(f, l, x):
109 def set_flags(f, l, x):
114 pass
110 pass
115
111
@@ -208,12 +204,6 b' def find_exe(command):'
208 return executable
204 return executable
209 return findexisting(os.path.expanduser(os.path.expandvars(command)))
205 return findexisting(os.path.expanduser(os.path.expandvars(command)))
210
206
211 def set_signal_handler():
212 try:
213 set_signal_handler_win32()
214 except NameError:
215 pass
216
217 def statfiles(files):
207 def statfiles(files):
218 '''Stat each file in files and yield stat or None if file does not exist.
208 '''Stat each file in files and yield stat or None if file does not exist.
219 Cluster and cache stat per directory to minimize number of OS stat calls.'''
209 Cluster and cache stat per directory to minimize number of OS stat calls.'''
@@ -241,11 +231,6 b' def statfiles(files):'
241 cache = dircache.setdefault(dir, dmap)
231 cache = dircache.setdefault(dir, dmap)
242 yield cache.get(base, None)
232 yield cache.get(base, None)
243
233
244 def getuser():
245 '''return name of current user'''
246 raise error.Abort(_('user name not available - set USERNAME '
247 'environment variable'))
248
249 def username(uid=None):
234 def username(uid=None):
250 """Return the name of the user with the given uid.
235 """Return the name of the user with the given uid.
251
236
@@ -335,37 +320,6 b' def rename(src, dst):'
335 unlink(dst)
320 unlink(dst)
336 os.rename(src, dst)
321 os.rename(src, dst)
337
322
338 def spawndetached(args):
339 # No standard library function really spawns a fully detached
340 # process under win32 because they allocate pipes or other objects
341 # to handle standard streams communications. Passing these objects
342 # to the child process requires handle inheritance to be enabled
343 # which makes really detached processes impossible.
344 class STARTUPINFO:
345 dwFlags = subprocess.STARTF_USESHOWWINDOW
346 hStdInput = None
347 hStdOutput = None
348 hStdError = None
349 wShowWindow = subprocess.SW_HIDE
350
351 args = subprocess.list2cmdline(args)
352 # Not running the command in shell mode makes python26 hang when
353 # writing to hgweb output socket.
354 comspec = os.environ.get("COMSPEC", "cmd.exe")
355 args = comspec + " /c " + args
356 hp, ht, pid, tid = subprocess.CreateProcess(
357 None, args,
358 # no special security
359 None, None,
360 # Do not inherit handles
361 0,
362 # DETACHED_PROCESS
363 0x00000008,
364 os.environ,
365 os.getcwd(),
366 STARTUPINFO())
367 return pid
368
369 def gethgcmd():
323 def gethgcmd():
370 return [sys.executable] + sys.argv[:1]
324 return [sys.executable] + sys.argv[:1]
371
325
@@ -380,10 +334,6 b' def groupmembers(name):'
380 # Don't support groups on Windows for now
334 # Don't support groups on Windows for now
381 raise KeyError()
335 raise KeyError()
382
336
383 try:
337 from win32 import *
384 # override functions with win32 versions if possible
385 from win32 import *
386 except ImportError:
387 pass
388
338
389 expandglobs = True
339 expandglobs = True
General Comments 0
You need to be logged in to leave comments. Login now