changeset 33884:af20468eb0a4

merge with stable
author Sean Farley <sean@farley.io>
date Mon, 21 Aug 2017 21:35:06 -0700
parents 70354bd4f19b (current diff) fb672eac2702 (diff)
children 4e8a46c25fac
files Makefile mercurial/commands.py mercurial/templatekw.py mercurial/ui.py setup.py tests/test-acl.t tests/test-command-template.t tests/test-context.py
diffstat 11 files changed, 459 insertions(+), 100 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Fri Aug 11 01:34:11 2017 -0700
+++ b/Makefile	Mon Aug 21 21:35:06 2017 -0700
@@ -187,7 +187,7 @@
 	  PREFIX=/usr/local \
 	  clean install
 	mkdir -p $${OUTPUTDIR:-dist}
-	HGVER=$$(shell python contrib/genosxversion.py $(OSXVERSIONFLAGS) build/mercurial/Library/Python/2.7/site-packages/mercurial/__version__.py ) && \
+	HGVER=$$(python contrib/genosxversion.py $(OSXVERSIONFLAGS) build/mercurial/Library/Python/2.7/site-packages/mercurial/__version__.py) && \
 	OSXVER=$$(sw_vers -productVersion | cut -d. -f1,2) && \
 	pkgbuild --filter \\.DS_Store --root build/mercurial/ \
 	  --identifier org.mercurial-scm.mercurial \
--- a/mercurial/branchmap.py	Fri Aug 11 01:34:11 2017 -0700
+++ b/mercurial/branchmap.py	Mon Aug 21 21:35:06 2017 -0700
@@ -406,7 +406,8 @@
 
         # fast path: extract data from cache, use it if node is matching
         reponode = changelog.node(rev)[:_rbcnodelen]
-        cachenode, branchidx = unpack_from(_rbcrecfmt, self._rbcrevs, rbcrevidx)
+        cachenode, branchidx = unpack_from(
+            _rbcrecfmt, util.buffer(self._rbcrevs), rbcrevidx)
         close = bool(branchidx & _rbccloseflag)
         if close:
             branchidx &= _rbcbranchidxmask
--- a/mercurial/commands.py	Fri Aug 11 01:34:11 2017 -0700
+++ b/mercurial/commands.py	Mon Aug 21 21:35:06 2017 -0700
@@ -3335,7 +3335,9 @@
     revisions.
 
     See :hg:`help templates` for more about pre-packaged styles and
-    specifying custom templates.
+    specifying custom templates. The default template used by the log
+    command can be customized via the ``ui.logtemplate`` configuration
+    setting.
 
     Returns 0 on success.
 
--- a/mercurial/templatekw.py	Fri Aug 11 01:34:11 2017 -0700
+++ b/mercurial/templatekw.py	Mon Aug 21 21:35:06 2017 -0700
@@ -208,10 +208,22 @@
             latesttags[rev] = ctx.date()[0], 0, [t for t in sorted(tags)]
             continue
         try:
-            # The tuples are laid out so the right one can be found by
-            # comparison.
-            pdate, pdist, ptag = max(
-                latesttags[p.rev()] for p in ctx.parents())
+            ptags = [latesttags[p.rev()] for p in ctx.parents()]
+            if len(ptags) > 1:
+                if ptags[0][2] == ptags[1][2]:
+                    # The tuples are laid out so the right one can be found by
+                    # comparison in this case.
+                    pdate, pdist, ptag = max(ptags)
+                else:
+                    def key(x):
+                        changessincetag = len(repo.revs('only(%d, %s)',
+                                                        ctx.rev(), x[2][0]))
+                        # Smallest number of changes since tag wins. Date is
+                        # used as tiebreaker.
+                        return [-changessincetag, x[0]]
+                    pdate, pdist, ptag = max(ptags, key=key)
+            else:
+                pdate, pdist, ptag = ptags[0]
         except KeyError:
             # Cache miss - recurse
             todo.append(rev)
--- a/mercurial/ui.py	Fri Aug 11 01:34:11 2017 -0700
+++ b/mercurial/ui.py	Mon Aug 21 21:35:06 2017 -0700
@@ -904,7 +904,8 @@
                 if not getattr(self.ferr, 'closed', False):
                     self.ferr.flush()
         except IOError as inst:
