# HG changeset patch # User Matt Mackall # Date 1469041965 18000 # Node ID d3df009ab1175a6792549b51ae66486dd98f398b # Parent 53e80179bd6ad4e03a0d1cc19dcb2deed8d2fbf5# Parent fe0eeef0986a24413b2a4880f91fc9cc177749dc merge with i18n diff -r fe0eeef0986a -r d3df009ab117 hgext/convert/bzr.py --- a/hgext/convert/bzr.py Tue Jul 19 19:01:11 2016 -0300 +++ b/hgext/convert/bzr.py Wed Jul 20 14:12:45 2016 -0500 @@ -228,9 +228,10 @@ renaming = paths[0] != paths[1] # neither an add nor an delete - a move # rename all directory contents manually - subdir = origin.inventory.path2id(paths[0]) + subdir = origin.root_inventory.path2id(paths[0]) # get all child-entries of the directory - for name, entry in origin.inventory.iter_entries(subdir): + for name, entry in origin.root_inventory.iter_entries( + subdir): # hg does not track directory renames if entry.kind == 'directory': continue diff -r fe0eeef0986a -r d3df009ab117 mercurial/branchmap.py --- a/mercurial/branchmap.py Tue Jul 19 19:01:11 2016 -0300 +++ b/mercurial/branchmap.py Wed Jul 20 14:12:45 2016 -0500 @@ -358,7 +358,7 @@ self._repo = repo self._names = [] # branch names in local encoding with static index self._rbcrevs = array('c') # structs of type _rbcrecfmt - self._rbcsnameslen = 0 + self._rbcsnameslen = 0 # length of names read at _rbcsnameslen try: bndata = repo.vfs.read(_rbcnames) self._rbcsnameslen = len(bndata) # for verification before writing @@ -380,7 +380,8 @@ len(repo.changelog)) if self._rbcrevslen == 0: self._names = [] - self._rbcnamescount = len(self._names) # number of good names on disk + self._rbcnamescount = len(self._names) # number of names read at + # _rbcsnameslen self._namesreverse = dict((b, r) for r, b in enumerate(self._names)) def _clear(self): @@ -416,13 +417,17 @@ if cachenode == '\0\0\0\0': pass elif cachenode == reponode: - if branchidx < self._rbcnamescount: + try: return self._names[branchidx], close - # referenced branch doesn't exist - rebuild is expensive but needed - self._repo.ui.debug("rebuilding corrupted revision branch cache\n") - self._clear() + except IndexError: + # recover from invalid reference to unknown branch + self._repo.ui.debug("referenced branch names not found" + " - rebuilding revision branch cache from scratch\n") + self._clear() else: # rev/node map has changed, invalidate the cache from here up + self._repo.ui.debug("history modification detected - truncating " + "revision branch cache to revision %s\n" % rev) truncate = rbcrevidx + _rbcrecsize del self._rbcrevs[truncate:] self._rbcrevslen = min(self._rbcrevslen, truncate) diff -r fe0eeef0986a -r d3df009ab117 mercurial/hg.py --- a/mercurial/hg.py Tue Jul 19 19:01:11 2016 -0300 +++ b/mercurial/hg.py Wed Jul 20 14:12:45 2016 -0500 @@ -923,7 +923,7 @@ dst.setconfig('bundle', 'mainreporoot', r, 'copied') # copy selected local settings to the remote ui - for sect in ('auth', 'hostfingerprints', 'http_proxy'): + for sect in ('auth', 'hostfingerprints', 'hostsecurity', 'http_proxy'): for key, val in src.configitems(sect): dst.setconfig(sect, key, val, 'copied') v = src.config('web', 'cacerts') diff -r fe0eeef0986a -r d3df009ab117 mercurial/sslutil.py --- a/mercurial/sslutil.py Tue Jul 19 19:01:11 2016 -0300 +++ b/mercurial/sslutil.py Wed Jul 20 14:12:45 2016 -0500 @@ -139,6 +139,9 @@ 'legacyfingerprint': False, # PROTOCOL_* constant to use for SSLContext.__init__. 'protocol': None, + # String representation of minimum protocol to be used for UI + # presentation. + 'protocolui': None, # ssl.CERT_* constant used by SSLContext.verify_mode. 'verifymode': None, # Defines extra ssl.OP* bitwise options to set. @@ -181,7 +184,13 @@ protocol = ui.config('hostsecurity', key, protocol) validateprotocol(protocol, key) - s['protocol'], s['ctxoptions'] = protocolsettings(protocol) + # If --insecure is used, we allow the use of TLS 1.0 despite config options. + # We always print a "connection security to %s is disabled..." message when + # --insecure is used. So no need to print anything more here. + if ui.insecureconnections: + protocol = 'tls1.0' + + s['protocol'], s['ctxoptions'], s['protocolui'] = protocolsettings(protocol) ciphers = ui.config('hostsecurity', 'ciphers') ciphers = ui.config('hostsecurity', '%s:ciphers' % hostname, ciphers) @@ -279,7 +288,12 @@ return s def protocolsettings(protocol): - """Resolve the protocol and context options for a config value.""" + """Resolve the protocol for a config value. + + Returns a 3-tuple of (protocol, options, ui value) where the first + 2 items are values used by SSLContext and the last is a string value + of the ``minimumprotocol`` config option equivalent. + """ if protocol not in configprotocols: raise ValueError('protocol value not supported: %s' % protocol) @@ -301,7 +315,7 @@ hint=_('upgrade Python or disable setting since ' 'only TLS 1.0 is supported')) - return ssl.PROTOCOL_TLSv1, 0 + return ssl.PROTOCOL_TLSv1, 0, 'tls1.0' # WARNING: returned options don't work unless the modern ssl module # is available. Be careful when adding options here. @@ -323,7 +337,7 @@ # There is no guarantee this attribute is defined on the module. options |= getattr(ssl, 'OP_NO_COMPRESSION', 0) - return ssl.PROTOCOL_SSLv23, options + return ssl.PROTOCOL_SSLv23, options, protocol def wrapsocket(sock, keyfile, certfile, ui, serverhostname=None): """Add SSL/TLS to a socket. @@ -403,11 +417,57 @@ 'how to configure Mercurial to avoid this error)\n')) # Try to print more helpful error messages for known failures. if util.safehasattr(e, 'reason'): + # This error occurs when the client and server don't share a + # common/supported SSL/TLS protocol. We've disabled SSLv2 and SSLv3 + # outright. Hopefully the reason for this error is that we require + # TLS 1.1+ and the server only supports TLS 1.0. Whatever the + # reason, try to emit an actionable warning. if e.reason == 'UNSUPPORTED_PROTOCOL': - ui.warn(_('(could not negotiate a common protocol; see ' - 'https://mercurial-scm.org/wiki/SecureConnections ' - 'for how to configure Mercurial to avoid this ' - 'error)\n')) + # We attempted TLS 1.0+. + if settings['protocolui'] == 'tls1.0': + # We support more than just TLS 1.0+. If this happens, + # the likely scenario is either the client or the server + # is really old. (e.g. server doesn't support TLS 1.0+ or + # client doesn't support modern TLS versions introduced + # several years from when this comment was written). + if supportedprotocols != set(['tls1.0']): + ui.warn(_( + '(could not communicate with %s using security ' + 'protocols %s; if you are using a modern Mercurial ' + 'version, consider contacting the operator of this ' + 'server; see ' + 'https://mercurial-scm.org/wiki/SecureConnections ' + 'for more info)\n') % ( + serverhostname, + ', '.join(sorted(supportedprotocols)))) + else: + ui.warn(_( + '(could not communicate with %s using TLS 1.0; the ' + 'likely cause of this is the server no longer ' + 'supports TLS 1.0 because it has known security ' + 'vulnerabilities; see ' + 'https://mercurial-scm.org/wiki/SecureConnections ' + 'for more info)\n') % serverhostname) + else: + # We attempted TLS 1.1+. We can only get here if the client + # supports the configured protocol. So the likely reason is + # the client wants better security than the server can + # offer. + ui.warn(_( + '(could not negotiate a common security protocol (%s+) ' + 'with %s; the likely cause is Mercurial is configured ' + 'to be more secure than the server can support)\n') % ( + settings['protocolui'], serverhostname)) + ui.warn(_('(consider contacting the operator of this ' + 'server and ask them to support modern TLS ' + 'protocol versions; or, set ' + 'hostsecurity.%s:minimumprotocol=tls1.0 to allow ' + 'use of legacy, less secure protocols when ' + 'communicating with this server)\n') % + serverhostname) + ui.warn(_( + '(see https://mercurial-scm.org/wiki/SecureConnections ' + 'for more info)\n')) raise # check if wrap_socket failed silently because socket had been @@ -439,7 +499,7 @@ Typically ``cafile`` is only defined if ``requireclientcert`` is true. """ - protocol, options = protocolsettings('tls1.0') + protocol, options, _protocolui = protocolsettings('tls1.0') # This config option is intended for use in tests only. It is a giant # footgun to kill security. Don't define it. diff -r fe0eeef0986a -r d3df009ab117 mercurial/util.py --- a/mercurial/util.py Tue Jul 19 19:01:11 2016 -0300 +++ b/mercurial/util.py Wed Jul 20 14:12:45 2016 -0500 @@ -396,10 +396,26 @@ (3, 6, None) >>> versiontuple(v, 4) (3, 6, None, None) + + >>> v = '3.9-rc' + >>> versiontuple(v, 2) + (3, 9) + >>> versiontuple(v, 3) + (3, 9, None) + >>> versiontuple(v, 4) + (3, 9, None, 'rc') + + >>> v = '3.9-rc+2-02a8fea4289b' + >>> versiontuple(v, 2) + (3, 9) + >>> versiontuple(v, 3) + (3, 9, None) + >>> versiontuple(v, 4) + (3, 9, None, 'rc+2-02a8fea4289b') """ if not v: v = version() - parts = v.split('+', 1) + parts = remod.split('[\+-]', v, 1) if len(parts) == 1: vparts, extra = parts[0], None else: diff -r fe0eeef0986a -r d3df009ab117 tests/test-branches.t --- a/tests/test-branches.t Tue Jul 19 19:01:11 2016 -0300 +++ b/tests/test-branches.t Wed Jul 20 14:12:45 2016 -0500 @@ -587,6 +587,8 @@ $ f --size .hg/cache/rbc-revs* .hg/cache/rbc-revs-v1: size=120 $ hg log -r 'branch(.)' -T '{rev} ' --debug + history modification detected - truncating revision branch cache to revision 13 + history modification detected - truncating revision branch cache to revision 1 3 4 8 9 10 11 12 13 truncating cache/rbc-revs-v1 to 8 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug 5 @@ -632,7 +634,7 @@ cache is rebuilt when corruption is detected $ echo > .hg/cache/rbc-names-v1 $ hg log -r '5:&branch(.)' -T '{rev} ' --debug - rebuilding corrupted revision branch cache + referenced branch names not found - rebuilding revision branch cache from scratch 8 9 10 11 12 13 truncating cache/rbc-revs-v1 to 40 $ f --size --hexdump .hg/cache/rbc-* .hg/cache/rbc-names-v1: size=79 @@ -668,3 +670,33 @@ 0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| $ cd .. + +Test for multiple incorrect branch cache entries: + + $ hg init b + $ cd b + $ touch f + $ hg ci -Aqmf + $ echo >> f + $ hg ci -Amf + $ hg branch -q branch + $ hg ci -Amf + + $ f --size --hexdump .hg/cache/rbc-* + .hg/cache/rbc-names-v1: size=14 + 0000: 64 65 66 61 75 6c 74 00 62 72 61 6e 63 68 |default.branch| + .hg/cache/rbc-revs-v1: size=24 + 0000: 66 e5 f5 aa 00 00 00 00 fa 4c 04 e5 00 00 00 00 |f........L......| + 0010: 56 46 78 69 00 00 00 01 |VFxi....| + $ : > .hg/cache/rbc-revs-v1 + +No superfluous rebuilding of cache: + $ hg log -r "branch(null)&branch(branch)" --debug + $ f --size --hexdump .hg/cache/rbc-* + .hg/cache/rbc-names-v1: size=14 + 0000: 64 65 66 61 75 6c 74 00 62 72 61 6e 63 68 |default.branch| + .hg/cache/rbc-revs-v1: size=24 + 0000: 66 e5 f5 aa 00 00 00 00 fa 4c 04 e5 00 00 00 00 |f........L......| + 0010: 56 46 78 69 00 00 00 01 |VFxi....| + + $ cd .. diff -r fe0eeef0986a -r d3df009ab117 tests/test-https.t --- a/tests/test-https.t Tue Jul 19 19:01:11 2016 -0300 +++ b/tests/test-https.t Wed Jul 20 14:12:45 2016 -0500 @@ -469,23 +469,37 @@ Clients requiring newer TLS version than what server supports fail $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ - (could not negotiate a common protocol; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error) + (could not negotiate a common security protocol (tls1.1+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support) + (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server) + (see https://mercurial-scm.org/wiki/SecureConnections for more info) abort: error: *unsupported protocol* (glob) [255] $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.1 id https://localhost:$HGPORT/ - (could not negotiate a common protocol; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error) + (could not negotiate a common security protocol (tls1.1+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support) + (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server) + (see https://mercurial-scm.org/wiki/SecureConnections for more info) abort: error: *unsupported protocol* (glob) [255] $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT/ - (could not negotiate a common protocol; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error) + (could not negotiate a common security protocol (tls1.2+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support) + (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server) + (see https://mercurial-scm.org/wiki/SecureConnections for more info) abort: error: *unsupported protocol* (glob) [255] $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT1/ - (could not negotiate a common protocol; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error) + (could not negotiate a common security protocol (tls1.2+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support) + (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server) + (see https://mercurial-scm.org/wiki/SecureConnections for more info) abort: error: *unsupported protocol* (glob) [255] +--insecure will allow TLS 1.0 connections and override configs + + $ hg --config hostsecurity.minimumprotocol=tls1.2 id --insecure https://localhost:$HGPORT1/ + warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering + 5fed3813f7f5 + The per-host config option overrides the default $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \ @@ -497,10 +511,25 @@ $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \ > --config hostsecurity.localhost:minimumprotocol=tls1.2 - (could not negotiate a common protocol; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error) + (could not negotiate a common security protocol (tls1.2+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support) + (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server) + (see https://mercurial-scm.org/wiki/SecureConnections for more info) abort: error: *unsupported protocol* (glob) [255] +.hg/hgrc file [hostsecurity] settings are applied to remote ui instances (issue5305) + + $ cat >> copy-pull/.hg/hgrc << EOF + > [hostsecurity] + > localhost:minimumprotocol=tls1.2 + > EOF + $ P="$CERTSDIR" hg -R copy-pull id https://localhost:$HGPORT/ + (could not negotiate a common security protocol (tls1.2+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support) + (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server) + (see https://mercurial-scm.org/wiki/SecureConnections for more info) + abort: error: [SSL: UNSUPPORTED_PROTOCOL] unsupported protocol (_ssl.c:590) + [255] + $ killdaemons.py hg0.pid $ killdaemons.py hg1.pid $ killdaemons.py hg2.pid diff -r fe0eeef0986a -r d3df009ab117 tests/test-rebase-conflicts.t --- a/tests/test-rebase-conflicts.t Tue Jul 19 19:01:11 2016 -0300 +++ b/tests/test-rebase-conflicts.t Wed Jul 20 14:12:45 2016 -0500 @@ -302,6 +302,7 @@ bundle2-input-part: total payload size 1713 bundle2-input-bundle: 0 parts total invalid branchheads cache (served): tip differs + history modification detected - truncating revision branch cache to revision 9 rebase completed updating the branch cache truncating cache/rbc-revs-v1 to 72