1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
# 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.
"""Utility functions that use win32 API.
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
import errno, os, sys, pywintypes, win32con, win32file, win32process
import winerror, win32gui, win32console
import osutil, encoding
from win32com.shell import shell, shellcon
def os_link(src, dst):
try:
win32file.CreateHardLink(dst, src)
except pywintypes.error:
raise OSError(errno.EINVAL, 'target implements hardlinks improperly')
except NotImplementedError: # Another fake error win Win98
raise OSError(errno.EINVAL, 'Hardlinking not supported')
def _getfileinfo(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)
except pywintypes.error:
raise OSError(errno.ENOENT, 'The system cannot find the file specified')
try:
return win32file.GetFileInformationByHandle(fh)
finally:
fh.Close()
def nlinks(pathname):
"""Return number of hardlinks for the given file."""
return _getfileinfo(pathname)[7]
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)
# Index 4 is the volume serial number, and 8 and 9 contain the file ID
return res1[4] == res2[4] and res1[8] == res2[8] and res1[9] == res2[9]
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[4] == res2[4]
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
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:
try:
val = QueryValueEx(OpenKey(s, key), valname)[0]
# never let a Unicode string escape into the wild
return encoding.tolocal(val.encode('UTF-8'))
except EnvironmentError:
pass
def system_rcpath_win32():
'''return default os-specific hgrc search path'''
filename = win32api.GetModuleFileName(0)
# 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]
# Use hgrc.d found in directory with hg.exe
progrcd = os.path.join(os.path.dirname(filename), 'hgrc.d')
if os.path.isdir(progrcd):
rcpath = []
for f, kind in osutil.listdir(progrcd):
if f.endswith('.rc'):
rcpath.append(os.path.join(progrcd, f))
return rcpath
# else look for a system rcpath in the registry
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:
return []
def user_rcpath_win32():
'''return os-specific hgrc search path to the user dir'''
userdir = os.path.expanduser('~')
if sys.getwindowsversion()[3] != 2 and userdir == '~':
# We are on win < nt: fetch the APPDATA directory location and use
# the parent directory as the user home dir.
appdir = shell.SHGetPathFromIDList(
shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
userdir = os.path.dirname(appdir)
return [os.path.join(userdir, 'mercurial.ini'),
os.path.join(userdir, '.hgrc')]
def getuser():
'''return name of current user'''
return win32api.GetUserName()
def set_signal_handler_win32():
"""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)
def hidewindow():
def callback(*args, **kwargs):
hwnd, pid = args
wpid = win32process.GetWindowThreadProcessId(hwnd)[1]
if pid == wpid:
win32gui.ShowWindow(hwnd, win32con.SW_HIDE)
pid = win32process.GetCurrentProcessId()
win32gui.EnumWindows(callback, pid)
def termwidth():
try:
# Query stderr to avoid problems with redirections
screenbuf = win32console.GetStdHandle(win32console.STD_ERROR_HANDLE)
try:
window = screenbuf.GetConsoleScreenBufferInfo()['Window']
width = window.Right - window.Left
return width
finally:
screenbuf.Detach()
except pywintypes.error:
return 79
|