-            raise error.StdioError(inst)
+            if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
+                raise error.StdioError(inst)
 
     def flush(self):
         # opencode timeblockedsection because this is a critical path
@@ -913,12 +914,14 @@
             try:
                 self.fout.flush()
             except IOError as err:
-                raise error.StdioError(err)
+                if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
+                    raise error.StdioError(err)
             finally:
                 try:
                     self.ferr.flush()
                 except IOError as err:
-                    raise error.StdioError(err)
+                    if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
+                        raise error.StdioError(err)
         finally:
             self._blockedtimes['stdio_blocked'] += \
                 (util.timer() - starttime) * 1000
--- a/setup.py	Fri Aug 11 01:34:11 2017 -0700
+++ b/setup.py	Mon Aug 21 21:35:06 2017 -0700
@@ -785,11 +785,11 @@
     from distutils import cygwinccompiler
 
     # the -mno-cygwin option has been deprecated for years
-    compiler = cygwinccompiler.Mingw32CCompiler
+    mingw32compilerclass = cygwinccompiler.Mingw32CCompiler
 
     class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
         def __init__(self, *args, **kwargs):
-            compiler.__init__(self, *args, **kwargs)
+            mingw32compilerclass.__init__(self, *args, **kwargs)
             for i in 'compiler compiler_so linker_exe linker_so'.split():
                 try:
                     getattr(self, i).remove('-mno-cygwin')
@@ -810,11 +810,11 @@
     # effect.
     from distutils import msvccompiler
 
-    compiler = msvccompiler.MSVCCompiler
+    msvccompilerclass = msvccompiler.MSVCCompiler
 
     class HackedMSVCCompiler(msvccompiler.MSVCCompiler):
         def initialize(self):
-            compiler.initialize(self)
+            msvccompilerclass.initialize(self)
             # "warning LNK4197: export 'func' specified multiple times"
             self.ldflags_shared.append('/ignore:4197')
             self.ldflags_shared_debug.append('/ignore:4197')
--- a/tests/test-acl.t	Fri Aug 11 01:34:11 2017 -0700
+++ b/tests/test-acl.t	Mon Aug 21 21:35:06 2017 -0700
@@ -883,7 +883,7 @@
   added 3 changesets with 3 changes to 3 files
   calling hook pretxnchangegroup.acl: hgext.acl.hook
   acl: checking access for user "barney"
-  error: pretxnchangegroup.acl hook raised an exception: [Errno 2] No such file or directory: '../acl.config'
+  error: pretxnchangegroup.acl hook raised an exception: [Errno *] * (glob)
   bundle2-input-part: total payload size 1553
   bundle2-input-bundle: 3 parts total
   transaction abort!
--- a/tests/test-command-template.t	Fri Aug 11 01:34:11 2017 -0700
+++ b/tests/test-command-template.t	Mon Aug 21 21:35:06 2017 -0700
@@ -2871,95 +2871,189 @@
 
 No tag set:
 
-  $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
-  5: null+5
-  4: null+4
-  3: null+3
-  2: null+3
-  1: null+2
-  0: null+1
-
-One common tag: longest path wins:
+  $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
+  @    5: null+5
+  |\
+  | o  4: null+4
+  | |
+  | o  3: null+3
+  | |
+  o |  2: null+3
+  |/
+  o  1: null+2
+  |
+  o  0: null+1
+  
+
+One common tag: longest path wins for {latesttagdistance}:
 
   $ hg tag -r 1 -m t1 -d '6 0' t1
-  $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
-  6: t1+4
-  5: t1+3
-  4: t1+2
-  3: t1+1
-  2: t1+1
-  1: t1+0
-  0: null+1
-
-One ancestor tag: more recent wins:
+  $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
+  @  6: t1+4
+  |
+  o    5: t1+3
+  |\
+  | o  4: t1+2
+  | |
+  | o  3: t1+1
+  | |
+  o |  2: t1+1
+  |/
+  o  1: t1+0
+  |
+  o  0: null+1
+  
+
+One ancestor tag: closest wins:
 
   $ hg tag -r 2 -m t2 -d '7 0' t2
