--- 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)