##// END OF EJS Templates
refactor version code...
refactor version code - simplify version detection code - move detection code into setup.py - move version reading function into util.py - drop version.py code This makes hg more closely follow its own recommendation of how to deal with versioning your builds: use hg id in your build script.

File last commit:

r7473:5185a24c default
r7632:9626819b default
Show More
util_win32.py
373 lines | 14.7 KiB | text/x-python | PythonLexer
Vadim Gelfer
fix exception handling on windows....
r2054 # util_win32.py - utility functions that use win32 API
#
# Copyright 2005 Matt Mackall <mpm@selenic.com>
# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
#
# This software may be used and distributed according to the terms of
# the GNU General Public License, incorporated herein by reference.
# Mark Hammond's win32all package allows better functionality on
# Windows. this module overrides definitions in util.py. if not
# available, import of this module will fail, and generic code will be
# used.
import win32api
Joel Rosdahl
Add missing import of sys
r6216 import errno, os, sys, pywintypes, win32con, win32file, win32process
Matt Mackall
Replace demandload with new demandimport
r3877 import cStringIO, winerror
Steve Borho
win32: read system rcpath from registry...
r5583 import osutil
Remy Roy
Folding correction and missing import
r6881 import util
Matt Mackall
Replace demandload with new demandimport
r3877 from win32com.shell import shell,shellcon
Vadim Gelfer
fix exception handling on windows....
r2054
Benoit Boissinot
exceptions should inherit the Exception class
r7473 class WinError(Exception):
Vadim Gelfer
fix exception handling on windows....
r2054 winerror_map = {
winerror.ERROR_ACCESS_DENIED: errno.EACCES,
winerror.ERROR_ACCOUNT_DISABLED: errno.EACCES,
winerror.ERROR_ACCOUNT_RESTRICTION: errno.EACCES,
winerror.ERROR_ALREADY_ASSIGNED: errno.EBUSY,
winerror.ERROR_ALREADY_EXISTS: errno.EEXIST,
winerror.ERROR_ARITHMETIC_OVERFLOW: errno.ERANGE,
winerror.ERROR_BAD_COMMAND: errno.EIO,
winerror.ERROR_BAD_DEVICE: errno.ENODEV,
winerror.ERROR_BAD_DRIVER_LEVEL: errno.ENXIO,
winerror.ERROR_BAD_EXE_FORMAT: errno.ENOEXEC,
winerror.ERROR_BAD_FORMAT: errno.ENOEXEC,
winerror.ERROR_BAD_LENGTH: errno.EINVAL,
winerror.ERROR_BAD_PATHNAME: errno.ENOENT,
winerror.ERROR_BAD_PIPE: errno.EPIPE,
winerror.ERROR_BAD_UNIT: errno.ENODEV,
winerror.ERROR_BAD_USERNAME: errno.EINVAL,
winerror.ERROR_BROKEN_PIPE: errno.EPIPE,
winerror.ERROR_BUFFER_OVERFLOW: errno.ENAMETOOLONG,
winerror.ERROR_BUSY: errno.EBUSY,
winerror.ERROR_BUSY_DRIVE: errno.EBUSY,
winerror.ERROR_CALL_NOT_IMPLEMENTED: errno.ENOSYS,
winerror.ERROR_CANNOT_MAKE: errno.EACCES,
winerror.ERROR_CANTOPEN: errno.EIO,
winerror.ERROR_CANTREAD: errno.EIO,
winerror.ERROR_CANTWRITE: errno.EIO,
winerror.ERROR_CRC: errno.EIO,
winerror.ERROR_CURRENT_DIRECTORY: errno.EACCES,
winerror.ERROR_DEVICE_IN_USE: errno.EBUSY,
winerror.ERROR_DEV_NOT_EXIST: errno.ENODEV,
winerror.ERROR_DIRECTORY: errno.EINVAL,
winerror.ERROR_DIR_NOT_EMPTY: errno.ENOTEMPTY,
winerror.ERROR_DISK_CHANGE: errno.EIO,
winerror.ERROR_DISK_FULL: errno.ENOSPC,
winerror.ERROR_DRIVE_LOCKED: errno.EBUSY,
winerror.ERROR_ENVVAR_NOT_FOUND: errno.EINVAL,
winerror.ERROR_EXE_MARKED_INVALID: errno.ENOEXEC,
winerror.ERROR_FILENAME_EXCED_RANGE: errno.ENAMETOOLONG,
winerror.ERROR_FILE_EXISTS: errno.EEXIST,
winerror.ERROR_FILE_INVALID: errno.ENODEV,
winerror.ERROR_FILE_NOT_FOUND: errno.ENOENT,
winerror.ERROR_GEN_FAILURE: errno.EIO,
winerror.ERROR_HANDLE_DISK_FULL: errno.ENOSPC,
winerror.ERROR_INSUFFICIENT_BUFFER: errno.ENOMEM,
winerror.ERROR_INVALID_ACCESS: errno.EACCES,
winerror.ERROR_INVALID_ADDRESS: errno.EFAULT,
winerror.ERROR_INVALID_BLOCK: errno.EFAULT,
winerror.ERROR_INVALID_DATA: errno.EINVAL,
winerror.ERROR_INVALID_DRIVE: errno.ENODEV,
winerror.ERROR_INVALID_EXE_SIGNATURE: errno.ENOEXEC,
winerror.ERROR_INVALID_FLAGS: errno.EINVAL,
winerror.ERROR_INVALID_FUNCTION: errno.ENOSYS,
winerror.ERROR_INVALID_HANDLE: errno.EBADF,
winerror.ERROR_INVALID_LOGON_HOURS: errno.EACCES,
winerror.ERROR_INVALID_NAME: errno.EINVAL,
winerror.ERROR_INVALID_OWNER: errno.EINVAL,
winerror.ERROR_INVALID_PARAMETER: errno.EINVAL,
winerror.ERROR_INVALID_PASSWORD: errno.EPERM,
winerror.ERROR_INVALID_PRIMARY_GROUP: errno.EINVAL,
winerror.ERROR_INVALID_SIGNAL_NUMBER: errno.EINVAL,
winerror.ERROR_INVALID_TARGET_HANDLE: errno.EIO,
winerror.ERROR_INVALID_WORKSTATION: errno.EACCES,
winerror.ERROR_IO_DEVICE: errno.EIO,
winerror.ERROR_IO_INCOMPLETE: errno.EINTR,
winerror.ERROR_LOCKED: errno.EBUSY,
winerror.ERROR_LOCK_VIOLATION: errno.EACCES,
winerror.ERROR_LOGON_FAILURE: errno.EACCES,
winerror.ERROR_MAPPED_ALIGNMENT: errno.EINVAL,
winerror.ERROR_META_EXPANSION_TOO_LONG: errno.E2BIG,
winerror.ERROR_MORE_DATA: errno.EPIPE,
winerror.ERROR_NEGATIVE_SEEK: errno.ESPIPE,
winerror.ERROR_NOACCESS: errno.EFAULT,
winerror.ERROR_NONE_MAPPED: errno.EINVAL,
winerror.ERROR_NOT_ENOUGH_MEMORY: errno.ENOMEM,
winerror.ERROR_NOT_READY: errno.EAGAIN,
winerror.ERROR_NOT_SAME_DEVICE: errno.EXDEV,
winerror.ERROR_NO_DATA: errno.EPIPE,
winerror.ERROR_NO_MORE_SEARCH_HANDLES: errno.EIO,
winerror.ERROR_NO_PROC_SLOTS: errno.EAGAIN,
winerror.ERROR_NO_SUCH_PRIVILEGE: errno.EACCES,
winerror.ERROR_OPEN_FAILED: errno.EIO,
winerror.ERROR_OPEN_FILES: errno.EBUSY,
winerror.ERROR_OPERATION_ABORTED: errno.EINTR,
winerror.ERROR_OUTOFMEMORY: errno.ENOMEM,
winerror.ERROR_PASSWORD_EXPIRED: errno.EACCES,
winerror.ERROR_PATH_BUSY: errno.EBUSY,
Vadim Gelfer
fix file handling bugs on windows....
r2176 winerror.ERROR_PATH_NOT_FOUND: errno.ENOENT,
Vadim Gelfer
fix exception handling on windows....
r2054 winerror.ERROR_PIPE_BUSY: errno.EBUSY,
winerror.ERROR_PIPE_CONNECTED: errno.EPIPE,
winerror.ERROR_PIPE_LISTENING: errno.EPIPE,
winerror.ERROR_PIPE_NOT_CONNECTED: errno.EPIPE,
winerror.ERROR_PRIVILEGE_NOT_HELD: errno.EACCES,
winerror.ERROR_READ_FAULT: errno.EIO,
winerror.ERROR_SEEK: errno.EIO,
winerror.ERROR_SEEK_ON_DEVICE: errno.ESPIPE,
winerror.ERROR_SHARING_BUFFER_EXCEEDED: errno.ENFILE,
winerror.ERROR_SHARING_VIOLATION: errno.EACCES,
winerror.ERROR_STACK_OVERFLOW: errno.ENOMEM,
winerror.ERROR_SWAPERROR: errno.ENOENT,
winerror.ERROR_TOO_MANY_MODULES: errno.EMFILE,
winerror.ERROR_TOO_MANY_OPEN_FILES: errno.EMFILE,
winerror.ERROR_UNRECOGNIZED_MEDIA: errno.ENXIO,
winerror.ERROR_UNRECOGNIZED_VOLUME: errno.ENODEV,
winerror.ERROR_WAIT_NO_CHILDREN: errno.ECHILD,
winerror.ERROR_WRITE_FAULT: errno.EIO,
winerror.ERROR_WRITE_PROTECT: errno.EROFS,
}
def __init__(self, err):
self.win_errno, self.win_function, self.win_strerror = err
Vadim Gelfer
fix file handling bugs on windows....
r2176 if self.win_strerror.endswith('.'):
self.win_strerror = self.win_strerror[:-1]
class WinIOError(WinError, IOError):
def __init__(self, err, filename=None):
WinError.__init__(self, err)
IOError.__init__(self, self.winerror_map.get(self.win_errno, 0),
self.win_strerror)
self.filename = filename
class WinOSError(WinError, OSError):
def __init__(self, err):
WinError.__init__(self, err)
Vadim Gelfer
fix exception handling on windows....
r2054 OSError.__init__(self, self.winerror_map.get(self.win_errno, 0),
self.win_strerror)
def os_link(src, dst):
try:
win32file.CreateHardLink(dst, src)
Patrick Mezard
util_win32: make os_link more robust (issue 761)...
r5879 # CreateHardLink sometimes succeeds on mapped drives but
# following nlinks() returns 1. Check it now and bail out.
if nlinks(src) < 2:
try:
win32file.DeleteFile(dst)
except:
pass
# Fake hardlinking error
raise WinOSError((18, 'CreateHardLink', 'The system cannot '
'move the file to a different disk drive'))
Vadim Gelfer
fix exception handling on windows....
r2054 except pywintypes.error, details:
Vadim Gelfer
fix file handling bugs on windows....
r2176 raise WinOSError(details)
Vadim Gelfer
fix exception handling on windows....
r2054
def nlinks(pathname):
"""Return number of hardlinks for the given file."""
try:
fh = win32file.CreateFile(pathname,
win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
None, win32file.OPEN_EXISTING, 0, None)
res = win32file.GetFileInformationByHandle(fh)
fh.Close()
return res[7]
except pywintypes.error:
Vadim Gelfer
replace os.stat with os.lstat in some where.
r2448 return os.lstat(pathname).st_nlink
Vadim Gelfer
fix exception handling on windows....
r2054
def testpid(pid):
'''return True if pid is still running or unable to
determine, False otherwise'''
try:
handle = win32api.OpenProcess(
win32con.PROCESS_QUERY_INFORMATION, False, pid)
if handle:
status = win32process.GetExitCodeProcess(handle)
return status == win32con.STILL_ACTIVE
except pywintypes.error, details:
return details[0] != winerror.ERROR_INVALID_PARAMETER
return True
Matt Mackall
merge: add registry look up bits to tool search
r6006 def lookup_reg(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).
'''
try:
from _winreg import HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, \
QueryValueEx, OpenKey
except ImportError:
return None
if scope is None:
scope = (HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE)
elif not isinstance(scope, (list, tuple)):
scope = (scope,)
for s in scope:
Matt Mackall
util: disinfect lookup_reg strings (issue1126)...
r6880 try:
Remy Roy
Folding correction and missing import
r6881 val = QueryValueEx(OpenKey(s, key), valname)[0]
Matt Mackall
util: disinfect lookup_reg strings (issue1126)...
r6880 # never let a Unicode string escape into the wild
return util.tolocal(val.encode('UTF-8'))
except EnvironmentError:
pass
Matt Mackall
merge: add registry look up bits to tool search
r6006
Vadim Gelfer
fix issue 217....
r2117 def system_rcpath_win32():
Vadim Gelfer
fix exception handling on windows....
r2054 '''return default os-specific hgrc search path'''
proc = win32api.GetCurrentProcess()
Volker Kleinfeld
win98: fall back to win32api.GetModuleFileName if needed.
r2285 try:
# This will fail on windows < NT
filename = win32process.GetModuleFileNameEx(proc, 0)
except:
filename = win32api.GetModuleFileName(0)
Steve Borho
win32: favor local mercurial.ini over registry key...
r5619 # Use mercurial.ini found in directory with hg.exe
progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
if os.path.isfile(progrc):
return [progrc]
# else look for a system rcpath in the registry
Steve Borho
win32: read system rcpath from registry...
r5583 try:
value = win32api.RegQueryValue(
win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Mercurial')
rcpath = []
for p in value.split(os.pathsep):
if p.lower().endswith('mercurial.ini'):
rcpath.append(p)
elif os.path.isdir(p):
for f, kind in osutil.listdir(p):
if f.endswith('.rc'):
rcpath.append(os.path.join(p, f))
return rcpath
except pywintypes.error:
Steve Borho
win32: favor local mercurial.ini over registry key...
r5619 return []
Vadim Gelfer
fix file handling bugs on windows....
r2176
Alexis S. L. Carvalho
util_win32.py: fix user_rcpath...
r4098 def user_rcpath_win32():
Volker Kleinfeld
On win98 os.path.expanuser('~') does not result in a useable directory....
r2284 '''return os-specific hgrc search path to the user dir'''
userdir = os.path.expanduser('~')
Patrick Mezard
util_win32: fix Windows version checking (issue1358)...
r7427 if sys.getwindowsversion()[3] != 2 and userdir == '~':
Volker Kleinfeld
On win98 os.path.expanuser('~') does not result in a useable directory....
r2284 # We are on win < nt: fetch the APPDATA directory location and use
# the parent directory as the user home dir.
appdir = shell.SHGetPathFromIDList(
Thomas Arendsen Hein
Fixed typo (qshell instead of shell) in win98 code (see issue244).
r2313 shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
Volker Kleinfeld
On win98 os.path.expanuser('~') does not result in a useable directory....
r2284 userdir = os.path.dirname(appdir)
Stefan Rank <strank(AT)strank(DOT)info>
Also search for .hgrc if mercurial.ini not found on windows
r6153 return [os.path.join(userdir, 'mercurial.ini'),
os.path.join(userdir, '.hgrc')]
Volker Kleinfeld
On win98 os.path.expanuser('~') does not result in a useable directory....
r2284
Vadim Gelfer
windows: revlog.lazyparser not always safe to use....
r2250 class posixfile_nt(object):
Vadim Gelfer
fix file handling bugs on windows....
r2176 '''file object with posix-like semantics. on windows, normal
files can not be deleted or renamed if they are open. must open
with win32file.FILE_SHARE_DELETE. this flag does not exist on
Vadim Gelfer
windows: revlog.lazyparser not always safe to use....
r2250 windows < nt, so do not use this class there.'''
Vadim Gelfer
fix file handling bugs on windows....
r2176
# tried to use win32file._open_osfhandle to pass fd to os.fdopen,
# but does not work at all. wrap win32 file api instead.
def __init__(self, name, mode='rb'):
Matt Mackall
posixfile_nt: set closed early...
r5840 self.closed = False
self.name = name
self.mode = mode
Vadim Gelfer
fix file handling bugs on windows....
r2176 access = 0
Shun-ichi GOTO
posixfile_nt: '+' should allow read access....
r4998 if 'r' in mode or '+' in mode:
Vadim Gelfer
fix file handling bugs on windows....
r2176 access |= win32file.GENERIC_READ
Patrick Mezard
posixfile_nt: '+' was understood as read mode instead of update.
r4921 if 'w' in mode or 'a' in mode or '+' in mode:
Vadim Gelfer
fix file handling bugs on windows....
r2176 access |= win32file.GENERIC_WRITE
if 'r' in mode:
creation = win32file.OPEN_EXISTING
elif 'a' in mode:
creation = win32file.OPEN_ALWAYS
else:
creation = win32file.CREATE_ALWAYS
try:
self.handle = win32file.CreateFile(name,
access,
win32file.FILE_SHARE_READ |
win32file.FILE_SHARE_WRITE |
win32file.FILE_SHARE_DELETE,
None,
creation,
win32file.FILE_ATTRIBUTE_NORMAL,
0)
except pywintypes.error, err:
raise WinIOError(err, name)
Christian Boos
The posixfile implemented using the win32 API should be iterable.
r2243 def __iter__(self):
Patrick Mezard
util_win32: implement posixfile_nt.readlines()
r7390 for line in self.readlines():
Christian Boos
The posixfile implemented using the win32 API should be iterable.
r2243 yield line
Vadim Gelfer
fix file handling bugs on windows....
r2176 def read(self, count=-1):
try:
cs = cStringIO.StringIO()
while count:
wincount = int(count)
if wincount == -1:
wincount = 1048576
val, data = win32file.ReadFile(self.handle, wincount)
if not data: break
cs.write(data)
if count != -1:
count -= len(data)
return cs.getvalue()
except pywintypes.error, err:
raise WinIOError(err)
Patrick Mezard
util_win32: implement posixfile_nt.readlines()
r7390 def readlines(self, sizehint=None):
# splitlines() splits on single '\r' while readlines()
# does not. cStringIO has a well behaving readlines() and is fast.
return cStringIO.StringIO(self.read()).readlines()
Vadim Gelfer
fix file handling bugs on windows....
r2176 def write(self, data):
try:
if 'a' in self.mode:
win32file.SetFilePointer(self.handle, 0, win32file.FILE_END)
nwrit = 0
while nwrit < len(data):
val, nwrit = win32file.WriteFile(self.handle, data)
data = data[nwrit:]
except pywintypes.error, err:
raise WinIOError(err)
Patrick Mezard
util_win32: implement posixfile_nt.writelines()...
r5847 def writelines(self, sequence):
for s in sequence:
self.write(s)
Vadim Gelfer
fix file handling bugs on windows....
r2176 def seek(self, pos, whence=0):
try:
win32file.SetFilePointer(self.handle, int(pos), whence)
except pywintypes.error, err:
raise WinIOError(err)
def tell(self):
try:
return win32file.SetFilePointer(self.handle, 0,
win32file.FILE_CURRENT)
except pywintypes.error, err:
raise WinIOError(err)
def close(self):
if not self.closed:
self.handle = None
self.closed = True
def flush(self):
Matt Mackall
win32: remove excessive flushing...
r5935 # we have no application-level buffering
pass
Vadim Gelfer
fix file handling bugs on windows....
r2176
def truncate(self, pos=0):
try:
win32file.SetFilePointer(self.handle, int(pos),
win32file.FILE_BEGIN)
win32file.SetEndOfFile(self.handle)
except pywintypes.error, err:
raise WinIOError(err)
Benoit Boissinot
only print a warning when no username is specified...
r3721
getuser_fallback = win32api.GetUserName
Marcos Chaves
Handle CTRL+C in serve under Windows.
r4672
Nathan Jones
Fix serve on Windows without win32* modules.
r4803 def set_signal_handler_win32():
Marcos Chaves
Handle CTRL+C in serve under Windows.
r4672 """Register a termination handler for console events including
CTRL+C. python signal handlers do not work well with socket
operations.
"""
def handler(event):
win32process.ExitProcess(1)
win32api.SetConsoleCtrlHandler(handler)