-  $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
-  7: t2+3
-  6: t2+2
-  5: t2+1
-  4: t1+2
-  3: t1+1
-  2: t2+0
-  1: t1+0
-  0: null+1
-
-Two branch tags: more recent wins:
+  $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
+  @  7: t2+3
+  |
+  o  6: t2+2
+  |
+  o    5: t2+1
+  |\
+  | o  4: t1+2
+  | |
+  | o  3: t1+1
+  | |
+  o |  2: t2+0
+  |/
+  o  1: t1+0
+  |
+  o  0: null+1
+  
+
+Two branch tags: more recent wins if same number of changes:
 
   $ hg tag -r 3 -m t3 -d '8 0' t3
-  $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
-  8: t3+5
-  7: t3+4
-  6: t3+3
-  5: t3+2
-  4: t3+1
-  3: t3+0
-  2: t2+0
-  1: t1+0
-  0: null+1
+  $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
+  @  8: t3+5
+  |
+  o  7: t3+4
+  |
+  o  6: t3+3
+  |
+  o    5: t3+2
+  |\
+  | o  4: t3+1
+  | |
+  | o  3: t3+0
+  | |
+  o |  2: t2+0
+  |/
+  o  1: t1+0
+  |
+  o  0: null+1
+  
+
+Two branch tags: fewest changes wins:
+
+  $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
+  $ hg log -G --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
+  @  9: t4+5,6
+  |
+  o  8: t4+4,5
+  |
+  o  7: t4+3,4
+  |
+  o  6: t4+2,3
+  |
+  o    5: t4+1,2
+  |\
+  | o  4: t4+0,0
+  | |
+  | o  3: t3+0,0
+  | |
+  o |  2: t2+0,0
+  |/
+  o  1: t1+0,0
+  |
+  o  0: null+1,1
+  
 
 Merged tag overrides:
 
   $ hg tag -r 5 -m t5 -d '9 0' t5
   $ hg tag -r 3 -m at3 -d '10 0' at3
-  $ hg log --template '{rev}: {latesttag}+{latesttagdistance}\n'
-  10: t5+5
-  9: t5+4
-  8: t5+3
-  7: t5+2
-  6: t5+1
-  5: t5+0
-  4: at3:t3+1
-  3: at3:t3+0
-  2: t2+0
-  1: t1+0
-  0: null+1
-
-  $ hg log --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
-  10: t5+5,5 
-  9: t5+4,4 
-  8: t5+3,3 
-  7: t5+2,2 
-  6: t5+1,1 
-  5: t5+0,0 
-  4: at3+1,1 t3+1,1 
-  3: at3+0,0 t3+0,0 
-  2: t2+0,0 
-  1: t1+0,0 
-  0: null+1,1 
-
-  $ hg log --template "{rev}: {latesttag('re:^t[13]$') % '{tag}, C: {changes}, D: {distance}'}\n"
-  10: t3, C: 8, D: 7
-  9: t3, C: 7, D: 6
-  8: t3, C: 6, D: 5
-  7: t3, C: 5, D: 4
-  6: t3, C: 4, D: 3
-  5: t3, C: 3, D: 2
-  4: t3, C: 1, D: 1
-  3: t3, C: 0, D: 0
-  2: t1, C: 1, D: 1
-  1: t1, C: 0, D: 0
-  0: null, C: 1, D: 1
+  $ hg log -G --template '{rev}: {latesttag}+{latesttagdistance}\n'
+  @  11: t5+6
+  |
+  o  10: t5+5
+  |
+  o  9: t5+4
+  |
+  o  8: t5+3
+  |
+  o  7: t5+2
+  |
+  o  6: t5+1
+  |
+  o    5: t5+0
+  |\
+  | o  4: t4+0
+  | |
+  | o  3: at3:t3+0
+  | |
+  o |  2: t2+0
+  |/
+  o  1: t1+0
+  |
+  o  0: null+1
+  
+
+  $ hg log -G --template "{rev}: {latesttag % '{tag}+{distance},{changes} '}\n"
+  @  11: t5+6,6
+  |
+  o  10: t5+5,5
+  |
+  o  9: t5+4,4
+  |
+  o  8: t5+3,3
+  |
+  o  7: t5+2,2
+  |
+  o  6: t5+1,1
+  |
+  o    5: t5+0,0
+  |\
+  | o  4: t4+0,0
+  | |
+  | o  3: at3+0,0 t3+0,0
+  | |
+  o |  2: t2+0,0
+  |/
+  o  1: t1+0,0
+  |
+  o  0: null+1,1
+  
+
+  $ hg log -G --template "{rev}: {latesttag('re:^t[13]$') % '{tag}, C: {changes}, D: {distance}'}\n"
+  @  11: t3, C: 9, D: 8
+  |
+  o  10: t3, C: 8, D: 7
+  |
+  o  9: t3, C: 7, D: 6
+  |
+  o  8: t3, C: 6, D: 5
+  |
+  o  7: t3, C: 5, D: 4
+  |
+  o  6: t3, C: 4, D: 3
+  |
+  o    5: t3, C: 3, D: 2
+  |\
+  | o  4: t3, C: 1, D: 1
+  | |
+  | o  3: t3, C: 0, D: 0
+  | |
+  o |  2: t1, C: 1, D: 1
+  |/
+  o  1: t1, C: 0, D: 0
+  |
+  o  0: null, C: 1, D: 1
+  
 
   $ cd ..
 
