diff --git a/contrib/hgk b/contrib/hgk
--- a/contrib/hgk
+++ b/contrib/hgk
@@ -482,7 +482,7 @@ proc makewindow {} {
.bar.file add command -label "Quit" -command doquit
menu .bar.help
.bar add cascade -label "Help" -menu .bar.help
- .bar.help add command -label "About gitk" -command about
+ .bar.help add command -label "About hgk" -command about
. configure -menu .bar
if {![info exists geometry(canv1)]} {
@@ -867,9 +867,9 @@ proc about {} {
return
}
toplevel $w
- wm title $w "About gitk"
+ wm title $w "About hgk"
message $w.m -text {
-Gitk version 1.2
+Hgk version 1.2
Copyright © 2005 Paul Mackerras
diff --git a/contrib/win32/buildlocal.bat b/contrib/win32/buildlocal.bat
new file mode 100644
--- /dev/null
+++ b/contrib/win32/buildlocal.bat
@@ -0,0 +1,9 @@
+@echo off
+rem Double-click this file to (re)build Mercurial for Windows in place.
+rem Useful for testing and development.
+cd ..\..
+del /Q mercurial\*.pyd
+del /Q mercurial\*.pyc
+rmdir /Q /S mercurial\locale
+python setup.py build_py -c -d . build_ext -i build_mo
+pause
diff --git a/contrib/wix/dist.wxs b/contrib/wix/dist.wxs
--- a/contrib/wix/dist.wxs
+++ b/contrib/wix/dist.wxs
@@ -16,23 +16,14 @@
-
-
-
-
-
-
-
-
-
+
-
diff --git a/contrib/wix/guids.wxi b/contrib/wix/guids.wxi
--- a/contrib/wix/guids.wxi
+++ b/contrib/wix/guids.wxi
@@ -9,7 +9,7 @@
-
+
diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py
--- a/mercurial/bookmarks.py
+++ b/mercurial/bookmarks.py
@@ -38,7 +38,7 @@ def readcurrent(repo):
if os.path.exists(repo.join('bookmarks.current')):
file = repo.opener('bookmarks.current')
# No readline() in posixfile_nt, reading everything is cheap
- mark = (file.readlines() or [''])[0]
+ mark = encoding.tolocal((file.readlines() or [''])[0])
if mark == '':
mark = None
file.close()
diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py
--- a/mercurial/bundlerepo.py
+++ b/mercurial/bundlerepo.py
@@ -251,11 +251,6 @@ class bundlerepository(localrepo.localre
self.bundle.close()
if self.tempfile is not None:
os.unlink(self.tempfile)
-
- def __del__(self):
- del self.bundle
- if self.tempfile is not None:
- os.unlink(self.tempfile)
if self._tempparent:
shutil.rmtree(self._tempparent, True)
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -806,6 +806,9 @@ class changeset_printer(object):
if branch != 'default':
self.ui.write(_("branch: %s\n") % branch,
label='log.branch')
+ for bookmark in self.repo.nodebookmarks(changenode):
+ self.ui.write(_("bookmark: %s\n") % bookmark,
+ label='log.bookmark')
for tag in self.repo.nodetags(changenode):
self.ui.write(_("tag: %s\n") % tag,
label='log.tag')
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -530,7 +530,7 @@ def bookmark(ui, repo, mark=None, rev=No
if len(marks) == 0:
ui.status(_("no bookmarks set\n"))
else:
- for bmark, n in marks.iteritems():
+ for bmark, n in sorted(marks.iteritems()):
if ui.configbool('bookmarks', 'track.current'):
current = repo._bookmarkcurrent
if bmark == current and n == cur:
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -114,6 +114,8 @@ class changectx(object):
return self._changeset[5]
def tags(self):
return self._repo.nodetags(self._node)
+ def bookmarks(self):
+ return self._repo.nodebookmarks(self._node)
def parents(self):
"""return contexts for each parent changeset"""
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -589,8 +589,12 @@ def _dispatch(ui, args):
msg = ' '.join(' ' in a and repr(a) or a for a in fullargs)
ui.log("command", msg + "\n")
d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
- return runcommand(lui, repo, cmd, fullargs, ui, options, d,
- cmdpats, cmdoptions)
+ try:
+ return runcommand(lui, repo, cmd, fullargs, ui, options, d,
+ cmdpats, cmdoptions)
+ finally:
+ if repo:
+ repo.close()
def _runcommand(ui, options, cmd, cmdfunc):
def checkargs():
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -360,7 +360,6 @@ class localrepository(repo.repository):
if node != nullid:
tags[encoding.tolocal(name)] = node
tags['tip'] = self.changelog.tip()
- tags.update(self._bookmarks)
tagtypes = dict([(encoding.tolocal(name), value)
for (name, value) in tagtypes.iteritems()])
return (tags, tagtypes)
@@ -399,6 +398,13 @@ class localrepository(repo.repository):
tags.sort()
return self.nodetagscache.get(node, [])
+ def nodebookmarks(self, node):
+ marks = []
+ for bookmark, n in self._bookmarks.iteritems():
+ if n == node:
+ marks.append(bookmark)
+ return sorted(marks)
+
def _branchtags(self, partial, lrev):
# TODO: rename this function?
tiprev = len(self) - 1
diff --git a/mercurial/posix.py b/mercurial/posix.py
--- a/mercurial/posix.py
+++ b/mercurial/posix.py
@@ -13,6 +13,7 @@ posixfile = open
nulldev = '/dev/null'
normpath = os.path.normpath
samestat = os.path.samestat
+os_link = os.link
unlink = os.unlink
rename = os.rename
expandglobs = False
@@ -24,6 +25,10 @@ def openhardlinks():
'''return true if it is safe to hold open file handles to hardlinks'''
return True
+def nlinks(name):
+ '''return number of hardlinks for the given file'''
+ return os.lstat(name).st_nlink
+
def rcfiles(path):
rcs = [os.path.join(path, 'hgrc')]
rcdir = os.path.join(path, 'hgrc.d')
diff --git a/mercurial/repo.py b/mercurial/repo.py
--- a/mercurial/repo.py
+++ b/mercurial/repo.py
@@ -35,3 +35,6 @@ class repository(object):
def cancopy(self):
return self.local()
+
+ def close(self):
+ pass
diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
--- a/mercurial/templatekw.py
+++ b/mercurial/templatekw.py
@@ -153,6 +153,10 @@ def showbranches(**args):
if branch != 'default':
return showlist('branch', [branch], plural='branches', **args)
+def showbookmarks(**args):
+ bookmarks = args['ctx'].bookmarks()
+ return showlist('bookmark', bookmarks, **args)
+
def showchildren(**args):
ctx = args['ctx']
childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
@@ -252,6 +256,7 @@ keywords = {
'author': showauthor,
'branch': showbranch,
'branches': showbranches,
+ 'bookmarks': showbookmarks,
'children': showchildren,
'date': showdate,
'desc': showdescription,
diff --git a/mercurial/templates/map-cmdline.default b/mercurial/templates/map-cmdline.default
--- a/mercurial/templates/map-cmdline.default
+++ b/mercurial/templates/map-cmdline.default
@@ -1,7 +1,7 @@
-changeset = 'changeset: {rev}:{node|short}\n{branches}{tags}{parents}user: {author}\ndate: {date|date}\nsummary: {desc|firstline}\n\n'
+changeset = 'changeset: {rev}:{node|short}\n{branches}{bookmarks}{tags}{parents}user: {author}\ndate: {date|date}\nsummary: {desc|firstline}\n\n'
changeset_quiet = '{rev}:{node|short}\n'
-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'
-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'
+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'
+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'
start_files = 'files: '
file = ' {file}'
end_files = '\n'
@@ -21,4 +21,5 @@ parent = 'parent: {rev}:{node|forma
manifest = 'manifest: {rev}:{node}\n'
branch = 'branch: {branch}\n'
tag = 'tag: {tag}\n'
+bookmark = 'bookmark: {bookmark}\n'
extra = 'extra: {key}={value|stringescape}\n'
diff --git a/mercurial/templates/map-cmdline.xml b/mercurial/templates/map-cmdline.xml
--- a/mercurial/templates/map-cmdline.xml
+++ b/mercurial/templates/map-cmdline.xml
@@ -1,9 +1,9 @@
header = '\n\n'
footer = '\n'
-changeset = '\n{branches}{tags}{parents}{author|person|xmlescape}\n{date|rfc3339date}\n{desc|xmlescape}\n\n'
-changeset_verbose = '\n{branches}{tags}{parents}{author|person|xmlescape}\n{date|rfc3339date}\n{desc|xmlescape}\n\n{file_adds}{file_dels}{file_mods}\n{file_copies}\n'
-changeset_debug = '\n{branches}{tags}{parents}{author|person|xmlescape}\n{date|rfc3339date}\n{desc|xmlescape}\n\n{file_adds}{file_dels}{file_mods}\n{file_copies}{extras}\n'
+changeset = '\n{branches}{bookmarks}{tags}{parents}{author|person|xmlescape}\n{date|rfc3339date}\n{desc|xmlescape}\n\n'
+changeset_verbose = '\n{branches}{bookmarks}{tags}{parents}{author|person|xmlescape}\n{date|rfc3339date}\n{desc|xmlescape}\n\n{file_adds}{file_dels}{file_mods}\n{file_copies}\n'
+changeset_debug = '\n{branches}{bookmarks}{tags}{parents}{author|person|xmlescape}\n{date|rfc3339date}\n{desc|xmlescape}\n\n{file_adds}{file_dels}{file_mods}\n{file_copies}{extras}\n'
file_add = '{file_add|xmlescape}\n'
file_mod = '{file_mod|xmlescape}\n'
@@ -16,4 +16,5 @@ end_file_copies = '\n'
parent = '\n'
branch = '{branch|xmlescape}\n'
tag = '{tag|xmlescape}\n'
+bookmark = '{bookmark|xmlescape}\n'
extra = '{value|xmlescape}\n'
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -554,16 +554,6 @@ class path_auditor(object):
# want to add "foo/bar/baz" before checking if there's a "foo/.hg"
self.auditeddir.update(prefixes)
-def nlinks(pathname):
- """Return number of hardlinks for the given file."""
- return os.lstat(pathname).st_nlink
-
-if hasattr(os, 'link'):
- os_link = os.link
-else:
- def os_link(src, dst):
- raise OSError(0, _("Hardlinks not supported"))
-
def lookup_reg(key, name=None, scope=None):
return None
diff --git a/mercurial/win32.py b/mercurial/win32.py
--- a/mercurial/win32.py
+++ b/mercurial/win32.py
@@ -5,73 +5,173 @@
# 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.
+import encoding
+import ctypes, errno, os, struct, subprocess
+
+_kernel32 = ctypes.windll.kernel32
+
+_BOOL = ctypes.c_long
+_WORD = ctypes.c_ushort
+_DWORD = ctypes.c_ulong
+_LPCSTR = _LPSTR = ctypes.c_char_p
+_HANDLE = ctypes.c_void_p
+_HWND = _HANDLE
+
+_INVALID_HANDLE_VALUE = -1
+
+# 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
+
+# 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
-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.
-"""
+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
-import win32api
+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)]
-import errno, os, sys, pywintypes, win32con, win32file, win32process
-import winerror, win32gui, win32console
-import osutil, encoding
-from win32com.shell import shell, shellcon
+_STD_ERROR_HANDLE = 0xfffffff4L # (DWORD)-12
+
+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 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')
+ if not _kernel32.CreateHardLinkA(dst, src, None):
+ _raiseoserror(src)
-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 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."""
+ '''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]
+ 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."""
+ '''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]
+ return res1.dwVolumeSerialNumber == res2.dwVolumeSerialNumber
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
+ 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 lookup_reg(key, valname=None, scope=None):
''' Look up a key/value name in the Windows registry.
@@ -82,101 +182,137 @@ def lookup_reg(key, valname=None, scope=
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
-
+ adv = ctypes.windll.advapi32
+ byref = ctypes.byref
if scope is None:
- scope = (HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE)
+ scope = (_HKEY_CURRENT_USER, _HKEY_LOCAL_MACHINE)
elif not isinstance(scope, (list, tuple)):
scope = (scope,)
for s in scope:
+ kh = _HANDLE()
+ res = adv.RegOpenKeyExA(s, key, 0, _KEY_READ, ctypes.byref(kh))
+ if res != _ERROR_SUCCESS:
+ continue
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
+ size = _DWORD(600)
+ type = _DWORD()
+ buf = ctypes.create_string_buffer(size.value + 1)
+ res = adv.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 = ' b
@@ -66,8 +66,8 @@ bookmarks revset
$ hg log -r 'bookmark()'
changeset: 1:925d80f479bb
- tag: X
- tag: X2
+ bookmark: X
+ bookmark: X2
tag: tip
user: test
date: Thu Jan 01 00:00:00 1970 +0000
@@ -76,8 +76,8 @@ bookmarks revset
$ hg log -r 'bookmark(Y)'
$ hg log -r 'bookmark(X2)'
changeset: 1:925d80f479bb
- tag: X
- tag: X2
+ bookmark: X
+ bookmark: X2
tag: tip
user: test
date: Thu Jan 01 00:00:00 1970 +0000
@@ -89,8 +89,8 @@ bookmarks revset
bookmarks X and X2 moved to rev 1, Y at rev -1
$ hg bookmarks
+ * X 1:925d80f479bb
* X2 1:925d80f479bb
- * X 1:925d80f479bb
Y -1:000000000000
bookmark rev 0 again
@@ -104,10 +104,10 @@ bookmark rev 0 again
bookmarks X and X2 moved to rev 2, Y at rev -1, Z at rev 0
$ hg bookmarks
+ * X 2:0316ce92851d
* X2 2:0316ce92851d
- * X 2:0316ce92851d
+ Y -1:000000000000
Z 0:f7b1eb17ad24
- Y -1:000000000000
rename nonexistent bookmark
@@ -166,10 +166,10 @@ look up stripped bookmark name
$ hg log -r '"x y"'
changeset: 2:0316ce92851d
- tag: X2
- tag: Y
+ bookmark: X2
+ bookmark: Y
+ bookmark: x y
tag: tip
- tag: x y
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: 2
diff --git a/tests/test-bundle.t b/tests/test-bundle.t
--- a/tests/test-bundle.t
+++ b/tests/test-bundle.t
@@ -188,6 +188,13 @@ Log -R full.hg in fresh empty
date: Thu Jan 01 00:00:00 1970 +0000
summary: 0.0
+Make sure bundlerepo doesn't leak tempfiles (issue2491)
+
+ $ ls .hg
+ 00changelog.i
+ cache
+ requires
+ store
Pull ../full.hg into empty (with hook)