Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/websdk/mercurial/win32.py
diff options
context:
space:
mode:
Diffstat (limited to 'websdk/mercurial/win32.py')
-rw-r--r--[l---------]websdk/mercurial/win32.py453
1 files changed, 452 insertions, 1 deletions
diff --git a/websdk/mercurial/win32.py b/websdk/mercurial/win32.py
index f45a5c5..e886caf 120000..100644
--- a/websdk/mercurial/win32.py
+++ b/websdk/mercurial/win32.py
@@ -1 +1,452 @@
-/usr/share/pyshared/mercurial/win32.py \ No newline at end of file
+# win32.py - utility functions that use win32 API
+#
+# Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+import encoding
+import ctypes, errno, os, struct, subprocess, random
+
+_kernel32 = ctypes.windll.kernel32
+_advapi32 = ctypes.windll.advapi32
+_user32 = ctypes.windll.user32
+
+_BOOL = ctypes.c_long
+_WORD = ctypes.c_ushort
+_DWORD = ctypes.c_ulong
+_UINT = ctypes.c_uint
+_LONG = ctypes.c_long
+_LPCSTR = _LPSTR = ctypes.c_char_p
+_HANDLE = ctypes.c_void_p
+_HWND = _HANDLE
+
+_INVALID_HANDLE_VALUE = _HANDLE(-1).value
+
+# GetLastError
+_ERROR_SUCCESS = 0
+_ERROR_INVALID_PARAMETER = 87
+_ERROR_INSUFFICIENT_BUFFER = 122
+
+# WPARAM is defined as UINT_PTR (unsigned type)
+# LPARAM is defined as LONG_PTR (signed type)
+if ctypes.sizeof(ctypes.c_long) == ctypes.sizeof(ctypes.c_void_p):
+ _WPARAM = ctypes.c_ulong
+ _LPARAM = ctypes.c_long
+elif ctypes.sizeof(ctypes.c_longlong) == ctypes.sizeof(ctypes.c_void_p):
+ _WPARAM = ctypes.c_ulonglong
+ _LPARAM = ctypes.c_longlong
+
+class _FILETIME(ctypes.Structure):
+ _fields_ = [('dwLowDateTime', _DWORD),
+ ('dwHighDateTime', _DWORD)]
+
+class _BY_HANDLE_FILE_INFORMATION(ctypes.Structure):
+ _fields_ = [('dwFileAttributes', _DWORD),
+ ('ftCreationTime', _FILETIME),
+ ('ftLastAccessTime', _FILETIME),
+ ('ftLastWriteTime', _FILETIME),
+ ('dwVolumeSerialNumber', _DWORD),
+ ('nFileSizeHigh', _DWORD),
+ ('nFileSizeLow', _DWORD),
+ ('nNumberOfLinks', _DWORD),
+ ('nFileIndexHigh', _DWORD),
+ ('nFileIndexLow', _DWORD)]
+
+# CreateFile
+_FILE_SHARE_READ = 0x00000001
+_FILE_SHARE_WRITE = 0x00000002
+_FILE_SHARE_DELETE = 0x00000004
+
+_OPEN_EXISTING = 3
+
+# SetFileAttributes
+_FILE_ATTRIBUTE_NORMAL = 0x80
+_FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000
+
+# Process Security and Access Rights
+_PROCESS_QUERY_INFORMATION = 0x0400
+
+# GetExitCodeProcess
+_STILL_ACTIVE = 259
+
+# registry
+_HKEY_CURRENT_USER = 0x80000001L
+_HKEY_LOCAL_MACHINE = 0x80000002L
+_KEY_READ = 0x20019
+_REG_SZ = 1
+_REG_DWORD = 4
+
+class _STARTUPINFO(ctypes.Structure):
+ _fields_ = [('cb', _DWORD),
+ ('lpReserved', _LPSTR),
+ ('lpDesktop', _LPSTR),
+ ('lpTitle', _LPSTR),
+ ('dwX', _DWORD),
+ ('dwY', _DWORD),
+ ('dwXSize', _DWORD),
+ ('dwYSize', _DWORD),
+ ('dwXCountChars', _DWORD),
+ ('dwYCountChars', _DWORD),
+ ('dwFillAttribute', _DWORD),
+ ('dwFlags', _DWORD),
+ ('wShowWindow', _WORD),
+ ('cbReserved2', _WORD),
+ ('lpReserved2', ctypes.c_char_p),
+ ('hStdInput', _HANDLE),
+ ('hStdOutput', _HANDLE),
+ ('hStdError', _HANDLE)]
+
+class _PROCESS_INFORMATION(ctypes.Structure):
+ _fields_ = [('hProcess', _HANDLE),
+ ('hThread', _HANDLE),
+ ('dwProcessId', _DWORD),
+ ('dwThreadId', _DWORD)]
+
+_DETACHED_PROCESS = 0x00000008
+_STARTF_USESHOWWINDOW = 0x00000001
+_SW_HIDE = 0
+
+class _COORD(ctypes.Structure):
+ _fields_ = [('X', ctypes.c_short),
+ ('Y', ctypes.c_short)]
+
+class _SMALL_RECT(ctypes.Structure):
+ _fields_ = [('Left', ctypes.c_short),
+ ('Top', ctypes.c_short),
+ ('Right', ctypes.c_short),
+ ('Bottom', ctypes.c_short)]
+
+class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
+ _fields_ = [('dwSize', _COORD),
+ ('dwCursorPosition', _COORD),
+ ('wAttributes', _WORD),
+ ('srWindow', _SMALL_RECT),
+ ('dwMaximumWindowSize', _COORD)]
+
+_STD_ERROR_HANDLE = _DWORD(-12).value
+
+# types of parameters of C functions used (required by pypy)
+
+_kernel32.CreateFileA.argtypes = [_LPCSTR, _DWORD, _DWORD, ctypes.c_void_p,
+ _DWORD, _DWORD, _HANDLE]
+_kernel32.CreateFileA.restype = _HANDLE
+
+_kernel32.GetFileInformationByHandle.argtypes = [_HANDLE, ctypes.c_void_p]
+_kernel32.GetFileInformationByHandle.restype = _BOOL
+
+_kernel32.CloseHandle.argtypes = [_HANDLE]
+_kernel32.CloseHandle.restype = _BOOL
+
+try:
+ _kernel32.CreateHardLinkA.argtypes = [_LPCSTR, _LPCSTR, ctypes.c_void_p]
+ _kernel32.CreateHardLinkA.restype = _BOOL
+except AttributeError:
+ pass
+
+_kernel32.SetFileAttributesA.argtypes = [_LPCSTR, _DWORD]
+_kernel32.SetFileAttributesA.restype = _BOOL
+
+_kernel32.OpenProcess.argtypes = [_DWORD, _BOOL, _DWORD]
+_kernel32.OpenProcess.restype = _HANDLE
+
+_kernel32.GetExitCodeProcess.argtypes = [_HANDLE, ctypes.c_void_p]
+_kernel32.GetExitCodeProcess.restype = _BOOL
+
+_kernel32.GetLastError.argtypes = []
+_kernel32.GetLastError.restype = _DWORD
+
+_kernel32.GetModuleFileNameA.argtypes = [_HANDLE, ctypes.c_void_p, _DWORD]
+_kernel32.GetModuleFileNameA.restype = _DWORD
+
+_kernel32.CreateProcessA.argtypes = [_LPCSTR, _LPCSTR, ctypes.c_void_p,
+ ctypes.c_void_p, _BOOL, _DWORD, ctypes.c_void_p, _LPCSTR, ctypes.c_void_p,
+ ctypes.c_void_p]
+_kernel32.CreateProcessA.restype = _BOOL
+
+_kernel32.ExitProcess.argtypes = [_UINT]
+_kernel32.ExitProcess.restype = None
+
+_kernel32.GetCurrentProcessId.argtypes = []
+_kernel32.GetCurrentProcessId.restype = _DWORD
+
+_SIGNAL_HANDLER = ctypes.WINFUNCTYPE(_BOOL, _DWORD)
+_kernel32.SetConsoleCtrlHandler.argtypes = [_SIGNAL_HANDLER, _BOOL]
+_kernel32.SetConsoleCtrlHandler.restype = _BOOL
+
+_kernel32.GetStdHandle.argtypes = [_DWORD]
+_kernel32.GetStdHandle.restype = _HANDLE
+
+_kernel32.GetConsoleScreenBufferInfo.argtypes = [_HANDLE, ctypes.c_void_p]
+_kernel32.GetConsoleScreenBufferInfo.restype = _BOOL
+
+_advapi32.RegOpenKeyExA.argtypes = [_HANDLE, _LPCSTR, _DWORD, _DWORD,
+ ctypes.c_void_p]
+_advapi32.RegOpenKeyExA.restype = _LONG
+
+_advapi32.RegQueryValueExA.argtypes = [_HANDLE, _LPCSTR, ctypes.c_void_p,
+ ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
+_advapi32.RegQueryValueExA.restype = _LONG
+
+_advapi32.RegCloseKey.argtypes = [_HANDLE]
+_advapi32.RegCloseKey.restype = _LONG
+
+_advapi32.GetUserNameA.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
+_advapi32.GetUserNameA.restype = _BOOL
+
+_user32.GetWindowThreadProcessId.argtypes = [_HANDLE, ctypes.c_void_p]
+_user32.GetWindowThreadProcessId.restype = _DWORD
+
+_user32.ShowWindow.argtypes = [_HANDLE, ctypes.c_int]
+_user32.ShowWindow.restype = _BOOL
+
+_WNDENUMPROC = ctypes.WINFUNCTYPE(_BOOL, _HWND, _LPARAM)
+_user32.EnumWindows.argtypes = [_WNDENUMPROC, _LPARAM]
+_user32.EnumWindows.restype = _BOOL
+
+def _raiseoserror(name):
+ err = ctypes.WinError()
+ raise OSError(err.errno, '%s: %s' % (name, err.strerror))
+
+def _getfileinfo(name):
+ fh = _kernel32.CreateFileA(name, 0,
+ _FILE_SHARE_READ | _FILE_SHARE_WRITE | _FILE_SHARE_DELETE,
+ None, _OPEN_EXISTING, 0, None)
+ if fh == _INVALID_HANDLE_VALUE:
+ _raiseoserror(name)
+ try:
+ fi = _BY_HANDLE_FILE_INFORMATION()
+ if not _kernel32.GetFileInformationByHandle(fh, ctypes.byref(fi)):
+ _raiseoserror(name)
+ return fi
+ finally:
+ _kernel32.CloseHandle(fh)
+
+def oslink(src, dst):
+ try:
+ if not _kernel32.CreateHardLinkA(dst, src, None):
+ _raiseoserror(src)
+ except AttributeError: # Wine doesn't support this function
+ _raiseoserror(src)
+
+def nlinks(name):
+ '''return number of hardlinks for the given file'''
+ return _getfileinfo(name).nNumberOfLinks
+
+def samefile(fpath1, fpath2):
+ '''Returns whether fpath1 and fpath2 refer to the same file. This is only
+ guaranteed to work for files, not directories.'''
+ res1 = _getfileinfo(fpath1)
+ res2 = _getfileinfo(fpath2)
+ return (res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
+ and res1.nFileIndexHigh == res2.nFileIndexHigh
+ and res1.nFileIndexLow == res2.nFileIndexLow)
+
+def samedevice(fpath1, fpath2):
+ '''Returns whether fpath1 and fpath2 are on the same device. This is only
+ guaranteed to work for files, not directories.'''
+ res1 = _getfileinfo(fpath1)
+ res2 = _getfileinfo(fpath2)
+ return res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
+
+def testpid(pid):
+ '''return True if pid is still running or unable to
+ determine, False otherwise'''
+ h = _kernel32.OpenProcess(_PROCESS_QUERY_INFORMATION, False, pid)
+ if h:
+ try:
+ status = _DWORD()
+ if _kernel32.GetExitCodeProcess(h, ctypes.byref(status)):
+ return status.value == _STILL_ACTIVE
+ finally:
+ _kernel32.CloseHandle(h)
+ return _kernel32.GetLastError() != _ERROR_INVALID_PARAMETER
+
+def lookupreg(key, valname=None, scope=None):
+ ''' Look up a key/value name in the Windows registry.
+
+ valname: value name. If unspecified, the default value for the key
+ is used.
+ scope: optionally specify scope for registry lookup, this can be
+ a sequence of scopes to look up in order. Default (CURRENT_USER,
+ LOCAL_MACHINE).
+ '''
+ byref = ctypes.byref
+ if scope is None:
+ scope = (_HKEY_CURRENT_USER, _HKEY_LOCAL_MACHINE)
+ elif not isinstance(scope, (list, tuple)):
+ scope = (scope,)
+ for s in scope:
+ kh = _HANDLE()
+ res = _advapi32.RegOpenKeyExA(s, key, 0, _KEY_READ, ctypes.byref(kh))
+ if res != _ERROR_SUCCESS:
+ continue
+ try:
+ size = _DWORD(600)
+ type = _DWORD()
+ buf = ctypes.create_string_buffer(size.value + 1)
+ res = _advapi32.RegQueryValueExA(kh.value, valname, None,
+ byref(type), buf, byref(size))
+ if res != _ERROR_SUCCESS:
+ continue
+ if type.value == _REG_SZ:
+ # never let a Unicode string escape into the wild
+ return encoding.tolocal(buf.value.encode('UTF-8'))
+ elif type.value == _REG_DWORD:
+ fmt = '<L'
+ s = ctypes.string_at(byref(buf), struct.calcsize(fmt))
+ return struct.unpack(fmt, s)[0]
+ finally:
+ _advapi32.RegCloseKey(kh.value)
+
+def executablepath():
+ '''return full path of hg.exe'''
+ size = 600
+ buf = ctypes.create_string_buffer(size + 1)
+ len = _kernel32.GetModuleFileNameA(None, ctypes.byref(buf), size)
+ if len == 0:
+ raise ctypes.WinError()
+ elif len == size:
+ raise ctypes.WinError(_ERROR_INSUFFICIENT_BUFFER)
+ return buf.value
+
+def getuser():
+ '''return name of current user'''
+ size = _DWORD(300)
+ buf = ctypes.create_string_buffer(size.value + 1)
+ if not _advapi32.GetUserNameA(ctypes.byref(buf), ctypes.byref(size)):
+ raise ctypes.WinError()
+ return buf.value
+
+_signalhandler = []
+
+def setsignalhandler():
+ '''Register a termination handler for console events including
+ CTRL+C. python signal handlers do not work well with socket
+ operations.
+ '''
+ def handler(event):
+ _kernel32.ExitProcess(1)
+
+ if _signalhandler:
+ return # already registered
+ h = _SIGNAL_HANDLER(handler)
+ _signalhandler.append(h) # needed to prevent garbage collection
+ if not _kernel32.SetConsoleCtrlHandler(h, True):
+ raise ctypes.WinError()
+
+def hidewindow():
+
+ def callback(hwnd, pid):
+ wpid = _DWORD()
+ _user32.GetWindowThreadProcessId(hwnd, ctypes.byref(wpid))
+ if pid == wpid.value:
+ _user32.ShowWindow(hwnd, _SW_HIDE)
+ return False # stop enumerating windows
+ return True
+
+ pid = _kernel32.GetCurrentProcessId()
+ _user32.EnumWindows(_WNDENUMPROC(callback), pid)
+
+def termwidth():
+ # cmd.exe does not handle CR like a unix console, the CR is
+ # counted in the line length. On 80 columns consoles, if 80
+ # characters are written, the following CR won't apply on the
+ # current line but on the new one. Keep room for it.
+ width = 79
+ # Query stderr to avoid problems with redirections
+ screenbuf = _kernel32.GetStdHandle(
+ _STD_ERROR_HANDLE) # don't close the handle returned
+ if screenbuf is None or screenbuf == _INVALID_HANDLE_VALUE:
+ return width
+ csbi = _CONSOLE_SCREEN_BUFFER_INFO()
+ if not _kernel32.GetConsoleScreenBufferInfo(
+ screenbuf, ctypes.byref(csbi)):
+ return width
+ width = csbi.srWindow.Right - csbi.srWindow.Left
+ return width
+
+def spawndetached(args):
+ # No standard library function really spawns a fully detached
+ # process under win32 because they allocate pipes or other objects
+ # to handle standard streams communications. Passing these objects
+ # to the child process requires handle inheritance to be enabled
+ # which makes really detached processes impossible.
+ si = _STARTUPINFO()
+ si.cb = ctypes.sizeof(_STARTUPINFO)
+ si.dwFlags = _STARTF_USESHOWWINDOW
+ si.wShowWindow = _SW_HIDE
+
+ pi = _PROCESS_INFORMATION()
+
+ env = ''
+ for k in os.environ:
+ env += "%s=%s\0" % (k, os.environ[k])
+ if not env:
+ env = '\0'
+ env += '\0'
+
+ args = subprocess.list2cmdline(args)
+ # Not running the command in shell mode makes python26 hang when
+ # writing to hgweb output socket.
+ comspec = os.environ.get("COMSPEC", "cmd.exe")
+ args = comspec + " /c " + args
+
+ res = _kernel32.CreateProcessA(
+ None, args, None, None, False, _DETACHED_PROCESS,
+ env, os.getcwd(), ctypes.byref(si), ctypes.byref(pi))
+ if not res:
+ raise ctypes.WinError()
+
+ return pi.dwProcessId
+
+def unlink(f):
+ '''try to implement POSIX' unlink semantics on Windows'''
+
+ # POSIX allows to unlink and rename open files. Windows has serious
+ # problems with doing that:
+ # - Calling os.unlink (or os.rename) on a file f fails if f or any
+ # hardlinked copy of f has been opened with Python's open(). There is no
+ # way such a file can be deleted or renamed on Windows (other than
+ # scheduling the delete or rename for the next reboot).
+ # - Calling os.unlink on a file that has been opened with Mercurial's
+ # posixfile (or comparable methods) will delay the actual deletion of
+ # the file for as long as the file is held open. The filename is blocked
+ # during that time and cannot be used for recreating a new file under
+ # that same name ("zombie file"). Directories containing such zombie files
+ # cannot be removed or moved.
+ # A file that has been opened with posixfile can be renamed, so we rename
+ # f to a random temporary name before calling os.unlink on it. This allows
+ # callers to recreate f immediately while having other readers do their
+ # implicit zombie filename blocking on a temporary name.
+
+ for tries in xrange(10):
+ temp = '%s-%08x' % (f, random.randint(0, 0xffffffff))
+ try:
+ os.rename(f, temp) # raises OSError EEXIST if temp exists
+ break
+ except OSError, e:
+ if e.errno != errno.EEXIST:
+ raise
+ else:
+ raise IOError, (errno.EEXIST, "No usable temporary filename found")
+
+ try:
+ os.unlink(temp)
+ except OSError:
+ # The unlink might have failed because the READONLY attribute may heave
+ # been set on the original file. Rename works fine with READONLY set,
+ # but not os.unlink. Reset all attributes and try again.
+ _kernel32.SetFileAttributesA(temp, _FILE_ATTRIBUTE_NORMAL)
+ try:
+ os.unlink(temp)
+ except OSError:
+ # The unlink might have failed due to some very rude AV-Scanners.
+ # Leaking a tempfile is the lesser evil than aborting here and
+ # leaving some potentially serious inconsistencies.
+ pass
+
+def makedir(path, notindexed):
+ os.mkdir(path)
+ if notindexed:
+ _kernel32.SetFileAttributesA(path, _FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)