@@ -2981,7 +3075,7 @@
   > EOF
 
   $ hg -R latesttag tip
-  test 10:9b4a630e5f5f
+  test 11:97e5943b523a
 
 Test recursive showlist template (issue1989):
 
@@ -2994,7 +3088,7 @@
 
   $ hg -R latesttag log -r tip --style=style1989
   M|test
-  10,test
+  11,test
   branch: test
 
 Test new-style inline templating:
@@ -3027,6 +3121,7 @@
   $ hg log -R latesttag --template '{desc}\n'
   at3
   t5
+  t4
   t3
   t2
   t1
@@ -3040,6 +3135,7 @@
   $ hg log -R latesttag --template '{strip(desc, "te")}\n'
   at3
   5
+  4
   3
   2
   1
@@ -3055,6 +3151,7 @@
   $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
   date: 70 01 01 10 +0000
   date: 70 01 01 09 +0000
+  date: 70 01 01 04 +0000
   date: 70 01 01 08 +0000
   date: 70 01 01 07 +0000
   date: 70 01 01 06 +0000
--- a/tests/test-context.py	Fri Aug 11 01:34:11 2017 -0700
+++ b/tests/test-context.py	Mon Aug 21 21:35:06 2017 -0700
@@ -24,11 +24,10 @@
 repo[None].add(['foo'])
 repo.commit(text='commit1', date="0 0")
 
+d = repo[None]['foo'].date()
 if os.name == 'nt':
-    d = repo[None]['foo'].date()
-    print("workingfilectx.date = (%d, %d)" % (d[0], d[1]))
-else:
-    print("workingfilectx.date =", repo[None]['foo'].date())
+    d = d[:2]
+print("workingfilectx.date = (%d, %d)" % d)
 
 # test memctx with non-ASCII commit message
 
--- a/tests/test-rollback.t	Fri Aug 11 01:34:11 2017 -0700
+++ b/tests/test-rollback.t	Mon Aug 21 21:35:06 2017 -0700
@@ -210,3 +210,248 @@
   abort: rollback is disabled because it is unsafe
   (see `hg help -v rollback` for information)
   [255]
