# HG changeset patch # User Sean Farley # Date 1503376506 25200 # Node ID af20468eb0a499c094dbd6e27ffcacf54cf5a8e6 # Parent 70354bd4f19b8d4c747112e921628c502e4212db# Parent fb672eac2702c019b92bf6cd83be2cc84a83fcf4 merge with stable diff -r 70354bd4f19b -r af20468eb0a4 Makefile --- 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 \ diff -r 70354bd4f19b -r af20468eb0a4 mercurial/branchmap.py --- 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 diff -r 70354bd4f19b -r af20468eb0a4 mercurial/commands.py --- 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. diff -r 70354bd4f19b -r af20468eb0a4 mercurial/templatekw.py --- 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) diff -r 70354bd4f19b -r af20468eb0a4 mercurial/ui.py --- 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 diff -r 70354bd4f19b -r af20468eb0a4 setup.py --- 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') diff -r 70354bd4f19b -r af20468eb0a4 tests/test-acl.t --- 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! diff -r 70354bd4f19b -r af20468eb0a4 tests/test-command-template.t --- 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 diff -r 70354bd4f19b -r af20468eb0a4 tests/test-context.py --- 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 diff -r 70354bd4f19b -r af20468eb0a4 tests/test-rollback.t --- 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 .. diff -r 70354bd4f19b -r af20468eb0a4 tests/test-tags.t --- 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)