##// END OF EJS Templates
localrepo: sort hg bookmark output...
David Soria Parra -
r13388:a184dbd9 merge default
parent child Browse files
Show More
@@ -0,0 +1,9 b''
1 @echo off
2 rem Double-click this file to (re)build Mercurial for Windows in place.
3 rem Useful for testing and development.
4 cd ..\..
5 del /Q mercurial\*.pyd
6 del /Q mercurial\*.pyc
7 rmdir /Q /S mercurial\locale
8 python setup.py build_py -c -d . build_ext -i build_mo
9 pause
@@ -482,7 +482,7 b' proc makewindow {} {'
482 482 .bar.file add command -label "Quit" -command doquit
483 483 menu .bar.help
484 484 .bar add cascade -label "Help" -menu .bar.help
485 .bar.help add command -label "About gitk" -command about
485 .bar.help add command -label "About hgk" -command about
486 486 . configure -menu .bar
487 487
488 488 if {![info exists geometry(canv1)]} {
@@ -867,9 +867,9 b' proc about {} {'
867 867 return
868 868 }
869 869 toplevel $w
870 wm title $w "About gitk"
870 wm title $w "About hgk"
871 871 message $w.m -text {
872 Gitk version 1.2
872 Hgk version 1.2
873 873
874 874 Copyright � 2005 Paul Mackerras
875 875
@@ -16,23 +16,14 b''
16 16 <File Name="mercurial.parsers.pyd" />
17 17 <File Name="pyexpat.pyd" />
18 18 <File Name="python26.dll" />
19 <File Name="pythoncom26.dll" />
20 <File Name="pywintypes26.dll" />
21 19 <File Name="bz2.pyd" />
22 20 <File Name="select.pyd" />
23 21 <File Name="unicodedata.pyd" />
24 <File Name="win32api.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" />
22 <File Name="_ctypes.pyd" />
31 23 <File Name="_elementtree.pyd" />
32 24 <File Name="_hashlib.pyd" />
33 25 <File Name="_socket.pyd" />
34 26 <File Name="_ssl.pyd" />
35 <File Name="_win32sysloader.pyd" />
36 27 </Component>
37 28 </DirectoryRef>
38 29 </Fragment>
@@ -9,7 +9,7 b''
9 9 <?define contrib.vim.guid = {BB04903A-652D-4C4F-9590-2BD07A2304F2} ?>
10 10
11 11 <!-- dist.wxs -->
12 <?define dist.guid = {0F63D160-0740-4BAF-BF25-0C6930310F51} ?>
12 <?define dist.guid = {C3B634A4-1B05-4A40-94A9-38EE853CF693} ?>
13 13
14 14 <!-- doc.wxs -->
15 15 <?define doc.hg.1.html.guid = {AAAA3FDA-EDC5-4220-B59D-D342722358A2} ?>
@@ -38,7 +38,7 b' def readcurrent(repo):'
38 38 if os.path.exists(repo.join('bookmarks.current')):
39 39 file = repo.opener('bookmarks.current')
40 40 # No readline() in posixfile_nt, reading everything is cheap
41 mark = (file.readlines() or [''])[0]
41 mark = encoding.tolocal((file.readlines() or [''])[0])
42 42 if mark == '':
43 43 mark = None
44 44 file.close()
@@ -251,11 +251,6 b' class bundlerepository(localrepo.localre'
251 251 self.bundle.close()
252 252 if self.tempfile is not None:
253 253 os.unlink(self.tempfile)
254
255 def __del__(self):
256 del self.bundle
257 if self.tempfile is not None:
258 os.unlink(self.tempfile)
259 254 if self._tempparent:
260 255 shutil.rmtree(self._tempparent, True)
261 256
@@ -806,6 +806,9 b' class changeset_printer(object):'
806 806 if branch != 'default':
807 807 self.ui.write(_("branch: %s\n") % branch,
808 808 label='log.branch')
809 for bookmark in self.repo.nodebookmarks(changenode):
810 self.ui.write(_("bookmark: %s\n") % bookmark,
811 label='log.bookmark')
809 812 for tag in self.repo.nodetags(changenode):
810 813 self.ui.write(_("tag: %s\n") % tag,
811 814 label='log.tag')
@@ -530,7 +530,7 b' def bookmark(ui, repo, mark=None, rev=No'
530 530 if len(marks) == 0:
531 531 ui.status(_("no bookmarks set\n"))
532 532 else:
533 for bmark, n in marks.iteritems():
533 for bmark, n in sorted(marks.iteritems()):
534 534 if ui.configbool('bookmarks', 'track.current'):
535 535 current = repo._bookmarkcurrent
536 536 if bmark == current and n == cur:
@@ -114,6 +114,8 b' class changectx(object):'
114 114 return self._changeset[5]
115 115 def tags(self):
116 116 return self._repo.nodetags(self._node)
117 def bookmarks(self):
118 return self._repo.nodebookmarks(self._node)
117 119
118 120 def parents(self):
119 121 """return contexts for each parent changeset"""
@@ -589,8 +589,12 b' def _dispatch(ui, args):'
589 589 msg = ' '.join(' ' in a and repr(a) or a for a in fullargs)
590 590 ui.log("command", msg + "\n")
591 591 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
592 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
593 cmdpats, cmdoptions)
592 try:
593 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
594 cmdpats, cmdoptions)
595 finally:
596 if repo:
597 repo.close()
594 598
595 599 def _runcommand(ui, options, cmd, cmdfunc):
596 600 def checkargs():
@@ -360,7 +360,6 b' class localrepository(repo.repository):'
360 360 if node != nullid:
361 361 tags[encoding.tolocal(name)] = node
362 362 tags['tip'] = self.changelog.tip()
363 tags.update(self._bookmarks)
364 363 tagtypes = dict([(encoding.tolocal(name), value)
365 364 for (name, value) in tagtypes.iteritems()])
366 365 return (tags, tagtypes)
@@ -399,6 +398,13 b' class localrepository(repo.repository):'
399 398 tags.sort()
400 399 return self.nodetagscache.get(node, [])
401 400
401 def nodebookmarks(self, node):
402 marks = []
403 for bookmark, n in self._bookmarks.iteritems():
404 if n == node:
405 marks.append(bookmark)
406 return sorted(marks)
407
402 408 def _branchtags(self, partial, lrev):
403 409 # TODO: rename this function?
404 410 tiprev = len(self) - 1
@@ -13,6 +13,7 b' posixfile = open'
13 13 nulldev = '/dev/null'
14 14 normpath = os.path.normpath
15 15 samestat = os.path.samestat
16 os_link = os.link
16 17 unlink = os.unlink
17 18 rename = os.rename
18 19 expandglobs = False
@@ -24,6 +25,10 b' def openhardlinks():'
24 25 '''return true if it is safe to hold open file handles to hardlinks'''
25 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 32 def rcfiles(path):
28 33 rcs = [os.path.join(path, 'hgrc')]
29 34 rcdir = os.path.join(path, 'hgrc.d')
@@ -35,3 +35,6 b' class repository(object):'
35 35
36 36 def cancopy(self):
37 37 return self.local()
38
39 def close(self):
40 pass
@@ -153,6 +153,10 b' def showbranches(**args):'
153 153 if branch != 'default':
154 154 return showlist('branch', [branch], plural='branches', **args)
155 155
156 def showbookmarks(**args):
157 bookmarks = args['ctx'].bookmarks()
158 return showlist('bookmark', bookmarks, **args)
159
156 160 def showchildren(**args):
157 161 ctx = args['ctx']
158 162 childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
@@ -252,6 +256,7 b' keywords = {'
252 256 'author': showauthor,
253 257 'branch': showbranch,
254 258 'branches': showbranches,
259 'bookmarks': showbookmarks,
255 260 'children': showchildren,
256 261 'date': showdate,
257 262 'desc': showdescription,
@@ -1,7 +1,7 b''
1 changeset = 'changeset: {rev}:{node|short}\n{branches}{tags}{parents}user: {author}\ndate: {date|date}\nsummary: {desc|firstline}\n\n'
1 changeset = 'changeset: {rev}:{node|short}\n{branches}{bookmarks}{tags}{parents}user: {author}\ndate: {date|date}\nsummary: {desc|firstline}\n\n'
2 2 changeset_quiet = '{rev}:{node|short}\n'
3 changeset_verbose = 'changeset: {rev}:{node|short}\n{branches}{tags}{parents}user: {author}\ndate: {date|date}\n{files}{file_copies_switch}description:\n{desc|strip}\n\n\n'
4 changeset_debug = 'changeset: {rev}:{node}\n{branches}{tags}{parents}{manifest}user: {author}\ndate: {date|date}\n{file_mods}{file_adds}{file_dels}{file_copies_switch}{extras}description:\n{desc|strip}\n\n\n'
3 changeset_verbose = 'changeset: {rev}:{node|short}\n{branches}{bookmarks}{tags}{parents}user: {author}\ndate: {date|date}\n{files}{file_copies_switch}description:\n{desc|strip}\n\n\n'
4 changeset_debug = 'changeset: {rev}:{node}\n{branches}{bookmarks}{tags}{parents}{manifest}user: {author}\ndate: {date|date}\n{file_mods}{file_adds}{file_dels}{file_copies_switch}{extras}description:\n{desc|strip}\n\n\n'
5 5 start_files = 'files: '
6 6 file = ' {file}'
7 7 end_files = '\n'
@@ -21,4 +21,5 b" parent = 'parent: {rev}:{node|forma"
21 21 manifest = 'manifest: {rev}:{node}\n'
22 22 branch = 'branch: {branch}\n'
23 23 tag = 'tag: {tag}\n'
24 bookmark = 'bookmark: {bookmark}\n'
24 25 extra = 'extra: {key}={value|stringescape}\n'
@@ -1,9 +1,9 b''
1 1 header = '<?xml version="1.0"?>\n<log>\n'
2 2 footer = '</log>\n'
3 3
4 changeset = '<logentry revision="{rev}" node="{node}">\n{branches}{tags}{parents}<author email="{author|email|xmlescape}">{author|person|xmlescape}</author>\n<date>{date|rfc3339date}</date>\n<msg xml:space="preserve">{desc|xmlescape}</msg>\n</logentry>\n'
5 changeset_verbose = '<logentry revision="{rev}" node="{node}">\n{branches}{tags}{parents}<author email="{author|email|xmlescape}">{author|person|xmlescape}</author>\n<date>{date|rfc3339date}</date>\n<msg xml:space="preserve">{desc|xmlescape}</msg>\n<paths>\n{file_adds}{file_dels}{file_mods}</paths>\n{file_copies}</logentry>\n'
6 changeset_debug = '<logentry revision="{rev}" node="{node}">\n{branches}{tags}{parents}<author email="{author|email|xmlescape}">{author|person|xmlescape}</author>\n<date>{date|rfc3339date}</date>\n<msg xml:space="preserve">{desc|xmlescape}</msg>\n<paths>\n{file_adds}{file_dels}{file_mods}</paths>\n{file_copies}{extras}</logentry>\n'
4 changeset = '<logentry revision="{rev}" node="{node}">\n{branches}{bookmarks}{tags}{parents}<author email="{author|email|xmlescape}">{author|person|xmlescape}</author>\n<date>{date|rfc3339date}</date>\n<msg xml:space="preserve">{desc|xmlescape}</msg>\n</logentry>\n'
5 changeset_verbose = '<logentry revision="{rev}" node="{node}">\n{branches}{bookmarks}{tags}{parents}<author email="{author|email|xmlescape}">{author|person|xmlescape}</author>\n<date>{date|rfc3339date}</date>\n<msg xml:space="preserve">{desc|xmlescape}</msg>\n<paths>\n{file_adds}{file_dels}{file_mods}</paths>\n{file_copies}</logentry>\n'
6 changeset_debug = '<logentry revision="{rev}" node="{node}">\n{branches}{bookmarks}{tags}{parents}<author email="{author|email|xmlescape}">{author|person|xmlescape}</author>\n<date>{date|rfc3339date}</date>\n<msg xml:space="preserve">{desc|xmlescape}</msg>\n<paths>\n{file_adds}{file_dels}{file_mods}</paths>\n{file_copies}{extras}</logentry>\n'
7 7
8 8 file_add = '<path action="A">{file_add|xmlescape}</path>\n'
9 9 file_mod = '<path action="M">{file_mod|xmlescape}</path>\n'
@@ -16,4 +16,5 b" end_file_copies = '</copies>\\n'"
16 16 parent = '<parent revision="{rev}" node="{node}" />\n'
17 17 branch = '<branch>{branch|xmlescape}</branch>\n'
18 18 tag = '<tag>{tag|xmlescape}</tag>\n'
19 bookmark = '<bookmark>{bookmark|xmlescape}</bookmark>\n'
19 20 extra = '<extra key="{key|xmlescape}">{value|xmlescape}</extra>\n'
@@ -554,16 +554,6 b' class path_auditor(object):'
554 554 # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
555 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 557 def lookup_reg(key, name=None, scope=None):
568 558 return None
569 559
@@ -5,73 +5,173 b''
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 """Utility functions that use win32 API.
8 import 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
11 Windows. This module overrides definitions in util.py. If not
12 available, import of this module will fail, and generic code will be
13 used.
14 """
72 class _STARTUPINFO(ctypes.Structure):
73 _fields_ = [('cb', _DWORD),
74 ('lpReserved', _LPSTR),
75 ('lpDesktop', _LPSTR),
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
19 import winerror, win32gui, win32console
20 import osutil, encoding
21 from win32com.shell import shell, shellcon
119 _STD_ERROR_HANDLE = 0xfffffff4L # (DWORD)-12
120
121 def _raiseoserror(name):
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 139 def os_link(src, dst):
24 try:
25 win32file.CreateHardLink(dst, 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')
140 if not _kernel32.CreateHardLinkA(dst, src, None):
141 _raiseoserror(src)
30 142
31 def _getfileinfo(pathname):
32 """Return number of hardlinks for the given file."""
33 try:
34 fh = win32file.CreateFile(pathname,
35 win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
36 None, win32file.OPEN_EXISTING, 0, None)
37 except pywintypes.error:
38 raise OSError(errno.ENOENT, 'The system cannot find the file specified')
39 try:
40 return win32file.GetFileInformationByHandle(fh)
41 finally:
42 fh.Close()
43
44 def nlinks(pathname):
45 """Return number of hardlinks for the given file."""
46 return _getfileinfo(pathname)[7]
143 def nlinks(name):
144 '''return number of hardlinks for the given file'''
145 return _getfileinfo(name).nNumberOfLinks
47 146
48 147 def samefile(fpath1, fpath2):
49 """Returns whether fpath1 and fpath2 refer to the same file. This is only
50 guaranteed to work for files, not directories."""
148 '''Returns whether fpath1 and fpath2 refer to the same file. This is only
149 guaranteed to work for files, not directories.'''
51 150 res1 = _getfileinfo(fpath1)
52 151 res2 = _getfileinfo(fpath2)
53 # Index 4 is the volume serial number, and 8 and 9 contain the file ID
54 return res1[4] == res2[4] and res1[8] == res2[8] and res1[9] == res2[9]
152 return (res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
153 and res1.nFileIndexHigh == res2.nFileIndexHigh
154 and res1.nFileIndexLow == res2.nFileIndexLow)
55 155
56 156 def samedevice(fpath1, fpath2):
57 """Returns whether fpath1 and fpath2 are on the same device. This is only
58 guaranteed to work for files, not directories."""
157 '''Returns whether fpath1 and fpath2 are on the same device. This is only
158 guaranteed to work for files, not directories.'''
59 159 res1 = _getfileinfo(fpath1)
60 160 res2 = _getfileinfo(fpath2)
61 return res1[4] == res2[4]
161 return res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
62 162
63 163 def testpid(pid):
64 164 '''return True if pid is still running or unable to
65 165 determine, False otherwise'''
66 try:
67 handle = win32api.OpenProcess(
68 win32con.PROCESS_QUERY_INFORMATION, False, pid)
69 if handle:
70 status = win32process.GetExitCodeProcess(handle)
71 return status == win32con.STILL_ACTIVE
72 except pywintypes.error, details:
73 return details[0] != winerror.ERROR_INVALID_PARAMETER
74 return True
166 h = _kernel32.OpenProcess(_PROCESS_QUERY_INFORMATION, False, pid)
167 if h:
168 try:
169 status = _DWORD()
170 if _kernel32.GetExitCodeProcess(h, ctypes.byref(status)):
171 return status.value == _STILL_ACTIVE
172 finally:
173 _kernel32.CloseHandle(h)
174 return _kernel32.GetLastError() != _ERROR_INVALID_PARAMETER
75 175
76 176 def lookup_reg(key, valname=None, scope=None):
77 177 ''' Look up a key/value name in the Windows registry.
@@ -82,101 +182,137 b' def lookup_reg(key, valname=None, scope='
82 182 a sequence of scopes to look up in order. Default (CURRENT_USER,
83 183 LOCAL_MACHINE).
84 184 '''
85 try:
86 from _winreg import HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, \
87 QueryValueEx, OpenKey
88 except ImportError:
89 return None
90
185 adv = ctypes.windll.advapi32
186 byref = ctypes.byref
91 187 if scope is None:
92 scope = (HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE)
188 scope = (_HKEY_CURRENT_USER, _HKEY_LOCAL_MACHINE)
93 189 elif not isinstance(scope, (list, tuple)):
94 190 scope = (scope,)
95 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
96 196 try:
97 val = QueryValueEx(OpenKey(s, key), valname)[0]
98 # never let a Unicode string escape into the wild
99 return encoding.tolocal(val.encode('UTF-8'))
100 except EnvironmentError:
101 pass
197 size = _DWORD(600)
198 type = _DWORD()
199 buf = ctypes.create_string_buffer(size.value + 1)
200 res = adv.RegQueryValueExA(kh.value, valname, None,
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)
102 213
103 def system_rcpath_win32():
104 '''return default os-specific hgrc search path'''
105 filename = win32api.GetModuleFileName(0)
106 # Use mercurial.ini found in directory with hg.exe
107 progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
108 if os.path.isfile(progrc):
109 return [progrc]
110 # Use hgrc.d found in directory with hg.exe
111 progrcd = os.path.join(os.path.dirname(filename), 'hgrc.d')
112 if os.path.isdir(progrcd):
113 rcpath = []
114 for f, kind in osutil.listdir(progrcd):
115 if f.endswith('.rc'):
116 rcpath.append(os.path.join(progrcd, f))
117 return rcpath
118 # else look for a system rcpath in the registry
119 try:
120 value = win32api.RegQueryValue(
121 win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Mercurial')
122 rcpath = []
123 for p in value.split(os.pathsep):
124 if p.lower().endswith('mercurial.ini'):
125 rcpath.append(p)
126 elif os.path.isdir(p):
127 for f, kind in osutil.listdir(p):
128 if f.endswith('.rc'):
129 rcpath.append(os.path.join(p, f))
130 return rcpath
131 except pywintypes.error:
132 return []
133
134 def user_rcpath_win32():
135 '''return os-specific hgrc search path to the user dir'''
136 userdir = os.path.expanduser('~')
137 if sys.getwindowsversion()[3] != 2 and userdir == '~':
138 # We are on win < nt: fetch the APPDATA directory location and use
139 # the parent directory as the user home dir.
140 appdir = shell.SHGetPathFromIDList(
141 shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA))
142 userdir = os.path.dirname(appdir)
143 return [os.path.join(userdir, 'mercurial.ini'),
144 os.path.join(userdir, '.hgrc')]
214 def executable_path():
215 '''return full path of hg.exe'''
216 size = 600
217 buf = ctypes.create_string_buffer(size + 1)
218 len = _kernel32.GetModuleFileNameA(None, ctypes.byref(buf), size)
219 if len == 0:
220 raise ctypes.WinError()
221 elif len == size:
222 raise ctypes.WinError(_ERROR_INSUFFICIENT_BUFFER)
223 return buf.value
145 224
146 225 def getuser():
147 226 '''return name of current user'''
148 return win32api.GetUserName()
227 adv = ctypes.windll.advapi32
228 size = _DWORD(300)
229 buf = ctypes.create_string_buffer(size.value + 1)
230 if not adv.GetUserNameA(ctypes.byref(buf), ctypes.byref(size)):
231 raise ctypes.WinError()
232 return buf.value
149 233
150 def set_signal_handler_win32():
151 """Register a termination handler for console events including
234 _SIGNAL_HANDLER = ctypes.WINFUNCTYPE(_BOOL, _DWORD)
235 _signal_handler = []
236
237 def set_signal_handler():
238 '''Register a termination handler for console events including
152 239 CTRL+C. python signal handlers do not work well with socket
153 240 operations.
154 """
241 '''
155 242 def handler(event):
156 win32process.ExitProcess(1)
157 win32api.SetConsoleCtrlHandler(handler)
243 _kernel32.ExitProcess(1)
244
245 if _signal_handler:
246 return # already registered
247 h = _SIGNAL_HANDLER(handler)
248 _signal_handler.append(h) # needed to prevent garbage collection
249 if not _kernel32.SetConsoleCtrlHandler(h, True):
250 raise ctypes.WinError()
251
252 _WNDENUMPROC = ctypes.WINFUNCTYPE(_BOOL, _HWND, _LPARAM)
158 253
159 254 def hidewindow():
160 def callback(*args, **kwargs):
161 hwnd, pid = args
162 wpid = win32process.GetWindowThreadProcessId(hwnd)[1]
163 if pid == wpid:
164 win32gui.ShowWindow(hwnd, win32con.SW_HIDE)
255 user32 = ctypes.windll.user32
165 256
166 pid = win32process.GetCurrentProcessId()
167 win32gui.EnumWindows(callback, pid)
257 def callback(hwnd, pid):
258 wpid = _DWORD()
259 user32.GetWindowThreadProcessId(hwnd, ctypes.byref(wpid))
260 if pid == wpid.value:
261 user32.ShowWindow(hwnd, _SW_HIDE)
262 return False # stop enumerating windows
263 return True
264
265 pid = _kernel32.GetCurrentProcessId()
266 user32.EnumWindows(_WNDENUMPROC(callback), pid)
168 267
169 268 def termwidth():
170 try:
171 # Query stderr to avoid problems with redirections
172 screenbuf = win32console.GetStdHandle(win32console.STD_ERROR_HANDLE)
173 if screenbuf is None:
174 return 79
175 try:
176 window = screenbuf.GetConsoleScreenBufferInfo()['Window']
177 width = window.Right - window.Left
178 return width
179 finally:
180 screenbuf.Detach()
181 except pywintypes.error:
182 return 79
269 # cmd.exe does not handle CR like a unix console, the CR is
270 # counted in the line length. On 80 columns consoles, if 80
271 # characters are written, the following CR won't apply on the
272 # current line but on the new one. Keep room for it.
273 width = 79
274 # Query stderr to avoid problems with redirections
275 screenbuf = _kernel32.GetStdHandle(
276 _STD_ERROR_HANDLE) # don't close the handle returned
277 if screenbuf is None or screenbuf == _INVALID_HANDLE_VALUE:
278 return width
279 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
280 if not _kernel32.GetConsoleScreenBufferInfo(
281 screenbuf, ctypes.byref(csbi)):
282 return width
283 width = csbi.srWindow.Right - csbi.srWindow.Left
284 return width
285
286 def spawndetached(args):
287 # No standard library function really spawns a fully detached
288 # process under win32 because they allocate pipes or other objects
289 # to handle standard streams communications. Passing these objects
290 # to the child process requires handle inheritance to be enabled
291 # which makes really detached processes impossible.
292 si = _STARTUPINFO()
293 si.cb = ctypes.sizeof(_STARTUPINFO)
294 si.dwFlags = _STARTF_USESHOWWINDOW
295 si.wShowWindow = _SW_HIDE
296
297 pi = _PROCESS_INFORMATION()
298
299 env = ''
300 for k in os.environ:
301 env += "%s=%s\0" % (k, os.environ[k])
302 if not env:
303 env = '\0'
304 env += '\0'
305
306 args = subprocess.list2cmdline(args)
307 # Not running the command in shell mode makes python26 hang when
308 # writing to hgweb output socket.
309 comspec = os.environ.get("COMSPEC", "cmd.exe")
310 args = comspec + " /c " + args
311
312 res = _kernel32.CreateProcessA(
313 None, args, None, None, False, _DETACHED_PROCESS,
314 env, os.getcwd(), ctypes.byref(si), ctypes.byref(pi))
315 if not res:
316 raise ctypes.WinError()
317
318 return pi.dwProcessId
@@ -71,22 +71,45 b' def _is_win_9x():'
71 71 return 'command' in os.environ.get('comspec', '')
72 72
73 73 def openhardlinks():
74 return not _is_win_9x() and "win32api" in globals()
74 return not _is_win_9x()
75
76 _HKEY_LOCAL_MACHINE = 0x80000002L
75 77
76 78 def system_rcpath():
77 try:
78 return system_rcpath_win32()
79 except:
80 return [r'c:\mercurial\mercurial.ini']
79 '''return default os-specific hgrc search path'''
80 rcpath = []
81 filename = executable_path()
82 # Use mercurial.ini found in directory with hg.exe
83 progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
84 if os.path.isfile(progrc):
85 rcpath.append(progrc)
86 return rcpath
87 # Use hgrc.d found in directory with hg.exe
88 progrcd = os.path.join(os.path.dirname(filename), 'hgrc.d')
89 if os.path.isdir(progrcd):
90 for f, kind in osutil.listdir(progrcd):
91 if f.endswith('.rc'):
92 rcpath.append(os.path.join(progrcd, f))
93 return rcpath
94 # else look for a system rcpath in the registry
95 value = lookup_reg('SOFTWARE\\Mercurial', None, _HKEY_LOCAL_MACHINE)
96 if not isinstance(value, str) or not value:
97 return rcpath
98 value = value.replace('/', os.sep)
99 for p in value.split(os.pathsep):
100 if p.lower().endswith('mercurial.ini'):
101 rcpath.append(p)
102 elif os.path.isdir(p):
103 for f, kind in osutil.listdir(p):
104 if f.endswith('.rc'):
105 rcpath.append(os.path.join(p, f))
106 return rcpath
81 107
82 108 def user_rcpath():
83 109 '''return os-specific hgrc search path to the user dir'''
84 try:
85 path = user_rcpath_win32()
86 except:
87 home = os.path.expanduser('~')
88 path = [os.path.join(home, 'mercurial.ini'),
89 os.path.join(home, '.hgrc')]
110 home = os.path.expanduser('~')
111 path = [os.path.join(home, 'mercurial.ini'),
112 os.path.join(home, '.hgrc')]
90 113 userprofile = os.environ.get('USERPROFILE')
91 114 if userprofile:
92 115 path.append(os.path.join(userprofile, 'mercurial.ini'))
@@ -106,10 +129,6 b' def sshargs(sshcmd, host, user, port):'
106 129 args = user and ("%s@%s" % (user, host)) or host
107 130 return port and ("%s %s %s" % (args, pflag, port)) or args
108 131
109 def testpid(pid):
110 '''return False if pid dead, True if running or not known'''
111 return True
112
113 132 def set_flags(f, l, x):
114 133 pass
115 134
@@ -208,12 +227,6 b' def find_exe(command):'
208 227 return executable
209 228 return findexisting(os.path.expanduser(os.path.expandvars(command)))
210 229
211 def set_signal_handler():
212 try:
213 set_signal_handler_win32()
214 except NameError:
215 pass
216
217 230 def statfiles(files):
218 231 '''Stat each file in files and yield stat or None if file does not exist.
219 232 Cluster and cache stat per directory to minimize number of OS stat calls.'''
@@ -241,11 +254,6 b' def statfiles(files):'
241 254 cache = dircache.setdefault(dir, dmap)
242 255 yield cache.get(base, None)
243 256
244 def getuser():
245 '''return name of current user'''
246 raise error.Abort(_('user name not available - set USERNAME '
247 'environment variable'))
248
249 257 def username(uid=None):
250 258 """Return the name of the user with the given uid.
251 259
@@ -335,37 +343,6 b' def rename(src, dst):'
335 343 unlink(dst)
336 344 os.rename(src, dst)
337 345
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 346 def gethgcmd():
370 347 return [sys.executable] + sys.argv[:1]
371 348
@@ -380,10 +357,6 b' def groupmembers(name):'
380 357 # Don't support groups on Windows for now
381 358 raise KeyError()
382 359
383 try:
384 # override functions with win32 versions if possible
385 from win32 import *
386 except ImportError:
387 pass
360 from win32 import *
388 361
389 362 expandglobs = True
@@ -48,8 +48,8 b' import bookmark by name'
48 48 no changes found
49 49 importing bookmark X
50 50 $ hg bookmark
51 X 0:4e3505fd9583
51 52 Y 0:4e3505fd9583
52 X 0:4e3505fd9583
53 53
54 54 export bookmark by name
55 55
@@ -62,10 +62,10 b' export bookmark by name'
62 62 no changes found
63 63 exporting bookmark W
64 64 $ hg -R ../a bookmarks
65 Y 0:4e3505fd9583
65 W -1:000000000000
66 66 X 0:4e3505fd9583
67 Y 0:4e3505fd9583
67 68 * Z 0:4e3505fd9583
68 W -1:000000000000
69 69
70 70 delete a remote bookmark
71 71
@@ -97,8 +97,8 b' divergent bookmarks'
97 97 adding f1
98 98 $ hg book -f X
99 99 $ hg book
100 * X 1:0d2164f0ce0d
100 101 Y 0:4e3505fd9583
101 * X 1:0d2164f0ce0d
102 102 Z 1:0d2164f0ce0d
103 103
104 104 $ cd ../b
@@ -109,8 +109,8 b' divergent bookmarks'
109 109 adding f2
110 110 $ hg book -f X
111 111 $ hg book
112 * X 1:9b140be10808
112 113 Y 0:4e3505fd9583
113 * X 1:9b140be10808
114 114 foo -1:000000000000
115 115 foobar -1:000000000000
116 116
@@ -124,8 +124,8 b' divergent bookmarks'
124 124 not updating divergent bookmark X
125 125 (run 'hg heads' to see heads, 'hg merge' to merge)
126 126 $ hg book
127 * X 1:9b140be10808
127 128 Y 0:4e3505fd9583
128 * X 1:9b140be10808
129 129 foo -1:000000000000
130 130 foobar -1:000000000000
131 131 $ hg push -f ../a
@@ -136,8 +136,8 b' divergent bookmarks'
136 136 adding file changes
137 137 added 1 changesets with 1 changes to 1 files (+1 heads)
138 138 $ hg -R ../a book
139 * X 1:0d2164f0ce0d
139 140 Y 0:4e3505fd9583
140 * X 1:0d2164f0ce0d
141 141 Z 1:0d2164f0ce0d
142 142
143 143 hgweb
@@ -31,8 +31,8 b' initialize repository'
31 31 bookmark list
32 32
33 33 $ hg bookmark
34 one 1:925d80f479bb
34 35 * two 3:2ae46b1d99a7
35 one 1:925d80f479bb
36 36
37 37 rebase
38 38
@@ -41,9 +41,9 b' rebase'
41 41
42 42 $ hg log
43 43 changeset: 3:9163974d1cb5
44 tag: one
44 bookmark: one
45 bookmark: two
45 46 tag: tip
46 tag: two
47 47 parent: 1:925d80f479bb
48 48 parent: 2:db815d6d32e6
49 49 user: test
@@ -36,7 +36,7 b' look up bookmark'
36 36
37 37 $ hg log -r X
38 38 changeset: 0:f7b1eb17ad24
39 tag: X
39 bookmark: X
40 40 tag: tip
41 41 user: test
42 42 date: Thu Jan 01 00:00:00 1970 +0000
@@ -54,8 +54,8 b' bookmark rev -1 again'
54 54 list bookmarks
55 55
56 56 $ hg bookmarks
57 * X 0:f7b1eb17ad24
57 58 * X2 0:f7b1eb17ad24
58 * X 0:f7b1eb17ad24
59 59 Y -1:000000000000
60 60
61 61 $ echo b > b
@@ -66,8 +66,8 b' bookmarks revset'
66 66
67 67 $ hg log -r 'bookmark()'
68 68 changeset: 1:925d80f479bb
69 tag: X
70 tag: X2
69 bookmark: X
70 bookmark: X2
71 71 tag: tip
72 72 user: test
73 73 date: Thu Jan 01 00:00:00 1970 +0000
@@ -76,8 +76,8 b' bookmarks revset'
76 76 $ hg log -r 'bookmark(Y)'
77 77 $ hg log -r 'bookmark(X2)'
78 78 changeset: 1:925d80f479bb
79 tag: X
80 tag: X2
79 bookmark: X
80 bookmark: X2
81 81 tag: tip
82 82 user: test
83 83 date: Thu Jan 01 00:00:00 1970 +0000
@@ -89,8 +89,8 b' bookmarks revset'
89 89 bookmarks X and X2 moved to rev 1, Y at rev -1
90 90
91 91 $ hg bookmarks
92 * X 1:925d80f479bb
92 93 * X2 1:925d80f479bb
93 * X 1:925d80f479bb
94 94 Y -1:000000000000
95 95
96 96 bookmark rev 0 again
@@ -104,10 +104,10 b' bookmark rev 0 again'
104 104 bookmarks X and X2 moved to rev 2, Y at rev -1, Z at rev 0
105 105
106 106 $ hg bookmarks
107 * X 2:0316ce92851d
107 108 * X2 2:0316ce92851d
108 * X 2:0316ce92851d
109 Y -1:000000000000
109 110 Z 0:f7b1eb17ad24
110 Y -1:000000000000
111 111
112 112 rename nonexistent bookmark
113 113
@@ -166,10 +166,10 b' look up stripped bookmark name'
166 166
167 167 $ hg log -r '"x y"'
168 168 changeset: 2:0316ce92851d
169 tag: X2
170 tag: Y
169 bookmark: X2
170 bookmark: Y
171 bookmark: x y
171 172 tag: tip
172 tag: x y
173 173 user: test
174 174 date: Thu Jan 01 00:00:00 1970 +0000
175 175 summary: 2
@@ -188,6 +188,13 b' Log -R full.hg in fresh empty'
188 188 date: Thu Jan 01 00:00:00 1970 +0000
189 189 summary: 0.0
190 190
191 Make sure bundlerepo doesn't leak tempfiles (issue2491)
192
193 $ ls .hg
194 00changelog.i
195 cache
196 requires
197 store
191 198
192 199 Pull ../full.hg into empty (with hook)
193 200
General Comments 0
You need to be logged in to leave comments. Login now