+
+  $ cd ..
+
+I/O errors on stdio are handled properly (issue5658)
+
+  $ cat > badui.py << EOF
+  > import errno
+  > from mercurial.i18n import _
+  > from mercurial import (
+  >     error,
+  >     ui as uimod,
+  > )
+  > 
+  > def pretxncommit(ui, repo, **kwargs):
+  >     ui.warn('warn during pretxncommit\n')
+  > 
+  > def pretxnclose(ui, repo, **kwargs):
+  >     ui.warn('warn during pretxnclose\n')
+  > 
+  > def txnclose(ui, repo, **kwargs):
+  >     ui.warn('warn during txnclose\n')
+  > 
+  > def txnabort(ui, repo, **kwargs):
+  >     ui.warn('warn during abort\n')
+  > 
+  > class fdproxy(object):
+  >     def __init__(self, ui, o):
+  >         self._ui = ui
+  >         self._o = o
+  > 
+  >     def __getattr__(self, attr):
+  >         return getattr(self._o, attr)
+  > 
+  >     def write(self, msg):
+  >         errors = set(self._ui.configlist('ui', 'ioerrors', []))
+  >         pretxncommit = msg == 'warn during pretxncommit\n'
+  >         pretxnclose = msg == 'warn during pretxnclose\n'
+  >         txnclose = msg == 'warn during txnclose\n'
+  >         txnabort = msg == 'warn during abort\n'
+  >         msgabort = msg == _('transaction abort!\n')
+  >         msgrollback = msg == _('rollback completed\n')
+  > 
+  >         if pretxncommit and 'pretxncommit' in errors:
+  >             raise IOError(errno.EPIPE, 'simulated epipe')
+  >         if pretxnclose and 'pretxnclose' in errors:
+  >             raise IOError(errno.EIO, 'simulated eio')
+  >         if txnclose and 'txnclose' in errors:
+  >             raise IOError(errno.EBADF, 'simulated badf')
+  >         if txnabort and 'txnabort' in errors:
+  >             raise IOError(errno.EPIPE, 'simulated epipe')
+  >         if msgabort and 'msgabort' in errors:
+  >             raise IOError(errno.EBADF, 'simulated ebadf')
+  >         if msgrollback and 'msgrollback' in errors:
+  >             raise IOError(errno.EIO, 'simulated eio')
+  > 
+  >         return self._o.write(msg)
+  > 
+  > def uisetup(ui):
+  >     class badui(ui.__class__):
+  >         def write_err(self, *args, **kwargs):
+  >             olderr = self.ferr
+  >             try:
+  >                 self.ferr = fdproxy(self, olderr)
+  >                 return super(badui, self).write_err(*args, **kwargs)
+  >             finally:
+  >                 self.ferr = olderr
+  > 
+  >     ui.__class__ = badui
+  > 
+  > def reposetup(ui, repo):
+  >     ui.setconfig('hooks', 'pretxnclose.badui', pretxnclose, 'badui')
+  >     ui.setconfig('hooks', 'txnclose.badui', txnclose, 'badui')
+  >     ui.setconfig('hooks', 'pretxncommit.badui', pretxncommit, 'badui')
+  >     ui.setconfig('hooks', 'txnabort.badui', txnabort, 'badui')
+  > EOF
+
+  $ cat >> $HGRCPATH << EOF
+  > [extensions]
+  > badui = $TESTTMP/badui.py
+  > EOF
+
+An I/O error during pretxncommit is handled
+
+  $ hg init ioerror-pretxncommit
+  $ cd ioerror-pretxncommit
+  $ echo 0 > foo
+  $ hg -q commit -A -m initial
+  warn during pretxncommit
+  warn during pretxnclose
+  warn during txnclose
+  $ echo 1 > foo
+  $ hg --config ui.ioerrors=pretxncommit commit -m 'error during pretxncommit'
+  warn during pretxnclose
+  warn during txnclose
+
+  $ hg commit -m 'commit 1'
+  nothing changed
+  [1]
+
+  $ cd ..
+
+An I/O error during pretxnclose is handled
+
+  $ hg init ioerror-pretxnclose
+  $ cd ioerror-pretxnclose
+  $ echo 0 > foo
+  $ hg -q commit -A -m initial
+  warn during pretxncommit
+  warn during pretxnclose
+  warn during txnclose
+
+  $ echo 1 > foo
+  $ hg --config ui.ioerrors=pretxnclose commit -m 'error during pretxnclose'
+  warn during pretxncommit
+  warn during txnclose
+
+  $ hg commit -m 'commit 1'
+  nothing changed
+  [1]
+
+  $ cd ..
+
+An I/O error during txnclose is handled
+
+  $ hg init ioerror-txnclose
+  $ cd ioerror-txnclose
+  $ echo 0 > foo
+  $ hg -q commit -A -m initial
+  warn during pretxncommit
+  warn during pretxnclose
+  warn during txnclose
+
+  $ echo 1 > foo
+  $ hg --config ui.ioerrors=txnclose commit -m 'error during txnclose'
+  warn during pretxncommit
+  warn during pretxnclose
+
+  $ hg commit -m 'commit 1'
+  nothing changed
+  [1]
+
+  $ cd ..
+
+An I/O error writing "transaction abort" is handled
+
+  $ hg init ioerror-msgabort
+  $ cd ioerror-msgabort
+
+  $ echo 0 > foo
+  $ hg -q commit -A -m initial
+  warn during pretxncommit
+  warn during pretxnclose
+  warn during txnclose
+
+  $ echo 1 > foo
+  $ hg --config ui.ioerrors=msgabort --config hooks.pretxncommit=false commit -m 'error during abort message'
+  warn during abort
+  rollback completed
+  abort: pretxncommit hook exited with status 1
+  [255]
+
+  $ hg commit -m 'commit 1'
+  warn during pretxncommit
+  warn during pretxnclose
+  warn during txnclose
+
+  $ cd ..
+
+An I/O error during txnabort should still result in rollback
+
+  $ hg init ioerror-txnabort
+  $ cd ioerror-txnabort
+
+  $ echo 0 > foo
+  $ hg -q commit -A -m initial
+  warn during pretxncommit
+  warn during pretxnclose
+  warn during txnclose
+
+  $ echo 1 > foo
+  $ hg --config ui.ioerrors=txnabort --config hooks.pretxncommit=false commit -m 'error during abort'
+  transaction abort!
+  rollback completed
+  abort: pretxncommit hook exited with status 1
+  [255]
+
+  $ hg commit -m 'commit 1'
+  warn during pretxncommit
+  warn during pretxnclose
+  warn during txnclose
+
+  $ cd ..
+
+An I/O error writing "rollback completed" is handled
+
+  $ hg init ioerror-msgrollback
+  $ cd ioerror-msgrollback
+
+  $ echo 0 > foo
+  $ hg -q commit -A -m initial
+  warn during pretxncommit
+  warn during pretxnclose
+  warn during txnclose
+
+  $ echo 1 > foo
+
+  $ hg --config ui.ioerrors=msgrollback --config hooks.pretxncommit=false commit -m 'error during rollback message'
+  transaction abort!
+  warn during abort
+  abort: pretxncommit hook exited with status 1
+  [255]
+
+  $ hg verify
+  checking changesets
+  checking manifests
+  crosschecking files in changesets and manifests
+  checking files
+  1 files, 1 changesets, 1 total revisions
+
+  $ cd ..
+
+Multiple I/O errors after transaction open are handled.
+This is effectively what happens if a peer disconnects in the middle
+of a transaction.
+
+  $ hg init ioerror-multiple
+  $ cd ioerror-multiple
+  $ echo 0 > foo
+  $ hg -q commit -A -m initial
+  warn during pretxncommit
+  warn during pretxnclose
+  warn during txnclose
+
+  $ echo 1 > foo
+
+  $ hg --config ui.ioerrors=pretxncommit,pretxnclose,txnclose,txnabort,msgabort,msgrollback commit -m 'multiple errors'
+
+  $ hg verify
+  checking changesets
+  checking manifests
+  crosschecking files in changesets and manifests
+  checking files
+  1 files, 2 changesets, 2 total revisions
+
+  $ cd ..
--- a/tests/test-tags.t	Fri Aug 11 01:34:11 2017 -0700
+++ b/tests/test-tags.t	Mon Aug 21 21:35:06 2017 -0700
@@ -381,7 +381,7 @@
 
   $ hg blackbox -l 6
   1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> tags
-  1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> couldn't write cache/hgtagsfnodes1: [Errno 13] Permission denied: '$TESTTMP/t2/.hg/cache/hgtagsfnodes1'
+  1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> couldn't write cache/hgtagsfnodes1: [Errno *] * (glob)
   1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> 2/3 cache hits/lookups in * seconds (glob)
   1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> writing .hg/cache/tags2-visible with 1 tags
   1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> tags exited 0 after * seconds (glob)