##// END OF EJS Templates
tests: remove "sslcontext" check...
Manuel Jacob -
r45417:89f83e47 default
parent child Browse files
Show More
@@ -1,1066 +1,1052 b''
1 from __future__ import absolute_import, print_function
1 from __future__ import absolute_import, print_function
2
2
3 import distutils.version
3 import distutils.version
4 import os
4 import os
5 import re
5 import re
6 import socket
6 import socket
7 import stat
7 import stat
8 import subprocess
8 import subprocess
9 import sys
9 import sys
10 import tempfile
10 import tempfile
11
11
12 tempprefix = 'hg-hghave-'
12 tempprefix = 'hg-hghave-'
13
13
14 checks = {
14 checks = {
15 "true": (lambda: True, "yak shaving"),
15 "true": (lambda: True, "yak shaving"),
16 "false": (lambda: False, "nail clipper"),
16 "false": (lambda: False, "nail clipper"),
17 }
17 }
18
18
19 try:
19 try:
20 import msvcrt
20 import msvcrt
21
21
22 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
22 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
23 msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
23 msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
24 except ImportError:
24 except ImportError:
25 pass
25 pass
26
26
27 stdout = getattr(sys.stdout, 'buffer', sys.stdout)
27 stdout = getattr(sys.stdout, 'buffer', sys.stdout)
28 stderr = getattr(sys.stderr, 'buffer', sys.stderr)
28 stderr = getattr(sys.stderr, 'buffer', sys.stderr)
29
29
30 if sys.version_info[0] >= 3:
30 if sys.version_info[0] >= 3:
31
31
32 def _sys2bytes(p):
32 def _sys2bytes(p):
33 if p is None:
33 if p is None:
34 return p
34 return p
35 return p.encode('utf-8')
35 return p.encode('utf-8')
36
36
37 def _bytes2sys(p):
37 def _bytes2sys(p):
38 if p is None:
38 if p is None:
39 return p
39 return p
40 return p.decode('utf-8')
40 return p.decode('utf-8')
41
41
42
42
43 else:
43 else:
44
44
45 def _sys2bytes(p):
45 def _sys2bytes(p):
46 return p
46 return p
47
47
48 _bytes2sys = _sys2bytes
48 _bytes2sys = _sys2bytes
49
49
50
50
51 def check(name, desc):
51 def check(name, desc):
52 """Registers a check function for a feature."""
52 """Registers a check function for a feature."""
53
53
54 def decorator(func):
54 def decorator(func):
55 checks[name] = (func, desc)
55 checks[name] = (func, desc)
56 return func
56 return func
57
57
58 return decorator
58 return decorator
59
59
60
60
61 def checkvers(name, desc, vers):
61 def checkvers(name, desc, vers):
62 """Registers a check function for each of a series of versions.
62 """Registers a check function for each of a series of versions.
63
63
64 vers can be a list or an iterator.
64 vers can be a list or an iterator.
65
65
66 Produces a series of feature checks that have the form <name><vers> without
66 Produces a series of feature checks that have the form <name><vers> without
67 any punctuation (even if there's punctuation in 'vers'; i.e. this produces
67 any punctuation (even if there's punctuation in 'vers'; i.e. this produces
68 'py38', not 'py3.8' or 'py-38')."""
68 'py38', not 'py3.8' or 'py-38')."""
69
69
70 def decorator(func):
70 def decorator(func):
71 def funcv(v):
71 def funcv(v):
72 def f():
72 def f():
73 return func(v)
73 return func(v)
74
74
75 return f
75 return f
76
76
77 for v in vers:
77 for v in vers:
78 v = str(v)
78 v = str(v)
79 f = funcv(v)
79 f = funcv(v)
80 checks['%s%s' % (name, v.replace('.', ''))] = (f, desc % v)
80 checks['%s%s' % (name, v.replace('.', ''))] = (f, desc % v)
81 return func
81 return func
82
82
83 return decorator
83 return decorator
84
84
85
85
86 def checkfeatures(features):
86 def checkfeatures(features):
87 result = {
87 result = {
88 'error': [],
88 'error': [],
89 'missing': [],
89 'missing': [],
90 'skipped': [],
90 'skipped': [],
91 }
91 }
92
92
93 for feature in features:
93 for feature in features:
94 negate = feature.startswith('no-')
94 negate = feature.startswith('no-')
95 if negate:
95 if negate:
96 feature = feature[3:]
96 feature = feature[3:]
97
97
98 if feature not in checks:
98 if feature not in checks:
99 result['missing'].append(feature)
99 result['missing'].append(feature)
100 continue
100 continue
101
101
102 check, desc = checks[feature]
102 check, desc = checks[feature]
103 try:
103 try:
104 available = check()
104 available = check()
105 except Exception:
105 except Exception:
106 result['error'].append('hghave check failed: %s' % feature)
106 result['error'].append('hghave check failed: %s' % feature)
107 continue
107 continue
108
108
109 if not negate and not available:
109 if not negate and not available:
110 result['skipped'].append('missing feature: %s' % desc)
110 result['skipped'].append('missing feature: %s' % desc)
111 elif negate and available:
111 elif negate and available:
112 result['skipped'].append('system supports %s' % desc)
112 result['skipped'].append('system supports %s' % desc)
113
113
114 return result
114 return result
115
115
116
116
117 def require(features):
117 def require(features):
118 """Require that features are available, exiting if not."""
118 """Require that features are available, exiting if not."""
119 result = checkfeatures(features)
119 result = checkfeatures(features)
120
120
121 for missing in result['missing']:
121 for missing in result['missing']:
122 stderr.write(
122 stderr.write(
123 ('skipped: unknown feature: %s\n' % missing).encode('utf-8')
123 ('skipped: unknown feature: %s\n' % missing).encode('utf-8')
124 )
124 )
125 for msg in result['skipped']:
125 for msg in result['skipped']:
126 stderr.write(('skipped: %s\n' % msg).encode('utf-8'))
126 stderr.write(('skipped: %s\n' % msg).encode('utf-8'))
127 for msg in result['error']:
127 for msg in result['error']:
128 stderr.write(('%s\n' % msg).encode('utf-8'))
128 stderr.write(('%s\n' % msg).encode('utf-8'))
129
129
130 if result['missing']:
130 if result['missing']:
131 sys.exit(2)
131 sys.exit(2)
132
132
133 if result['skipped'] or result['error']:
133 if result['skipped'] or result['error']:
134 sys.exit(1)
134 sys.exit(1)
135
135
136
136
137 def matchoutput(cmd, regexp, ignorestatus=False):
137 def matchoutput(cmd, regexp, ignorestatus=False):
138 """Return the match object if cmd executes successfully and its output
138 """Return the match object if cmd executes successfully and its output
139 is matched by the supplied regular expression.
139 is matched by the supplied regular expression.
140 """
140 """
141 r = re.compile(regexp)
141 r = re.compile(regexp)
142 p = subprocess.Popen(
142 p = subprocess.Popen(
143 cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
143 cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
144 )
144 )
145 s = p.communicate()[0]
145 s = p.communicate()[0]
146 ret = p.returncode
146 ret = p.returncode
147 return (ignorestatus or not ret) and r.search(s)
147 return (ignorestatus or not ret) and r.search(s)
148
148
149
149
150 @check("baz", "GNU Arch baz client")
150 @check("baz", "GNU Arch baz client")
151 def has_baz():
151 def has_baz():
152 return matchoutput('baz --version 2>&1', br'baz Bazaar version')
152 return matchoutput('baz --version 2>&1', br'baz Bazaar version')
153
153
154
154
155 @check("bzr", "Canonical's Bazaar client")
155 @check("bzr", "Canonical's Bazaar client")
156 def has_bzr():
156 def has_bzr():
157 try:
157 try:
158 import bzrlib
158 import bzrlib
159 import bzrlib.bzrdir
159 import bzrlib.bzrdir
160 import bzrlib.errors
160 import bzrlib.errors
161 import bzrlib.revision
161 import bzrlib.revision
162 import bzrlib.revisionspec
162 import bzrlib.revisionspec
163
163
164 bzrlib.revisionspec.RevisionSpec
164 bzrlib.revisionspec.RevisionSpec
165 return bzrlib.__doc__ is not None
165 return bzrlib.__doc__ is not None
166 except (AttributeError, ImportError):
166 except (AttributeError, ImportError):
167 return False
167 return False
168
168
169
169
170 @checkvers("bzr", "Canonical's Bazaar client >= %s", (1.14,))
170 @checkvers("bzr", "Canonical's Bazaar client >= %s", (1.14,))
171 def has_bzr_range(v):
171 def has_bzr_range(v):
172 major, minor = v.split('rc')[0].split('.')[0:2]
172 major, minor = v.split('rc')[0].split('.')[0:2]
173 try:
173 try:
174 import bzrlib
174 import bzrlib
175
175
176 return bzrlib.__doc__ is not None and bzrlib.version_info[:2] >= (
176 return bzrlib.__doc__ is not None and bzrlib.version_info[:2] >= (
177 int(major),
177 int(major),
178 int(minor),
178 int(minor),
179 )
179 )
180 except ImportError:
180 except ImportError:
181 return False
181 return False
182
182
183
183
184 @check("chg", "running with chg")
184 @check("chg", "running with chg")
185 def has_chg():
185 def has_chg():
186 return 'CHGHG' in os.environ
186 return 'CHGHG' in os.environ
187
187
188
188
189 @check("cvs", "cvs client/server")
189 @check("cvs", "cvs client/server")
190 def has_cvs():
190 def has_cvs():
191 re = br'Concurrent Versions System.*?server'
191 re = br'Concurrent Versions System.*?server'
192 return matchoutput('cvs --version 2>&1', re) and not has_msys()
192 return matchoutput('cvs --version 2>&1', re) and not has_msys()
193
193
194
194
195 @check("cvs112", "cvs client/server 1.12.* (not cvsnt)")
195 @check("cvs112", "cvs client/server 1.12.* (not cvsnt)")
196 def has_cvs112():
196 def has_cvs112():
197 re = br'Concurrent Versions System \(CVS\) 1.12.*?server'
197 re = br'Concurrent Versions System \(CVS\) 1.12.*?server'
198 return matchoutput('cvs --version 2>&1', re) and not has_msys()
198 return matchoutput('cvs --version 2>&1', re) and not has_msys()
199
199
200
200
201 @check("cvsnt", "cvsnt client/server")
201 @check("cvsnt", "cvsnt client/server")
202 def has_cvsnt():
202 def has_cvsnt():
203 re = br'Concurrent Versions System \(CVSNT\) (\d+).(\d+).*\(client/server\)'
203 re = br'Concurrent Versions System \(CVSNT\) (\d+).(\d+).*\(client/server\)'
204 return matchoutput('cvsnt --version 2>&1', re)
204 return matchoutput('cvsnt --version 2>&1', re)
205
205
206
206
207 @check("darcs", "darcs client")
207 @check("darcs", "darcs client")
208 def has_darcs():
208 def has_darcs():
209 return matchoutput('darcs --version', br'\b2\.([2-9]|\d{2})', True)
209 return matchoutput('darcs --version', br'\b2\.([2-9]|\d{2})', True)
210
210
211
211
212 @check("mtn", "monotone client (>= 1.0)")
212 @check("mtn", "monotone client (>= 1.0)")
213 def has_mtn():
213 def has_mtn():
214 return matchoutput('mtn --version', br'monotone', True) and not matchoutput(
214 return matchoutput('mtn --version', br'monotone', True) and not matchoutput(
215 'mtn --version', br'monotone 0\.', True
215 'mtn --version', br'monotone 0\.', True
216 )
216 )
217
217
218
218
219 @check("eol-in-paths", "end-of-lines in paths")
219 @check("eol-in-paths", "end-of-lines in paths")
220 def has_eol_in_paths():
220 def has_eol_in_paths():
221 try:
221 try:
222 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
222 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
223 os.close(fd)
223 os.close(fd)
224 os.remove(path)
224 os.remove(path)
225 return True
225 return True
226 except (IOError, OSError):
226 except (IOError, OSError):
227 return False
227 return False
228
228
229
229
230 @check("execbit", "executable bit")
230 @check("execbit", "executable bit")
231 def has_executablebit():
231 def has_executablebit():
232 try:
232 try:
233 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
233 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
234 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
234 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
235 try:
235 try:
236 os.close(fh)
236 os.close(fh)
237 m = os.stat(fn).st_mode & 0o777
237 m = os.stat(fn).st_mode & 0o777
238 new_file_has_exec = m & EXECFLAGS
238 new_file_has_exec = m & EXECFLAGS
239 os.chmod(fn, m ^ EXECFLAGS)
239 os.chmod(fn, m ^ EXECFLAGS)
240 exec_flags_cannot_flip = (os.stat(fn).st_mode & 0o777) == m
240 exec_flags_cannot_flip = (os.stat(fn).st_mode & 0o777) == m
241 finally:
241 finally:
242 os.unlink(fn)
242 os.unlink(fn)
243 except (IOError, OSError):
243 except (IOError, OSError):
244 # we don't care, the user probably won't be able to commit anyway
244 # we don't care, the user probably won't be able to commit anyway
245 return False
245 return False
246 return not (new_file_has_exec or exec_flags_cannot_flip)
246 return not (new_file_has_exec or exec_flags_cannot_flip)
247
247
248
248
249 @check("icasefs", "case insensitive file system")
249 @check("icasefs", "case insensitive file system")
250 def has_icasefs():
250 def has_icasefs():
251 # Stolen from mercurial.util
251 # Stolen from mercurial.util
252 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
252 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
253 os.close(fd)
253 os.close(fd)
254 try:
254 try:
255 s1 = os.stat(path)
255 s1 = os.stat(path)
256 d, b = os.path.split(path)
256 d, b = os.path.split(path)
257 p2 = os.path.join(d, b.upper())
257 p2 = os.path.join(d, b.upper())
258 if path == p2:
258 if path == p2:
259 p2 = os.path.join(d, b.lower())
259 p2 = os.path.join(d, b.lower())
260 try:
260 try:
261 s2 = os.stat(p2)
261 s2 = os.stat(p2)
262 return s2 == s1
262 return s2 == s1
263 except OSError:
263 except OSError:
264 return False
264 return False
265 finally:
265 finally:
266 os.remove(path)
266 os.remove(path)
267
267
268
268
269 @check("fifo", "named pipes")
269 @check("fifo", "named pipes")
270 def has_fifo():
270 def has_fifo():
271 if getattr(os, "mkfifo", None) is None:
271 if getattr(os, "mkfifo", None) is None:
272 return False
272 return False
273 name = tempfile.mktemp(dir='.', prefix=tempprefix)
273 name = tempfile.mktemp(dir='.', prefix=tempprefix)
274 try:
274 try:
275 os.mkfifo(name)
275 os.mkfifo(name)
276 os.unlink(name)
276 os.unlink(name)
277 return True
277 return True
278 except OSError:
278 except OSError:
279 return False
279 return False
280
280
281
281
282 @check("killdaemons", 'killdaemons.py support')
282 @check("killdaemons", 'killdaemons.py support')
283 def has_killdaemons():
283 def has_killdaemons():
284 return True
284 return True
285
285
286
286
287 @check("cacheable", "cacheable filesystem")
287 @check("cacheable", "cacheable filesystem")
288 def has_cacheable_fs():
288 def has_cacheable_fs():
289 from mercurial import util
289 from mercurial import util
290
290
291 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
291 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
292 os.close(fd)
292 os.close(fd)
293 try:
293 try:
294 return util.cachestat(path).cacheable()
294 return util.cachestat(path).cacheable()
295 finally:
295 finally:
296 os.remove(path)
296 os.remove(path)
297
297
298
298
299 @check("lsprof", "python lsprof module")
299 @check("lsprof", "python lsprof module")
300 def has_lsprof():
300 def has_lsprof():
301 try:
301 try:
302 import _lsprof
302 import _lsprof
303
303
304 _lsprof.Profiler # silence unused import warning
304 _lsprof.Profiler # silence unused import warning
305 return True
305 return True
306 except ImportError:
306 except ImportError:
307 return False
307 return False
308
308
309
309
310 def _gethgversion():
310 def _gethgversion():
311 m = matchoutput('hg --version --quiet 2>&1', br'(\d+)\.(\d+)')
311 m = matchoutput('hg --version --quiet 2>&1', br'(\d+)\.(\d+)')
312 if not m:
312 if not m:
313 return (0, 0)
313 return (0, 0)
314 return (int(m.group(1)), int(m.group(2)))
314 return (int(m.group(1)), int(m.group(2)))
315
315
316
316
317 _hgversion = None
317 _hgversion = None
318
318
319
319
320 def gethgversion():
320 def gethgversion():
321 global _hgversion
321 global _hgversion
322 if _hgversion is None:
322 if _hgversion is None:
323 _hgversion = _gethgversion()
323 _hgversion = _gethgversion()
324 return _hgversion
324 return _hgversion
325
325
326
326
327 @checkvers(
327 @checkvers(
328 "hg", "Mercurial >= %s", list([(1.0 * x) / 10 for x in range(9, 99)])
328 "hg", "Mercurial >= %s", list([(1.0 * x) / 10 for x in range(9, 99)])
329 )
329 )
330 def has_hg_range(v):
330 def has_hg_range(v):
331 major, minor = v.split('.')[0:2]
331 major, minor = v.split('.')[0:2]
332 return gethgversion() >= (int(major), int(minor))
332 return gethgversion() >= (int(major), int(minor))
333
333
334
334
335 @check("rust", "Using the Rust extensions")
335 @check("rust", "Using the Rust extensions")
336 def has_rust():
336 def has_rust():
337 """Check is the mercurial currently running is using some rust code"""
337 """Check is the mercurial currently running is using some rust code"""
338 cmd = 'hg debuginstall --quiet 2>&1'
338 cmd = 'hg debuginstall --quiet 2>&1'
339 match = br'checking module policy \(([^)]+)\)'
339 match = br'checking module policy \(([^)]+)\)'
340 policy = matchoutput(cmd, match)
340 policy = matchoutput(cmd, match)
341 if not policy:
341 if not policy:
342 return False
342 return False
343 return b'rust' in policy.group(1)
343 return b'rust' in policy.group(1)
344
344
345
345
346 @check("hg08", "Mercurial >= 0.8")
346 @check("hg08", "Mercurial >= 0.8")
347 def has_hg08():
347 def has_hg08():
348 if checks["hg09"][0]():
348 if checks["hg09"][0]():
349 return True
349 return True
350 return matchoutput('hg help annotate 2>&1', '--date')
350 return matchoutput('hg help annotate 2>&1', '--date')
351
351
352
352
353 @check("hg07", "Mercurial >= 0.7")
353 @check("hg07", "Mercurial >= 0.7")
354 def has_hg07():
354 def has_hg07():
355 if checks["hg08"][0]():
355 if checks["hg08"][0]():
356 return True
356 return True
357 return matchoutput('hg --version --quiet 2>&1', 'Mercurial Distributed SCM')
357 return matchoutput('hg --version --quiet 2>&1', 'Mercurial Distributed SCM')
358
358
359
359
360 @check("hg06", "Mercurial >= 0.6")
360 @check("hg06", "Mercurial >= 0.6")
361 def has_hg06():
361 def has_hg06():
362 if checks["hg07"][0]():
362 if checks["hg07"][0]():
363 return True
363 return True
364 return matchoutput('hg --version --quiet 2>&1', 'Mercurial version')
364 return matchoutput('hg --version --quiet 2>&1', 'Mercurial version')
365
365
366
366
367 @check("gettext", "GNU Gettext (msgfmt)")
367 @check("gettext", "GNU Gettext (msgfmt)")
368 def has_gettext():
368 def has_gettext():
369 return matchoutput('msgfmt --version', br'GNU gettext-tools')
369 return matchoutput('msgfmt --version', br'GNU gettext-tools')
370
370
371
371
372 @check("git", "git command line client")
372 @check("git", "git command line client")
373 def has_git():
373 def has_git():
374 return matchoutput('git --version 2>&1', br'^git version')
374 return matchoutput('git --version 2>&1', br'^git version')
375
375
376
376
377 def getgitversion():
377 def getgitversion():
378 m = matchoutput('git --version 2>&1', br'git version (\d+)\.(\d+)')
378 m = matchoutput('git --version 2>&1', br'git version (\d+)\.(\d+)')
379 if not m:
379 if not m:
380 return (0, 0)
380 return (0, 0)
381 return (int(m.group(1)), int(m.group(2)))
381 return (int(m.group(1)), int(m.group(2)))
382
382
383
383
384 @check("pygit2", "pygit2 Python library")
384 @check("pygit2", "pygit2 Python library")
385 def has_git():
385 def has_git():
386 try:
386 try:
387 import pygit2
387 import pygit2
388
388
389 pygit2.Oid # silence unused import
389 pygit2.Oid # silence unused import
390 return True
390 return True
391 except ImportError:
391 except ImportError:
392 return False
392 return False
393
393
394
394
395 # https://github.com/git-lfs/lfs-test-server
395 # https://github.com/git-lfs/lfs-test-server
396 @check("lfs-test-server", "git-lfs test server")
396 @check("lfs-test-server", "git-lfs test server")
397 def has_lfsserver():
397 def has_lfsserver():
398 exe = 'lfs-test-server'
398 exe = 'lfs-test-server'
399 if has_windows():
399 if has_windows():
400 exe = 'lfs-test-server.exe'
400 exe = 'lfs-test-server.exe'
401 return any(
401 return any(
402 os.access(os.path.join(path, exe), os.X_OK)
402 os.access(os.path.join(path, exe), os.X_OK)
403 for path in os.environ["PATH"].split(os.pathsep)
403 for path in os.environ["PATH"].split(os.pathsep)
404 )
404 )
405
405
406
406
407 @checkvers("git", "git client (with ext::sh support) version >= %s", (1.9,))
407 @checkvers("git", "git client (with ext::sh support) version >= %s", (1.9,))
408 def has_git_range(v):
408 def has_git_range(v):
409 major, minor = v.split('.')[0:2]
409 major, minor = v.split('.')[0:2]
410 return getgitversion() >= (int(major), int(minor))
410 return getgitversion() >= (int(major), int(minor))
411
411
412
412
413 @check("docutils", "Docutils text processing library")
413 @check("docutils", "Docutils text processing library")
414 def has_docutils():
414 def has_docutils():
415 try:
415 try:
416 import docutils.core
416 import docutils.core
417
417
418 docutils.core.publish_cmdline # silence unused import
418 docutils.core.publish_cmdline # silence unused import
419 return True
419 return True
420 except ImportError:
420 except ImportError:
421 return False
421 return False
422
422
423
423
424 def getsvnversion():
424 def getsvnversion():
425 m = matchoutput('svn --version --quiet 2>&1', br'^(\d+)\.(\d+)')
425 m = matchoutput('svn --version --quiet 2>&1', br'^(\d+)\.(\d+)')
426 if not m:
426 if not m:
427 return (0, 0)
427 return (0, 0)
428 return (int(m.group(1)), int(m.group(2)))
428 return (int(m.group(1)), int(m.group(2)))
429
429
430
430
431 @checkvers("svn", "subversion client and admin tools >= %s", (1.3, 1.5))
431 @checkvers("svn", "subversion client and admin tools >= %s", (1.3, 1.5))
432 def has_svn_range(v):
432 def has_svn_range(v):
433 major, minor = v.split('.')[0:2]
433 major, minor = v.split('.')[0:2]
434 return getsvnversion() >= (int(major), int(minor))
434 return getsvnversion() >= (int(major), int(minor))
435
435
436
436
437 @check("svn", "subversion client and admin tools")
437 @check("svn", "subversion client and admin tools")
438 def has_svn():
438 def has_svn():
439 return matchoutput('svn --version 2>&1', br'^svn, version') and matchoutput(
439 return matchoutput('svn --version 2>&1', br'^svn, version') and matchoutput(
440 'svnadmin --version 2>&1', br'^svnadmin, version'
440 'svnadmin --version 2>&1', br'^svnadmin, version'
441 )
441 )
442
442
443
443
444 @check("svn-bindings", "subversion python bindings")
444 @check("svn-bindings", "subversion python bindings")
445 def has_svn_bindings():
445 def has_svn_bindings():
446 try:
446 try:
447 import svn.core
447 import svn.core
448
448
449 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
449 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
450 if version < (1, 4):
450 if version < (1, 4):
451 return False
451 return False
452 return True
452 return True
453 except ImportError:
453 except ImportError:
454 return False
454 return False
455
455
456
456
457 @check("p4", "Perforce server and client")
457 @check("p4", "Perforce server and client")
458 def has_p4():
458 def has_p4():
459 return matchoutput('p4 -V', br'Rev\. P4/') and matchoutput(
459 return matchoutput('p4 -V', br'Rev\. P4/') and matchoutput(
460 'p4d -V', br'Rev\. P4D/'
460 'p4d -V', br'Rev\. P4D/'
461 )
461 )
462
462
463
463
464 @check("symlink", "symbolic links")
464 @check("symlink", "symbolic links")
465 def has_symlink():
465 def has_symlink():
466 # mercurial.windows.checklink() is a hard 'no' at the moment
466 # mercurial.windows.checklink() is a hard 'no' at the moment
467 if os.name == 'nt' or getattr(os, "symlink", None) is None:
467 if os.name == 'nt' or getattr(os, "symlink", None) is None:
468 return False
468 return False
469 name = tempfile.mktemp(dir='.', prefix=tempprefix)
469 name = tempfile.mktemp(dir='.', prefix=tempprefix)
470 try:
470 try:
471 os.symlink(".", name)
471 os.symlink(".", name)
472 os.unlink(name)
472 os.unlink(name)
473 return True
473 return True
474 except (OSError, AttributeError):
474 except (OSError, AttributeError):
475 return False
475 return False
476
476
477
477
478 @check("hardlink", "hardlinks")
478 @check("hardlink", "hardlinks")
479 def has_hardlink():
479 def has_hardlink():
480 from mercurial import util
480 from mercurial import util
481
481
482 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
482 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
483 os.close(fh)
483 os.close(fh)
484 name = tempfile.mktemp(dir='.', prefix=tempprefix)
484 name = tempfile.mktemp(dir='.', prefix=tempprefix)
485 try:
485 try:
486 util.oslink(_sys2bytes(fn), _sys2bytes(name))
486 util.oslink(_sys2bytes(fn), _sys2bytes(name))
487 os.unlink(name)
487 os.unlink(name)
488 return True
488 return True
489 except OSError:
489 except OSError:
490 return False
490 return False
491 finally:
491 finally:
492 os.unlink(fn)
492 os.unlink(fn)
493
493
494
494
495 @check("hardlink-whitelisted", "hardlinks on whitelisted filesystems")
495 @check("hardlink-whitelisted", "hardlinks on whitelisted filesystems")
496 def has_hardlink_whitelisted():
496 def has_hardlink_whitelisted():
497 from mercurial import util
497 from mercurial import util
498
498
499 try:
499 try:
500 fstype = util.getfstype(b'.')
500 fstype = util.getfstype(b'.')
501 except OSError:
501 except OSError:
502 return False
502 return False
503 return fstype in util._hardlinkfswhitelist
503 return fstype in util._hardlinkfswhitelist
504
504
505
505
506 @check("rmcwd", "can remove current working directory")
506 @check("rmcwd", "can remove current working directory")
507 def has_rmcwd():
507 def has_rmcwd():
508 ocwd = os.getcwd()
508 ocwd = os.getcwd()
509 temp = tempfile.mkdtemp(dir='.', prefix=tempprefix)
509 temp = tempfile.mkdtemp(dir='.', prefix=tempprefix)
510 try:
510 try:
511 os.chdir(temp)
511 os.chdir(temp)
512 # On Linux, 'rmdir .' isn't allowed, but the other names are okay.
512 # On Linux, 'rmdir .' isn't allowed, but the other names are okay.
513 # On Solaris and Windows, the cwd can't be removed by any names.
513 # On Solaris and Windows, the cwd can't be removed by any names.
514 os.rmdir(os.getcwd())
514 os.rmdir(os.getcwd())
515 return True
515 return True
516 except OSError:
516 except OSError:
517 return False
517 return False
518 finally:
518 finally:
519 os.chdir(ocwd)
519 os.chdir(ocwd)
520 # clean up temp dir on platforms where cwd can't be removed
520 # clean up temp dir on platforms where cwd can't be removed
521 try:
521 try:
522 os.rmdir(temp)
522 os.rmdir(temp)
523 except OSError:
523 except OSError:
524 pass
524 pass
525
525
526
526
527 @check("tla", "GNU Arch tla client")
527 @check("tla", "GNU Arch tla client")
528 def has_tla():
528 def has_tla():
529 return matchoutput('tla --version 2>&1', br'The GNU Arch Revision')
529 return matchoutput('tla --version 2>&1', br'The GNU Arch Revision')
530
530
531
531
532 @check("gpg", "gpg client")
532 @check("gpg", "gpg client")
533 def has_gpg():
533 def has_gpg():
534 return matchoutput('gpg --version 2>&1', br'GnuPG')
534 return matchoutput('gpg --version 2>&1', br'GnuPG')
535
535
536
536
537 @check("gpg2", "gpg client v2")
537 @check("gpg2", "gpg client v2")
538 def has_gpg2():
538 def has_gpg2():
539 return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.')
539 return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.')
540
540
541
541
542 @check("gpg21", "gpg client v2.1+")
542 @check("gpg21", "gpg client v2.1+")
543 def has_gpg21():
543 def has_gpg21():
544 return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.(?!0)')
544 return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.(?!0)')
545
545
546
546
547 @check("unix-permissions", "unix-style permissions")
547 @check("unix-permissions", "unix-style permissions")
548 def has_unix_permissions():
548 def has_unix_permissions():
549 d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
549 d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
550 try:
550 try:
551 fname = os.path.join(d, 'foo')
551 fname = os.path.join(d, 'foo')
552 for umask in (0o77, 0o07, 0o22):
552 for umask in (0o77, 0o07, 0o22):
553 os.umask(umask)
553 os.umask(umask)
554 f = open(fname, 'w')
554 f = open(fname, 'w')
555 f.close()
555 f.close()
556 mode = os.stat(fname).st_mode
556 mode = os.stat(fname).st_mode
557 os.unlink(fname)
557 os.unlink(fname)
558 if mode & 0o777 != ~umask & 0o666:
558 if mode & 0o777 != ~umask & 0o666:
559 return False
559 return False
560 return True
560 return True
561 finally:
561 finally:
562 os.rmdir(d)
562 os.rmdir(d)
563
563
564
564
565 @check("unix-socket", "AF_UNIX socket family")
565 @check("unix-socket", "AF_UNIX socket family")
566 def has_unix_socket():
566 def has_unix_socket():
567 return getattr(socket, 'AF_UNIX', None) is not None
567 return getattr(socket, 'AF_UNIX', None) is not None
568
568
569
569
570 @check("root", "root permissions")
570 @check("root", "root permissions")
571 def has_root():
571 def has_root():
572 return getattr(os, 'geteuid', None) and os.geteuid() == 0
572 return getattr(os, 'geteuid', None) and os.geteuid() == 0
573
573
574
574
575 @check("pyflakes", "Pyflakes python linter")
575 @check("pyflakes", "Pyflakes python linter")
576 def has_pyflakes():
576 def has_pyflakes():
577 try:
577 try:
578 import pyflakes
578 import pyflakes
579
579
580 pyflakes.__version__
580 pyflakes.__version__
581 except ImportError:
581 except ImportError:
582 return False
582 return False
583 else:
583 else:
584 return True
584 return True
585
585
586
586
587 @check("pylint", "Pylint python linter")
587 @check("pylint", "Pylint python linter")
588 def has_pylint():
588 def has_pylint():
589 return matchoutput("pylint --help", br"Usage: pylint", True)
589 return matchoutput("pylint --help", br"Usage: pylint", True)
590
590
591
591
592 @check("clang-format", "clang-format C code formatter")
592 @check("clang-format", "clang-format C code formatter")
593 def has_clang_format():
593 def has_clang_format():
594 m = matchoutput('clang-format --version', br'clang-format version (\d)')
594 m = matchoutput('clang-format --version', br'clang-format version (\d)')
595 # style changed somewhere between 4.x and 6.x
595 # style changed somewhere between 4.x and 6.x
596 return m and int(m.group(1)) >= 6
596 return m and int(m.group(1)) >= 6
597
597
598
598
599 @check("jshint", "JSHint static code analysis tool")
599 @check("jshint", "JSHint static code analysis tool")
600 def has_jshint():
600 def has_jshint():
601 return matchoutput("jshint --version 2>&1", br"jshint v")
601 return matchoutput("jshint --version 2>&1", br"jshint v")
602
602
603
603
604 @check("pygments", "Pygments source highlighting library")
604 @check("pygments", "Pygments source highlighting library")
605 def has_pygments():
605 def has_pygments():
606 try:
606 try:
607 import pygments
607 import pygments
608
608
609 pygments.highlight # silence unused import warning
609 pygments.highlight # silence unused import warning
610 return True
610 return True
611 except ImportError:
611 except ImportError:
612 return False
612 return False
613
613
614
614
615 @check("pygments25", "Pygments version >= 2.5")
615 @check("pygments25", "Pygments version >= 2.5")
616 def pygments25():
616 def pygments25():
617 try:
617 try:
618 import pygments
618 import pygments
619
619
620 v = pygments.__version__
620 v = pygments.__version__
621 except ImportError:
621 except ImportError:
622 return False
622 return False
623
623
624 parts = v.split(".")
624 parts = v.split(".")
625 major = int(parts[0])
625 major = int(parts[0])
626 minor = int(parts[1])
626 minor = int(parts[1])
627
627
628 return (major, minor) >= (2, 5)
628 return (major, minor) >= (2, 5)
629
629
630
630
631 @check("outer-repo", "outer repo")
631 @check("outer-repo", "outer repo")
632 def has_outer_repo():
632 def has_outer_repo():
633 # failing for other reasons than 'no repo' imply that there is a repo
633 # failing for other reasons than 'no repo' imply that there is a repo
634 return not matchoutput('hg root 2>&1', br'abort: no repository found', True)
634 return not matchoutput('hg root 2>&1', br'abort: no repository found', True)
635
635
636
636
637 @check("ssl", "ssl module available")
637 @check("ssl", "ssl module available")
638 def has_ssl():
638 def has_ssl():
639 try:
639 try:
640 import ssl
640 import ssl
641
641
642 ssl.CERT_NONE
642 ssl.CERT_NONE
643 return True
643 return True
644 except ImportError:
644 except ImportError:
645 return False
645 return False
646
646
647
647
648 @check("sslcontext", "python >= 2.7.9 ssl")
649 def has_sslcontext():
650 try:
651 import ssl
652
653 ssl.SSLContext
654 return True
655 except (ImportError, AttributeError):
656 return False
657
658
659 @check("defaultcacertsloaded", "detected presence of loaded system CA certs")
648 @check("defaultcacertsloaded", "detected presence of loaded system CA certs")
660 def has_defaultcacertsloaded():
649 def has_defaultcacertsloaded():
661 import ssl
650 import ssl
662 from mercurial import sslutil, ui as uimod
651 from mercurial import sslutil, ui as uimod
663
652
664 if not has_sslcontext():
665 return False
666
667 ui = uimod.ui.load()
653 ui = uimod.ui.load()
668 cafile = sslutil._defaultcacerts(ui)
654 cafile = sslutil._defaultcacerts(ui)
669 ctx = ssl.create_default_context()
655 ctx = ssl.create_default_context()
670 if cafile:
656 if cafile:
671 ctx.load_verify_locations(cafile=cafile)
657 ctx.load_verify_locations(cafile=cafile)
672 else:
658 else:
673 ctx.load_default_certs()
659 ctx.load_default_certs()
674
660
675 return len(ctx.get_ca_certs()) > 0
661 return len(ctx.get_ca_certs()) > 0
676
662
677
663
678 @check("tls1.2", "TLS 1.2 protocol support")
664 @check("tls1.2", "TLS 1.2 protocol support")
679 def has_tls1_2():
665 def has_tls1_2():
680 from mercurial import sslutil
666 from mercurial import sslutil
681
667
682 return b'tls1.2' in sslutil.supportedprotocols
668 return b'tls1.2' in sslutil.supportedprotocols
683
669
684
670
685 @check("windows", "Windows")
671 @check("windows", "Windows")
686 def has_windows():
672 def has_windows():
687 return os.name == 'nt'
673 return os.name == 'nt'
688
674
689
675
690 @check("system-sh", "system() uses sh")
676 @check("system-sh", "system() uses sh")
691 def has_system_sh():
677 def has_system_sh():
692 return os.name != 'nt'
678 return os.name != 'nt'
693
679
694
680
695 @check("serve", "platform and python can manage 'hg serve -d'")
681 @check("serve", "platform and python can manage 'hg serve -d'")
696 def has_serve():
682 def has_serve():
697 return True
683 return True
698
684
699
685
700 @check("test-repo", "running tests from repository")
686 @check("test-repo", "running tests from repository")
701 def has_test_repo():
687 def has_test_repo():
702 t = os.environ["TESTDIR"]
688 t = os.environ["TESTDIR"]
703 return os.path.isdir(os.path.join(t, "..", ".hg"))
689 return os.path.isdir(os.path.join(t, "..", ".hg"))
704
690
705
691
706 @check("tic", "terminfo compiler and curses module")
692 @check("tic", "terminfo compiler and curses module")
707 def has_tic():
693 def has_tic():
708 try:
694 try:
709 import curses
695 import curses
710
696
711 curses.COLOR_BLUE
697 curses.COLOR_BLUE
712 return matchoutput('test -x "`which tic`"', br'')
698 return matchoutput('test -x "`which tic`"', br'')
713 except (ImportError, AttributeError):
699 except (ImportError, AttributeError):
714 return False
700 return False
715
701
716
702
717 @check("xz", "xz compression utility")
703 @check("xz", "xz compression utility")
718 def has_xz():
704 def has_xz():
719 # When Windows invokes a subprocess in shell mode, it uses `cmd.exe`, which
705 # When Windows invokes a subprocess in shell mode, it uses `cmd.exe`, which
720 # only knows `where`, not `which`. So invoke MSYS shell explicitly.
706 # only knows `where`, not `which`. So invoke MSYS shell explicitly.
721 return matchoutput("sh -c 'test -x \"`which xz`\"'", b'')
707 return matchoutput("sh -c 'test -x \"`which xz`\"'", b'')
722
708
723
709
724 @check("msys", "Windows with MSYS")
710 @check("msys", "Windows with MSYS")
725 def has_msys():
711 def has_msys():
726 return os.getenv('MSYSTEM')
712 return os.getenv('MSYSTEM')
727
713
728
714
729 @check("aix", "AIX")
715 @check("aix", "AIX")
730 def has_aix():
716 def has_aix():
731 return sys.platform.startswith("aix")
717 return sys.platform.startswith("aix")
732
718
733
719
734 @check("osx", "OS X")
720 @check("osx", "OS X")
735 def has_osx():
721 def has_osx():
736 return sys.platform == 'darwin'
722 return sys.platform == 'darwin'
737
723
738
724
739 @check("osxpackaging", "OS X packaging tools")
725 @check("osxpackaging", "OS X packaging tools")
740 def has_osxpackaging():
726 def has_osxpackaging():
741 try:
727 try:
742 return (
728 return (
743 matchoutput('pkgbuild', br'Usage: pkgbuild ', ignorestatus=1)
729 matchoutput('pkgbuild', br'Usage: pkgbuild ', ignorestatus=1)
744 and matchoutput(
730 and matchoutput(
745 'productbuild', br'Usage: productbuild ', ignorestatus=1
731 'productbuild', br'Usage: productbuild ', ignorestatus=1
746 )
732 )
747 and matchoutput('lsbom', br'Usage: lsbom', ignorestatus=1)
733 and matchoutput('lsbom', br'Usage: lsbom', ignorestatus=1)
748 and matchoutput('xar --help', br'Usage: xar', ignorestatus=1)
734 and matchoutput('xar --help', br'Usage: xar', ignorestatus=1)
749 )
735 )
750 except ImportError:
736 except ImportError:
751 return False
737 return False
752
738
753
739
754 @check('linuxormacos', 'Linux or MacOS')
740 @check('linuxormacos', 'Linux or MacOS')
755 def has_linuxormacos():
741 def has_linuxormacos():
756 # This isn't a perfect test for MacOS. But it is sufficient for our needs.
742 # This isn't a perfect test for MacOS. But it is sufficient for our needs.
757 return sys.platform.startswith(('linux', 'darwin'))
743 return sys.platform.startswith(('linux', 'darwin'))
758
744
759
745
760 @check("docker", "docker support")
746 @check("docker", "docker support")
761 def has_docker():
747 def has_docker():
762 pat = br'A self-sufficient runtime for'
748 pat = br'A self-sufficient runtime for'
763 if matchoutput('docker --help', pat):
749 if matchoutput('docker --help', pat):
764 if 'linux' not in sys.platform:
750 if 'linux' not in sys.platform:
765 # TODO: in theory we should be able to test docker-based
751 # TODO: in theory we should be able to test docker-based
766 # package creation on non-linux using boot2docker, but in
752 # package creation on non-linux using boot2docker, but in
767 # practice that requires extra coordination to make sure
753 # practice that requires extra coordination to make sure
768 # $TESTTEMP is going to be visible at the same path to the
754 # $TESTTEMP is going to be visible at the same path to the
769 # boot2docker VM. If we figure out how to verify that, we
755 # boot2docker VM. If we figure out how to verify that, we
770 # can use the following instead of just saying False:
756 # can use the following instead of just saying False:
771 # return 'DOCKER_HOST' in os.environ
757 # return 'DOCKER_HOST' in os.environ
772 return False
758 return False
773
759
774 return True
760 return True
775 return False
761 return False
776
762
777
763
778 @check("debhelper", "debian packaging tools")
764 @check("debhelper", "debian packaging tools")
779 def has_debhelper():
765 def has_debhelper():
780 # Some versions of dpkg say `dpkg', some say 'dpkg' (` vs ' on the first
766 # Some versions of dpkg say `dpkg', some say 'dpkg' (` vs ' on the first
781 # quote), so just accept anything in that spot.
767 # quote), so just accept anything in that spot.
782 dpkg = matchoutput(
768 dpkg = matchoutput(
783 'dpkg --version', br"Debian .dpkg' package management program"
769 'dpkg --version', br"Debian .dpkg' package management program"
784 )
770 )
785 dh = matchoutput(
771 dh = matchoutput(
786 'dh --help', br'dh is a part of debhelper.', ignorestatus=True
772 'dh --help', br'dh is a part of debhelper.', ignorestatus=True
787 )
773 )
788 dh_py2 = matchoutput(
774 dh_py2 = matchoutput(
789 'dh_python2 --help', br'other supported Python versions'
775 'dh_python2 --help', br'other supported Python versions'
790 )
776 )
791 # debuild comes from the 'devscripts' package, though you might want
777 # debuild comes from the 'devscripts' package, though you might want
792 # the 'build-debs' package instead, which has a dependency on devscripts.
778 # the 'build-debs' package instead, which has a dependency on devscripts.
793 debuild = matchoutput(
779 debuild = matchoutput(
794 'debuild --help', br'to run debian/rules with given parameter'
780 'debuild --help', br'to run debian/rules with given parameter'
795 )
781 )
796 return dpkg and dh and dh_py2 and debuild
782 return dpkg and dh and dh_py2 and debuild
797
783
798
784
799 @check(
785 @check(
800 "debdeps", "debian build dependencies (run dpkg-checkbuilddeps in contrib/)"
786 "debdeps", "debian build dependencies (run dpkg-checkbuilddeps in contrib/)"
801 )
787 )
802 def has_debdeps():
788 def has_debdeps():
803 # just check exit status (ignoring output)
789 # just check exit status (ignoring output)
804 path = '%s/../contrib/packaging/debian/control' % os.environ['TESTDIR']
790 path = '%s/../contrib/packaging/debian/control' % os.environ['TESTDIR']
805 return matchoutput('dpkg-checkbuilddeps %s' % path, br'')
791 return matchoutput('dpkg-checkbuilddeps %s' % path, br'')
806
792
807
793
808 @check("demandimport", "demandimport enabled")
794 @check("demandimport", "demandimport enabled")
809 def has_demandimport():
795 def has_demandimport():
810 # chg disables demandimport intentionally for performance wins.
796 # chg disables demandimport intentionally for performance wins.
811 return (not has_chg()) and os.environ.get('HGDEMANDIMPORT') != 'disable'
797 return (not has_chg()) and os.environ.get('HGDEMANDIMPORT') != 'disable'
812
798
813
799
814 # Add "py27", "py35", ... as possible feature checks. Note that there's no
800 # Add "py27", "py35", ... as possible feature checks. Note that there's no
815 # punctuation here.
801 # punctuation here.
816 @checkvers("py", "Python >= %s", (2.7, 3.5, 3.6, 3.7, 3.8, 3.9))
802 @checkvers("py", "Python >= %s", (2.7, 3.5, 3.6, 3.7, 3.8, 3.9))
817 def has_python_range(v):
803 def has_python_range(v):
818 major, minor = v.split('.')[0:2]
804 major, minor = v.split('.')[0:2]
819 py_major, py_minor = sys.version_info.major, sys.version_info.minor
805 py_major, py_minor = sys.version_info.major, sys.version_info.minor
820
806
821 return (py_major, py_minor) >= (int(major), int(minor))
807 return (py_major, py_minor) >= (int(major), int(minor))
822
808
823
809
824 @check("py3", "running with Python 3.x")
810 @check("py3", "running with Python 3.x")
825 def has_py3():
811 def has_py3():
826 return 3 == sys.version_info[0]
812 return 3 == sys.version_info[0]
827
813
828
814
829 @check("py3exe", "a Python 3.x interpreter is available")
815 @check("py3exe", "a Python 3.x interpreter is available")
830 def has_python3exe():
816 def has_python3exe():
831 return matchoutput('python3 -V', br'^Python 3.(5|6|7|8|9)')
817 return matchoutput('python3 -V', br'^Python 3.(5|6|7|8|9)')
832
818
833
819
834 @check("pure", "running with pure Python code")
820 @check("pure", "running with pure Python code")
835 def has_pure():
821 def has_pure():
836 return any(
822 return any(
837 [
823 [
838 os.environ.get("HGMODULEPOLICY") == "py",
824 os.environ.get("HGMODULEPOLICY") == "py",
839 os.environ.get("HGTEST_RUN_TESTS_PURE") == "--pure",
825 os.environ.get("HGTEST_RUN_TESTS_PURE") == "--pure",
840 ]
826 ]
841 )
827 )
842
828
843
829
844 @check("slow", "allow slow tests (use --allow-slow-tests)")
830 @check("slow", "allow slow tests (use --allow-slow-tests)")
845 def has_slow():
831 def has_slow():
846 return os.environ.get('HGTEST_SLOW') == 'slow'
832 return os.environ.get('HGTEST_SLOW') == 'slow'
847
833
848
834
849 @check("hypothesis", "Hypothesis automated test generation")
835 @check("hypothesis", "Hypothesis automated test generation")
850 def has_hypothesis():
836 def has_hypothesis():
851 try:
837 try:
852 import hypothesis
838 import hypothesis
853
839
854 hypothesis.given
840 hypothesis.given
855 return True
841 return True
856 except ImportError:
842 except ImportError:
857 return False
843 return False
858
844
859
845
860 @check("unziplinks", "unzip(1) understands and extracts symlinks")
846 @check("unziplinks", "unzip(1) understands and extracts symlinks")
861 def unzip_understands_symlinks():
847 def unzip_understands_symlinks():
862 return matchoutput('unzip --help', br'Info-ZIP')
848 return matchoutput('unzip --help', br'Info-ZIP')
863
849
864
850
865 @check("zstd", "zstd Python module available")
851 @check("zstd", "zstd Python module available")
866 def has_zstd():
852 def has_zstd():
867 try:
853 try:
868 import mercurial.zstd
854 import mercurial.zstd
869
855
870 mercurial.zstd.__version__
856 mercurial.zstd.__version__
871 return True
857 return True
872 except ImportError:
858 except ImportError:
873 return False
859 return False
874
860
875
861
876 @check("devfull", "/dev/full special file")
862 @check("devfull", "/dev/full special file")
877 def has_dev_full():
863 def has_dev_full():
878 return os.path.exists('/dev/full')
864 return os.path.exists('/dev/full')
879
865
880
866
881 @check("ensurepip", "ensurepip module")
867 @check("ensurepip", "ensurepip module")
882 def has_ensurepip():
868 def has_ensurepip():
883 try:
869 try:
884 import ensurepip
870 import ensurepip
885
871
886 ensurepip.bootstrap
872 ensurepip.bootstrap
887 return True
873 return True
888 except ImportError:
874 except ImportError:
889 return False
875 return False
890
876
891
877
892 @check("virtualenv", "Python virtualenv support")
878 @check("virtualenv", "Python virtualenv support")
893 def has_virtualenv():
879 def has_virtualenv():
894 try:
880 try:
895 import virtualenv
881 import virtualenv
896
882
897 virtualenv.ACTIVATE_SH
883 virtualenv.ACTIVATE_SH
898 return True
884 return True
899 except ImportError:
885 except ImportError:
900 return False
886 return False
901
887
902
888
903 @check("fsmonitor", "running tests with fsmonitor")
889 @check("fsmonitor", "running tests with fsmonitor")
904 def has_fsmonitor():
890 def has_fsmonitor():
905 return 'HGFSMONITOR_TESTS' in os.environ
891 return 'HGFSMONITOR_TESTS' in os.environ
906
892
907
893
908 @check("fuzzywuzzy", "Fuzzy string matching library")
894 @check("fuzzywuzzy", "Fuzzy string matching library")
909 def has_fuzzywuzzy():
895 def has_fuzzywuzzy():
910 try:
896 try:
911 import fuzzywuzzy
897 import fuzzywuzzy
912
898
913 fuzzywuzzy.__version__
899 fuzzywuzzy.__version__
914 return True
900 return True
915 except ImportError:
901 except ImportError:
916 return False
902 return False
917
903
918
904
919 @check("clang-libfuzzer", "clang new enough to include libfuzzer")
905 @check("clang-libfuzzer", "clang new enough to include libfuzzer")
920 def has_clang_libfuzzer():
906 def has_clang_libfuzzer():
921 mat = matchoutput('clang --version', br'clang version (\d)')
907 mat = matchoutput('clang --version', br'clang version (\d)')
922 if mat:
908 if mat:
923 # libfuzzer is new in clang 6
909 # libfuzzer is new in clang 6
924 return int(mat.group(1)) > 5
910 return int(mat.group(1)) > 5
925 return False
911 return False
926
912
927
913
928 @check("clang-6.0", "clang 6.0 with version suffix (libfuzzer included)")
914 @check("clang-6.0", "clang 6.0 with version suffix (libfuzzer included)")
929 def has_clang60():
915 def has_clang60():
930 return matchoutput('clang-6.0 --version', br'clang version 6\.')
916 return matchoutput('clang-6.0 --version', br'clang version 6\.')
931
917
932
918
933 @check("xdiff", "xdiff algorithm")
919 @check("xdiff", "xdiff algorithm")
934 def has_xdiff():
920 def has_xdiff():
935 try:
921 try:
936 from mercurial import policy
922 from mercurial import policy
937
923
938 bdiff = policy.importmod('bdiff')
924 bdiff = policy.importmod('bdiff')
939 return bdiff.xdiffblocks(b'', b'') == [(0, 0, 0, 0)]
925 return bdiff.xdiffblocks(b'', b'') == [(0, 0, 0, 0)]
940 except (ImportError, AttributeError):
926 except (ImportError, AttributeError):
941 return False
927 return False
942
928
943
929
944 @check('extraextensions', 'whether tests are running with extra extensions')
930 @check('extraextensions', 'whether tests are running with extra extensions')
945 def has_extraextensions():
931 def has_extraextensions():
946 return 'HGTESTEXTRAEXTENSIONS' in os.environ
932 return 'HGTESTEXTRAEXTENSIONS' in os.environ
947
933
948
934
949 def getrepofeatures():
935 def getrepofeatures():
950 """Obtain set of repository features in use.
936 """Obtain set of repository features in use.
951
937
952 HGREPOFEATURES can be used to define or remove features. It contains
938 HGREPOFEATURES can be used to define or remove features. It contains
953 a space-delimited list of feature strings. Strings beginning with ``-``
939 a space-delimited list of feature strings. Strings beginning with ``-``
954 mean to remove.
940 mean to remove.
955 """
941 """
956 # Default list provided by core.
942 # Default list provided by core.
957 features = {
943 features = {
958 'bundlerepo',
944 'bundlerepo',
959 'revlogstore',
945 'revlogstore',
960 'fncache',
946 'fncache',
961 }
947 }
962
948
963 # Features that imply other features.
949 # Features that imply other features.
964 implies = {
950 implies = {
965 'simplestore': ['-revlogstore', '-bundlerepo', '-fncache'],
951 'simplestore': ['-revlogstore', '-bundlerepo', '-fncache'],
966 }
952 }
967
953
968 for override in os.environ.get('HGREPOFEATURES', '').split(' '):
954 for override in os.environ.get('HGREPOFEATURES', '').split(' '):
969 if not override:
955 if not override:
970 continue
956 continue
971
957
972 if override.startswith('-'):
958 if override.startswith('-'):
973 if override[1:] in features:
959 if override[1:] in features:
974 features.remove(override[1:])
960 features.remove(override[1:])
975 else:
961 else:
976 features.add(override)
962 features.add(override)
977
963
978 for imply in implies.get(override, []):
964 for imply in implies.get(override, []):
979 if imply.startswith('-'):
965 if imply.startswith('-'):
980 if imply[1:] in features:
966 if imply[1:] in features:
981 features.remove(imply[1:])
967 features.remove(imply[1:])
982 else:
968 else:
983 features.add(imply)
969 features.add(imply)
984
970
985 return features
971 return features
986
972
987
973
988 @check('reporevlogstore', 'repository using the default revlog store')
974 @check('reporevlogstore', 'repository using the default revlog store')
989 def has_reporevlogstore():
975 def has_reporevlogstore():
990 return 'revlogstore' in getrepofeatures()
976 return 'revlogstore' in getrepofeatures()
991
977
992
978
993 @check('reposimplestore', 'repository using simple storage extension')
979 @check('reposimplestore', 'repository using simple storage extension')
994 def has_reposimplestore():
980 def has_reposimplestore():
995 return 'simplestore' in getrepofeatures()
981 return 'simplestore' in getrepofeatures()
996
982
997
983
998 @check('repobundlerepo', 'whether we can open bundle files as repos')
984 @check('repobundlerepo', 'whether we can open bundle files as repos')
999 def has_repobundlerepo():
985 def has_repobundlerepo():
1000 return 'bundlerepo' in getrepofeatures()
986 return 'bundlerepo' in getrepofeatures()
1001
987
1002
988
1003 @check('repofncache', 'repository has an fncache')
989 @check('repofncache', 'repository has an fncache')
1004 def has_repofncache():
990 def has_repofncache():
1005 return 'fncache' in getrepofeatures()
991 return 'fncache' in getrepofeatures()
1006
992
1007
993
1008 @check('sqlite', 'sqlite3 module is available')
994 @check('sqlite', 'sqlite3 module is available')
1009 def has_sqlite():
995 def has_sqlite():
1010 try:
996 try:
1011 import sqlite3
997 import sqlite3
1012
998
1013 version = sqlite3.sqlite_version_info
999 version = sqlite3.sqlite_version_info
1014 except ImportError:
1000 except ImportError:
1015 return False
1001 return False
1016
1002
1017 if version < (3, 8, 3):
1003 if version < (3, 8, 3):
1018 # WITH clause not supported
1004 # WITH clause not supported
1019 return False
1005 return False
1020
1006
1021 return matchoutput('sqlite3 -version', br'^3\.\d+')
1007 return matchoutput('sqlite3 -version', br'^3\.\d+')
1022
1008
1023
1009
1024 @check('vcr', 'vcr http mocking library')
1010 @check('vcr', 'vcr http mocking library')
1025 def has_vcr():
1011 def has_vcr():
1026 try:
1012 try:
1027 import vcr
1013 import vcr
1028
1014
1029 vcr.VCR
1015 vcr.VCR
1030 return True
1016 return True
1031 except (ImportError, AttributeError):
1017 except (ImportError, AttributeError):
1032 pass
1018 pass
1033 return False
1019 return False
1034
1020
1035
1021
1036 @check('emacs', 'GNU Emacs')
1022 @check('emacs', 'GNU Emacs')
1037 def has_emacs():
1023 def has_emacs():
1038 # Our emacs lisp uses `with-eval-after-load` which is new in emacs
1024 # Our emacs lisp uses `with-eval-after-load` which is new in emacs
1039 # 24.4, so we allow emacs 24.4, 24.5, and 25+ (24.5 was the last
1025 # 24.4, so we allow emacs 24.4, 24.5, and 25+ (24.5 was the last
1040 # 24 release)
1026 # 24 release)
1041 return matchoutput('emacs --version', b'GNU Emacs 2(4.4|4.5|5|6|7|8|9)')
1027 return matchoutput('emacs --version', b'GNU Emacs 2(4.4|4.5|5|6|7|8|9)')
1042
1028
1043
1029
1044 @check('black', 'the black formatter for python')
1030 @check('black', 'the black formatter for python')
1045 def has_black():
1031 def has_black():
1046 blackcmd = 'black --version'
1032 blackcmd = 'black --version'
1047 version_regex = b'black, version ([0-9a-b.]+)'
1033 version_regex = b'black, version ([0-9a-b.]+)'
1048 version = matchoutput(blackcmd, version_regex)
1034 version = matchoutput(blackcmd, version_regex)
1049 sv = distutils.version.StrictVersion
1035 sv = distutils.version.StrictVersion
1050 return version and sv(_bytes2sys(version.group(1))) >= sv('19.10b0')
1036 return version and sv(_bytes2sys(version.group(1))) >= sv('19.10b0')
1051
1037
1052
1038
1053 @check('pytype', 'the pytype type checker')
1039 @check('pytype', 'the pytype type checker')
1054 def has_pytype():
1040 def has_pytype():
1055 pytypecmd = 'pytype --version'
1041 pytypecmd = 'pytype --version'
1056 version = matchoutput(pytypecmd, b'[0-9a-b.]+')
1042 version = matchoutput(pytypecmd, b'[0-9a-b.]+')
1057 sv = distutils.version.StrictVersion
1043 sv = distutils.version.StrictVersion
1058 return version and sv(_bytes2sys(version.group(0))) >= sv('2019.10.17')
1044 return version and sv(_bytes2sys(version.group(0))) >= sv('2019.10.17')
1059
1045
1060
1046
1061 @check("rustfmt", "rustfmt tool")
1047 @check("rustfmt", "rustfmt tool")
1062 def has_rustfmt():
1048 def has_rustfmt():
1063 # We use Nightly's rustfmt due to current unstable config options.
1049 # We use Nightly's rustfmt due to current unstable config options.
1064 return matchoutput(
1050 return matchoutput(
1065 '`rustup which --toolchain nightly rustfmt` --version', b'rustfmt'
1051 '`rustup which --toolchain nightly rustfmt` --version', b'rustfmt'
1066 )
1052 )
@@ -1,569 +1,553 b''
1 #require no-reposimplestore no-chg
1 #require no-reposimplestore no-chg
2
2
3 Set up a server
3 Set up a server
4
4
5 $ hg init server
5 $ hg init server
6 $ cd server
6 $ cd server
7 $ cat >> .hg/hgrc << EOF
7 $ cat >> .hg/hgrc << EOF
8 > [extensions]
8 > [extensions]
9 > clonebundles =
9 > clonebundles =
10 > EOF
10 > EOF
11
11
12 $ touch foo
12 $ touch foo
13 $ hg -q commit -A -m 'add foo'
13 $ hg -q commit -A -m 'add foo'
14 $ touch bar
14 $ touch bar
15 $ hg -q commit -A -m 'add bar'
15 $ hg -q commit -A -m 'add bar'
16
16
17 $ hg serve -d -p $HGPORT --pid-file hg.pid --accesslog access.log
17 $ hg serve -d -p $HGPORT --pid-file hg.pid --accesslog access.log
18 $ cat hg.pid >> $DAEMON_PIDS
18 $ cat hg.pid >> $DAEMON_PIDS
19 $ cd ..
19 $ cd ..
20
20
21 Missing manifest should not result in server lookup
21 Missing manifest should not result in server lookup
22
22
23 $ hg --verbose clone -U http://localhost:$HGPORT no-manifest
23 $ hg --verbose clone -U http://localhost:$HGPORT no-manifest
24 requesting all changes
24 requesting all changes
25 adding changesets
25 adding changesets
26 adding manifests
26 adding manifests
27 adding file changes
27 adding file changes
28 added 2 changesets with 2 changes to 2 files
28 added 2 changesets with 2 changes to 2 files
29 new changesets 53245c60e682:aaff8d2ffbbf
29 new changesets 53245c60e682:aaff8d2ffbbf
30 (sent 3 HTTP requests and * bytes; received * bytes in responses) (glob)
30 (sent 3 HTTP requests and * bytes; received * bytes in responses) (glob)
31
31
32 $ cat server/access.log
32 $ cat server/access.log
33 * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
33 * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
34 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
34 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
35 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=aaff8d2ffbbf07a46dd1f05d8ae7877e3f56e2a2&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
35 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=aaff8d2ffbbf07a46dd1f05d8ae7877e3f56e2a2&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
36
36
37 Empty manifest file results in retrieval
37 Empty manifest file results in retrieval
38 (the extension only checks if the manifest file exists)
38 (the extension only checks if the manifest file exists)
39
39
40 $ touch server/.hg/clonebundles.manifest
40 $ touch server/.hg/clonebundles.manifest
41 $ hg --verbose clone -U http://localhost:$HGPORT empty-manifest
41 $ hg --verbose clone -U http://localhost:$HGPORT empty-manifest
42 no clone bundles available on remote; falling back to regular clone
42 no clone bundles available on remote; falling back to regular clone
43 requesting all changes
43 requesting all changes
44 adding changesets
44 adding changesets
45 adding manifests
45 adding manifests
46 adding file changes
46 adding file changes
47 added 2 changesets with 2 changes to 2 files
47 added 2 changesets with 2 changes to 2 files
48 new changesets 53245c60e682:aaff8d2ffbbf
48 new changesets 53245c60e682:aaff8d2ffbbf
49 (sent 4 HTTP requests and * bytes; received * bytes in responses) (glob)
49 (sent 4 HTTP requests and * bytes; received * bytes in responses) (glob)
50
50
51 Manifest file with invalid URL aborts
51 Manifest file with invalid URL aborts
52
52
53 $ echo 'http://does.not.exist/bundle.hg' > server/.hg/clonebundles.manifest
53 $ echo 'http://does.not.exist/bundle.hg' > server/.hg/clonebundles.manifest
54 $ hg clone http://localhost:$HGPORT 404-url
54 $ hg clone http://localhost:$HGPORT 404-url
55 applying clone bundle from http://does.not.exist/bundle.hg
55 applying clone bundle from http://does.not.exist/bundle.hg
56 error fetching bundle: (.* not known|(\[Errno -?\d+] )?([Nn]o address associated with (host)?name|Temporary failure in name resolution|Name does not resolve)) (re) (no-windows !)
56 error fetching bundle: (.* not known|(\[Errno -?\d+] )?([Nn]o address associated with (host)?name|Temporary failure in name resolution|Name does not resolve)) (re) (no-windows !)
57 error fetching bundle: [Errno 1100*] getaddrinfo failed (glob) (windows !)
57 error fetching bundle: [Errno 1100*] getaddrinfo failed (glob) (windows !)
58 abort: error applying bundle
58 abort: error applying bundle
59 (if this error persists, consider contacting the server operator or disable clone bundles via "--config ui.clonebundles=false")
59 (if this error persists, consider contacting the server operator or disable clone bundles via "--config ui.clonebundles=false")
60 [255]
60 [255]
61
61
62 Server is not running aborts
62 Server is not running aborts
63
63
64 $ echo "http://localhost:$HGPORT1/bundle.hg" > server/.hg/clonebundles.manifest
64 $ echo "http://localhost:$HGPORT1/bundle.hg" > server/.hg/clonebundles.manifest
65 $ hg clone http://localhost:$HGPORT server-not-runner
65 $ hg clone http://localhost:$HGPORT server-not-runner
66 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
66 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
67 error fetching bundle: (.* refused.*|Protocol not supported|(.* )?\$EADDRNOTAVAIL\$|.* No route to host) (re)
67 error fetching bundle: (.* refused.*|Protocol not supported|(.* )?\$EADDRNOTAVAIL\$|.* No route to host) (re)
68 abort: error applying bundle
68 abort: error applying bundle
69 (if this error persists, consider contacting the server operator or disable clone bundles via "--config ui.clonebundles=false")
69 (if this error persists, consider contacting the server operator or disable clone bundles via "--config ui.clonebundles=false")
70 [255]
70 [255]
71
71
72 Server returns 404
72 Server returns 404
73
73
74 $ "$PYTHON" $TESTDIR/dumbhttp.py -p $HGPORT1 --pid http.pid
74 $ "$PYTHON" $TESTDIR/dumbhttp.py -p $HGPORT1 --pid http.pid
75 $ cat http.pid >> $DAEMON_PIDS
75 $ cat http.pid >> $DAEMON_PIDS
76 $ hg clone http://localhost:$HGPORT running-404
76 $ hg clone http://localhost:$HGPORT running-404
77 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
77 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
78 HTTP error fetching bundle: HTTP Error 404: File not found
78 HTTP error fetching bundle: HTTP Error 404: File not found
79 abort: error applying bundle
79 abort: error applying bundle
80 (if this error persists, consider contacting the server operator or disable clone bundles via "--config ui.clonebundles=false")
80 (if this error persists, consider contacting the server operator or disable clone bundles via "--config ui.clonebundles=false")
81 [255]
81 [255]
82
82
83 We can override failure to fall back to regular clone
83 We can override failure to fall back to regular clone
84
84
85 $ hg --config ui.clonebundlefallback=true clone -U http://localhost:$HGPORT 404-fallback
85 $ hg --config ui.clonebundlefallback=true clone -U http://localhost:$HGPORT 404-fallback
86 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
86 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
87 HTTP error fetching bundle: HTTP Error 404: File not found
87 HTTP error fetching bundle: HTTP Error 404: File not found
88 falling back to normal clone
88 falling back to normal clone
89 requesting all changes
89 requesting all changes
90 adding changesets
90 adding changesets
91 adding manifests
91 adding manifests
92 adding file changes
92 adding file changes
93 added 2 changesets with 2 changes to 2 files
93 added 2 changesets with 2 changes to 2 files
94 new changesets 53245c60e682:aaff8d2ffbbf
94 new changesets 53245c60e682:aaff8d2ffbbf
95
95
96 Bundle with partial content works
96 Bundle with partial content works
97
97
98 $ hg -R server bundle --type gzip-v1 --base null -r 53245c60e682 partial.hg
98 $ hg -R server bundle --type gzip-v1 --base null -r 53245c60e682 partial.hg
99 1 changesets found
99 1 changesets found
100
100
101 We verify exact bundle content as an extra check against accidental future
101 We verify exact bundle content as an extra check against accidental future
102 changes. If this output changes, we could break old clients.
102 changes. If this output changes, we could break old clients.
103
103
104 $ f --size --hexdump partial.hg
104 $ f --size --hexdump partial.hg
105 partial.hg: size=207
105 partial.hg: size=207
106 0000: 48 47 31 30 47 5a 78 9c 63 60 60 98 17 ac 12 93 |HG10GZx.c``.....|
106 0000: 48 47 31 30 47 5a 78 9c 63 60 60 98 17 ac 12 93 |HG10GZx.c``.....|
107 0010: f0 ac a9 23 45 70 cb bf 0d 5f 59 4e 4a 7f 79 21 |...#Ep..._YNJ.y!|
107 0010: f0 ac a9 23 45 70 cb bf 0d 5f 59 4e 4a 7f 79 21 |...#Ep..._YNJ.y!|
108 0020: 9b cc 40 24 20 a0 d7 ce 2c d1 38 25 cd 24 25 d5 |..@$ ...,.8%.$%.|
108 0020: 9b cc 40 24 20 a0 d7 ce 2c d1 38 25 cd 24 25 d5 |..@$ ...,.8%.$%.|
109 0030: d8 c2 22 cd 38 d9 24 cd 22 d5 c8 22 cd 24 cd 32 |..".8.$."..".$.2|
109 0030: d8 c2 22 cd 38 d9 24 cd 22 d5 c8 22 cd 24 cd 32 |..".8.$."..".$.2|
110 0040: d1 c2 d0 c4 c8 d2 32 d1 38 39 29 c9 34 cd d4 80 |......2.89).4...|
110 0040: d1 c2 d0 c4 c8 d2 32 d1 38 39 29 c9 34 cd d4 80 |......2.89).4...|
111 0050: ab 24 b5 b8 84 cb 40 c1 80 2b 2d 3f 9f 8b 2b 31 |.$....@..+-?..+1|
111 0050: ab 24 b5 b8 84 cb 40 c1 80 2b 2d 3f 9f 8b 2b 31 |.$....@..+-?..+1|
112 0060: 25 45 01 c8 80 9a d2 9b 65 fb e5 9e 45 bf 8d 7f |%E......e...E...|
112 0060: 25 45 01 c8 80 9a d2 9b 65 fb e5 9e 45 bf 8d 7f |%E......e...E...|
113 0070: 9f c6 97 9f 2b 44 34 67 d9 ec 8e 0f a0 92 0b 75 |....+D4g.......u|
113 0070: 9f c6 97 9f 2b 44 34 67 d9 ec 8e 0f a0 92 0b 75 |....+D4g.......u|
114 0080: 41 d6 24 59 18 a4 a4 9a a6 18 1a 5b 98 9b 5a 98 |A.$Y.......[..Z.|
114 0080: 41 d6 24 59 18 a4 a4 9a a6 18 1a 5b 98 9b 5a 98 |A.$Y.......[..Z.|
115 0090: 9a 18 26 9b a6 19 98 1a 99 99 26 a6 18 9a 98 24 |..&.......&....$|
115 0090: 9a 18 26 9b a6 19 98 1a 99 99 26 a6 18 9a 98 24 |..&.......&....$|
116 00a0: 26 59 a6 25 5a 98 a5 18 a6 24 71 41 35 b1 43 dc |&Y.%Z....$qA5.C.|
116 00a0: 26 59 a6 25 5a 98 a5 18 a6 24 71 41 35 b1 43 dc |&Y.%Z....$qA5.C.|
117 00b0: 16 b2 83 f7 e9 45 8b d2 56 c7 a3 1f 82 52 d7 8a |.....E..V....R..|
117 00b0: 16 b2 83 f7 e9 45 8b d2 56 c7 a3 1f 82 52 d7 8a |.....E..V....R..|
118 00c0: 78 ed fc d5 76 f1 36 35 dc 05 00 36 ed 5e c7 |x...v.65...6.^.|
118 00c0: 78 ed fc d5 76 f1 36 35 dc 05 00 36 ed 5e c7 |x...v.65...6.^.|
119
119
120 $ echo "http://localhost:$HGPORT1/partial.hg" > server/.hg/clonebundles.manifest
120 $ echo "http://localhost:$HGPORT1/partial.hg" > server/.hg/clonebundles.manifest
121 $ hg clone -U http://localhost:$HGPORT partial-bundle
121 $ hg clone -U http://localhost:$HGPORT partial-bundle
122 applying clone bundle from http://localhost:$HGPORT1/partial.hg
122 applying clone bundle from http://localhost:$HGPORT1/partial.hg
123 adding changesets
123 adding changesets
124 adding manifests
124 adding manifests
125 adding file changes
125 adding file changes
126 added 1 changesets with 1 changes to 1 files
126 added 1 changesets with 1 changes to 1 files
127 finished applying clone bundle
127 finished applying clone bundle
128 searching for changes
128 searching for changes
129 adding changesets
129 adding changesets
130 adding manifests
130 adding manifests
131 adding file changes
131 adding file changes
132 added 1 changesets with 1 changes to 1 files
132 added 1 changesets with 1 changes to 1 files
133 new changesets aaff8d2ffbbf
133 new changesets aaff8d2ffbbf
134 1 local changesets published
134 1 local changesets published
135
135
136 Incremental pull doesn't fetch bundle
136 Incremental pull doesn't fetch bundle
137
137
138 $ hg clone -r 53245c60e682 -U http://localhost:$HGPORT partial-clone
138 $ hg clone -r 53245c60e682 -U http://localhost:$HGPORT partial-clone
139 adding changesets
139 adding changesets
140 adding manifests
140 adding manifests
141 adding file changes
141 adding file changes
142 added 1 changesets with 1 changes to 1 files
142 added 1 changesets with 1 changes to 1 files
143 new changesets 53245c60e682
143 new changesets 53245c60e682
144
144
145 $ cd partial-clone
145 $ cd partial-clone
146 $ hg pull
146 $ hg pull
147 pulling from http://localhost:$HGPORT/
147 pulling from http://localhost:$HGPORT/
148 searching for changes
148 searching for changes
149 adding changesets
149 adding changesets
150 adding manifests
150 adding manifests
151 adding file changes
151 adding file changes
152 added 1 changesets with 1 changes to 1 files
152 added 1 changesets with 1 changes to 1 files
153 new changesets aaff8d2ffbbf
153 new changesets aaff8d2ffbbf
154 (run 'hg update' to get a working copy)
154 (run 'hg update' to get a working copy)
155 $ cd ..
155 $ cd ..
156
156
157 Bundle with full content works
157 Bundle with full content works
158
158
159 $ hg -R server bundle --type gzip-v2 --base null -r tip full.hg
159 $ hg -R server bundle --type gzip-v2 --base null -r tip full.hg
160 2 changesets found
160 2 changesets found
161
161
162 Again, we perform an extra check against bundle content changes. If this content
162 Again, we perform an extra check against bundle content changes. If this content
163 changes, clone bundles produced by new Mercurial versions may not be readable
163 changes, clone bundles produced by new Mercurial versions may not be readable
164 by old clients.
164 by old clients.
165
165
166 $ f --size --hexdump full.hg
166 $ f --size --hexdump full.hg
167 full.hg: size=442
167 full.hg: size=442
168 0000: 48 47 32 30 00 00 00 0e 43 6f 6d 70 72 65 73 73 |HG20....Compress|
168 0000: 48 47 32 30 00 00 00 0e 43 6f 6d 70 72 65 73 73 |HG20....Compress|
169 0010: 69 6f 6e 3d 47 5a 78 9c 63 60 60 d0 e4 76 f6 70 |ion=GZx.c``..v.p|
169 0010: 69 6f 6e 3d 47 5a 78 9c 63 60 60 d0 e4 76 f6 70 |ion=GZx.c``..v.p|
170 0020: f4 73 77 75 0f f2 0f 0d 60 00 02 46 46 76 26 4e |.swu....`..FFv&N|
170 0020: f4 73 77 75 0f f2 0f 0d 60 00 02 46 46 76 26 4e |.swu....`..FFv&N|
171 0030: c6 b2 d4 a2 e2 cc fc 3c 03 a3 bc a4 e4 8c c4 bc |.......<........|
171 0030: c6 b2 d4 a2 e2 cc fc 3c 03 a3 bc a4 e4 8c c4 bc |.......<........|
172 0040: f4 d4 62 23 06 06 e6 19 40 f9 4d c1 2a 31 09 cf |..b#....@.M.*1..|
172 0040: f4 d4 62 23 06 06 e6 19 40 f9 4d c1 2a 31 09 cf |..b#....@.M.*1..|
173 0050: 9a 3a 52 04 b7 fc db f0 95 e5 a4 f4 97 17 b2 c9 |.:R.............|
173 0050: 9a 3a 52 04 b7 fc db f0 95 e5 a4 f4 97 17 b2 c9 |.:R.............|
174 0060: 0c 14 00 02 e6 d9 99 25 1a a7 a4 99 a4 a4 1a 5b |.......%.......[|
174 0060: 0c 14 00 02 e6 d9 99 25 1a a7 a4 99 a4 a4 1a 5b |.......%.......[|
175 0070: 58 a4 19 27 9b a4 59 a4 1a 59 a4 99 a4 59 26 5a |X..'..Y..Y...Y&Z|
175 0070: 58 a4 19 27 9b a4 59 a4 1a 59 a4 99 a4 59 26 5a |X..'..Y..Y...Y&Z|
176 0080: 18 9a 18 59 5a 26 1a 27 27 25 99 a6 99 1a 70 95 |...YZ&.''%....p.|
176 0080: 18 9a 18 59 5a 26 1a 27 27 25 99 a6 99 1a 70 95 |...YZ&.''%....p.|
177 0090: a4 16 97 70 19 28 18 70 a5 e5 e7 73 71 25 a6 a4 |...p.(.p...sq%..|
177 0090: a4 16 97 70 19 28 18 70 a5 e5 e7 73 71 25 a6 a4 |...p.(.p...sq%..|
178 00a0: 28 00 19 20 17 af fa df ab ff 7b 3f fb 92 dc 8b |(.. ......{?....|
178 00a0: 28 00 19 20 17 af fa df ab ff 7b 3f fb 92 dc 8b |(.. ......{?....|
179 00b0: 1f 62 bb 9e b7 d7 d9 87 3d 5a 44 89 2f b0 99 87 |.b......=ZD./...|
179 00b0: 1f 62 bb 9e b7 d7 d9 87 3d 5a 44 89 2f b0 99 87 |.b......=ZD./...|
180 00c0: ec e2 54 63 43 e3 b4 64 43 73 23 33 43 53 0b 63 |..TcC..dCs#3CS.c|
180 00c0: ec e2 54 63 43 e3 b4 64 43 73 23 33 43 53 0b 63 |..TcC..dCs#3CS.c|
181 00d0: d3 14 23 03 a0 fb 2c 2c 0c d3 80 1e 30 49 49 b1 |..#...,,....0II.|
181 00d0: d3 14 23 03 a0 fb 2c 2c 0c d3 80 1e 30 49 49 b1 |..#...,,....0II.|
182 00e0: 4c 4a 32 48 33 30 b0 34 42 b8 38 29 b1 08 e2 62 |LJ2H30.4B.8)...b|
182 00e0: 4c 4a 32 48 33 30 b0 34 42 b8 38 29 b1 08 e2 62 |LJ2H30.4B.8)...b|
183 00f0: 20 03 6a ca c2 2c db 2f f7 2c fa 6d fc fb 34 be | .j..,./.,.m..4.|
183 00f0: 20 03 6a ca c2 2c db 2f f7 2c fa 6d fc fb 34 be | .j..,./.,.m..4.|
184 0100: fc 5c 21 a2 39 cb 66 77 7c 00 0d c3 59 17 14 58 |.\!.9.fw|...Y..X|
184 0100: fc 5c 21 a2 39 cb 66 77 7c 00 0d c3 59 17 14 58 |.\!.9.fw|...Y..X|
185 0110: 49 16 06 29 a9 a6 29 86 c6 16 e6 a6 16 a6 26 86 |I..)..).......&.|
185 0110: 49 16 06 29 a9 a6 29 86 c6 16 e6 a6 16 a6 26 86 |I..)..).......&.|
186 0120: c9 a6 69 06 a6 46 66 a6 89 29 86 26 26 89 49 96 |..i..Ff..).&&.I.|
186 0120: c9 a6 69 06 a6 46 66 a6 89 29 86 26 26 89 49 96 |..i..Ff..).&&.I.|
187 0130: 69 89 16 66 29 86 29 49 5c 20 07 3e 16 fe 23 ae |i..f).)I\ .>..#.|
187 0130: 69 89 16 66 29 86 29 49 5c 20 07 3e 16 fe 23 ae |i..f).)I\ .>..#.|
188 0140: 26 da 1c ab 10 1f d1 f8 e3 b3 ef cd dd fc 0c 93 |&...............|
188 0140: 26 da 1c ab 10 1f d1 f8 e3 b3 ef cd dd fc 0c 93 |&...............|
189 0150: 88 75 34 36 75 04 82 55 17 14 36 a4 38 10 04 d8 |.u46u..U..6.8...|
189 0150: 88 75 34 36 75 04 82 55 17 14 36 a4 38 10 04 d8 |.u46u..U..6.8...|
190 0160: 21 01 9a b1 83 f7 e9 45 8b d2 56 c7 a3 1f 82 52 |!......E..V....R|
190 0160: 21 01 9a b1 83 f7 e9 45 8b d2 56 c7 a3 1f 82 52 |!......E..V....R|
191 0170: d7 8a 78 ed fc d5 76 f1 36 25 81 89 c7 ad ec 90 |..x...v.6%......|
191 0170: d7 8a 78 ed fc d5 76 f1 36 25 81 89 c7 ad ec 90 |..x...v.6%......|
192 0180: 54 47 75 2b 89 48 b1 b2 62 c9 89 c9 19 a9 56 45 |TGu+.H..b.....VE|
192 0180: 54 47 75 2b 89 48 b1 b2 62 c9 89 c9 19 a9 56 45 |TGu+.H..b.....VE|
193 0190: a9 65 ba 49 45 89 79 c9 19 ba 60 01 a0 14 23 58 |.e.IE.y...`...#X|
193 0190: a9 65 ba 49 45 89 79 c9 19 ba 60 01 a0 14 23 58 |.e.IE.y...`...#X|
194 01a0: 81 35 c8 7d 40 cc 04 e2 a4 a4 a6 25 96 e6 94 60 |.5.}@......%...`|
194 01a0: 81 35 c8 7d 40 cc 04 e2 a4 a4 a6 25 96 e6 94 60 |.5.}@......%...`|
195 01b0: 33 17 5f 54 00 00 d3 1b 0d 4c |3._T.....L|
195 01b0: 33 17 5f 54 00 00 d3 1b 0d 4c |3._T.....L|
196
196
197 $ echo "http://localhost:$HGPORT1/full.hg" > server/.hg/clonebundles.manifest
197 $ echo "http://localhost:$HGPORT1/full.hg" > server/.hg/clonebundles.manifest
198 $ hg clone -U http://localhost:$HGPORT full-bundle
198 $ hg clone -U http://localhost:$HGPORT full-bundle
199 applying clone bundle from http://localhost:$HGPORT1/full.hg
199 applying clone bundle from http://localhost:$HGPORT1/full.hg
200 adding changesets
200 adding changesets
201 adding manifests
201 adding manifests
202 adding file changes
202 adding file changes
203 added 2 changesets with 2 changes to 2 files
203 added 2 changesets with 2 changes to 2 files
204 finished applying clone bundle
204 finished applying clone bundle
205 searching for changes
205 searching for changes
206 no changes found
206 no changes found
207 2 local changesets published
207 2 local changesets published
208
208
209 Feature works over SSH
209 Feature works over SSH
210
210
211 $ hg clone -U -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/server ssh-full-clone
211 $ hg clone -U -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/server ssh-full-clone
212 applying clone bundle from http://localhost:$HGPORT1/full.hg
212 applying clone bundle from http://localhost:$HGPORT1/full.hg
213 adding changesets
213 adding changesets
214 adding manifests
214 adding manifests
215 adding file changes
215 adding file changes
216 added 2 changesets with 2 changes to 2 files
216 added 2 changesets with 2 changes to 2 files
217 finished applying clone bundle
217 finished applying clone bundle
218 searching for changes
218 searching for changes
219 no changes found
219 no changes found
220 2 local changesets published
220 2 local changesets published
221
221
222 Entry with unknown BUNDLESPEC is filtered and not used
222 Entry with unknown BUNDLESPEC is filtered and not used
223
223
224 $ cat > server/.hg/clonebundles.manifest << EOF
224 $ cat > server/.hg/clonebundles.manifest << EOF
225 > http://bad.entry1 BUNDLESPEC=UNKNOWN
225 > http://bad.entry1 BUNDLESPEC=UNKNOWN
226 > http://bad.entry2 BUNDLESPEC=xz-v1
226 > http://bad.entry2 BUNDLESPEC=xz-v1
227 > http://bad.entry3 BUNDLESPEC=none-v100
227 > http://bad.entry3 BUNDLESPEC=none-v100
228 > http://localhost:$HGPORT1/full.hg BUNDLESPEC=gzip-v2
228 > http://localhost:$HGPORT1/full.hg BUNDLESPEC=gzip-v2
229 > EOF
229 > EOF
230
230
231 $ hg clone -U http://localhost:$HGPORT filter-unknown-type
231 $ hg clone -U http://localhost:$HGPORT filter-unknown-type
232 applying clone bundle from http://localhost:$HGPORT1/full.hg
232 applying clone bundle from http://localhost:$HGPORT1/full.hg
233 adding changesets
233 adding changesets
234 adding manifests
234 adding manifests
235 adding file changes
235 adding file changes
236 added 2 changesets with 2 changes to 2 files
236 added 2 changesets with 2 changes to 2 files
237 finished applying clone bundle
237 finished applying clone bundle
238 searching for changes
238 searching for changes
239 no changes found
239 no changes found
240 2 local changesets published
240 2 local changesets published
241
241
242 Automatic fallback when all entries are filtered
242 Automatic fallback when all entries are filtered
243
243
244 $ cat > server/.hg/clonebundles.manifest << EOF
244 $ cat > server/.hg/clonebundles.manifest << EOF
245 > http://bad.entry BUNDLESPEC=UNKNOWN
245 > http://bad.entry BUNDLESPEC=UNKNOWN
246 > EOF
246 > EOF
247
247
248 $ hg clone -U http://localhost:$HGPORT filter-all
248 $ hg clone -U http://localhost:$HGPORT filter-all
249 no compatible clone bundles available on server; falling back to regular clone
249 no compatible clone bundles available on server; falling back to regular clone
250 (you may want to report this to the server operator)
250 (you may want to report this to the server operator)
251 requesting all changes
251 requesting all changes
252 adding changesets
252 adding changesets
253 adding manifests
253 adding manifests
254 adding file changes
254 adding file changes
255 added 2 changesets with 2 changes to 2 files
255 added 2 changesets with 2 changes to 2 files
256 new changesets 53245c60e682:aaff8d2ffbbf
256 new changesets 53245c60e682:aaff8d2ffbbf
257
257
258 URLs requiring SNI are filtered in Python <2.7.9
258 We require a Python version that supports SNI. Therefore, URLs requiring SNI
259 are not filtered.
259
260
260 $ cp full.hg sni.hg
261 $ cp full.hg sni.hg
261 $ cat > server/.hg/clonebundles.manifest << EOF
262 $ cat > server/.hg/clonebundles.manifest << EOF
262 > http://localhost:$HGPORT1/sni.hg REQUIRESNI=true
263 > http://localhost:$HGPORT1/sni.hg REQUIRESNI=true
263 > http://localhost:$HGPORT1/full.hg
264 > http://localhost:$HGPORT1/full.hg
264 > EOF
265 > EOF
265
266
266 #if sslcontext
267 Python 2.7.9+ support SNI
268
269 $ hg clone -U http://localhost:$HGPORT sni-supported
267 $ hg clone -U http://localhost:$HGPORT sni-supported
270 applying clone bundle from http://localhost:$HGPORT1/sni.hg
268 applying clone bundle from http://localhost:$HGPORT1/sni.hg
271 adding changesets
269 adding changesets
272 adding manifests
270 adding manifests
273 adding file changes
271 adding file changes
274 added 2 changesets with 2 changes to 2 files
272 added 2 changesets with 2 changes to 2 files
275 finished applying clone bundle
273 finished applying clone bundle
276 searching for changes
274 searching for changes
277 no changes found
275 no changes found
278 2 local changesets published
276 2 local changesets published
279 #else
280 Python <2.7.9 will filter SNI URLs
281
282 $ hg clone -U http://localhost:$HGPORT sni-unsupported
283 applying clone bundle from http://localhost:$HGPORT1/full.hg
284 adding changesets
285 adding manifests
286 adding file changes
287 added 2 changesets with 2 changes to 2 files
288 finished applying clone bundle
289 searching for changes
290 no changes found
291 2 local changesets published
292 #endif
293
277
294 Stream clone bundles are supported
278 Stream clone bundles are supported
295
279
296 $ hg -R server debugcreatestreamclonebundle packed.hg
280 $ hg -R server debugcreatestreamclonebundle packed.hg
297 writing 613 bytes for 4 files
281 writing 613 bytes for 4 files
298 bundle requirements: generaldelta, revlogv1, sparserevlog
282 bundle requirements: generaldelta, revlogv1, sparserevlog
299
283
300 No bundle spec should work
284 No bundle spec should work
301
285
302 $ cat > server/.hg/clonebundles.manifest << EOF
286 $ cat > server/.hg/clonebundles.manifest << EOF
303 > http://localhost:$HGPORT1/packed.hg
287 > http://localhost:$HGPORT1/packed.hg
304 > EOF
288 > EOF
305
289
306 $ hg clone -U http://localhost:$HGPORT stream-clone-no-spec
290 $ hg clone -U http://localhost:$HGPORT stream-clone-no-spec
307 applying clone bundle from http://localhost:$HGPORT1/packed.hg
291 applying clone bundle from http://localhost:$HGPORT1/packed.hg
308 4 files to transfer, 613 bytes of data
292 4 files to transfer, 613 bytes of data
309 transferred 613 bytes in *.* seconds (*) (glob)
293 transferred 613 bytes in *.* seconds (*) (glob)
310 finished applying clone bundle
294 finished applying clone bundle
311 searching for changes
295 searching for changes
312 no changes found
296 no changes found
313
297
314 Bundle spec without parameters should work
298 Bundle spec without parameters should work
315
299
316 $ cat > server/.hg/clonebundles.manifest << EOF
300 $ cat > server/.hg/clonebundles.manifest << EOF
317 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1
301 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1
318 > EOF
302 > EOF
319
303
320 $ hg clone -U http://localhost:$HGPORT stream-clone-vanilla-spec
304 $ hg clone -U http://localhost:$HGPORT stream-clone-vanilla-spec
321 applying clone bundle from http://localhost:$HGPORT1/packed.hg
305 applying clone bundle from http://localhost:$HGPORT1/packed.hg
322 4 files to transfer, 613 bytes of data
306 4 files to transfer, 613 bytes of data
323 transferred 613 bytes in *.* seconds (*) (glob)
307 transferred 613 bytes in *.* seconds (*) (glob)
324 finished applying clone bundle
308 finished applying clone bundle
325 searching for changes
309 searching for changes
326 no changes found
310 no changes found
327
311
328 Bundle spec with format requirements should work
312 Bundle spec with format requirements should work
329
313
330 $ cat > server/.hg/clonebundles.manifest << EOF
314 $ cat > server/.hg/clonebundles.manifest << EOF
331 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1;requirements%3Drevlogv1
315 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1;requirements%3Drevlogv1
332 > EOF
316 > EOF
333
317
334 $ hg clone -U http://localhost:$HGPORT stream-clone-supported-requirements
318 $ hg clone -U http://localhost:$HGPORT stream-clone-supported-requirements
335 applying clone bundle from http://localhost:$HGPORT1/packed.hg
319 applying clone bundle from http://localhost:$HGPORT1/packed.hg
336 4 files to transfer, 613 bytes of data
320 4 files to transfer, 613 bytes of data
337 transferred 613 bytes in *.* seconds (*) (glob)
321 transferred 613 bytes in *.* seconds (*) (glob)
338 finished applying clone bundle
322 finished applying clone bundle
339 searching for changes
323 searching for changes
340 no changes found
324 no changes found
341
325
342 Stream bundle spec with unknown requirements should be filtered out
326 Stream bundle spec with unknown requirements should be filtered out
343
327
344 $ cat > server/.hg/clonebundles.manifest << EOF
328 $ cat > server/.hg/clonebundles.manifest << EOF
345 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1;requirements%3Drevlogv42
329 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1;requirements%3Drevlogv42
346 > EOF
330 > EOF
347
331
348 $ hg clone -U http://localhost:$HGPORT stream-clone-unsupported-requirements
332 $ hg clone -U http://localhost:$HGPORT stream-clone-unsupported-requirements
349 no compatible clone bundles available on server; falling back to regular clone
333 no compatible clone bundles available on server; falling back to regular clone
350 (you may want to report this to the server operator)
334 (you may want to report this to the server operator)
351 requesting all changes
335 requesting all changes
352 adding changesets
336 adding changesets
353 adding manifests
337 adding manifests
354 adding file changes
338 adding file changes
355 added 2 changesets with 2 changes to 2 files
339 added 2 changesets with 2 changes to 2 files
356 new changesets 53245c60e682:aaff8d2ffbbf
340 new changesets 53245c60e682:aaff8d2ffbbf
357
341
358 Set up manifest for testing preferences
342 Set up manifest for testing preferences
359 (Remember, the TYPE does not have to match reality - the URL is
343 (Remember, the TYPE does not have to match reality - the URL is
360 important)
344 important)
361
345
362 $ cp full.hg gz-a.hg
346 $ cp full.hg gz-a.hg
363 $ cp full.hg gz-b.hg
347 $ cp full.hg gz-b.hg
364 $ cp full.hg bz2-a.hg
348 $ cp full.hg bz2-a.hg
365 $ cp full.hg bz2-b.hg
349 $ cp full.hg bz2-b.hg
366 $ cat > server/.hg/clonebundles.manifest << EOF
350 $ cat > server/.hg/clonebundles.manifest << EOF
367 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2 extra=a
351 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2 extra=a
368 > http://localhost:$HGPORT1/bz2-a.hg BUNDLESPEC=bzip2-v2 extra=a
352 > http://localhost:$HGPORT1/bz2-a.hg BUNDLESPEC=bzip2-v2 extra=a
369 > http://localhost:$HGPORT1/gz-b.hg BUNDLESPEC=gzip-v2 extra=b
353 > http://localhost:$HGPORT1/gz-b.hg BUNDLESPEC=gzip-v2 extra=b
370 > http://localhost:$HGPORT1/bz2-b.hg BUNDLESPEC=bzip2-v2 extra=b
354 > http://localhost:$HGPORT1/bz2-b.hg BUNDLESPEC=bzip2-v2 extra=b
371 > EOF
355 > EOF
372
356
373 Preferring an undefined attribute will take first entry
357 Preferring an undefined attribute will take first entry
374
358
375 $ hg --config ui.clonebundleprefers=foo=bar clone -U http://localhost:$HGPORT prefer-foo
359 $ hg --config ui.clonebundleprefers=foo=bar clone -U http://localhost:$HGPORT prefer-foo
376 applying clone bundle from http://localhost:$HGPORT1/gz-a.hg
360 applying clone bundle from http://localhost:$HGPORT1/gz-a.hg
377 adding changesets
361 adding changesets
378 adding manifests
362 adding manifests
379 adding file changes
363 adding file changes
380 added 2 changesets with 2 changes to 2 files
364 added 2 changesets with 2 changes to 2 files
381 finished applying clone bundle
365 finished applying clone bundle
382 searching for changes
366 searching for changes
383 no changes found
367 no changes found
384 2 local changesets published
368 2 local changesets published
385
369
386 Preferring bz2 type will download first entry of that type
370 Preferring bz2 type will download first entry of that type
387
371
388 $ hg --config ui.clonebundleprefers=COMPRESSION=bzip2 clone -U http://localhost:$HGPORT prefer-bz
372 $ hg --config ui.clonebundleprefers=COMPRESSION=bzip2 clone -U http://localhost:$HGPORT prefer-bz
389 applying clone bundle from http://localhost:$HGPORT1/bz2-a.hg
373 applying clone bundle from http://localhost:$HGPORT1/bz2-a.hg
390 adding changesets
374 adding changesets
391 adding manifests
375 adding manifests
392 adding file changes
376 adding file changes
393 added 2 changesets with 2 changes to 2 files
377 added 2 changesets with 2 changes to 2 files
394 finished applying clone bundle
378 finished applying clone bundle
395 searching for changes
379 searching for changes
396 no changes found
380 no changes found
397 2 local changesets published
381 2 local changesets published
398
382
399 Preferring multiple values of an option works
383 Preferring multiple values of an option works
400
384
401 $ hg --config ui.clonebundleprefers=COMPRESSION=unknown,COMPRESSION=bzip2 clone -U http://localhost:$HGPORT prefer-multiple-bz
385 $ hg --config ui.clonebundleprefers=COMPRESSION=unknown,COMPRESSION=bzip2 clone -U http://localhost:$HGPORT prefer-multiple-bz
402 applying clone bundle from http://localhost:$HGPORT1/bz2-a.hg
386 applying clone bundle from http://localhost:$HGPORT1/bz2-a.hg
403 adding changesets
387 adding changesets
404 adding manifests
388 adding manifests
405 adding file changes
389 adding file changes
406 added 2 changesets with 2 changes to 2 files
390 added 2 changesets with 2 changes to 2 files
407 finished applying clone bundle
391 finished applying clone bundle
408 searching for changes
392 searching for changes
409 no changes found
393 no changes found
410 2 local changesets published
394 2 local changesets published
411
395
412 Sorting multiple values should get us back to original first entry
396 Sorting multiple values should get us back to original first entry
413
397
414 $ hg --config ui.clonebundleprefers=BUNDLESPEC=unknown,BUNDLESPEC=gzip-v2,BUNDLESPEC=bzip2-v2 clone -U http://localhost:$HGPORT prefer-multiple-gz
398 $ hg --config ui.clonebundleprefers=BUNDLESPEC=unknown,BUNDLESPEC=gzip-v2,BUNDLESPEC=bzip2-v2 clone -U http://localhost:$HGPORT prefer-multiple-gz
415 applying clone bundle from http://localhost:$HGPORT1/gz-a.hg
399 applying clone bundle from http://localhost:$HGPORT1/gz-a.hg
416 adding changesets
400 adding changesets
417 adding manifests
401 adding manifests
418 adding file changes
402 adding file changes
419 added 2 changesets with 2 changes to 2 files
403 added 2 changesets with 2 changes to 2 files
420 finished applying clone bundle
404 finished applying clone bundle
421 searching for changes
405 searching for changes
422 no changes found
406 no changes found
423 2 local changesets published
407 2 local changesets published
424
408
425 Preferring multiple attributes has correct order
409 Preferring multiple attributes has correct order
426
410
427 $ hg --config ui.clonebundleprefers=extra=b,BUNDLESPEC=bzip2-v2 clone -U http://localhost:$HGPORT prefer-separate-attributes
411 $ hg --config ui.clonebundleprefers=extra=b,BUNDLESPEC=bzip2-v2 clone -U http://localhost:$HGPORT prefer-separate-attributes
428 applying clone bundle from http://localhost:$HGPORT1/bz2-b.hg
412 applying clone bundle from http://localhost:$HGPORT1/bz2-b.hg
429 adding changesets
413 adding changesets
430 adding manifests
414 adding manifests
431 adding file changes
415 adding file changes
432 added 2 changesets with 2 changes to 2 files
416 added 2 changesets with 2 changes to 2 files
433 finished applying clone bundle
417 finished applying clone bundle
434 searching for changes
418 searching for changes
435 no changes found
419 no changes found
436 2 local changesets published
420 2 local changesets published
437
421
438 Test where attribute is missing from some entries
422 Test where attribute is missing from some entries
439
423
440 $ cat > server/.hg/clonebundles.manifest << EOF
424 $ cat > server/.hg/clonebundles.manifest << EOF
441 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
425 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
442 > http://localhost:$HGPORT1/bz2-a.hg BUNDLESPEC=bzip2-v2
426 > http://localhost:$HGPORT1/bz2-a.hg BUNDLESPEC=bzip2-v2
443 > http://localhost:$HGPORT1/gz-b.hg BUNDLESPEC=gzip-v2 extra=b
427 > http://localhost:$HGPORT1/gz-b.hg BUNDLESPEC=gzip-v2 extra=b
444 > http://localhost:$HGPORT1/bz2-b.hg BUNDLESPEC=bzip2-v2 extra=b
428 > http://localhost:$HGPORT1/bz2-b.hg BUNDLESPEC=bzip2-v2 extra=b
445 > EOF
429 > EOF
446
430
447 $ hg --config ui.clonebundleprefers=extra=b clone -U http://localhost:$HGPORT prefer-partially-defined-attribute
431 $ hg --config ui.clonebundleprefers=extra=b clone -U http://localhost:$HGPORT prefer-partially-defined-attribute
448 applying clone bundle from http://localhost:$HGPORT1/gz-b.hg
432 applying clone bundle from http://localhost:$HGPORT1/gz-b.hg
449 adding changesets
433 adding changesets
450 adding manifests
434 adding manifests
451 adding file changes
435 adding file changes
452 added 2 changesets with 2 changes to 2 files
436 added 2 changesets with 2 changes to 2 files
453 finished applying clone bundle
437 finished applying clone bundle
454 searching for changes
438 searching for changes
455 no changes found
439 no changes found
456 2 local changesets published
440 2 local changesets published
457
441
458 Test a bad attribute list
442 Test a bad attribute list
459
443
460 $ hg --config ui.clonebundleprefers=bad clone -U http://localhost:$HGPORT bad-input
444 $ hg --config ui.clonebundleprefers=bad clone -U http://localhost:$HGPORT bad-input
461 abort: invalid ui.clonebundleprefers item: bad
445 abort: invalid ui.clonebundleprefers item: bad
462 (each comma separated item should be key=value pairs)
446 (each comma separated item should be key=value pairs)
463 [255]
447 [255]
464 $ hg --config ui.clonebundleprefers=key=val,bad,key2=val2 clone \
448 $ hg --config ui.clonebundleprefers=key=val,bad,key2=val2 clone \
465 > -U http://localhost:$HGPORT bad-input
449 > -U http://localhost:$HGPORT bad-input
466 abort: invalid ui.clonebundleprefers item: bad
450 abort: invalid ui.clonebundleprefers item: bad
467 (each comma separated item should be key=value pairs)
451 (each comma separated item should be key=value pairs)
468 [255]
452 [255]
469
453
470
454
471 Test interaction between clone bundles and --stream
455 Test interaction between clone bundles and --stream
472
456
473 A manifest with just a gzip bundle
457 A manifest with just a gzip bundle
474
458
475 $ cat > server/.hg/clonebundles.manifest << EOF
459 $ cat > server/.hg/clonebundles.manifest << EOF
476 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
460 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
477 > EOF
461 > EOF
478
462
479 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-gzip
463 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-gzip
480 no compatible clone bundles available on server; falling back to regular clone
464 no compatible clone bundles available on server; falling back to regular clone
481 (you may want to report this to the server operator)
465 (you may want to report this to the server operator)
482 streaming all changes
466 streaming all changes
483 9 files to transfer, 816 bytes of data
467 9 files to transfer, 816 bytes of data
484 transferred 816 bytes in * seconds (*) (glob)
468 transferred 816 bytes in * seconds (*) (glob)
485
469
486 A manifest with a stream clone but no BUNDLESPEC
470 A manifest with a stream clone but no BUNDLESPEC
487
471
488 $ cat > server/.hg/clonebundles.manifest << EOF
472 $ cat > server/.hg/clonebundles.manifest << EOF
489 > http://localhost:$HGPORT1/packed.hg
473 > http://localhost:$HGPORT1/packed.hg
490 > EOF
474 > EOF
491
475
492 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-no-bundlespec
476 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-no-bundlespec
493 no compatible clone bundles available on server; falling back to regular clone
477 no compatible clone bundles available on server; falling back to regular clone
494 (you may want to report this to the server operator)
478 (you may want to report this to the server operator)
495 streaming all changes
479 streaming all changes
496 9 files to transfer, 816 bytes of data
480 9 files to transfer, 816 bytes of data
497 transferred 816 bytes in * seconds (*) (glob)
481 transferred 816 bytes in * seconds (*) (glob)
498
482
499 A manifest with a gzip bundle and a stream clone
483 A manifest with a gzip bundle and a stream clone
500
484
501 $ cat > server/.hg/clonebundles.manifest << EOF
485 $ cat > server/.hg/clonebundles.manifest << EOF
502 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
486 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
503 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1
487 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1
504 > EOF
488 > EOF
505
489
506 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-gzip-packed
490 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-gzip-packed
507 applying clone bundle from http://localhost:$HGPORT1/packed.hg
491 applying clone bundle from http://localhost:$HGPORT1/packed.hg
508 4 files to transfer, 613 bytes of data
492 4 files to transfer, 613 bytes of data
509 transferred 613 bytes in * seconds (*) (glob)
493 transferred 613 bytes in * seconds (*) (glob)
510 finished applying clone bundle
494 finished applying clone bundle
511 searching for changes
495 searching for changes
512 no changes found
496 no changes found
513
497
514 A manifest with a gzip bundle and stream clone with supported requirements
498 A manifest with a gzip bundle and stream clone with supported requirements
515
499
516 $ cat > server/.hg/clonebundles.manifest << EOF
500 $ cat > server/.hg/clonebundles.manifest << EOF
517 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
501 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
518 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1;requirements%3Drevlogv1
502 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1;requirements%3Drevlogv1
519 > EOF
503 > EOF
520
504
521 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-gzip-packed-requirements
505 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-gzip-packed-requirements
522 applying clone bundle from http://localhost:$HGPORT1/packed.hg
506 applying clone bundle from http://localhost:$HGPORT1/packed.hg
523 4 files to transfer, 613 bytes of data
507 4 files to transfer, 613 bytes of data
524 transferred 613 bytes in * seconds (*) (glob)
508 transferred 613 bytes in * seconds (*) (glob)
525 finished applying clone bundle
509 finished applying clone bundle
526 searching for changes
510 searching for changes
527 no changes found
511 no changes found
528
512
529 A manifest with a gzip bundle and a stream clone with unsupported requirements
513 A manifest with a gzip bundle and a stream clone with unsupported requirements
530
514
531 $ cat > server/.hg/clonebundles.manifest << EOF
515 $ cat > server/.hg/clonebundles.manifest << EOF
532 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
516 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
533 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1;requirements%3Drevlogv42
517 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1;requirements%3Drevlogv42
534 > EOF
518 > EOF
535
519
536 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-gzip-packed-unsupported-requirements
520 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-gzip-packed-unsupported-requirements
537 no compatible clone bundles available on server; falling back to regular clone
521 no compatible clone bundles available on server; falling back to regular clone
538 (you may want to report this to the server operator)
522 (you may want to report this to the server operator)
539 streaming all changes
523 streaming all changes
540 9 files to transfer, 816 bytes of data
524 9 files to transfer, 816 bytes of data
541 transferred 816 bytes in * seconds (*) (glob)
525 transferred 816 bytes in * seconds (*) (glob)
542
526
543 Test clone bundle retrieved through bundle2
527 Test clone bundle retrieved through bundle2
544
528
545 $ cat << EOF >> $HGRCPATH
529 $ cat << EOF >> $HGRCPATH
546 > [extensions]
530 > [extensions]
547 > largefiles=
531 > largefiles=
548 > EOF
532 > EOF
549 $ killdaemons.py
533 $ killdaemons.py
550 $ hg -R server serve -d -p $HGPORT --pid-file hg.pid --accesslog access.log
534 $ hg -R server serve -d -p $HGPORT --pid-file hg.pid --accesslog access.log
551 $ cat hg.pid >> $DAEMON_PIDS
535 $ cat hg.pid >> $DAEMON_PIDS
552
536
553 $ hg -R server debuglfput gz-a.hg
537 $ hg -R server debuglfput gz-a.hg
554 1f74b3d08286b9b3a16fb3fa185dd29219cbc6ae
538 1f74b3d08286b9b3a16fb3fa185dd29219cbc6ae
555
539
556 $ cat > server/.hg/clonebundles.manifest << EOF
540 $ cat > server/.hg/clonebundles.manifest << EOF
557 > largefile://1f74b3d08286b9b3a16fb3fa185dd29219cbc6ae BUNDLESPEC=gzip-v2
541 > largefile://1f74b3d08286b9b3a16fb3fa185dd29219cbc6ae BUNDLESPEC=gzip-v2
558 > EOF
542 > EOF
559
543
560 $ hg clone -U http://localhost:$HGPORT largefile-provided --traceback
544 $ hg clone -U http://localhost:$HGPORT largefile-provided --traceback
561 applying clone bundle from largefile://1f74b3d08286b9b3a16fb3fa185dd29219cbc6ae
545 applying clone bundle from largefile://1f74b3d08286b9b3a16fb3fa185dd29219cbc6ae
562 adding changesets
546 adding changesets
563 adding manifests
547 adding manifests
564 adding file changes
548 adding file changes
565 added 2 changesets with 2 changes to 2 files
549 added 2 changesets with 2 changes to 2 files
566 finished applying clone bundle
550 finished applying clone bundle
567 searching for changes
551 searching for changes
568 no changes found
552 no changes found
569 2 local changesets published
553 2 local changesets published
@@ -1,672 +1,606 b''
1 #require serve ssl
1 #require serve ssl
2
2
3 Proper https client requires the built-in ssl from Python 2.6.
3 Proper https client requires the built-in ssl from Python 2.6.
4
4
5 Disable the system configuration which may set stricter TLS requirements.
5 Disable the system configuration which may set stricter TLS requirements.
6 This test expects that legacy TLS versions are supported.
6 This test expects that legacy TLS versions are supported.
7
7
8 $ OPENSSL_CONF=
8 $ OPENSSL_CONF=
9 $ export OPENSSL_CONF
9 $ export OPENSSL_CONF
10
10
11 Make server certificates:
11 Make server certificates:
12
12
13 $ CERTSDIR="$TESTDIR/sslcerts"
13 $ CERTSDIR="$TESTDIR/sslcerts"
14 $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub.pem" >> server.pem
14 $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub.pem" >> server.pem
15 $ PRIV=`pwd`/server.pem
15 $ PRIV=`pwd`/server.pem
16 $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub-not-yet.pem" > server-not-yet.pem
16 $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub-not-yet.pem" > server-not-yet.pem
17 $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub-expired.pem" > server-expired.pem
17 $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub-expired.pem" > server-expired.pem
18
18
19 $ hg init test
19 $ hg init test
20 $ cd test
20 $ cd test
21 $ echo foo>foo
21 $ echo foo>foo
22 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
22 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
23 $ echo foo>foo.d/foo
23 $ echo foo>foo.d/foo
24 $ echo bar>foo.d/bAr.hg.d/BaR
24 $ echo bar>foo.d/bAr.hg.d/BaR
25 $ echo bar>foo.d/baR.d.hg/bAR
25 $ echo bar>foo.d/baR.d.hg/bAR
26 $ hg commit -A -m 1
26 $ hg commit -A -m 1
27 adding foo
27 adding foo
28 adding foo.d/bAr.hg.d/BaR
28 adding foo.d/bAr.hg.d/BaR
29 adding foo.d/baR.d.hg/bAR
29 adding foo.d/baR.d.hg/bAR
30 adding foo.d/foo
30 adding foo.d/foo
31 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV
31 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV
32 $ cat ../hg0.pid >> $DAEMON_PIDS
32 $ cat ../hg0.pid >> $DAEMON_PIDS
33
33
34 cacert not found
34 cacert not found
35
35
36 $ hg in --config web.cacerts=no-such.pem https://localhost:$HGPORT/
36 $ hg in --config web.cacerts=no-such.pem https://localhost:$HGPORT/
37 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
37 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
38 abort: could not find web.cacerts: no-such.pem
38 abort: could not find web.cacerts: no-such.pem
39 [255]
39 [255]
40
40
41 Test server address cannot be reused
41 Test server address cannot be reused
42
42
43 $ hg serve -p $HGPORT --certificate=$PRIV 2>&1
43 $ hg serve -p $HGPORT --certificate=$PRIV 2>&1
44 abort: cannot start server at 'localhost:$HGPORT': $EADDRINUSE$
44 abort: cannot start server at 'localhost:$HGPORT': $EADDRINUSE$
45 [255]
45 [255]
46
46
47 $ cd ..
47 $ cd ..
48
48
49 Our test cert is not signed by a trusted CA. It should fail to verify if
49 Our test cert is not signed by a trusted CA. It should fail to verify if
50 we are able to load CA certs.
50 we are able to load CA certs.
51
51
52 #if sslcontext no-defaultcacertsloaded
52 #if no-defaultcacertsloaded
53 $ hg clone https://localhost:$HGPORT/ copy-pull
53 $ hg clone https://localhost:$HGPORT/ copy-pull
54 (an attempt was made to load CA certificates but none were loaded; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error)
54 (an attempt was made to load CA certificates but none were loaded; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error)
55 abort: error: *certificate verify failed* (glob)
55 abort: error: *certificate verify failed* (glob)
56 [255]
56 [255]
57 #endif
57 #endif
58
58
59 #if no-sslcontext
60 $ hg clone https://localhost:$HGPORT/ copy-pull
61 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
62 (using CA certificates from *; if you see this message, your Mercurial install is not properly configured; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?)
63 abort: error: *certificate verify failed* (glob)
64 [255]
65 #endif
66
67 #if no-sslcontext windows
68 $ hg clone https://localhost:$HGPORT/ copy-pull
69 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info
70 (unable to load Windows CA certificates; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message)
71 abort: error: *certificate verify failed* (glob)
72 [255]
73 #endif
74
75 #if no-sslcontext osx
76 $ hg clone https://localhost:$HGPORT/ copy-pull
77 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info
78 (unable to load CA certificates; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message)
79 abort: localhost certificate error: no certificate received
80 (set hostsecurity.localhost:certfingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e config setting or use --insecure to connect insecurely)
81 [255]
82 #endif
83
84 #if defaultcacertsloaded
59 #if defaultcacertsloaded
85 $ hg clone https://localhost:$HGPORT/ copy-pull
60 $ hg clone https://localhost:$HGPORT/ copy-pull
86 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
61 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
87 (using CA certificates from *; if you see this message, your Mercurial install is not properly configured; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?)
62 (using CA certificates from *; if you see this message, your Mercurial install is not properly configured; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?)
88 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
63 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
89 abort: error: *certificate verify failed* (glob)
64 abort: error: *certificate verify failed* (glob)
90 [255]
65 [255]
91 #endif
66 #endif
92
67
93 Specifying a per-host certificate file that doesn't exist will abort. The full
68 Specifying a per-host certificate file that doesn't exist will abort. The full
94 C:/path/to/msysroot will print on Windows.
69 C:/path/to/msysroot will print on Windows.
95
70
96 $ hg --config hostsecurity.localhost:verifycertsfile=/does/not/exist clone https://localhost:$HGPORT/
71 $ hg --config hostsecurity.localhost:verifycertsfile=/does/not/exist clone https://localhost:$HGPORT/
97 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
72 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
98 abort: path specified by hostsecurity.localhost:verifycertsfile does not exist: */does/not/exist (glob)
73 abort: path specified by hostsecurity.localhost:verifycertsfile does not exist: */does/not/exist (glob)
99 [255]
74 [255]
100
75
101 A malformed per-host certificate file will raise an error
76 A malformed per-host certificate file will raise an error
102
77
103 $ echo baddata > badca.pem
78 $ echo baddata > badca.pem
104 #if sslcontext
105 $ hg --config hostsecurity.localhost:verifycertsfile=badca.pem clone https://localhost:$HGPORT/
79 $ hg --config hostsecurity.localhost:verifycertsfile=badca.pem clone https://localhost:$HGPORT/
106 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
80 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
107 abort: error loading CA file badca.pem: * (glob)
81 abort: error loading CA file badca.pem: * (glob)
108 (file is empty or malformed?)
82 (file is empty or malformed?)
109 [255]
83 [255]
110 #else
111 $ hg --config hostsecurity.localhost:verifycertsfile=badca.pem clone https://localhost:$HGPORT/
112 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
113 abort: error: * (glob)
114 [255]
115 #endif
116
84
117 A per-host certificate mismatching the server will fail verification
85 A per-host certificate mismatching the server will fail verification
118
86
119 (modern ssl is able to discern whether the loaded cert is a CA cert)
87 (modern ssl is able to discern whether the loaded cert is a CA cert)
120 #if sslcontext
121 $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/client-cert.pem" clone https://localhost:$HGPORT/
88 $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/client-cert.pem" clone https://localhost:$HGPORT/
122 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
89 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
123 (an attempt was made to load CA certificates but none were loaded; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error)
90 (an attempt was made to load CA certificates but none were loaded; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error)
124 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
91 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
125 abort: error: *certificate verify failed* (glob)
92 abort: error: *certificate verify failed* (glob)
126 [255]
93 [255]
127 #else
128 $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/client-cert.pem" clone https://localhost:$HGPORT/
129 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
130 abort: error: *certificate verify failed* (glob)
131 [255]
132 #endif
133
94
134 A per-host certificate matching the server's cert will be accepted
95 A per-host certificate matching the server's cert will be accepted
135
96
136 $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/pub.pem" clone -U https://localhost:$HGPORT/ perhostgood1
97 $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/pub.pem" clone -U https://localhost:$HGPORT/ perhostgood1
137 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
98 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
138 requesting all changes
99 requesting all changes
139 adding changesets
100 adding changesets
140 adding manifests
101 adding manifests
141 adding file changes
102 adding file changes
142 added 1 changesets with 4 changes to 4 files
103 added 1 changesets with 4 changes to 4 files
143 new changesets 8b6053c928fe
104 new changesets 8b6053c928fe
144
105
145 A per-host certificate with multiple certs and one matching will be accepted
106 A per-host certificate with multiple certs and one matching will be accepted
146
107
147 $ cat "$CERTSDIR/client-cert.pem" "$CERTSDIR/pub.pem" > perhost.pem
108 $ cat "$CERTSDIR/client-cert.pem" "$CERTSDIR/pub.pem" > perhost.pem
148 $ hg --config hostsecurity.localhost:verifycertsfile=perhost.pem clone -U https://localhost:$HGPORT/ perhostgood2
109 $ hg --config hostsecurity.localhost:verifycertsfile=perhost.pem clone -U https://localhost:$HGPORT/ perhostgood2
149 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
110 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
150 requesting all changes
111 requesting all changes
151 adding changesets
112 adding changesets
152 adding manifests
113 adding manifests
153 adding file changes
114 adding file changes
154 added 1 changesets with 4 changes to 4 files
115 added 1 changesets with 4 changes to 4 files
155 new changesets 8b6053c928fe
116 new changesets 8b6053c928fe
156
117
157 Defining both per-host certificate and a fingerprint will print a warning
118 Defining both per-host certificate and a fingerprint will print a warning
158
119
159 $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/pub.pem" --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 clone -U https://localhost:$HGPORT/ caandfingerwarning
120 $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/pub.pem" --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 clone -U https://localhost:$HGPORT/ caandfingerwarning
160 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
121 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
161 (hostsecurity.localhost:verifycertsfile ignored when host fingerprints defined; using host fingerprints for verification)
122 (hostsecurity.localhost:verifycertsfile ignored when host fingerprints defined; using host fingerprints for verification)
162 requesting all changes
123 requesting all changes
163 adding changesets
124 adding changesets
164 adding manifests
125 adding manifests
165 adding file changes
126 adding file changes
166 added 1 changesets with 4 changes to 4 files
127 added 1 changesets with 4 changes to 4 files
167 new changesets 8b6053c928fe
128 new changesets 8b6053c928fe
168
129
169 $ DISABLECACERTS="--config devel.disableloaddefaultcerts=true"
130 $ DISABLECACERTS="--config devel.disableloaddefaultcerts=true"
170
131
171 Inability to verify peer certificate will result in abort
132 Inability to verify peer certificate will result in abort
172
133
173 $ hg clone https://localhost:$HGPORT/ copy-pull $DISABLECACERTS
134 $ hg clone https://localhost:$HGPORT/ copy-pull $DISABLECACERTS
174 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
135 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
175 abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect
136 abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect
176 (see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server)
137 (see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server)
177 [255]
138 [255]
178
139
179 $ hg clone --insecure https://localhost:$HGPORT/ copy-pull
140 $ hg clone --insecure https://localhost:$HGPORT/ copy-pull
180 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
141 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
181 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
142 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
182 requesting all changes
143 requesting all changes
183 adding changesets
144 adding changesets
184 adding manifests
145 adding manifests
185 adding file changes
146 adding file changes
186 added 1 changesets with 4 changes to 4 files
147 added 1 changesets with 4 changes to 4 files
187 new changesets 8b6053c928fe
148 new changesets 8b6053c928fe
188 updating to branch default
149 updating to branch default
189 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
150 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 $ hg verify -R copy-pull
151 $ hg verify -R copy-pull
191 checking changesets
152 checking changesets
192 checking manifests
153 checking manifests
193 crosschecking files in changesets and manifests
154 crosschecking files in changesets and manifests
194 checking files
155 checking files
195 checked 1 changesets with 4 changes to 4 files
156 checked 1 changesets with 4 changes to 4 files
196 $ cd test
157 $ cd test
197 $ echo bar > bar
158 $ echo bar > bar
198 $ hg commit -A -d '1 0' -m 2
159 $ hg commit -A -d '1 0' -m 2
199 adding bar
160 adding bar
200 $ cd ..
161 $ cd ..
201
162
202 pull without cacert
163 pull without cacert
203
164
204 $ cd copy-pull
165 $ cd copy-pull
205 $ cat >> .hg/hgrc <<EOF
166 $ cat >> .hg/hgrc <<EOF
206 > [hooks]
167 > [hooks]
207 > changegroup = sh -c "printenv.py --line changegroup"
168 > changegroup = sh -c "printenv.py --line changegroup"
208 > EOF
169 > EOF
209 $ hg pull $DISABLECACERTS
170 $ hg pull $DISABLECACERTS
210 pulling from https://localhost:$HGPORT/
171 pulling from https://localhost:$HGPORT/
211 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
172 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
212 abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect
173 abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect
213 (see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server)
174 (see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server)
214 [255]
175 [255]
215
176
216 $ hg pull --insecure
177 $ hg pull --insecure
217 pulling from https://localhost:$HGPORT/
178 pulling from https://localhost:$HGPORT/
218 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
179 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
219 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
180 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
220 searching for changes
181 searching for changes
221 adding changesets
182 adding changesets
222 adding manifests
183 adding manifests
223 adding file changes
184 adding file changes
224 added 1 changesets with 1 changes to 1 files
185 added 1 changesets with 1 changes to 1 files
225 new changesets 5fed3813f7f5
186 new changesets 5fed3813f7f5
226 changegroup hook: HG_HOOKNAME=changegroup
187 changegroup hook: HG_HOOKNAME=changegroup
227 HG_HOOKTYPE=changegroup
188 HG_HOOKTYPE=changegroup
228 HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d
189 HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d
229 HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d
190 HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d
230 HG_SOURCE=pull
191 HG_SOURCE=pull
231 HG_TXNID=TXN:$ID$
192 HG_TXNID=TXN:$ID$
232 HG_TXNNAME=pull
193 HG_TXNNAME=pull
233 https://localhost:$HGPORT/
194 https://localhost:$HGPORT/
234 HG_URL=https://localhost:$HGPORT/
195 HG_URL=https://localhost:$HGPORT/
235
196
236 (run 'hg update' to get a working copy)
197 (run 'hg update' to get a working copy)
237 $ cd ..
198 $ cd ..
238
199
239 cacert configured in local repo
200 cacert configured in local repo
240
201
241 $ cp copy-pull/.hg/hgrc copy-pull/.hg/hgrc.bu
202 $ cp copy-pull/.hg/hgrc copy-pull/.hg/hgrc.bu
242 $ echo "[web]" >> copy-pull/.hg/hgrc
203 $ echo "[web]" >> copy-pull/.hg/hgrc
243 $ echo "cacerts=$CERTSDIR/pub.pem" >> copy-pull/.hg/hgrc
204 $ echo "cacerts=$CERTSDIR/pub.pem" >> copy-pull/.hg/hgrc
244 $ hg -R copy-pull pull
205 $ hg -R copy-pull pull
245 pulling from https://localhost:$HGPORT/
206 pulling from https://localhost:$HGPORT/
246 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
207 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
247 searching for changes
208 searching for changes
248 no changes found
209 no changes found
249 $ mv copy-pull/.hg/hgrc.bu copy-pull/.hg/hgrc
210 $ mv copy-pull/.hg/hgrc.bu copy-pull/.hg/hgrc
250
211
251 cacert configured globally, also testing expansion of environment
212 cacert configured globally, also testing expansion of environment
252 variables in the filename
213 variables in the filename
253
214
254 $ echo "[web]" >> $HGRCPATH
215 $ echo "[web]" >> $HGRCPATH
255 $ echo 'cacerts=$P/pub.pem' >> $HGRCPATH
216 $ echo 'cacerts=$P/pub.pem' >> $HGRCPATH
256 $ P="$CERTSDIR" hg -R copy-pull pull
217 $ P="$CERTSDIR" hg -R copy-pull pull
257 pulling from https://localhost:$HGPORT/
218 pulling from https://localhost:$HGPORT/
258 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
219 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
259 searching for changes
220 searching for changes
260 no changes found
221 no changes found
261 $ P="$CERTSDIR" hg -R copy-pull pull --insecure
222 $ P="$CERTSDIR" hg -R copy-pull pull --insecure
262 pulling from https://localhost:$HGPORT/
223 pulling from https://localhost:$HGPORT/
263 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
224 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
264 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
225 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
265 searching for changes
226 searching for changes
266 no changes found
227 no changes found
267
228
268 empty cacert file
229 empty cacert file
269
230
270 $ touch emptycafile
231 $ touch emptycafile
271
232
272 #if sslcontext
273 $ hg --config web.cacerts=emptycafile -R copy-pull pull
233 $ hg --config web.cacerts=emptycafile -R copy-pull pull
274 pulling from https://localhost:$HGPORT/
234 pulling from https://localhost:$HGPORT/
275 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
235 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
276 abort: error loading CA file emptycafile: * (glob)
236 abort: error loading CA file emptycafile: * (glob)
277 (file is empty or malformed?)
237 (file is empty or malformed?)
278 [255]
238 [255]
279 #else
280 $ hg --config web.cacerts=emptycafile -R copy-pull pull
281 pulling from https://localhost:$HGPORT/
282 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
283 abort: error: * (glob)
284 [255]
285 #endif
286
239
287 cacert mismatch
240 cacert mismatch
288
241
289 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub.pem" \
242 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub.pem" \
290 > https://$LOCALIP:$HGPORT/
243 > https://$LOCALIP:$HGPORT/
291 pulling from https://*:$HGPORT/ (glob)
244 pulling from https://*:$HGPORT/ (glob)
292 warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
245 warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
293 abort: $LOCALIP certificate error: certificate is for localhost (glob)
246 abort: $LOCALIP certificate error: certificate is for localhost (glob)
294 (set hostsecurity.$LOCALIP:certfingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e config setting or use --insecure to connect insecurely)
247 (set hostsecurity.$LOCALIP:certfingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e config setting or use --insecure to connect insecurely)
295 [255]
248 [255]
296 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub.pem" \
249 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub.pem" \
297 > https://$LOCALIP:$HGPORT/ --insecure
250 > https://$LOCALIP:$HGPORT/ --insecure
298 pulling from https://*:$HGPORT/ (glob)
251 pulling from https://*:$HGPORT/ (glob)
299 warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
252 warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
300 warning: connection security to $LOCALIP is disabled per current settings; communication is susceptible to eavesdropping and tampering (glob)
253 warning: connection security to $LOCALIP is disabled per current settings; communication is susceptible to eavesdropping and tampering (glob)
301 searching for changes
254 searching for changes
302 no changes found
255 no changes found
303 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-other.pem"
256 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-other.pem"
304 pulling from https://localhost:$HGPORT/
257 pulling from https://localhost:$HGPORT/
305 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
258 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
306 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
259 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
307 abort: error: *certificate verify failed* (glob)
260 abort: error: *certificate verify failed* (glob)
308 [255]
261 [255]
309 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-other.pem" \
262 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-other.pem" \
310 > --insecure
263 > --insecure
311 pulling from https://localhost:$HGPORT/
264 pulling from https://localhost:$HGPORT/
312 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
265 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
313 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
266 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
314 searching for changes
267 searching for changes
315 no changes found
268 no changes found
316
269
317 Test server cert which isn't valid yet
270 Test server cert which isn't valid yet
318
271
319 $ hg serve -R test -p $HGPORT1 -d --pid-file=hg1.pid --certificate=server-not-yet.pem
272 $ hg serve -R test -p $HGPORT1 -d --pid-file=hg1.pid --certificate=server-not-yet.pem
320 $ cat hg1.pid >> $DAEMON_PIDS
273 $ cat hg1.pid >> $DAEMON_PIDS
321 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-not-yet.pem" \
274 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-not-yet.pem" \
322 > https://localhost:$HGPORT1/
275 > https://localhost:$HGPORT1/
323 pulling from https://localhost:$HGPORT1/
276 pulling from https://localhost:$HGPORT1/
324 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
277 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
325 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
278 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
326 abort: error: *certificate verify failed* (glob)
279 abort: error: *certificate verify failed* (glob)
327 [255]
280 [255]
328
281
329 Test server cert which no longer is valid
282 Test server cert which no longer is valid
330
283
331 $ hg serve -R test -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem
284 $ hg serve -R test -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem
332 $ cat hg2.pid >> $DAEMON_PIDS
285 $ cat hg2.pid >> $DAEMON_PIDS
333 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-expired.pem" \
286 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-expired.pem" \
334 > https://localhost:$HGPORT2/
287 > https://localhost:$HGPORT2/
335 pulling from https://localhost:$HGPORT2/
288 pulling from https://localhost:$HGPORT2/
336 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
289 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
337 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
290 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
338 abort: error: *certificate verify failed* (glob)
291 abort: error: *certificate verify failed* (glob)
339 [255]
292 [255]
340
293
341 Disabling the TLS 1.0 warning works
294 Disabling the TLS 1.0 warning works
342 $ hg -R copy-pull id https://localhost:$HGPORT/ \
295 $ hg -R copy-pull id https://localhost:$HGPORT/ \
343 > --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 \
296 > --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 \
344 > --config hostsecurity.disabletls10warning=true
297 > --config hostsecurity.disabletls10warning=true
345 5fed3813f7f5
298 5fed3813f7f5
346
299
347 Error message for setting ciphers is different depending on SSLContext support
348
349 #if no-sslcontext
350 $ P="$CERTSDIR" hg --config hostsecurity.ciphers=invalid -R copy-pull id https://localhost:$HGPORT/
351 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info
352 abort: *No cipher can be selected. (glob)
353 [255]
354
355 $ P="$CERTSDIR" hg --config hostsecurity.ciphers=HIGH -R copy-pull id https://localhost:$HGPORT/
356 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info
357 5fed3813f7f5
358 #endif
359
360 #if sslcontext
361 Setting ciphers to an invalid value aborts
300 Setting ciphers to an invalid value aborts
362 $ P="$CERTSDIR" hg --config hostsecurity.ciphers=invalid -R copy-pull id https://localhost:$HGPORT/
301 $ P="$CERTSDIR" hg --config hostsecurity.ciphers=invalid -R copy-pull id https://localhost:$HGPORT/
363 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
302 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
364 abort: could not set ciphers: No cipher can be selected.
303 abort: could not set ciphers: No cipher can be selected.
365 (change cipher string (invalid) in config)
304 (change cipher string (invalid) in config)
366 [255]
305 [255]
367
306
368 $ P="$CERTSDIR" hg --config hostsecurity.localhost:ciphers=invalid -R copy-pull id https://localhost:$HGPORT/
307 $ P="$CERTSDIR" hg --config hostsecurity.localhost:ciphers=invalid -R copy-pull id https://localhost:$HGPORT/
369 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
308 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
370 abort: could not set ciphers: No cipher can be selected.
309 abort: could not set ciphers: No cipher can be selected.
371 (change cipher string (invalid) in config)
310 (change cipher string (invalid) in config)
372 [255]
311 [255]
373
312
374 Changing the cipher string works
313 Changing the cipher string works
375
314
376 $ P="$CERTSDIR" hg --config hostsecurity.ciphers=HIGH -R copy-pull id https://localhost:$HGPORT/
315 $ P="$CERTSDIR" hg --config hostsecurity.ciphers=HIGH -R copy-pull id https://localhost:$HGPORT/
377 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
316 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
378 5fed3813f7f5
317 5fed3813f7f5
379 #endif
380
318
381 Fingerprints
319 Fingerprints
382
320
383 - works without cacerts (hostfingerprints)
321 - works without cacerts (hostfingerprints)
384 $ hg -R copy-pull id https://localhost:$HGPORT/ --insecure --config hostfingerprints.localhost=ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03
322 $ hg -R copy-pull id https://localhost:$HGPORT/ --insecure --config hostfingerprints.localhost=ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03
385 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
323 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
386 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
324 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
387 5fed3813f7f5
325 5fed3813f7f5
388
326
389 - works without cacerts (hostsecurity)
327 - works without cacerts (hostsecurity)
390 $ hg -R copy-pull id https://localhost:$HGPORT/ --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03
328 $ hg -R copy-pull id https://localhost:$HGPORT/ --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03
391 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
329 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
392 5fed3813f7f5
330 5fed3813f7f5
393
331
394 $ hg -R copy-pull id https://localhost:$HGPORT/ --config hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e
332 $ hg -R copy-pull id https://localhost:$HGPORT/ --config hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e
395 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
333 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
396 5fed3813f7f5
334 5fed3813f7f5
397
335
398 - multiple fingerprints specified and first matches
336 - multiple fingerprints specified and first matches
399 $ hg --config 'hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03, deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure
337 $ hg --config 'hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03, deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure
400 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
338 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
401 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
339 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
402 5fed3813f7f5
340 5fed3813f7f5
403
341
404 $ hg --config 'hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03, sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/
342 $ hg --config 'hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03, sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/
405 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
343 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
406 5fed3813f7f5
344 5fed3813f7f5
407
345
408 - multiple fingerprints specified and last matches
346 - multiple fingerprints specified and last matches
409 $ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03' -R copy-pull id https://localhost:$HGPORT/ --insecure
347 $ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03' -R copy-pull id https://localhost:$HGPORT/ --insecure
410 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
348 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
411 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
349 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
412 5fed3813f7f5
350 5fed3813f7f5
413
351
414 $ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03' -R copy-pull id https://localhost:$HGPORT/
352 $ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03' -R copy-pull id https://localhost:$HGPORT/
415 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
353 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
416 5fed3813f7f5
354 5fed3813f7f5
417
355
418 - multiple fingerprints specified and none match
356 - multiple fingerprints specified and none match
419
357
420 $ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure
358 $ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure
421 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
359 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
422 abort: certificate for localhost has unexpected fingerprint ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03
360 abort: certificate for localhost has unexpected fingerprint ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03
423 (check hostfingerprint configuration)
361 (check hostfingerprint configuration)
424 [255]
362 [255]
425
363
426 $ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/
364 $ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/
427 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
365 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
428 abort: certificate for localhost has unexpected fingerprint sha1:ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03
366 abort: certificate for localhost has unexpected fingerprint sha1:ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03
429 (check hostsecurity configuration)
367 (check hostsecurity configuration)
430 [255]
368 [255]
431
369
432 - fails when cert doesn't match hostname (port is ignored)
370 - fails when cert doesn't match hostname (port is ignored)
433 $ hg -R copy-pull id https://localhost:$HGPORT1/ --config hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03
371 $ hg -R copy-pull id https://localhost:$HGPORT1/ --config hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03
434 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
372 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
435 abort: certificate for localhost has unexpected fingerprint f4:2f:5a:0c:3e:52:5b:db:e7:24:a8:32:1d:18:97:6d:69:b5:87:84
373 abort: certificate for localhost has unexpected fingerprint f4:2f:5a:0c:3e:52:5b:db:e7:24:a8:32:1d:18:97:6d:69:b5:87:84
436 (check hostfingerprint configuration)
374 (check hostfingerprint configuration)
437 [255]
375 [255]
438
376
439
377
440 - ignores that certificate doesn't match hostname
378 - ignores that certificate doesn't match hostname
441 $ hg -R copy-pull id https://$LOCALIP:$HGPORT/ --config hostfingerprints.$LOCALIP=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03
379 $ hg -R copy-pull id https://$LOCALIP:$HGPORT/ --config hostfingerprints.$LOCALIP=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03
442 warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
380 warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
443 (SHA-1 fingerprint for $LOCALIP found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: $LOCALIP:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
381 (SHA-1 fingerprint for $LOCALIP found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: $LOCALIP:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
444 5fed3813f7f5
382 5fed3813f7f5
445
383
446 Ports used by next test. Kill servers.
384 Ports used by next test. Kill servers.
447
385
448 $ killdaemons.py hg0.pid
386 $ killdaemons.py hg0.pid
449 $ killdaemons.py hg1.pid
387 $ killdaemons.py hg1.pid
450 $ killdaemons.py hg2.pid
388 $ killdaemons.py hg2.pid
451
389
452 #if sslcontext tls1.2
390 #if tls1.2
453 Start servers running supported TLS versions
391 Start servers running supported TLS versions
454
392
455 $ cd test
393 $ cd test
456 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV \
394 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV \
457 > --config devel.serverexactprotocol=tls1.0
395 > --config devel.serverexactprotocol=tls1.0
458 $ cat ../hg0.pid >> $DAEMON_PIDS
396 $ cat ../hg0.pid >> $DAEMON_PIDS
459 $ hg serve -p $HGPORT1 -d --pid-file=../hg1.pid --certificate=$PRIV \
397 $ hg serve -p $HGPORT1 -d --pid-file=../hg1.pid --certificate=$PRIV \
460 > --config devel.serverexactprotocol=tls1.1
398 > --config devel.serverexactprotocol=tls1.1
461 $ cat ../hg1.pid >> $DAEMON_PIDS
399 $ cat ../hg1.pid >> $DAEMON_PIDS
462 $ hg serve -p $HGPORT2 -d --pid-file=../hg2.pid --certificate=$PRIV \
400 $ hg serve -p $HGPORT2 -d --pid-file=../hg2.pid --certificate=$PRIV \
463 > --config devel.serverexactprotocol=tls1.2
401 > --config devel.serverexactprotocol=tls1.2
464 $ cat ../hg2.pid >> $DAEMON_PIDS
402 $ cat ../hg2.pid >> $DAEMON_PIDS
465 $ cd ..
403 $ cd ..
466
404
467 Clients talking same TLS versions work
405 Clients talking same TLS versions work
468
406
469 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.0 id https://localhost:$HGPORT/
407 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.0 id https://localhost:$HGPORT/
470 5fed3813f7f5
408 5fed3813f7f5
471 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.1 id https://localhost:$HGPORT1/
409 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.1 id https://localhost:$HGPORT1/
472 5fed3813f7f5
410 5fed3813f7f5
473 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT2/
411 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT2/
474 5fed3813f7f5
412 5fed3813f7f5
475
413
476 Clients requiring newer TLS version than what server supports fail
414 Clients requiring newer TLS version than what server supports fail
477
415
478 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/
416 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/
479 (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)
417 (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)
480 (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)
418 (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)
481 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
419 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
482 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
420 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
483 [255]
421 [255]
484
422
485 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.1 id https://localhost:$HGPORT/
423 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.1 id https://localhost:$HGPORT/
486 (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)
424 (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)
487 (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)
425 (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)
488 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
426 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
489 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
427 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
490 [255]
428 [255]
491 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT/
429 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT/
492 (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)
430 (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)
493 (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)
431 (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)
494 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
432 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
495 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
433 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
496 [255]
434 [255]
497 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT1/
435 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT1/
498 (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)
436 (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)
499 (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)
437 (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)
500 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
438 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
501 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
439 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
502 [255]
440 [255]
503
441
504 --insecure will allow TLS 1.0 connections and override configs
442 --insecure will allow TLS 1.0 connections and override configs
505
443
506 $ hg --config hostsecurity.minimumprotocol=tls1.2 id --insecure https://localhost:$HGPORT1/
444 $ hg --config hostsecurity.minimumprotocol=tls1.2 id --insecure https://localhost:$HGPORT1/
507 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
445 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
508 5fed3813f7f5
446 5fed3813f7f5
509
447
510 The per-host config option overrides the default
448 The per-host config option overrides the default
511
449
512 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
450 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
513 > --config hostsecurity.minimumprotocol=tls1.2 \
451 > --config hostsecurity.minimumprotocol=tls1.2 \
514 > --config hostsecurity.localhost:minimumprotocol=tls1.0
452 > --config hostsecurity.localhost:minimumprotocol=tls1.0
515 5fed3813f7f5
453 5fed3813f7f5
516
454
517 The per-host config option by itself works
455 The per-host config option by itself works
518
456
519 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
457 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
520 > --config hostsecurity.localhost:minimumprotocol=tls1.2
458 > --config hostsecurity.localhost:minimumprotocol=tls1.2
521 (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)
459 (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)
522 (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)
460 (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)
523 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
461 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
524 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
462 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
525 [255]
463 [255]
526
464
527 .hg/hgrc file [hostsecurity] settings are applied to remote ui instances (issue5305)
465 .hg/hgrc file [hostsecurity] settings are applied to remote ui instances (issue5305)
528
466
529 $ cat >> copy-pull/.hg/hgrc << EOF
467 $ cat >> copy-pull/.hg/hgrc << EOF
530 > [hostsecurity]
468 > [hostsecurity]
531 > localhost:minimumprotocol=tls1.2
469 > localhost:minimumprotocol=tls1.2
532 > EOF
470 > EOF
533 $ P="$CERTSDIR" hg -R copy-pull id https://localhost:$HGPORT/
471 $ P="$CERTSDIR" hg -R copy-pull id https://localhost:$HGPORT/
534 (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)
472 (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)
535 (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)
473 (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)
536 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
474 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
537 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
475 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
538 [255]
476 [255]
539
477
540 $ killdaemons.py hg0.pid
478 $ killdaemons.py hg0.pid
541 $ killdaemons.py hg1.pid
479 $ killdaemons.py hg1.pid
542 $ killdaemons.py hg2.pid
480 $ killdaemons.py hg2.pid
543 #endif
481 #endif
544
482
545 Prepare for connecting through proxy
483 Prepare for connecting through proxy
546
484
547 $ hg serve -R test -p $HGPORT -d --pid-file=hg0.pid --certificate=$PRIV
485 $ hg serve -R test -p $HGPORT -d --pid-file=hg0.pid --certificate=$PRIV
548 $ cat hg0.pid >> $DAEMON_PIDS
486 $ cat hg0.pid >> $DAEMON_PIDS
549 $ hg serve -R test -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem
487 $ hg serve -R test -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem
550 $ cat hg2.pid >> $DAEMON_PIDS
488 $ cat hg2.pid >> $DAEMON_PIDS
551 tinyproxy.py doesn't fully detach, so killing it may result in extra output
489 tinyproxy.py doesn't fully detach, so killing it may result in extra output
552 from the shell. So don't kill it.
490 from the shell. So don't kill it.
553 $ tinyproxy.py $HGPORT1 localhost >proxy.log </dev/null 2>&1 &
491 $ tinyproxy.py $HGPORT1 localhost >proxy.log </dev/null 2>&1 &
554 $ while [ ! -f proxy.pid ]; do sleep 0; done
492 $ while [ ! -f proxy.pid ]; do sleep 0; done
555 $ cat proxy.pid >> $DAEMON_PIDS
493 $ cat proxy.pid >> $DAEMON_PIDS
556
494
557 $ echo "[http_proxy]" >> copy-pull/.hg/hgrc
495 $ echo "[http_proxy]" >> copy-pull/.hg/hgrc
558 $ echo "always=True" >> copy-pull/.hg/hgrc
496 $ echo "always=True" >> copy-pull/.hg/hgrc
559 $ echo "[hostfingerprints]" >> copy-pull/.hg/hgrc
497 $ echo "[hostfingerprints]" >> copy-pull/.hg/hgrc
560 $ echo "localhost =" >> copy-pull/.hg/hgrc
498 $ echo "localhost =" >> copy-pull/.hg/hgrc
561
499
562 Test unvalidated https through proxy
500 Test unvalidated https through proxy
563
501
564 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull --insecure
502 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull --insecure
565 pulling from https://localhost:$HGPORT/
503 pulling from https://localhost:$HGPORT/
566 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
504 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
567 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
505 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
568 searching for changes
506 searching for changes
569 no changes found
507 no changes found
570
508
571 Test https with cacert and fingerprint through proxy
509 Test https with cacert and fingerprint through proxy
572
510
573 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \
511 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \
574 > --config web.cacerts="$CERTSDIR/pub.pem"
512 > --config web.cacerts="$CERTSDIR/pub.pem"
575 pulling from https://localhost:$HGPORT/
513 pulling from https://localhost:$HGPORT/
576 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
514 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
577 searching for changes
515 searching for changes
578 no changes found
516 no changes found
579 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull https://localhost:$HGPORT/ --config hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 --trace
517 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull https://localhost:$HGPORT/ --config hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 --trace
580 pulling from https://*:$HGPORT/ (glob)
518 pulling from https://*:$HGPORT/ (glob)
581 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
519 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
582 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
520 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
583 searching for changes
521 searching for changes
584 no changes found
522 no changes found
585
523
586 Test https with cert problems through proxy
524 Test https with cert problems through proxy
587
525
588 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \
526 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \
589 > --config web.cacerts="$CERTSDIR/pub-other.pem"
527 > --config web.cacerts="$CERTSDIR/pub-other.pem"
590 pulling from https://localhost:$HGPORT/
528 pulling from https://localhost:$HGPORT/
591 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
529 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
592 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
530 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
593 abort: error: *certificate verify failed* (glob)
531 abort: error: *certificate verify failed* (glob)
594 [255]
532 [255]
595 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \
533 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \
596 > --config web.cacerts="$CERTSDIR/pub-expired.pem" https://localhost:$HGPORT2/
534 > --config web.cacerts="$CERTSDIR/pub-expired.pem" https://localhost:$HGPORT2/
597 pulling from https://localhost:$HGPORT2/
535 pulling from https://localhost:$HGPORT2/
598 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
536 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
599 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
537 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
600 abort: error: *certificate verify failed* (glob)
538 abort: error: *certificate verify failed* (glob)
601 [255]
539 [255]
602
540
603
541
604 $ killdaemons.py hg0.pid
542 $ killdaemons.py hg0.pid
605
543
606 #if sslcontext
607
608 $ cd test
544 $ cd test
609
545
610 Missing certificate file(s) are detected
546 Missing certificate file(s) are detected
611
547
612 $ hg serve -p $HGPORT --certificate=/missing/certificate \
548 $ hg serve -p $HGPORT --certificate=/missing/certificate \
613 > --config devel.servercafile=$PRIV --config devel.serverrequirecert=true
549 > --config devel.servercafile=$PRIV --config devel.serverrequirecert=true
614 abort: referenced certificate file (*/missing/certificate) does not exist (glob)
550 abort: referenced certificate file (*/missing/certificate) does not exist (glob)
615 [255]
551 [255]
616
552
617 $ hg serve -p $HGPORT --certificate=$PRIV \
553 $ hg serve -p $HGPORT --certificate=$PRIV \
618 > --config devel.servercafile=/missing/cafile --config devel.serverrequirecert=true
554 > --config devel.servercafile=/missing/cafile --config devel.serverrequirecert=true
619 abort: referenced certificate file (*/missing/cafile) does not exist (glob)
555 abort: referenced certificate file (*/missing/cafile) does not exist (glob)
620 [255]
556 [255]
621
557
622 Start hgweb that requires client certificates:
558 Start hgweb that requires client certificates:
623
559
624 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV \
560 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV \
625 > --config devel.servercafile=$PRIV --config devel.serverrequirecert=true
561 > --config devel.servercafile=$PRIV --config devel.serverrequirecert=true
626 $ cat ../hg0.pid >> $DAEMON_PIDS
562 $ cat ../hg0.pid >> $DAEMON_PIDS
627 $ cd ..
563 $ cd ..
628
564
629 without client certificate:
565 without client certificate:
630
566
631 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/
567 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/
632 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
568 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
633 abort: error: .*(\$ECONNRESET\$|certificate required|handshake failure).* (re)
569 abort: error: .*(\$ECONNRESET\$|certificate required|handshake failure).* (re)
634 [255]
570 [255]
635
571
636 with client certificate:
572 with client certificate:
637
573
638 $ cat << EOT >> $HGRCPATH
574 $ cat << EOT >> $HGRCPATH
639 > [auth]
575 > [auth]
640 > l.prefix = localhost
576 > l.prefix = localhost
641 > l.cert = $CERTSDIR/client-cert.pem
577 > l.cert = $CERTSDIR/client-cert.pem
642 > l.key = $CERTSDIR/client-key.pem
578 > l.key = $CERTSDIR/client-key.pem
643 > EOT
579 > EOT
644
580
645 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
581 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
646 > --config auth.l.key="$CERTSDIR/client-key-decrypted.pem"
582 > --config auth.l.key="$CERTSDIR/client-key-decrypted.pem"
647 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
583 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
648 5fed3813f7f5
584 5fed3813f7f5
649
585
650 $ printf '1234\n' | env P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
586 $ printf '1234\n' | env P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
651 > --config ui.interactive=True --config ui.nontty=True
587 > --config ui.interactive=True --config ui.nontty=True
652 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
588 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
653 passphrase for */client-key.pem: 5fed3813f7f5 (glob)
589 passphrase for */client-key.pem: 5fed3813f7f5 (glob)
654
590
655 $ env P="$CERTSDIR" hg id https://localhost:$HGPORT/
591 $ env P="$CERTSDIR" hg id https://localhost:$HGPORT/
656 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
592 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
657 abort: error: * (glob)
593 abort: error: * (glob)
658 [255]
594 [255]
659
595
660 Missing certficate and key files result in error
596 Missing certficate and key files result in error
661
597
662 $ hg id https://localhost:$HGPORT/ --config auth.l.cert=/missing/cert
598 $ hg id https://localhost:$HGPORT/ --config auth.l.cert=/missing/cert
663 abort: certificate file (*/missing/cert) does not exist; cannot connect to localhost (glob)
599 abort: certificate file (*/missing/cert) does not exist; cannot connect to localhost (glob)
664 (restore missing file or fix references in Mercurial config)
600 (restore missing file or fix references in Mercurial config)
665 [255]
601 [255]
666
602
667 $ hg id https://localhost:$HGPORT/ --config auth.l.key=/missing/key
603 $ hg id https://localhost:$HGPORT/ --config auth.l.key=/missing/key
668 abort: certificate file (*/missing/key) does not exist; cannot connect to localhost (glob)
604 abort: certificate file (*/missing/key) does not exist; cannot connect to localhost (glob)
669 (restore missing file or fix references in Mercurial config)
605 (restore missing file or fix references in Mercurial config)
670 [255]
606 [255]
671
672 #endif
@@ -1,115 +1,104 b''
1 #require serve ssl
1 #require serve ssl
2
2
3 Set up SMTP server:
3 Set up SMTP server:
4
4
5 $ CERTSDIR="$TESTDIR/sslcerts"
5 $ CERTSDIR="$TESTDIR/sslcerts"
6 $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub.pem" >> server.pem
6 $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub.pem" >> server.pem
7
7
8 $ "$PYTHON" "$TESTDIR/dummysmtpd.py" -p $HGPORT --pid-file a.pid -d \
8 $ "$PYTHON" "$TESTDIR/dummysmtpd.py" -p $HGPORT --pid-file a.pid -d \
9 > --tls smtps --certificate `pwd`/server.pem
9 > --tls smtps --certificate `pwd`/server.pem
10 listening at localhost:$HGPORT (?)
10 listening at localhost:$HGPORT (?)
11 $ cat a.pid >> $DAEMON_PIDS
11 $ cat a.pid >> $DAEMON_PIDS
12
12
13 Set up repository:
13 Set up repository:
14
14
15 $ hg init t
15 $ hg init t
16 $ cd t
16 $ cd t
17 $ cat <<EOF >> .hg/hgrc
17 $ cat <<EOF >> .hg/hgrc
18 > [extensions]
18 > [extensions]
19 > patchbomb =
19 > patchbomb =
20 > [email]
20 > [email]
21 > method = smtp
21 > method = smtp
22 > [smtp]
22 > [smtp]
23 > host = localhost
23 > host = localhost
24 > port = $HGPORT
24 > port = $HGPORT
25 > tls = smtps
25 > tls = smtps
26 > EOF
26 > EOF
27
27
28 $ echo a > a
28 $ echo a > a
29 $ hg commit -Ama -d '1 0'
29 $ hg commit -Ama -d '1 0'
30 adding a
30 adding a
31
31
32 Utility functions:
32 Utility functions:
33
33
34 $ DISABLECACERTS=
34 $ DISABLECACERTS=
35 $ try () {
35 $ try () {
36 > hg email $DISABLECACERTS -f quux -t foo -c bar -r tip "$@"
36 > hg email $DISABLECACERTS -f quux -t foo -c bar -r tip "$@"
37 > }
37 > }
38
38
39 Our test cert is not signed by a trusted CA. It should fail to verify if
39 Our test cert is not signed by a trusted CA. It should fail to verify if
40 we are able to load CA certs:
40 we are able to load CA certs:
41
41
42 #if sslcontext no-defaultcacertsloaded
42 #if no-defaultcacertsloaded
43 $ try
43 $ try
44 this patch series consists of 1 patches.
44 this patch series consists of 1 patches.
45
45
46
46
47 (an attempt was made to load CA certificates but none were loaded; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error)
47 (an attempt was made to load CA certificates but none were loaded; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error)
48 (?i)abort: .*?certificate.verify.failed.* (re)
48 (?i)abort: .*?certificate.verify.failed.* (re)
49 [255]
49 [255]
50 #endif
50 #endif
51
51
52 #if no-sslcontext
53 $ try
54 this patch series consists of 1 patches.
55
56
57 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info
58 (using CA certificates from *; if you see this message, your Mercurial install is not properly configured; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?)
59 (?i)abort: .*?certificate.verify.failed.* (re)
60 [255]
61 #endif
62
63 #if defaultcacertsloaded
52 #if defaultcacertsloaded
64 $ try
53 $ try
65 this patch series consists of 1 patches.
54 this patch series consists of 1 patches.
66
55
67
56
68 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
57 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
69 (using CA certificates from *; if you see this message, your Mercurial install is not properly configured; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?)
58 (using CA certificates from *; if you see this message, your Mercurial install is not properly configured; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?)
70 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
59 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
71 (?i)abort: .*?certificate.verify.failed.* (re)
60 (?i)abort: .*?certificate.verify.failed.* (re)
72 [255]
61 [255]
73
62
74 #endif
63 #endif
75
64
76 $ DISABLECACERTS="--config devel.disableloaddefaultcerts=true"
65 $ DISABLECACERTS="--config devel.disableloaddefaultcerts=true"
77
66
78 Without certificates:
67 Without certificates:
79
68
80 $ try --debug
69 $ try --debug
81 this patch series consists of 1 patches.
70 this patch series consists of 1 patches.
82
71
83
72
84 (using smtps)
73 (using smtps)
85 sending mail: smtp host localhost, port * (glob)
74 sending mail: smtp host localhost, port * (glob)
86 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
75 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
87 (verifying remote certificate)
76 (verifying remote certificate)
88 abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect
77 abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect
89 (see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server)
78 (see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server)
90 [255]
79 [255]
91
80
92 With global certificates:
81 With global certificates:
93
82
94 $ try --debug --config web.cacerts="$CERTSDIR/pub.pem"
83 $ try --debug --config web.cacerts="$CERTSDIR/pub.pem"
95 this patch series consists of 1 patches.
84 this patch series consists of 1 patches.
96
85
97
86
98 (using smtps)
87 (using smtps)
99 sending mail: smtp host localhost, port * (glob)
88 sending mail: smtp host localhost, port * (glob)
100 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
89 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
101 (verifying remote certificate)
90 (verifying remote certificate)
102 sending [PATCH] a ...
91 sending [PATCH] a ...
103
92
104 With invalid certificates:
93 With invalid certificates:
105
94
106 $ try --config web.cacerts="$CERTSDIR/pub-other.pem"
95 $ try --config web.cacerts="$CERTSDIR/pub-other.pem"
107 this patch series consists of 1 patches.
96 this patch series consists of 1 patches.
108
97
109
98
110 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
99 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
111 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
100 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
112 (?i)abort: .*?certificate.verify.failed.* (re)
101 (?i)abort: .*?certificate.verify.failed.* (re)
113 [255]
102 [255]
114
103
115 $ cd ..
104 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now