Show More
@@ -1,2638 +1,2639 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # |
|
2 | # | |
3 | # run-tests.py - Run a set of tests on Mercurial |
|
3 | # run-tests.py - Run a set of tests on Mercurial | |
4 | # |
|
4 | # | |
5 | # Copyright 2006 Matt Mackall <mpm@selenic.com> |
|
5 | # Copyright 2006 Matt Mackall <mpm@selenic.com> | |
6 | # |
|
6 | # | |
7 | # This software may be used and distributed according to the terms of the |
|
7 | # This software may be used and distributed according to the terms of the | |
8 | # GNU General Public License version 2 or any later version. |
|
8 | # GNU General Public License version 2 or any later version. | |
9 |
|
9 | |||
10 | # Modifying this script is tricky because it has many modes: |
|
10 | # Modifying this script is tricky because it has many modes: | |
11 | # - serial (default) vs parallel (-jN, N > 1) |
|
11 | # - serial (default) vs parallel (-jN, N > 1) | |
12 | # - no coverage (default) vs coverage (-c, -C, -s) |
|
12 | # - no coverage (default) vs coverage (-c, -C, -s) | |
13 | # - temp install (default) vs specific hg script (--with-hg, --local) |
|
13 | # - temp install (default) vs specific hg script (--with-hg, --local) | |
14 | # - tests are a mix of shell scripts and Python scripts |
|
14 | # - tests are a mix of shell scripts and Python scripts | |
15 | # |
|
15 | # | |
16 | # If you change this script, it is recommended that you ensure you |
|
16 | # If you change this script, it is recommended that you ensure you | |
17 | # haven't broken it by running it in various modes with a representative |
|
17 | # haven't broken it by running it in various modes with a representative | |
18 | # sample of test scripts. For example: |
|
18 | # sample of test scripts. For example: | |
19 | # |
|
19 | # | |
20 | # 1) serial, no coverage, temp install: |
|
20 | # 1) serial, no coverage, temp install: | |
21 | # ./run-tests.py test-s* |
|
21 | # ./run-tests.py test-s* | |
22 | # 2) serial, no coverage, local hg: |
|
22 | # 2) serial, no coverage, local hg: | |
23 | # ./run-tests.py --local test-s* |
|
23 | # ./run-tests.py --local test-s* | |
24 | # 3) serial, coverage, temp install: |
|
24 | # 3) serial, coverage, temp install: | |
25 | # ./run-tests.py -c test-s* |
|
25 | # ./run-tests.py -c test-s* | |
26 | # 4) serial, coverage, local hg: |
|
26 | # 4) serial, coverage, local hg: | |
27 | # ./run-tests.py -c --local test-s* # unsupported |
|
27 | # ./run-tests.py -c --local test-s* # unsupported | |
28 | # 5) parallel, no coverage, temp install: |
|
28 | # 5) parallel, no coverage, temp install: | |
29 | # ./run-tests.py -j2 test-s* |
|
29 | # ./run-tests.py -j2 test-s* | |
30 | # 6) parallel, no coverage, local hg: |
|
30 | # 6) parallel, no coverage, local hg: | |
31 | # ./run-tests.py -j2 --local test-s* |
|
31 | # ./run-tests.py -j2 --local test-s* | |
32 | # 7) parallel, coverage, temp install: |
|
32 | # 7) parallel, coverage, temp install: | |
33 | # ./run-tests.py -j2 -c test-s* # currently broken |
|
33 | # ./run-tests.py -j2 -c test-s* # currently broken | |
34 | # 8) parallel, coverage, local install: |
|
34 | # 8) parallel, coverage, local install: | |
35 | # ./run-tests.py -j2 -c --local test-s* # unsupported (and broken) |
|
35 | # ./run-tests.py -j2 -c --local test-s* # unsupported (and broken) | |
36 | # 9) parallel, custom tmp dir: |
|
36 | # 9) parallel, custom tmp dir: | |
37 | # ./run-tests.py -j2 --tmpdir /tmp/myhgtests |
|
37 | # ./run-tests.py -j2 --tmpdir /tmp/myhgtests | |
38 | # 10) parallel, pure, tests that call run-tests: |
|
38 | # 10) parallel, pure, tests that call run-tests: | |
39 | # ./run-tests.py --pure `grep -l run-tests.py *.t` |
|
39 | # ./run-tests.py --pure `grep -l run-tests.py *.t` | |
40 | # |
|
40 | # | |
41 | # (You could use any subset of the tests: test-s* happens to match |
|
41 | # (You could use any subset of the tests: test-s* happens to match | |
42 | # enough that it's worth doing parallel runs, few enough that it |
|
42 | # enough that it's worth doing parallel runs, few enough that it | |
43 | # completes fairly quickly, includes both shell and Python scripts, and |
|
43 | # completes fairly quickly, includes both shell and Python scripts, and | |
44 | # includes some scripts that run daemon processes.) |
|
44 | # includes some scripts that run daemon processes.) | |
45 |
|
45 | |||
46 | from __future__ import absolute_import, print_function |
|
46 | from __future__ import absolute_import, print_function | |
47 |
|
47 | |||
48 | import difflib |
|
48 | import difflib | |
49 | import distutils.version as version |
|
49 | import distutils.version as version | |
50 | import errno |
|
50 | import errno | |
51 | import json |
|
51 | import json | |
52 | import optparse |
|
52 | import optparse | |
53 | import os |
|
53 | import os | |
54 | import random |
|
54 | import random | |
55 | import re |
|
55 | import re | |
56 | import shutil |
|
56 | import shutil | |
57 | import signal |
|
57 | import signal | |
58 | import socket |
|
58 | import socket | |
59 | import subprocess |
|
59 | import subprocess | |
60 | import sys |
|
60 | import sys | |
61 | try: |
|
61 | try: | |
62 | import sysconfig |
|
62 | import sysconfig | |
63 | except ImportError: |
|
63 | except ImportError: | |
64 | # sysconfig doesn't exist in Python 2.6 |
|
64 | # sysconfig doesn't exist in Python 2.6 | |
65 | sysconfig = None |
|
65 | sysconfig = None | |
66 | import tempfile |
|
66 | import tempfile | |
67 | import threading |
|
67 | import threading | |
68 | import time |
|
68 | import time | |
69 | import unittest |
|
69 | import unittest | |
70 | import xml.dom.minidom as minidom |
|
70 | import xml.dom.minidom as minidom | |
71 |
|
71 | |||
72 | try: |
|
72 | try: | |
73 | import Queue as queue |
|
73 | import Queue as queue | |
74 | except ImportError: |
|
74 | except ImportError: | |
75 | import queue |
|
75 | import queue | |
76 |
|
76 | |||
77 | if os.environ.get('RTUNICODEPEDANTRY', False): |
|
77 | if os.environ.get('RTUNICODEPEDANTRY', False): | |
78 | try: |
|
78 | try: | |
79 | reload(sys) |
|
79 | reload(sys) | |
80 | sys.setdefaultencoding("undefined") |
|
80 | sys.setdefaultencoding("undefined") | |
81 | except NameError: |
|
81 | except NameError: | |
82 | pass |
|
82 | pass | |
83 |
|
83 | |||
84 | osenvironb = getattr(os, 'environb', os.environ) |
|
84 | osenvironb = getattr(os, 'environb', os.environ) | |
85 | processlock = threading.Lock() |
|
85 | processlock = threading.Lock() | |
86 |
|
86 | |||
87 | if sys.version_info > (3, 5, 0): |
|
87 | if sys.version_info > (3, 5, 0): | |
88 | PYTHON3 = True |
|
88 | PYTHON3 = True | |
89 | xrange = range # we use xrange in one place, and we'd rather not use range |
|
89 | xrange = range # we use xrange in one place, and we'd rather not use range | |
90 | def _bytespath(p): |
|
90 | def _bytespath(p): | |
91 | return p.encode('utf-8') |
|
91 | return p.encode('utf-8') | |
92 |
|
92 | |||
93 | def _strpath(p): |
|
93 | def _strpath(p): | |
94 | return p.decode('utf-8') |
|
94 | return p.decode('utf-8') | |
95 |
|
95 | |||
96 | elif sys.version_info >= (3, 0, 0): |
|
96 | elif sys.version_info >= (3, 0, 0): | |
97 | print('%s is only supported on Python 3.5+ and 2.6-2.7, not %s' % |
|
97 | print('%s is only supported on Python 3.5+ and 2.6-2.7, not %s' % | |
98 | (sys.argv[0], '.'.join(str(v) for v in sys.version_info[:3]))) |
|
98 | (sys.argv[0], '.'.join(str(v) for v in sys.version_info[:3]))) | |
99 | sys.exit(70) # EX_SOFTWARE from `man 3 sysexit` |
|
99 | sys.exit(70) # EX_SOFTWARE from `man 3 sysexit` | |
100 | else: |
|
100 | else: | |
101 | PYTHON3 = False |
|
101 | PYTHON3 = False | |
102 |
|
102 | |||
103 | # In python 2.x, path operations are generally done using |
|
103 | # In python 2.x, path operations are generally done using | |
104 | # bytestrings by default, so we don't have to do any extra |
|
104 | # bytestrings by default, so we don't have to do any extra | |
105 | # fiddling there. We define the wrapper functions anyway just to |
|
105 | # fiddling there. We define the wrapper functions anyway just to | |
106 | # help keep code consistent between platforms. |
|
106 | # help keep code consistent between platforms. | |
107 | def _bytespath(p): |
|
107 | def _bytespath(p): | |
108 | return p |
|
108 | return p | |
109 |
|
109 | |||
110 | _strpath = _bytespath |
|
110 | _strpath = _bytespath | |
111 |
|
111 | |||
112 | # For Windows support |
|
112 | # For Windows support | |
113 | wifexited = getattr(os, "WIFEXITED", lambda x: False) |
|
113 | wifexited = getattr(os, "WIFEXITED", lambda x: False) | |
114 |
|
114 | |||
115 | # Whether to use IPv6 |
|
115 | # Whether to use IPv6 | |
116 | def checksocketfamily(name, port=20058): |
|
116 | def checksocketfamily(name, port=20058): | |
117 | """return true if we can listen on localhost using family=name |
|
117 | """return true if we can listen on localhost using family=name | |
118 |
|
118 | |||
119 | name should be either 'AF_INET', or 'AF_INET6'. |
|
119 | name should be either 'AF_INET', or 'AF_INET6'. | |
120 | port being used is okay - EADDRINUSE is considered as successful. |
|
120 | port being used is okay - EADDRINUSE is considered as successful. | |
121 | """ |
|
121 | """ | |
122 | family = getattr(socket, name, None) |
|
122 | family = getattr(socket, name, None) | |
123 | if family is None: |
|
123 | if family is None: | |
124 | return False |
|
124 | return False | |
125 | try: |
|
125 | try: | |
126 | s = socket.socket(family, socket.SOCK_STREAM) |
|
126 | s = socket.socket(family, socket.SOCK_STREAM) | |
127 | s.bind(('localhost', port)) |
|
127 | s.bind(('localhost', port)) | |
128 | s.close() |
|
128 | s.close() | |
129 | return True |
|
129 | return True | |
130 | except socket.error as exc: |
|
130 | except socket.error as exc: | |
131 | if exc.errno == errno.EADDRINUSE: |
|
131 | if exc.errno == errno.EADDRINUSE: | |
132 | return True |
|
132 | return True | |
133 | elif exc.errno in (errno.EADDRNOTAVAIL, errno.EPROTONOSUPPORT): |
|
133 | elif exc.errno in (errno.EADDRNOTAVAIL, errno.EPROTONOSUPPORT): | |
134 | return False |
|
134 | return False | |
135 | else: |
|
135 | else: | |
136 | raise |
|
136 | raise | |
137 | else: |
|
137 | else: | |
138 | return False |
|
138 | return False | |
139 |
|
139 | |||
140 | # useipv6 will be set by parseargs |
|
140 | # useipv6 will be set by parseargs | |
141 | useipv6 = None |
|
141 | useipv6 = None | |
142 |
|
142 | |||
143 | def checkportisavailable(port): |
|
143 | def checkportisavailable(port): | |
144 | """return true if a port seems free to bind on localhost""" |
|
144 | """return true if a port seems free to bind on localhost""" | |
145 | if useipv6: |
|
145 | if useipv6: | |
146 | family = socket.AF_INET6 |
|
146 | family = socket.AF_INET6 | |
147 | else: |
|
147 | else: | |
148 | family = socket.AF_INET |
|
148 | family = socket.AF_INET | |
149 | try: |
|
149 | try: | |
150 | s = socket.socket(family, socket.SOCK_STREAM) |
|
150 | s = socket.socket(family, socket.SOCK_STREAM) | |
151 | s.bind(('localhost', port)) |
|
151 | s.bind(('localhost', port)) | |
152 | s.close() |
|
152 | s.close() | |
153 | return True |
|
153 | return True | |
154 | except socket.error as exc: |
|
154 | except socket.error as exc: | |
155 | if exc.errno not in (errno.EADDRINUSE, errno.EADDRNOTAVAIL, |
|
155 | if exc.errno not in (errno.EADDRINUSE, errno.EADDRNOTAVAIL, | |
156 | errno.EPROTONOSUPPORT): |
|
156 | errno.EPROTONOSUPPORT): | |
157 | raise |
|
157 | raise | |
158 | return False |
|
158 | return False | |
159 |
|
159 | |||
160 | closefds = os.name == 'posix' |
|
160 | closefds = os.name == 'posix' | |
161 | def Popen4(cmd, wd, timeout, env=None): |
|
161 | def Popen4(cmd, wd, timeout, env=None): | |
162 | processlock.acquire() |
|
162 | processlock.acquire() | |
163 | p = subprocess.Popen(cmd, shell=True, bufsize=-1, cwd=wd, env=env, |
|
163 | p = subprocess.Popen(cmd, shell=True, bufsize=-1, cwd=wd, env=env, | |
164 | close_fds=closefds, |
|
164 | close_fds=closefds, | |
165 | stdin=subprocess.PIPE, stdout=subprocess.PIPE, |
|
165 | stdin=subprocess.PIPE, stdout=subprocess.PIPE, | |
166 | stderr=subprocess.STDOUT) |
|
166 | stderr=subprocess.STDOUT) | |
167 | processlock.release() |
|
167 | processlock.release() | |
168 |
|
168 | |||
169 | p.fromchild = p.stdout |
|
169 | p.fromchild = p.stdout | |
170 | p.tochild = p.stdin |
|
170 | p.tochild = p.stdin | |
171 | p.childerr = p.stderr |
|
171 | p.childerr = p.stderr | |
172 |
|
172 | |||
173 | p.timeout = False |
|
173 | p.timeout = False | |
174 | if timeout: |
|
174 | if timeout: | |
175 | def t(): |
|
175 | def t(): | |
176 | start = time.time() |
|
176 | start = time.time() | |
177 | while time.time() - start < timeout and p.returncode is None: |
|
177 | while time.time() - start < timeout and p.returncode is None: | |
178 | time.sleep(.1) |
|
178 | time.sleep(.1) | |
179 | p.timeout = True |
|
179 | p.timeout = True | |
180 | if p.returncode is None: |
|
180 | if p.returncode is None: | |
181 | terminate(p) |
|
181 | terminate(p) | |
182 | threading.Thread(target=t).start() |
|
182 | threading.Thread(target=t).start() | |
183 |
|
183 | |||
184 | return p |
|
184 | return p | |
185 |
|
185 | |||
186 | PYTHON = _bytespath(sys.executable.replace('\\', '/')) |
|
186 | PYTHON = _bytespath(sys.executable.replace('\\', '/')) | |
187 | IMPL_PATH = b'PYTHONPATH' |
|
187 | IMPL_PATH = b'PYTHONPATH' | |
188 | if 'java' in sys.platform: |
|
188 | if 'java' in sys.platform: | |
189 | IMPL_PATH = b'JYTHONPATH' |
|
189 | IMPL_PATH = b'JYTHONPATH' | |
190 |
|
190 | |||
191 | defaults = { |
|
191 | defaults = { | |
192 | 'jobs': ('HGTEST_JOBS', 1), |
|
192 | 'jobs': ('HGTEST_JOBS', 1), | |
193 | 'timeout': ('HGTEST_TIMEOUT', 180), |
|
193 | 'timeout': ('HGTEST_TIMEOUT', 180), | |
194 | 'slowtimeout': ('HGTEST_SLOWTIMEOUT', 500), |
|
194 | 'slowtimeout': ('HGTEST_SLOWTIMEOUT', 500), | |
195 | 'port': ('HGTEST_PORT', 20059), |
|
195 | 'port': ('HGTEST_PORT', 20059), | |
196 | 'shell': ('HGTEST_SHELL', 'sh'), |
|
196 | 'shell': ('HGTEST_SHELL', 'sh'), | |
197 | } |
|
197 | } | |
198 |
|
198 | |||
199 | def canonpath(path): |
|
199 | def canonpath(path): | |
200 | return os.path.realpath(os.path.expanduser(path)) |
|
200 | return os.path.realpath(os.path.expanduser(path)) | |
201 |
|
201 | |||
202 | def parselistfiles(files, listtype, warn=True): |
|
202 | def parselistfiles(files, listtype, warn=True): | |
203 | entries = dict() |
|
203 | entries = dict() | |
204 | for filename in files: |
|
204 | for filename in files: | |
205 | try: |
|
205 | try: | |
206 | path = os.path.expanduser(os.path.expandvars(filename)) |
|
206 | path = os.path.expanduser(os.path.expandvars(filename)) | |
207 | f = open(path, "rb") |
|
207 | f = open(path, "rb") | |
208 | except IOError as err: |
|
208 | except IOError as err: | |
209 | if err.errno != errno.ENOENT: |
|
209 | if err.errno != errno.ENOENT: | |
210 | raise |
|
210 | raise | |
211 | if warn: |
|
211 | if warn: | |
212 | print("warning: no such %s file: %s" % (listtype, filename)) |
|
212 | print("warning: no such %s file: %s" % (listtype, filename)) | |
213 | continue |
|
213 | continue | |
214 |
|
214 | |||
215 | for line in f.readlines(): |
|
215 | for line in f.readlines(): | |
216 | line = line.split(b'#', 1)[0].strip() |
|
216 | line = line.split(b'#', 1)[0].strip() | |
217 | if line: |
|
217 | if line: | |
218 | entries[line] = filename |
|
218 | entries[line] = filename | |
219 |
|
219 | |||
220 | f.close() |
|
220 | f.close() | |
221 | return entries |
|
221 | return entries | |
222 |
|
222 | |||
223 | def getparser(): |
|
223 | def getparser(): | |
224 | """Obtain the OptionParser used by the CLI.""" |
|
224 | """Obtain the OptionParser used by the CLI.""" | |
225 | parser = optparse.OptionParser("%prog [options] [tests]") |
|
225 | parser = optparse.OptionParser("%prog [options] [tests]") | |
226 |
|
226 | |||
227 | # keep these sorted |
|
227 | # keep these sorted | |
228 | parser.add_option("--blacklist", action="append", |
|
228 | parser.add_option("--blacklist", action="append", | |
229 | help="skip tests listed in the specified blacklist file") |
|
229 | help="skip tests listed in the specified blacklist file") | |
230 | parser.add_option("--whitelist", action="append", |
|
230 | parser.add_option("--whitelist", action="append", | |
231 | help="always run tests listed in the specified whitelist file") |
|
231 | help="always run tests listed in the specified whitelist file") | |
232 | parser.add_option("--changed", type="string", |
|
232 | parser.add_option("--changed", type="string", | |
233 | help="run tests that are changed in parent rev or working directory") |
|
233 | help="run tests that are changed in parent rev or working directory") | |
234 | parser.add_option("-C", "--annotate", action="store_true", |
|
234 | parser.add_option("-C", "--annotate", action="store_true", | |
235 | help="output files annotated with coverage") |
|
235 | help="output files annotated with coverage") | |
236 | parser.add_option("-c", "--cover", action="store_true", |
|
236 | parser.add_option("-c", "--cover", action="store_true", | |
237 | help="print a test coverage report") |
|
237 | help="print a test coverage report") | |
238 | parser.add_option("-d", "--debug", action="store_true", |
|
238 | parser.add_option("-d", "--debug", action="store_true", | |
239 | help="debug mode: write output of test scripts to console" |
|
239 | help="debug mode: write output of test scripts to console" | |
240 | " rather than capturing and diffing it (disables timeout)") |
|
240 | " rather than capturing and diffing it (disables timeout)") | |
241 | parser.add_option("-f", "--first", action="store_true", |
|
241 | parser.add_option("-f", "--first", action="store_true", | |
242 | help="exit on the first test failure") |
|
242 | help="exit on the first test failure") | |
243 | parser.add_option("-H", "--htmlcov", action="store_true", |
|
243 | parser.add_option("-H", "--htmlcov", action="store_true", | |
244 | help="create an HTML report of the coverage of the files") |
|
244 | help="create an HTML report of the coverage of the files") | |
245 | parser.add_option("-i", "--interactive", action="store_true", |
|
245 | parser.add_option("-i", "--interactive", action="store_true", | |
246 | help="prompt to accept changed output") |
|
246 | help="prompt to accept changed output") | |
247 | parser.add_option("-j", "--jobs", type="int", |
|
247 | parser.add_option("-j", "--jobs", type="int", | |
248 | help="number of jobs to run in parallel" |
|
248 | help="number of jobs to run in parallel" | |
249 | " (default: $%s or %d)" % defaults['jobs']) |
|
249 | " (default: $%s or %d)" % defaults['jobs']) | |
250 | parser.add_option("--keep-tmpdir", action="store_true", |
|
250 | parser.add_option("--keep-tmpdir", action="store_true", | |
251 | help="keep temporary directory after running tests") |
|
251 | help="keep temporary directory after running tests") | |
252 | parser.add_option("-k", "--keywords", |
|
252 | parser.add_option("-k", "--keywords", | |
253 | help="run tests matching keywords") |
|
253 | help="run tests matching keywords") | |
254 | parser.add_option("-l", "--local", action="store_true", |
|
254 | parser.add_option("-l", "--local", action="store_true", | |
255 | help="shortcut for --with-hg=<testdir>/../hg, " |
|
255 | help="shortcut for --with-hg=<testdir>/../hg, " | |
256 | "and --with-chg=<testdir>/../contrib/chg/chg if --chg is set") |
|
256 | "and --with-chg=<testdir>/../contrib/chg/chg if --chg is set") | |
257 | parser.add_option("--loop", action="store_true", |
|
257 | parser.add_option("--loop", action="store_true", | |
258 | help="loop tests repeatedly") |
|
258 | help="loop tests repeatedly") | |
259 | parser.add_option("--runs-per-test", type="int", dest="runs_per_test", |
|
259 | parser.add_option("--runs-per-test", type="int", dest="runs_per_test", | |
260 | help="run each test N times (default=1)", default=1) |
|
260 | help="run each test N times (default=1)", default=1) | |
261 | parser.add_option("-n", "--nodiff", action="store_true", |
|
261 | parser.add_option("-n", "--nodiff", action="store_true", | |
262 | help="skip showing test changes") |
|
262 | help="skip showing test changes") | |
263 | parser.add_option("-p", "--port", type="int", |
|
263 | parser.add_option("-p", "--port", type="int", | |
264 | help="port on which servers should listen" |
|
264 | help="port on which servers should listen" | |
265 | " (default: $%s or %d)" % defaults['port']) |
|
265 | " (default: $%s or %d)" % defaults['port']) | |
266 | parser.add_option("--compiler", type="string", |
|
266 | parser.add_option("--compiler", type="string", | |
267 | help="compiler to build with") |
|
267 | help="compiler to build with") | |
268 | parser.add_option("--pure", action="store_true", |
|
268 | parser.add_option("--pure", action="store_true", | |
269 | help="use pure Python code instead of C extensions") |
|
269 | help="use pure Python code instead of C extensions") | |
270 | parser.add_option("-R", "--restart", action="store_true", |
|
270 | parser.add_option("-R", "--restart", action="store_true", | |
271 | help="restart at last error") |
|
271 | help="restart at last error") | |
272 | parser.add_option("-r", "--retest", action="store_true", |
|
272 | parser.add_option("-r", "--retest", action="store_true", | |
273 | help="retest failed tests") |
|
273 | help="retest failed tests") | |
274 | parser.add_option("-S", "--noskips", action="store_true", |
|
274 | parser.add_option("-S", "--noskips", action="store_true", | |
275 | help="don't report skip tests verbosely") |
|
275 | help="don't report skip tests verbosely") | |
276 | parser.add_option("--shell", type="string", |
|
276 | parser.add_option("--shell", type="string", | |
277 | help="shell to use (default: $%s or %s)" % defaults['shell']) |
|
277 | help="shell to use (default: $%s or %s)" % defaults['shell']) | |
278 | parser.add_option("-t", "--timeout", type="int", |
|
278 | parser.add_option("-t", "--timeout", type="int", | |
279 | help="kill errant tests after TIMEOUT seconds" |
|
279 | help="kill errant tests after TIMEOUT seconds" | |
280 | " (default: $%s or %d)" % defaults['timeout']) |
|
280 | " (default: $%s or %d)" % defaults['timeout']) | |
281 | parser.add_option("--slowtimeout", type="int", |
|
281 | parser.add_option("--slowtimeout", type="int", | |
282 | help="kill errant slow tests after SLOWTIMEOUT seconds" |
|
282 | help="kill errant slow tests after SLOWTIMEOUT seconds" | |
283 | " (default: $%s or %d)" % defaults['slowtimeout']) |
|
283 | " (default: $%s or %d)" % defaults['slowtimeout']) | |
284 | parser.add_option("--time", action="store_true", |
|
284 | parser.add_option("--time", action="store_true", | |
285 | help="time how long each test takes") |
|
285 | help="time how long each test takes") | |
286 | parser.add_option("--json", action="store_true", |
|
286 | parser.add_option("--json", action="store_true", | |
287 | help="store test result data in 'report.json' file") |
|
287 | help="store test result data in 'report.json' file") | |
288 | parser.add_option("--tmpdir", type="string", |
|
288 | parser.add_option("--tmpdir", type="string", | |
289 | help="run tests in the given temporary directory" |
|
289 | help="run tests in the given temporary directory" | |
290 | " (implies --keep-tmpdir)") |
|
290 | " (implies --keep-tmpdir)") | |
291 | parser.add_option("-v", "--verbose", action="store_true", |
|
291 | parser.add_option("-v", "--verbose", action="store_true", | |
292 | help="output verbose messages") |
|
292 | help="output verbose messages") | |
293 | parser.add_option("--xunit", type="string", |
|
293 | parser.add_option("--xunit", type="string", | |
294 | help="record xunit results at specified path") |
|
294 | help="record xunit results at specified path") | |
295 | parser.add_option("--view", type="string", |
|
295 | parser.add_option("--view", type="string", | |
296 | help="external diff viewer") |
|
296 | help="external diff viewer") | |
297 | parser.add_option("--with-hg", type="string", |
|
297 | parser.add_option("--with-hg", type="string", | |
298 | metavar="HG", |
|
298 | metavar="HG", | |
299 | help="test using specified hg script rather than a " |
|
299 | help="test using specified hg script rather than a " | |
300 | "temporary installation") |
|
300 | "temporary installation") | |
301 | parser.add_option("--chg", action="store_true", |
|
301 | parser.add_option("--chg", action="store_true", | |
302 | help="install and use chg wrapper in place of hg") |
|
302 | help="install and use chg wrapper in place of hg") | |
303 | parser.add_option("--with-chg", metavar="CHG", |
|
303 | parser.add_option("--with-chg", metavar="CHG", | |
304 | help="use specified chg wrapper in place of hg") |
|
304 | help="use specified chg wrapper in place of hg") | |
305 | parser.add_option("--ipv6", action="store_true", |
|
305 | parser.add_option("--ipv6", action="store_true", | |
306 | help="prefer IPv6 to IPv4 for network related tests") |
|
306 | help="prefer IPv6 to IPv4 for network related tests") | |
307 | parser.add_option("-3", "--py3k-warnings", action="store_true", |
|
307 | parser.add_option("-3", "--py3k-warnings", action="store_true", | |
308 | help="enable Py3k warnings on Python 2.6+") |
|
308 | help="enable Py3k warnings on Python 2.6+") | |
309 | # This option should be deleted once test-check-py3-compat.t and other |
|
309 | # This option should be deleted once test-check-py3-compat.t and other | |
310 | # Python 3 tests run with Python 3. |
|
310 | # Python 3 tests run with Python 3. | |
311 | parser.add_option("--with-python3", metavar="PYTHON3", |
|
311 | parser.add_option("--with-python3", metavar="PYTHON3", | |
312 | help="Python 3 interpreter (if running under Python 2)" |
|
312 | help="Python 3 interpreter (if running under Python 2)" | |
313 | " (TEMPORARY)") |
|
313 | " (TEMPORARY)") | |
314 | parser.add_option('--extra-config-opt', action="append", |
|
314 | parser.add_option('--extra-config-opt', action="append", | |
315 | help='set the given config opt in the test hgrc') |
|
315 | help='set the given config opt in the test hgrc') | |
316 | parser.add_option('--random', action="store_true", |
|
316 | parser.add_option('--random', action="store_true", | |
317 | help='run tests in random order') |
|
317 | help='run tests in random order') | |
318 | parser.add_option('--profile-runner', action='store_true', |
|
318 | parser.add_option('--profile-runner', action='store_true', | |
319 | help='run statprof on run-tests') |
|
319 | help='run statprof on run-tests') | |
320 | parser.add_option('--allow-slow-tests', action='store_true', |
|
320 | parser.add_option('--allow-slow-tests', action='store_true', | |
321 | help='allow extremely slow tests') |
|
321 | help='allow extremely slow tests') | |
322 | parser.add_option('--showchannels', action='store_true', |
|
322 | parser.add_option('--showchannels', action='store_true', | |
323 | help='show scheduling channels') |
|
323 | help='show scheduling channels') | |
324 | parser.add_option('--known-good-rev', type="string", |
|
324 | parser.add_option('--known-good-rev', type="string", | |
325 | metavar="known_good_rev", |
|
325 | metavar="known_good_rev", | |
326 | help=("Automatically bisect any failures using this " |
|
326 | help=("Automatically bisect any failures using this " | |
327 | "revision as a known-good revision.")) |
|
327 | "revision as a known-good revision.")) | |
328 |
|
328 | |||
329 | for option, (envvar, default) in defaults.items(): |
|
329 | for option, (envvar, default) in defaults.items(): | |
330 | defaults[option] = type(default)(os.environ.get(envvar, default)) |
|
330 | defaults[option] = type(default)(os.environ.get(envvar, default)) | |
331 | parser.set_defaults(**defaults) |
|
331 | parser.set_defaults(**defaults) | |
332 |
|
332 | |||
333 | return parser |
|
333 | return parser | |
334 |
|
334 | |||
335 | def parseargs(args, parser): |
|
335 | def parseargs(args, parser): | |
336 | """Parse arguments with our OptionParser and validate results.""" |
|
336 | """Parse arguments with our OptionParser and validate results.""" | |
337 | (options, args) = parser.parse_args(args) |
|
337 | (options, args) = parser.parse_args(args) | |
338 |
|
338 | |||
339 | # jython is always pure |
|
339 | # jython is always pure | |
340 | if 'java' in sys.platform or '__pypy__' in sys.modules: |
|
340 | if 'java' in sys.platform or '__pypy__' in sys.modules: | |
341 | options.pure = True |
|
341 | options.pure = True | |
342 |
|
342 | |||
343 | if options.with_hg: |
|
343 | if options.with_hg: | |
344 | options.with_hg = canonpath(_bytespath(options.with_hg)) |
|
344 | options.with_hg = canonpath(_bytespath(options.with_hg)) | |
345 | if not (os.path.isfile(options.with_hg) and |
|
345 | if not (os.path.isfile(options.with_hg) and | |
346 | os.access(options.with_hg, os.X_OK)): |
|
346 | os.access(options.with_hg, os.X_OK)): | |
347 | parser.error('--with-hg must specify an executable hg script') |
|
347 | parser.error('--with-hg must specify an executable hg script') | |
348 | if not os.path.basename(options.with_hg) == b'hg': |
|
348 | if not os.path.basename(options.with_hg) == b'hg': | |
349 | sys.stderr.write('warning: --with-hg should specify an hg script\n') |
|
349 | sys.stderr.write('warning: --with-hg should specify an hg script\n') | |
350 | if options.local: |
|
350 | if options.local: | |
351 | testdir = os.path.dirname(_bytespath(canonpath(sys.argv[0]))) |
|
351 | testdir = os.path.dirname(_bytespath(canonpath(sys.argv[0]))) | |
352 | reporootdir = os.path.dirname(testdir) |
|
352 | reporootdir = os.path.dirname(testdir) | |
353 | pathandattrs = [(b'hg', 'with_hg')] |
|
353 | pathandattrs = [(b'hg', 'with_hg')] | |
354 | if options.chg: |
|
354 | if options.chg: | |
355 | pathandattrs.append((b'contrib/chg/chg', 'with_chg')) |
|
355 | pathandattrs.append((b'contrib/chg/chg', 'with_chg')) | |
356 | for relpath, attr in pathandattrs: |
|
356 | for relpath, attr in pathandattrs: | |
357 | binpath = os.path.join(reporootdir, relpath) |
|
357 | binpath = os.path.join(reporootdir, relpath) | |
358 | if os.name != 'nt' and not os.access(binpath, os.X_OK): |
|
358 | if os.name != 'nt' and not os.access(binpath, os.X_OK): | |
359 | parser.error('--local specified, but %r not found or ' |
|
359 | parser.error('--local specified, but %r not found or ' | |
360 | 'not executable' % binpath) |
|
360 | 'not executable' % binpath) | |
361 | setattr(options, attr, binpath) |
|
361 | setattr(options, attr, binpath) | |
362 |
|
362 | |||
363 | if (options.chg or options.with_chg) and os.name == 'nt': |
|
363 | if (options.chg or options.with_chg) and os.name == 'nt': | |
364 | parser.error('chg does not work on %s' % os.name) |
|
364 | parser.error('chg does not work on %s' % os.name) | |
365 | if options.with_chg: |
|
365 | if options.with_chg: | |
366 | options.chg = False # no installation to temporary location |
|
366 | options.chg = False # no installation to temporary location | |
367 | options.with_chg = canonpath(_bytespath(options.with_chg)) |
|
367 | options.with_chg = canonpath(_bytespath(options.with_chg)) | |
368 | if not (os.path.isfile(options.with_chg) and |
|
368 | if not (os.path.isfile(options.with_chg) and | |
369 | os.access(options.with_chg, os.X_OK)): |
|
369 | os.access(options.with_chg, os.X_OK)): | |
370 | parser.error('--with-chg must specify a chg executable') |
|
370 | parser.error('--with-chg must specify a chg executable') | |
371 | if options.chg and options.with_hg: |
|
371 | if options.chg and options.with_hg: | |
372 | # chg shares installation location with hg |
|
372 | # chg shares installation location with hg | |
373 | parser.error('--chg does not work when --with-hg is specified ' |
|
373 | parser.error('--chg does not work when --with-hg is specified ' | |
374 | '(use --with-chg instead)') |
|
374 | '(use --with-chg instead)') | |
375 |
|
375 | |||
376 | global useipv6 |
|
376 | global useipv6 | |
377 | if options.ipv6: |
|
377 | if options.ipv6: | |
378 | useipv6 = checksocketfamily('AF_INET6') |
|
378 | useipv6 = checksocketfamily('AF_INET6') | |
379 | else: |
|
379 | else: | |
380 | # only use IPv6 if IPv4 is unavailable and IPv6 is available |
|
380 | # only use IPv6 if IPv4 is unavailable and IPv6 is available | |
381 | useipv6 = ((not checksocketfamily('AF_INET')) |
|
381 | useipv6 = ((not checksocketfamily('AF_INET')) | |
382 | and checksocketfamily('AF_INET6')) |
|
382 | and checksocketfamily('AF_INET6')) | |
383 |
|
383 | |||
384 | options.anycoverage = options.cover or options.annotate or options.htmlcov |
|
384 | options.anycoverage = options.cover or options.annotate or options.htmlcov | |
385 | if options.anycoverage: |
|
385 | if options.anycoverage: | |
386 | try: |
|
386 | try: | |
387 | import coverage |
|
387 | import coverage | |
388 | covver = version.StrictVersion(coverage.__version__).version |
|
388 | covver = version.StrictVersion(coverage.__version__).version | |
389 | if covver < (3, 3): |
|
389 | if covver < (3, 3): | |
390 | parser.error('coverage options require coverage 3.3 or later') |
|
390 | parser.error('coverage options require coverage 3.3 or later') | |
391 | except ImportError: |
|
391 | except ImportError: | |
392 | parser.error('coverage options now require the coverage package') |
|
392 | parser.error('coverage options now require the coverage package') | |
393 |
|
393 | |||
394 | if options.anycoverage and options.local: |
|
394 | if options.anycoverage and options.local: | |
395 | # this needs some path mangling somewhere, I guess |
|
395 | # this needs some path mangling somewhere, I guess | |
396 | parser.error("sorry, coverage options do not work when --local " |
|
396 | parser.error("sorry, coverage options do not work when --local " | |
397 | "is specified") |
|
397 | "is specified") | |
398 |
|
398 | |||
399 | if options.anycoverage and options.with_hg: |
|
399 | if options.anycoverage and options.with_hg: | |
400 | parser.error("sorry, coverage options do not work when --with-hg " |
|
400 | parser.error("sorry, coverage options do not work when --with-hg " | |
401 | "is specified") |
|
401 | "is specified") | |
402 |
|
402 | |||
403 | global verbose |
|
403 | global verbose | |
404 | if options.verbose: |
|
404 | if options.verbose: | |
405 | verbose = '' |
|
405 | verbose = '' | |
406 |
|
406 | |||
407 | if options.tmpdir: |
|
407 | if options.tmpdir: | |
408 | options.tmpdir = canonpath(options.tmpdir) |
|
408 | options.tmpdir = canonpath(options.tmpdir) | |
409 |
|
409 | |||
410 | if options.jobs < 1: |
|
410 | if options.jobs < 1: | |
411 | parser.error('--jobs must be positive') |
|
411 | parser.error('--jobs must be positive') | |
412 | if options.interactive and options.debug: |
|
412 | if options.interactive and options.debug: | |
413 | parser.error("-i/--interactive and -d/--debug are incompatible") |
|
413 | parser.error("-i/--interactive and -d/--debug are incompatible") | |
414 | if options.debug: |
|
414 | if options.debug: | |
415 | if options.timeout != defaults['timeout']: |
|
415 | if options.timeout != defaults['timeout']: | |
416 | sys.stderr.write( |
|
416 | sys.stderr.write( | |
417 | 'warning: --timeout option ignored with --debug\n') |
|
417 | 'warning: --timeout option ignored with --debug\n') | |
418 | if options.slowtimeout != defaults['slowtimeout']: |
|
418 | if options.slowtimeout != defaults['slowtimeout']: | |
419 | sys.stderr.write( |
|
419 | sys.stderr.write( | |
420 | 'warning: --slowtimeout option ignored with --debug\n') |
|
420 | 'warning: --slowtimeout option ignored with --debug\n') | |
421 | options.timeout = 0 |
|
421 | options.timeout = 0 | |
422 | options.slowtimeout = 0 |
|
422 | options.slowtimeout = 0 | |
423 | if options.py3k_warnings: |
|
423 | if options.py3k_warnings: | |
424 | if PYTHON3: |
|
424 | if PYTHON3: | |
425 | parser.error( |
|
425 | parser.error( | |
426 | '--py3k-warnings can only be used on Python 2.6 and 2.7') |
|
426 | '--py3k-warnings can only be used on Python 2.6 and 2.7') | |
427 | if options.with_python3: |
|
427 | if options.with_python3: | |
428 | if PYTHON3: |
|
428 | if PYTHON3: | |
429 | parser.error('--with-python3 cannot be used when executing with ' |
|
429 | parser.error('--with-python3 cannot be used when executing with ' | |
430 | 'Python 3') |
|
430 | 'Python 3') | |
431 |
|
431 | |||
432 | options.with_python3 = canonpath(options.with_python3) |
|
432 | options.with_python3 = canonpath(options.with_python3) | |
433 | # Verify Python3 executable is acceptable. |
|
433 | # Verify Python3 executable is acceptable. | |
434 | proc = subprocess.Popen([options.with_python3, b'--version'], |
|
434 | proc = subprocess.Popen([options.with_python3, b'--version'], | |
435 | stdout=subprocess.PIPE, |
|
435 | stdout=subprocess.PIPE, | |
436 | stderr=subprocess.STDOUT) |
|
436 | stderr=subprocess.STDOUT) | |
437 | out, _err = proc.communicate() |
|
437 | out, _err = proc.communicate() | |
438 | ret = proc.wait() |
|
438 | ret = proc.wait() | |
439 | if ret != 0: |
|
439 | if ret != 0: | |
440 | parser.error('could not determine version of python 3') |
|
440 | parser.error('could not determine version of python 3') | |
441 | if not out.startswith('Python '): |
|
441 | if not out.startswith('Python '): | |
442 | parser.error('unexpected output from python3 --version: %s' % |
|
442 | parser.error('unexpected output from python3 --version: %s' % | |
443 | out) |
|
443 | out) | |
444 | vers = version.LooseVersion(out[len('Python '):]) |
|
444 | vers = version.LooseVersion(out[len('Python '):]) | |
445 | if vers < version.LooseVersion('3.5.0'): |
|
445 | if vers < version.LooseVersion('3.5.0'): | |
446 | parser.error('--with-python3 version must be 3.5.0 or greater; ' |
|
446 | parser.error('--with-python3 version must be 3.5.0 or greater; ' | |
447 | 'got %s' % out) |
|
447 | 'got %s' % out) | |
448 |
|
448 | |||
449 | if options.blacklist: |
|
449 | if options.blacklist: | |
450 | options.blacklist = parselistfiles(options.blacklist, 'blacklist') |
|
450 | options.blacklist = parselistfiles(options.blacklist, 'blacklist') | |
451 | if options.whitelist: |
|
451 | if options.whitelist: | |
452 | options.whitelisted = parselistfiles(options.whitelist, 'whitelist') |
|
452 | options.whitelisted = parselistfiles(options.whitelist, 'whitelist') | |
453 | else: |
|
453 | else: | |
454 | options.whitelisted = {} |
|
454 | options.whitelisted = {} | |
455 |
|
455 | |||
456 | if options.showchannels: |
|
456 | if options.showchannels: | |
457 | options.nodiff = True |
|
457 | options.nodiff = True | |
458 |
|
458 | |||
459 | return (options, args) |
|
459 | return (options, args) | |
460 |
|
460 | |||
461 | def rename(src, dst): |
|
461 | def rename(src, dst): | |
462 | """Like os.rename(), trade atomicity and opened files friendliness |
|
462 | """Like os.rename(), trade atomicity and opened files friendliness | |
463 | for existing destination support. |
|
463 | for existing destination support. | |
464 | """ |
|
464 | """ | |
465 | shutil.copy(src, dst) |
|
465 | shutil.copy(src, dst) | |
466 | os.remove(src) |
|
466 | os.remove(src) | |
467 |
|
467 | |||
468 | _unified_diff = difflib.unified_diff |
|
468 | _unified_diff = difflib.unified_diff | |
469 | if PYTHON3: |
|
469 | if PYTHON3: | |
470 | import functools |
|
470 | import functools | |
471 | _unified_diff = functools.partial(difflib.diff_bytes, difflib.unified_diff) |
|
471 | _unified_diff = functools.partial(difflib.diff_bytes, difflib.unified_diff) | |
472 |
|
472 | |||
473 | def getdiff(expected, output, ref, err): |
|
473 | def getdiff(expected, output, ref, err): | |
474 | servefail = False |
|
474 | servefail = False | |
475 | lines = [] |
|
475 | lines = [] | |
476 | for line in _unified_diff(expected, output, ref, err): |
|
476 | for line in _unified_diff(expected, output, ref, err): | |
477 | if line.startswith(b'+++') or line.startswith(b'---'): |
|
477 | if line.startswith(b'+++') or line.startswith(b'---'): | |
478 | line = line.replace(b'\\', b'/') |
|
478 | line = line.replace(b'\\', b'/') | |
479 | if line.endswith(b' \n'): |
|
479 | if line.endswith(b' \n'): | |
480 | line = line[:-2] + b'\n' |
|
480 | line = line[:-2] + b'\n' | |
481 | lines.append(line) |
|
481 | lines.append(line) | |
482 | if not servefail and line.startswith( |
|
482 | if not servefail and line.startswith( | |
483 | b'+ abort: child process failed to start'): |
|
483 | b'+ abort: child process failed to start'): | |
484 | servefail = True |
|
484 | servefail = True | |
485 |
|
485 | |||
486 | return servefail, lines |
|
486 | return servefail, lines | |
487 |
|
487 | |||
488 | verbose = False |
|
488 | verbose = False | |
489 | def vlog(*msg): |
|
489 | def vlog(*msg): | |
490 | """Log only when in verbose mode.""" |
|
490 | """Log only when in verbose mode.""" | |
491 | if verbose is False: |
|
491 | if verbose is False: | |
492 | return |
|
492 | return | |
493 |
|
493 | |||
494 | return log(*msg) |
|
494 | return log(*msg) | |
495 |
|
495 | |||
496 | # Bytes that break XML even in a CDATA block: control characters 0-31 |
|
496 | # Bytes that break XML even in a CDATA block: control characters 0-31 | |
497 | # sans \t, \n and \r |
|
497 | # sans \t, \n and \r | |
498 | CDATA_EVIL = re.compile(br"[\000-\010\013\014\016-\037]") |
|
498 | CDATA_EVIL = re.compile(br"[\000-\010\013\014\016-\037]") | |
499 |
|
499 | |||
500 | def cdatasafe(data): |
|
500 | def cdatasafe(data): | |
501 | """Make a string safe to include in a CDATA block. |
|
501 | """Make a string safe to include in a CDATA block. | |
502 |
|
502 | |||
503 | Certain control characters are illegal in a CDATA block, and |
|
503 | Certain control characters are illegal in a CDATA block, and | |
504 | there's no way to include a ]]> in a CDATA either. This function |
|
504 | there's no way to include a ]]> in a CDATA either. This function | |
505 | replaces illegal bytes with ? and adds a space between the ]] so |
|
505 | replaces illegal bytes with ? and adds a space between the ]] so | |
506 | that it won't break the CDATA block. |
|
506 | that it won't break the CDATA block. | |
507 | """ |
|
507 | """ | |
508 | return CDATA_EVIL.sub(b'?', data).replace(b']]>', b'] ]>') |
|
508 | return CDATA_EVIL.sub(b'?', data).replace(b']]>', b'] ]>') | |
509 |
|
509 | |||
510 | def log(*msg): |
|
510 | def log(*msg): | |
511 | """Log something to stdout. |
|
511 | """Log something to stdout. | |
512 |
|
512 | |||
513 | Arguments are strings to print. |
|
513 | Arguments are strings to print. | |
514 | """ |
|
514 | """ | |
515 | with iolock: |
|
515 | with iolock: | |
516 | if verbose: |
|
516 | if verbose: | |
517 | print(verbose, end=' ') |
|
517 | print(verbose, end=' ') | |
518 | for m in msg: |
|
518 | for m in msg: | |
519 | print(m, end=' ') |
|
519 | print(m, end=' ') | |
520 | print() |
|
520 | print() | |
521 | sys.stdout.flush() |
|
521 | sys.stdout.flush() | |
522 |
|
522 | |||
523 | def terminate(proc): |
|
523 | def terminate(proc): | |
524 | """Terminate subprocess (with fallback for Python versions < 2.6)""" |
|
524 | """Terminate subprocess (with fallback for Python versions < 2.6)""" | |
525 | vlog('# Terminating process %d' % proc.pid) |
|
525 | vlog('# Terminating process %d' % proc.pid) | |
526 | try: |
|
526 | try: | |
527 | getattr(proc, 'terminate', lambda : os.kill(proc.pid, signal.SIGTERM))() |
|
527 | getattr(proc, 'terminate', lambda : os.kill(proc.pid, signal.SIGTERM))() | |
528 | except OSError: |
|
528 | except OSError: | |
529 | pass |
|
529 | pass | |
530 |
|
530 | |||
531 | def killdaemons(pidfile): |
|
531 | def killdaemons(pidfile): | |
532 | import killdaemons as killmod |
|
532 | import killdaemons as killmod | |
533 | return killmod.killdaemons(pidfile, tryhard=False, remove=True, |
|
533 | return killmod.killdaemons(pidfile, tryhard=False, remove=True, | |
534 | logfn=vlog) |
|
534 | logfn=vlog) | |
535 |
|
535 | |||
536 | class Test(unittest.TestCase): |
|
536 | class Test(unittest.TestCase): | |
537 | """Encapsulates a single, runnable test. |
|
537 | """Encapsulates a single, runnable test. | |
538 |
|
538 | |||
539 | While this class conforms to the unittest.TestCase API, it differs in that |
|
539 | While this class conforms to the unittest.TestCase API, it differs in that | |
540 | instances need to be instantiated manually. (Typically, unittest.TestCase |
|
540 | instances need to be instantiated manually. (Typically, unittest.TestCase | |
541 | classes are instantiated automatically by scanning modules.) |
|
541 | classes are instantiated automatically by scanning modules.) | |
542 | """ |
|
542 | """ | |
543 |
|
543 | |||
544 | # Status code reserved for skipped tests (used by hghave). |
|
544 | # Status code reserved for skipped tests (used by hghave). | |
545 | SKIPPED_STATUS = 80 |
|
545 | SKIPPED_STATUS = 80 | |
546 |
|
546 | |||
547 | def __init__(self, path, tmpdir, keeptmpdir=False, |
|
547 | def __init__(self, path, tmpdir, keeptmpdir=False, | |
548 | debug=False, |
|
548 | debug=False, | |
549 | timeout=defaults['timeout'], |
|
549 | timeout=defaults['timeout'], | |
550 | startport=defaults['port'], extraconfigopts=None, |
|
550 | startport=defaults['port'], extraconfigopts=None, | |
551 | py3kwarnings=False, shell=None, hgcommand=None, |
|
551 | py3kwarnings=False, shell=None, hgcommand=None, | |
552 | slowtimeout=defaults['slowtimeout'], usechg=False, |
|
552 | slowtimeout=defaults['slowtimeout'], usechg=False, | |
553 | useipv6=False): |
|
553 | useipv6=False): | |
554 | """Create a test from parameters. |
|
554 | """Create a test from parameters. | |
555 |
|
555 | |||
556 | path is the full path to the file defining the test. |
|
556 | path is the full path to the file defining the test. | |
557 |
|
557 | |||
558 | tmpdir is the main temporary directory to use for this test. |
|
558 | tmpdir is the main temporary directory to use for this test. | |
559 |
|
559 | |||
560 | keeptmpdir determines whether to keep the test's temporary directory |
|
560 | keeptmpdir determines whether to keep the test's temporary directory | |
561 | after execution. It defaults to removal (False). |
|
561 | after execution. It defaults to removal (False). | |
562 |
|
562 | |||
563 | debug mode will make the test execute verbosely, with unfiltered |
|
563 | debug mode will make the test execute verbosely, with unfiltered | |
564 | output. |
|
564 | output. | |
565 |
|
565 | |||
566 | timeout controls the maximum run time of the test. It is ignored when |
|
566 | timeout controls the maximum run time of the test. It is ignored when | |
567 | debug is True. See slowtimeout for tests with #require slow. |
|
567 | debug is True. See slowtimeout for tests with #require slow. | |
568 |
|
568 | |||
569 | slowtimeout overrides timeout if the test has #require slow. |
|
569 | slowtimeout overrides timeout if the test has #require slow. | |
570 |
|
570 | |||
571 | startport controls the starting port number to use for this test. Each |
|
571 | startport controls the starting port number to use for this test. Each | |
572 | test will reserve 3 port numbers for execution. It is the caller's |
|
572 | test will reserve 3 port numbers for execution. It is the caller's | |
573 | responsibility to allocate a non-overlapping port range to Test |
|
573 | responsibility to allocate a non-overlapping port range to Test | |
574 | instances. |
|
574 | instances. | |
575 |
|
575 | |||
576 | extraconfigopts is an iterable of extra hgrc config options. Values |
|
576 | extraconfigopts is an iterable of extra hgrc config options. Values | |
577 | must have the form "key=value" (something understood by hgrc). Values |
|
577 | must have the form "key=value" (something understood by hgrc). Values | |
578 | of the form "foo.key=value" will result in "[foo] key=value". |
|
578 | of the form "foo.key=value" will result in "[foo] key=value". | |
579 |
|
579 | |||
580 | py3kwarnings enables Py3k warnings. |
|
580 | py3kwarnings enables Py3k warnings. | |
581 |
|
581 | |||
582 | shell is the shell to execute tests in. |
|
582 | shell is the shell to execute tests in. | |
583 | """ |
|
583 | """ | |
584 | self.path = path |
|
584 | self.path = path | |
585 | self.bname = os.path.basename(path) |
|
585 | self.bname = os.path.basename(path) | |
586 | self.name = _strpath(self.bname) |
|
586 | self.name = _strpath(self.bname) | |
587 | self._testdir = os.path.dirname(path) |
|
587 | self._testdir = os.path.dirname(path) | |
588 | self.errpath = os.path.join(self._testdir, b'%s.err' % self.bname) |
|
588 | self.errpath = os.path.join(self._testdir, b'%s.err' % self.bname) | |
589 |
|
589 | |||
590 | self._threadtmp = tmpdir |
|
590 | self._threadtmp = tmpdir | |
591 | self._keeptmpdir = keeptmpdir |
|
591 | self._keeptmpdir = keeptmpdir | |
592 | self._debug = debug |
|
592 | self._debug = debug | |
593 | self._timeout = timeout |
|
593 | self._timeout = timeout | |
594 | self._slowtimeout = slowtimeout |
|
594 | self._slowtimeout = slowtimeout | |
595 | self._startport = startport |
|
595 | self._startport = startport | |
596 | self._extraconfigopts = extraconfigopts or [] |
|
596 | self._extraconfigopts = extraconfigopts or [] | |
597 | self._py3kwarnings = py3kwarnings |
|
597 | self._py3kwarnings = py3kwarnings | |
598 | self._shell = _bytespath(shell) |
|
598 | self._shell = _bytespath(shell) | |
599 | self._hgcommand = hgcommand or b'hg' |
|
599 | self._hgcommand = hgcommand or b'hg' | |
600 | self._usechg = usechg |
|
600 | self._usechg = usechg | |
601 | self._useipv6 = useipv6 |
|
601 | self._useipv6 = useipv6 | |
602 |
|
602 | |||
603 | self._aborted = False |
|
603 | self._aborted = False | |
604 | self._daemonpids = [] |
|
604 | self._daemonpids = [] | |
605 | self._finished = None |
|
605 | self._finished = None | |
606 | self._ret = None |
|
606 | self._ret = None | |
607 | self._out = None |
|
607 | self._out = None | |
608 | self._skipped = None |
|
608 | self._skipped = None | |
609 | self._testtmp = None |
|
609 | self._testtmp = None | |
610 | self._chgsockdir = None |
|
610 | self._chgsockdir = None | |
611 |
|
611 | |||
612 | # If we're not in --debug mode and reference output file exists, |
|
612 | # If we're not in --debug mode and reference output file exists, | |
613 | # check test output against it. |
|
613 | # check test output against it. | |
614 | if debug: |
|
614 | if debug: | |
615 | self._refout = None # to match "out is None" |
|
615 | self._refout = None # to match "out is None" | |
616 | elif os.path.exists(self.refpath): |
|
616 | elif os.path.exists(self.refpath): | |
617 | f = open(self.refpath, 'rb') |
|
617 | f = open(self.refpath, 'rb') | |
618 | self._refout = f.read().splitlines(True) |
|
618 | self._refout = f.read().splitlines(True) | |
619 | f.close() |
|
619 | f.close() | |
620 | else: |
|
620 | else: | |
621 | self._refout = [] |
|
621 | self._refout = [] | |
622 |
|
622 | |||
623 | # needed to get base class __repr__ running |
|
623 | # needed to get base class __repr__ running | |
624 | @property |
|
624 | @property | |
625 | def _testMethodName(self): |
|
625 | def _testMethodName(self): | |
626 | return self.name |
|
626 | return self.name | |
627 |
|
627 | |||
628 | def __str__(self): |
|
628 | def __str__(self): | |
629 | return self.name |
|
629 | return self.name | |
630 |
|
630 | |||
631 | def shortDescription(self): |
|
631 | def shortDescription(self): | |
632 | return self.name |
|
632 | return self.name | |
633 |
|
633 | |||
634 | def setUp(self): |
|
634 | def setUp(self): | |
635 | """Tasks to perform before run().""" |
|
635 | """Tasks to perform before run().""" | |
636 | self._finished = False |
|
636 | self._finished = False | |
637 | self._ret = None |
|
637 | self._ret = None | |
638 | self._out = None |
|
638 | self._out = None | |
639 | self._skipped = None |
|
639 | self._skipped = None | |
640 |
|
640 | |||
641 | try: |
|
641 | try: | |
642 | os.mkdir(self._threadtmp) |
|
642 | os.mkdir(self._threadtmp) | |
643 | except OSError as e: |
|
643 | except OSError as e: | |
644 | if e.errno != errno.EEXIST: |
|
644 | if e.errno != errno.EEXIST: | |
645 | raise |
|
645 | raise | |
646 |
|
646 | |||
647 | name = os.path.basename(self.path) |
|
647 | name = os.path.basename(self.path) | |
648 | self._testtmp = os.path.join(self._threadtmp, name) |
|
648 | self._testtmp = os.path.join(self._threadtmp, name) | |
649 | os.mkdir(self._testtmp) |
|
649 | os.mkdir(self._testtmp) | |
650 |
|
650 | |||
651 | # Remove any previous output files. |
|
651 | # Remove any previous output files. | |
652 | if os.path.exists(self.errpath): |
|
652 | if os.path.exists(self.errpath): | |
653 | try: |
|
653 | try: | |
654 | os.remove(self.errpath) |
|
654 | os.remove(self.errpath) | |
655 | except OSError as e: |
|
655 | except OSError as e: | |
656 | # We might have raced another test to clean up a .err |
|
656 | # We might have raced another test to clean up a .err | |
657 | # file, so ignore ENOENT when removing a previous .err |
|
657 | # file, so ignore ENOENT when removing a previous .err | |
658 | # file. |
|
658 | # file. | |
659 | if e.errno != errno.ENOENT: |
|
659 | if e.errno != errno.ENOENT: | |
660 | raise |
|
660 | raise | |
661 |
|
661 | |||
662 | if self._usechg: |
|
662 | if self._usechg: | |
663 | self._chgsockdir = os.path.join(self._threadtmp, |
|
663 | self._chgsockdir = os.path.join(self._threadtmp, | |
664 | b'%s.chgsock' % name) |
|
664 | b'%s.chgsock' % name) | |
665 | os.mkdir(self._chgsockdir) |
|
665 | os.mkdir(self._chgsockdir) | |
666 |
|
666 | |||
667 | def run(self, result): |
|
667 | def run(self, result): | |
668 | """Run this test and report results against a TestResult instance.""" |
|
668 | """Run this test and report results against a TestResult instance.""" | |
669 | # This function is extremely similar to unittest.TestCase.run(). Once |
|
669 | # This function is extremely similar to unittest.TestCase.run(). Once | |
670 | # we require Python 2.7 (or at least its version of unittest), this |
|
670 | # we require Python 2.7 (or at least its version of unittest), this | |
671 | # function can largely go away. |
|
671 | # function can largely go away. | |
672 | self._result = result |
|
672 | self._result = result | |
673 | result.startTest(self) |
|
673 | result.startTest(self) | |
674 | try: |
|
674 | try: | |
675 | try: |
|
675 | try: | |
676 | self.setUp() |
|
676 | self.setUp() | |
677 | except (KeyboardInterrupt, SystemExit): |
|
677 | except (KeyboardInterrupt, SystemExit): | |
678 | self._aborted = True |
|
678 | self._aborted = True | |
679 | raise |
|
679 | raise | |
680 | except Exception: |
|
680 | except Exception: | |
681 | result.addError(self, sys.exc_info()) |
|
681 | result.addError(self, sys.exc_info()) | |
682 | return |
|
682 | return | |
683 |
|
683 | |||
684 | success = False |
|
684 | success = False | |
685 | try: |
|
685 | try: | |
686 | self.runTest() |
|
686 | self.runTest() | |
687 | except KeyboardInterrupt: |
|
687 | except KeyboardInterrupt: | |
688 | self._aborted = True |
|
688 | self._aborted = True | |
689 | raise |
|
689 | raise | |
690 | except SkipTest as e: |
|
690 | except SkipTest as e: | |
691 | result.addSkip(self, str(e)) |
|
691 | result.addSkip(self, str(e)) | |
692 | # The base class will have already counted this as a |
|
692 | # The base class will have already counted this as a | |
693 | # test we "ran", but we want to exclude skipped tests |
|
693 | # test we "ran", but we want to exclude skipped tests | |
694 | # from those we count towards those run. |
|
694 | # from those we count towards those run. | |
695 | result.testsRun -= 1 |
|
695 | result.testsRun -= 1 | |
696 | except IgnoreTest as e: |
|
696 | except IgnoreTest as e: | |
697 | result.addIgnore(self, str(e)) |
|
697 | result.addIgnore(self, str(e)) | |
698 | # As with skips, ignores also should be excluded from |
|
698 | # As with skips, ignores also should be excluded from | |
699 | # the number of tests executed. |
|
699 | # the number of tests executed. | |
700 | result.testsRun -= 1 |
|
700 | result.testsRun -= 1 | |
701 | except WarnTest as e: |
|
701 | except WarnTest as e: | |
702 | result.addWarn(self, str(e)) |
|
702 | result.addWarn(self, str(e)) | |
703 | except ReportedTest as e: |
|
703 | except ReportedTest as e: | |
704 | pass |
|
704 | pass | |
705 | except self.failureException as e: |
|
705 | except self.failureException as e: | |
706 | # This differs from unittest in that we don't capture |
|
706 | # This differs from unittest in that we don't capture | |
707 | # the stack trace. This is for historical reasons and |
|
707 | # the stack trace. This is for historical reasons and | |
708 | # this decision could be revisited in the future, |
|
708 | # this decision could be revisited in the future, | |
709 | # especially for PythonTest instances. |
|
709 | # especially for PythonTest instances. | |
710 | if result.addFailure(self, str(e)): |
|
710 | if result.addFailure(self, str(e)): | |
711 | success = True |
|
711 | success = True | |
712 | except Exception: |
|
712 | except Exception: | |
713 | result.addError(self, sys.exc_info()) |
|
713 | result.addError(self, sys.exc_info()) | |
714 | else: |
|
714 | else: | |
715 | success = True |
|
715 | success = True | |
716 |
|
716 | |||
717 | try: |
|
717 | try: | |
718 | self.tearDown() |
|
718 | self.tearDown() | |
719 | except (KeyboardInterrupt, SystemExit): |
|
719 | except (KeyboardInterrupt, SystemExit): | |
720 | self._aborted = True |
|
720 | self._aborted = True | |
721 | raise |
|
721 | raise | |
722 | except Exception: |
|
722 | except Exception: | |
723 | result.addError(self, sys.exc_info()) |
|
723 | result.addError(self, sys.exc_info()) | |
724 | success = False |
|
724 | success = False | |
725 |
|
725 | |||
726 | if success: |
|
726 | if success: | |
727 | result.addSuccess(self) |
|
727 | result.addSuccess(self) | |
728 | finally: |
|
728 | finally: | |
729 | result.stopTest(self, interrupted=self._aborted) |
|
729 | result.stopTest(self, interrupted=self._aborted) | |
730 |
|
730 | |||
731 | def runTest(self): |
|
731 | def runTest(self): | |
732 | """Run this test instance. |
|
732 | """Run this test instance. | |
733 |
|
733 | |||
734 | This will return a tuple describing the result of the test. |
|
734 | This will return a tuple describing the result of the test. | |
735 | """ |
|
735 | """ | |
736 | env = self._getenv() |
|
736 | env = self._getenv() | |
737 | self._daemonpids.append(env['DAEMON_PIDS']) |
|
737 | self._daemonpids.append(env['DAEMON_PIDS']) | |
738 | self._createhgrc(env['HGRCPATH']) |
|
738 | self._createhgrc(env['HGRCPATH']) | |
739 |
|
739 | |||
740 | vlog('# Test', self.name) |
|
740 | vlog('# Test', self.name) | |
741 |
|
741 | |||
742 | ret, out = self._run(env) |
|
742 | ret, out = self._run(env) | |
743 | self._finished = True |
|
743 | self._finished = True | |
744 | self._ret = ret |
|
744 | self._ret = ret | |
745 | self._out = out |
|
745 | self._out = out | |
746 |
|
746 | |||
747 | def describe(ret): |
|
747 | def describe(ret): | |
748 | if ret < 0: |
|
748 | if ret < 0: | |
749 | return 'killed by signal: %d' % -ret |
|
749 | return 'killed by signal: %d' % -ret | |
750 | return 'returned error code %d' % ret |
|
750 | return 'returned error code %d' % ret | |
751 |
|
751 | |||
752 | self._skipped = False |
|
752 | self._skipped = False | |
753 |
|
753 | |||
754 | if ret == self.SKIPPED_STATUS: |
|
754 | if ret == self.SKIPPED_STATUS: | |
755 | if out is None: # Debug mode, nothing to parse. |
|
755 | if out is None: # Debug mode, nothing to parse. | |
756 | missing = ['unknown'] |
|
756 | missing = ['unknown'] | |
757 | failed = None |
|
757 | failed = None | |
758 | else: |
|
758 | else: | |
759 | missing, failed = TTest.parsehghaveoutput(out) |
|
759 | missing, failed = TTest.parsehghaveoutput(out) | |
760 |
|
760 | |||
761 | if not missing: |
|
761 | if not missing: | |
762 | missing = ['skipped'] |
|
762 | missing = ['skipped'] | |
763 |
|
763 | |||
764 | if failed: |
|
764 | if failed: | |
765 | self.fail('hg have failed checking for %s' % failed[-1]) |
|
765 | self.fail('hg have failed checking for %s' % failed[-1]) | |
766 | else: |
|
766 | else: | |
767 | self._skipped = True |
|
767 | self._skipped = True | |
768 | raise SkipTest(missing[-1]) |
|
768 | raise SkipTest(missing[-1]) | |
769 | elif ret == 'timeout': |
|
769 | elif ret == 'timeout': | |
770 | self.fail('timed out') |
|
770 | self.fail('timed out') | |
771 | elif ret is False: |
|
771 | elif ret is False: | |
772 | raise WarnTest('no result code from test') |
|
772 | raise WarnTest('no result code from test') | |
773 | elif out != self._refout: |
|
773 | elif out != self._refout: | |
774 | # Diff generation may rely on written .err file. |
|
774 | # Diff generation may rely on written .err file. | |
775 | if (ret != 0 or out != self._refout) and not self._skipped \ |
|
775 | if (ret != 0 or out != self._refout) and not self._skipped \ | |
776 | and not self._debug: |
|
776 | and not self._debug: | |
777 | f = open(self.errpath, 'wb') |
|
777 | f = open(self.errpath, 'wb') | |
778 | for line in out: |
|
778 | for line in out: | |
779 | f.write(line) |
|
779 | f.write(line) | |
780 | f.close() |
|
780 | f.close() | |
781 |
|
781 | |||
782 | # The result object handles diff calculation for us. |
|
782 | # The result object handles diff calculation for us. | |
783 | if self._result.addOutputMismatch(self, ret, out, self._refout): |
|
783 | if self._result.addOutputMismatch(self, ret, out, self._refout): | |
784 | # change was accepted, skip failing |
|
784 | # change was accepted, skip failing | |
785 | return |
|
785 | return | |
786 |
|
786 | |||
787 | if ret: |
|
787 | if ret: | |
788 | msg = 'output changed and ' + describe(ret) |
|
788 | msg = 'output changed and ' + describe(ret) | |
789 | else: |
|
789 | else: | |
790 | msg = 'output changed' |
|
790 | msg = 'output changed' | |
791 |
|
791 | |||
792 | self.fail(msg) |
|
792 | self.fail(msg) | |
793 | elif ret: |
|
793 | elif ret: | |
794 | self.fail(describe(ret)) |
|
794 | self.fail(describe(ret)) | |
795 |
|
795 | |||
796 | def tearDown(self): |
|
796 | def tearDown(self): | |
797 | """Tasks to perform after run().""" |
|
797 | """Tasks to perform after run().""" | |
798 | for entry in self._daemonpids: |
|
798 | for entry in self._daemonpids: | |
799 | killdaemons(entry) |
|
799 | killdaemons(entry) | |
800 | self._daemonpids = [] |
|
800 | self._daemonpids = [] | |
801 |
|
801 | |||
802 | if self._keeptmpdir: |
|
802 | if self._keeptmpdir: | |
803 | log('\nKeeping testtmp dir: %s\nKeeping threadtmp dir: %s' % |
|
803 | log('\nKeeping testtmp dir: %s\nKeeping threadtmp dir: %s' % | |
804 | (self._testtmp.decode('utf-8'), |
|
804 | (self._testtmp.decode('utf-8'), | |
805 | self._threadtmp.decode('utf-8'))) |
|
805 | self._threadtmp.decode('utf-8'))) | |
806 | else: |
|
806 | else: | |
807 | shutil.rmtree(self._testtmp, True) |
|
807 | shutil.rmtree(self._testtmp, True) | |
808 | shutil.rmtree(self._threadtmp, True) |
|
808 | shutil.rmtree(self._threadtmp, True) | |
809 |
|
809 | |||
810 | if self._usechg: |
|
810 | if self._usechg: | |
811 | # chgservers will stop automatically after they find the socket |
|
811 | # chgservers will stop automatically after they find the socket | |
812 | # files are deleted |
|
812 | # files are deleted | |
813 | shutil.rmtree(self._chgsockdir, True) |
|
813 | shutil.rmtree(self._chgsockdir, True) | |
814 |
|
814 | |||
815 | if (self._ret != 0 or self._out != self._refout) and not self._skipped \ |
|
815 | if (self._ret != 0 or self._out != self._refout) and not self._skipped \ | |
816 | and not self._debug and self._out: |
|
816 | and not self._debug and self._out: | |
817 | f = open(self.errpath, 'wb') |
|
817 | f = open(self.errpath, 'wb') | |
818 | for line in self._out: |
|
818 | for line in self._out: | |
819 | f.write(line) |
|
819 | f.write(line) | |
820 | f.close() |
|
820 | f.close() | |
821 |
|
821 | |||
822 | vlog("# Ret was:", self._ret, '(%s)' % self.name) |
|
822 | vlog("# Ret was:", self._ret, '(%s)' % self.name) | |
823 |
|
823 | |||
824 | def _run(self, env): |
|
824 | def _run(self, env): | |
825 | # This should be implemented in child classes to run tests. |
|
825 | # This should be implemented in child classes to run tests. | |
826 | raise SkipTest('unknown test type') |
|
826 | raise SkipTest('unknown test type') | |
827 |
|
827 | |||
828 | def abort(self): |
|
828 | def abort(self): | |
829 | """Terminate execution of this test.""" |
|
829 | """Terminate execution of this test.""" | |
830 | self._aborted = True |
|
830 | self._aborted = True | |
831 |
|
831 | |||
832 | def _portmap(self, i): |
|
832 | def _portmap(self, i): | |
833 | offset = b'' if i == 0 else b'%d' % i |
|
833 | offset = b'' if i == 0 else b'%d' % i | |
834 | return (br':%d\b' % (self._startport + i), b':$HGPORT%s' % offset) |
|
834 | return (br':%d\b' % (self._startport + i), b':$HGPORT%s' % offset) | |
835 |
|
835 | |||
836 | def _getreplacements(self): |
|
836 | def _getreplacements(self): | |
837 | """Obtain a mapping of text replacements to apply to test output. |
|
837 | """Obtain a mapping of text replacements to apply to test output. | |
838 |
|
838 | |||
839 | Test output needs to be normalized so it can be compared to expected |
|
839 | Test output needs to be normalized so it can be compared to expected | |
840 | output. This function defines how some of that normalization will |
|
840 | output. This function defines how some of that normalization will | |
841 | occur. |
|
841 | occur. | |
842 | """ |
|
842 | """ | |
843 | r = [ |
|
843 | r = [ | |
844 | # This list should be parallel to defineport in _getenv |
|
844 | # This list should be parallel to defineport in _getenv | |
845 | self._portmap(0), |
|
845 | self._portmap(0), | |
846 | self._portmap(1), |
|
846 | self._portmap(1), | |
847 | self._portmap(2), |
|
847 | self._portmap(2), | |
848 | (br'(?m)^(saved backup bundle to .*\.hg)( \(glob\))?$', |
|
848 | (br'(?m)^(saved backup bundle to .*\.hg)( \(glob\))?$', | |
849 | br'\1 (glob)'), |
|
849 | br'\1 (glob)'), | |
850 | (br'([^0-9])%s' % re.escape(self._localip()), br'\1$LOCALIP'), |
|
850 | (br'([^0-9])%s' % re.escape(self._localip()), br'\1$LOCALIP'), | |
|
851 | (br'\bHG_TXNID=TXN:[a-f0-9]{40}\b', br'HG_TXNID=TXN:$ID$'), | |||
851 | ] |
|
852 | ] | |
852 | r.append((self._escapepath(self._testtmp), b'$TESTTMP')) |
|
853 | r.append((self._escapepath(self._testtmp), b'$TESTTMP')) | |
853 |
|
854 | |||
854 | return r |
|
855 | return r | |
855 |
|
856 | |||
856 | def _escapepath(self, p): |
|
857 | def _escapepath(self, p): | |
857 | if os.name == 'nt': |
|
858 | if os.name == 'nt': | |
858 | return ( |
|
859 | return ( | |
859 | (b''.join(c.isalpha() and b'[%s%s]' % (c.lower(), c.upper()) or |
|
860 | (b''.join(c.isalpha() and b'[%s%s]' % (c.lower(), c.upper()) or | |
860 | c in b'/\\' and br'[/\\]' or c.isdigit() and c or b'\\' + c |
|
861 | c in b'/\\' and br'[/\\]' or c.isdigit() and c or b'\\' + c | |
861 | for c in p)) |
|
862 | for c in p)) | |
862 | ) |
|
863 | ) | |
863 | else: |
|
864 | else: | |
864 | return re.escape(p) |
|
865 | return re.escape(p) | |
865 |
|
866 | |||
866 | def _localip(self): |
|
867 | def _localip(self): | |
867 | if self._useipv6: |
|
868 | if self._useipv6: | |
868 | return b'::1' |
|
869 | return b'::1' | |
869 | else: |
|
870 | else: | |
870 | return b'127.0.0.1' |
|
871 | return b'127.0.0.1' | |
871 |
|
872 | |||
872 | def _getenv(self): |
|
873 | def _getenv(self): | |
873 | """Obtain environment variables to use during test execution.""" |
|
874 | """Obtain environment variables to use during test execution.""" | |
874 | def defineport(i): |
|
875 | def defineport(i): | |
875 | offset = '' if i == 0 else '%s' % i |
|
876 | offset = '' if i == 0 else '%s' % i | |
876 | env["HGPORT%s" % offset] = '%s' % (self._startport + i) |
|
877 | env["HGPORT%s" % offset] = '%s' % (self._startport + i) | |
877 | env = os.environ.copy() |
|
878 | env = os.environ.copy() | |
878 | if sysconfig is not None: |
|
879 | if sysconfig is not None: | |
879 | env['PYTHONUSERBASE'] = sysconfig.get_config_var('userbase') |
|
880 | env['PYTHONUSERBASE'] = sysconfig.get_config_var('userbase') | |
880 | env['TESTTMP'] = self._testtmp |
|
881 | env['TESTTMP'] = self._testtmp | |
881 | env['HOME'] = self._testtmp |
|
882 | env['HOME'] = self._testtmp | |
882 | # This number should match portneeded in _getport |
|
883 | # This number should match portneeded in _getport | |
883 | for port in xrange(3): |
|
884 | for port in xrange(3): | |
884 | # This list should be parallel to _portmap in _getreplacements |
|
885 | # This list should be parallel to _portmap in _getreplacements | |
885 | defineport(port) |
|
886 | defineport(port) | |
886 | env["HGRCPATH"] = os.path.join(self._threadtmp, b'.hgrc') |
|
887 | env["HGRCPATH"] = os.path.join(self._threadtmp, b'.hgrc') | |
887 | env["DAEMON_PIDS"] = os.path.join(self._threadtmp, b'daemon.pids') |
|
888 | env["DAEMON_PIDS"] = os.path.join(self._threadtmp, b'daemon.pids') | |
888 | env["HGEDITOR"] = ('"' + sys.executable + '"' |
|
889 | env["HGEDITOR"] = ('"' + sys.executable + '"' | |
889 | + ' -c "import sys; sys.exit(0)"') |
|
890 | + ' -c "import sys; sys.exit(0)"') | |
890 | env["HGMERGE"] = "internal:merge" |
|
891 | env["HGMERGE"] = "internal:merge" | |
891 | env["HGUSER"] = "test" |
|
892 | env["HGUSER"] = "test" | |
892 | env["HGENCODING"] = "ascii" |
|
893 | env["HGENCODING"] = "ascii" | |
893 | env["HGENCODINGMODE"] = "strict" |
|
894 | env["HGENCODINGMODE"] = "strict" | |
894 | env['HGIPV6'] = str(int(self._useipv6)) |
|
895 | env['HGIPV6'] = str(int(self._useipv6)) | |
895 |
|
896 | |||
896 | # LOCALIP could be ::1 or 127.0.0.1. Useful for tests that require raw |
|
897 | # LOCALIP could be ::1 or 127.0.0.1. Useful for tests that require raw | |
897 | # IP addresses. |
|
898 | # IP addresses. | |
898 | env['LOCALIP'] = self._localip() |
|
899 | env['LOCALIP'] = self._localip() | |
899 |
|
900 | |||
900 | # Reset some environment variables to well-known values so that |
|
901 | # Reset some environment variables to well-known values so that | |
901 | # the tests produce repeatable output. |
|
902 | # the tests produce repeatable output. | |
902 | env['LANG'] = env['LC_ALL'] = env['LANGUAGE'] = 'C' |
|
903 | env['LANG'] = env['LC_ALL'] = env['LANGUAGE'] = 'C' | |
903 | env['TZ'] = 'GMT' |
|
904 | env['TZ'] = 'GMT' | |
904 | env["EMAIL"] = "Foo Bar <foo.bar@example.com>" |
|
905 | env["EMAIL"] = "Foo Bar <foo.bar@example.com>" | |
905 | env['COLUMNS'] = '80' |
|
906 | env['COLUMNS'] = '80' | |
906 | env['TERM'] = 'xterm' |
|
907 | env['TERM'] = 'xterm' | |
907 |
|
908 | |||
908 | for k in ('HG HGPROF CDPATH GREP_OPTIONS http_proxy no_proxy ' + |
|
909 | for k in ('HG HGPROF CDPATH GREP_OPTIONS http_proxy no_proxy ' + | |
909 | 'HGPLAIN HGPLAINEXCEPT EDITOR VISUAL PAGER ' + |
|
910 | 'HGPLAIN HGPLAINEXCEPT EDITOR VISUAL PAGER ' + | |
910 | 'NO_PROXY CHGDEBUG').split(): |
|
911 | 'NO_PROXY CHGDEBUG').split(): | |
911 | if k in env: |
|
912 | if k in env: | |
912 | del env[k] |
|
913 | del env[k] | |
913 |
|
914 | |||
914 | # unset env related to hooks |
|
915 | # unset env related to hooks | |
915 | for k in env.keys(): |
|
916 | for k in env.keys(): | |
916 | if k.startswith('HG_'): |
|
917 | if k.startswith('HG_'): | |
917 | del env[k] |
|
918 | del env[k] | |
918 |
|
919 | |||
919 | if self._usechg: |
|
920 | if self._usechg: | |
920 | env['CHGSOCKNAME'] = os.path.join(self._chgsockdir, b'server') |
|
921 | env['CHGSOCKNAME'] = os.path.join(self._chgsockdir, b'server') | |
921 |
|
922 | |||
922 | return env |
|
923 | return env | |
923 |
|
924 | |||
924 | def _createhgrc(self, path): |
|
925 | def _createhgrc(self, path): | |
925 | """Create an hgrc file for this test.""" |
|
926 | """Create an hgrc file for this test.""" | |
926 | hgrc = open(path, 'wb') |
|
927 | hgrc = open(path, 'wb') | |
927 | hgrc.write(b'[ui]\n') |
|
928 | hgrc.write(b'[ui]\n') | |
928 | hgrc.write(b'slash = True\n') |
|
929 | hgrc.write(b'slash = True\n') | |
929 | hgrc.write(b'interactive = False\n') |
|
930 | hgrc.write(b'interactive = False\n') | |
930 | hgrc.write(b'mergemarkers = detailed\n') |
|
931 | hgrc.write(b'mergemarkers = detailed\n') | |
931 | hgrc.write(b'promptecho = True\n') |
|
932 | hgrc.write(b'promptecho = True\n') | |
932 | hgrc.write(b'[defaults]\n') |
|
933 | hgrc.write(b'[defaults]\n') | |
933 | hgrc.write(b'backout = -d "0 0"\n') |
|
934 | hgrc.write(b'backout = -d "0 0"\n') | |
934 | hgrc.write(b'commit = -d "0 0"\n') |
|
935 | hgrc.write(b'commit = -d "0 0"\n') | |
935 | hgrc.write(b'shelve = --date "0 0"\n') |
|
936 | hgrc.write(b'shelve = --date "0 0"\n') | |
936 | hgrc.write(b'tag = -d "0 0"\n') |
|
937 | hgrc.write(b'tag = -d "0 0"\n') | |
937 | hgrc.write(b'[devel]\n') |
|
938 | hgrc.write(b'[devel]\n') | |
938 | hgrc.write(b'all-warnings = true\n') |
|
939 | hgrc.write(b'all-warnings = true\n') | |
939 | hgrc.write(b'[largefiles]\n') |
|
940 | hgrc.write(b'[largefiles]\n') | |
940 | hgrc.write(b'usercache = %s\n' % |
|
941 | hgrc.write(b'usercache = %s\n' % | |
941 | (os.path.join(self._testtmp, b'.cache/largefiles'))) |
|
942 | (os.path.join(self._testtmp, b'.cache/largefiles'))) | |
942 | hgrc.write(b'[web]\n') |
|
943 | hgrc.write(b'[web]\n') | |
943 | hgrc.write(b'address = localhost\n') |
|
944 | hgrc.write(b'address = localhost\n') | |
944 | hgrc.write(b'ipv6 = %s\n' % str(self._useipv6).encode('ascii')) |
|
945 | hgrc.write(b'ipv6 = %s\n' % str(self._useipv6).encode('ascii')) | |
945 |
|
946 | |||
946 | for opt in self._extraconfigopts: |
|
947 | for opt in self._extraconfigopts: | |
947 | section, key = opt.split('.', 1) |
|
948 | section, key = opt.split('.', 1) | |
948 | assert '=' in key, ('extra config opt %s must ' |
|
949 | assert '=' in key, ('extra config opt %s must ' | |
949 | 'have an = for assignment' % opt) |
|
950 | 'have an = for assignment' % opt) | |
950 | hgrc.write(b'[%s]\n%s\n' % (section, key)) |
|
951 | hgrc.write(b'[%s]\n%s\n' % (section, key)) | |
951 | hgrc.close() |
|
952 | hgrc.close() | |
952 |
|
953 | |||
953 | def fail(self, msg): |
|
954 | def fail(self, msg): | |
954 | # unittest differentiates between errored and failed. |
|
955 | # unittest differentiates between errored and failed. | |
955 | # Failed is denoted by AssertionError (by default at least). |
|
956 | # Failed is denoted by AssertionError (by default at least). | |
956 | raise AssertionError(msg) |
|
957 | raise AssertionError(msg) | |
957 |
|
958 | |||
958 | def _runcommand(self, cmd, env, normalizenewlines=False): |
|
959 | def _runcommand(self, cmd, env, normalizenewlines=False): | |
959 | """Run command in a sub-process, capturing the output (stdout and |
|
960 | """Run command in a sub-process, capturing the output (stdout and | |
960 | stderr). |
|
961 | stderr). | |
961 |
|
962 | |||
962 | Return a tuple (exitcode, output). output is None in debug mode. |
|
963 | Return a tuple (exitcode, output). output is None in debug mode. | |
963 | """ |
|
964 | """ | |
964 | if self._debug: |
|
965 | if self._debug: | |
965 | proc = subprocess.Popen(cmd, shell=True, cwd=self._testtmp, |
|
966 | proc = subprocess.Popen(cmd, shell=True, cwd=self._testtmp, | |
966 | env=env) |
|
967 | env=env) | |
967 | ret = proc.wait() |
|
968 | ret = proc.wait() | |
968 | return (ret, None) |
|
969 | return (ret, None) | |
969 |
|
970 | |||
970 | proc = Popen4(cmd, self._testtmp, self._timeout, env) |
|
971 | proc = Popen4(cmd, self._testtmp, self._timeout, env) | |
971 | def cleanup(): |
|
972 | def cleanup(): | |
972 | terminate(proc) |
|
973 | terminate(proc) | |
973 | ret = proc.wait() |
|
974 | ret = proc.wait() | |
974 | if ret == 0: |
|
975 | if ret == 0: | |
975 | ret = signal.SIGTERM << 8 |
|
976 | ret = signal.SIGTERM << 8 | |
976 | killdaemons(env['DAEMON_PIDS']) |
|
977 | killdaemons(env['DAEMON_PIDS']) | |
977 | return ret |
|
978 | return ret | |
978 |
|
979 | |||
979 | output = '' |
|
980 | output = '' | |
980 | proc.tochild.close() |
|
981 | proc.tochild.close() | |
981 |
|
982 | |||
982 | try: |
|
983 | try: | |
983 | output = proc.fromchild.read() |
|
984 | output = proc.fromchild.read() | |
984 | except KeyboardInterrupt: |
|
985 | except KeyboardInterrupt: | |
985 | vlog('# Handling keyboard interrupt') |
|
986 | vlog('# Handling keyboard interrupt') | |
986 | cleanup() |
|
987 | cleanup() | |
987 | raise |
|
988 | raise | |
988 |
|
989 | |||
989 | ret = proc.wait() |
|
990 | ret = proc.wait() | |
990 | if wifexited(ret): |
|
991 | if wifexited(ret): | |
991 | ret = os.WEXITSTATUS(ret) |
|
992 | ret = os.WEXITSTATUS(ret) | |
992 |
|
993 | |||
993 | if proc.timeout: |
|
994 | if proc.timeout: | |
994 | ret = 'timeout' |
|
995 | ret = 'timeout' | |
995 |
|
996 | |||
996 | if ret: |
|
997 | if ret: | |
997 | killdaemons(env['DAEMON_PIDS']) |
|
998 | killdaemons(env['DAEMON_PIDS']) | |
998 |
|
999 | |||
999 | for s, r in self._getreplacements(): |
|
1000 | for s, r in self._getreplacements(): | |
1000 | output = re.sub(s, r, output) |
|
1001 | output = re.sub(s, r, output) | |
1001 |
|
1002 | |||
1002 | if normalizenewlines: |
|
1003 | if normalizenewlines: | |
1003 | output = output.replace('\r\n', '\n') |
|
1004 | output = output.replace('\r\n', '\n') | |
1004 |
|
1005 | |||
1005 | return ret, output.splitlines(True) |
|
1006 | return ret, output.splitlines(True) | |
1006 |
|
1007 | |||
1007 | class PythonTest(Test): |
|
1008 | class PythonTest(Test): | |
1008 | """A Python-based test.""" |
|
1009 | """A Python-based test.""" | |
1009 |
|
1010 | |||
1010 | @property |
|
1011 | @property | |
1011 | def refpath(self): |
|
1012 | def refpath(self): | |
1012 | return os.path.join(self._testdir, b'%s.out' % self.bname) |
|
1013 | return os.path.join(self._testdir, b'%s.out' % self.bname) | |
1013 |
|
1014 | |||
1014 | def _run(self, env): |
|
1015 | def _run(self, env): | |
1015 | py3kswitch = self._py3kwarnings and b' -3' or b'' |
|
1016 | py3kswitch = self._py3kwarnings and b' -3' or b'' | |
1016 | cmd = b'%s%s "%s"' % (PYTHON, py3kswitch, self.path) |
|
1017 | cmd = b'%s%s "%s"' % (PYTHON, py3kswitch, self.path) | |
1017 | vlog("# Running", cmd) |
|
1018 | vlog("# Running", cmd) | |
1018 | normalizenewlines = os.name == 'nt' |
|
1019 | normalizenewlines = os.name == 'nt' | |
1019 | result = self._runcommand(cmd, env, |
|
1020 | result = self._runcommand(cmd, env, | |
1020 | normalizenewlines=normalizenewlines) |
|
1021 | normalizenewlines=normalizenewlines) | |
1021 | if self._aborted: |
|
1022 | if self._aborted: | |
1022 | raise KeyboardInterrupt() |
|
1023 | raise KeyboardInterrupt() | |
1023 |
|
1024 | |||
1024 | return result |
|
1025 | return result | |
1025 |
|
1026 | |||
1026 | # Some glob patterns apply only in some circumstances, so the script |
|
1027 | # Some glob patterns apply only in some circumstances, so the script | |
1027 | # might want to remove (glob) annotations that otherwise should be |
|
1028 | # might want to remove (glob) annotations that otherwise should be | |
1028 | # retained. |
|
1029 | # retained. | |
1029 | checkcodeglobpats = [ |
|
1030 | checkcodeglobpats = [ | |
1030 | # On Windows it looks like \ doesn't require a (glob), but we know |
|
1031 | # On Windows it looks like \ doesn't require a (glob), but we know | |
1031 | # better. |
|
1032 | # better. | |
1032 | re.compile(br'^pushing to \$TESTTMP/.*[^)]$'), |
|
1033 | re.compile(br'^pushing to \$TESTTMP/.*[^)]$'), | |
1033 | re.compile(br'^moving \S+/.*[^)]$'), |
|
1034 | re.compile(br'^moving \S+/.*[^)]$'), | |
1034 | re.compile(br'^pulling from \$TESTTMP/.*[^)]$'), |
|
1035 | re.compile(br'^pulling from \$TESTTMP/.*[^)]$'), | |
1035 | # Not all platforms have 127.0.0.1 as loopback (though most do), |
|
1036 | # Not all platforms have 127.0.0.1 as loopback (though most do), | |
1036 | # so we always glob that too. |
|
1037 | # so we always glob that too. | |
1037 | re.compile(br'.*\$LOCALIP.*$'), |
|
1038 | re.compile(br'.*\$LOCALIP.*$'), | |
1038 | ] |
|
1039 | ] | |
1039 |
|
1040 | |||
1040 | bchr = chr |
|
1041 | bchr = chr | |
1041 | if PYTHON3: |
|
1042 | if PYTHON3: | |
1042 | bchr = lambda x: bytes([x]) |
|
1043 | bchr = lambda x: bytes([x]) | |
1043 |
|
1044 | |||
1044 | class TTest(Test): |
|
1045 | class TTest(Test): | |
1045 | """A "t test" is a test backed by a .t file.""" |
|
1046 | """A "t test" is a test backed by a .t file.""" | |
1046 |
|
1047 | |||
1047 | SKIPPED_PREFIX = b'skipped: ' |
|
1048 | SKIPPED_PREFIX = b'skipped: ' | |
1048 | FAILED_PREFIX = b'hghave check failed: ' |
|
1049 | FAILED_PREFIX = b'hghave check failed: ' | |
1049 | NEEDESCAPE = re.compile(br'[\x00-\x08\x0b-\x1f\x7f-\xff]').search |
|
1050 | NEEDESCAPE = re.compile(br'[\x00-\x08\x0b-\x1f\x7f-\xff]').search | |
1050 |
|
1051 | |||
1051 | ESCAPESUB = re.compile(br'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub |
|
1052 | ESCAPESUB = re.compile(br'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub | |
1052 | ESCAPEMAP = dict((bchr(i), br'\x%02x' % i) for i in range(256)) |
|
1053 | ESCAPEMAP = dict((bchr(i), br'\x%02x' % i) for i in range(256)) | |
1053 | ESCAPEMAP.update({b'\\': b'\\\\', b'\r': br'\r'}) |
|
1054 | ESCAPEMAP.update({b'\\': b'\\\\', b'\r': br'\r'}) | |
1054 |
|
1055 | |||
1055 | @property |
|
1056 | @property | |
1056 | def refpath(self): |
|
1057 | def refpath(self): | |
1057 | return os.path.join(self._testdir, self.bname) |
|
1058 | return os.path.join(self._testdir, self.bname) | |
1058 |
|
1059 | |||
1059 | def _run(self, env): |
|
1060 | def _run(self, env): | |
1060 | f = open(self.path, 'rb') |
|
1061 | f = open(self.path, 'rb') | |
1061 | lines = f.readlines() |
|
1062 | lines = f.readlines() | |
1062 | f.close() |
|
1063 | f.close() | |
1063 |
|
1064 | |||
1064 | salt, script, after, expected = self._parsetest(lines) |
|
1065 | salt, script, after, expected = self._parsetest(lines) | |
1065 |
|
1066 | |||
1066 | # Write out the generated script. |
|
1067 | # Write out the generated script. | |
1067 | fname = b'%s.sh' % self._testtmp |
|
1068 | fname = b'%s.sh' % self._testtmp | |
1068 | f = open(fname, 'wb') |
|
1069 | f = open(fname, 'wb') | |
1069 | for l in script: |
|
1070 | for l in script: | |
1070 | f.write(l) |
|
1071 | f.write(l) | |
1071 | f.close() |
|
1072 | f.close() | |
1072 |
|
1073 | |||
1073 | cmd = b'%s "%s"' % (self._shell, fname) |
|
1074 | cmd = b'%s "%s"' % (self._shell, fname) | |
1074 | vlog("# Running", cmd) |
|
1075 | vlog("# Running", cmd) | |
1075 |
|
1076 | |||
1076 | exitcode, output = self._runcommand(cmd, env) |
|
1077 | exitcode, output = self._runcommand(cmd, env) | |
1077 |
|
1078 | |||
1078 | if self._aborted: |
|
1079 | if self._aborted: | |
1079 | raise KeyboardInterrupt() |
|
1080 | raise KeyboardInterrupt() | |
1080 |
|
1081 | |||
1081 | # Do not merge output if skipped. Return hghave message instead. |
|
1082 | # Do not merge output if skipped. Return hghave message instead. | |
1082 | # Similarly, with --debug, output is None. |
|
1083 | # Similarly, with --debug, output is None. | |
1083 | if exitcode == self.SKIPPED_STATUS or output is None: |
|
1084 | if exitcode == self.SKIPPED_STATUS or output is None: | |
1084 | return exitcode, output |
|
1085 | return exitcode, output | |
1085 |
|
1086 | |||
1086 | return self._processoutput(exitcode, output, salt, after, expected) |
|
1087 | return self._processoutput(exitcode, output, salt, after, expected) | |
1087 |
|
1088 | |||
1088 | def _hghave(self, reqs): |
|
1089 | def _hghave(self, reqs): | |
1089 | # TODO do something smarter when all other uses of hghave are gone. |
|
1090 | # TODO do something smarter when all other uses of hghave are gone. | |
1090 | runtestdir = os.path.abspath(os.path.dirname(_bytespath(__file__))) |
|
1091 | runtestdir = os.path.abspath(os.path.dirname(_bytespath(__file__))) | |
1091 | tdir = runtestdir.replace(b'\\', b'/') |
|
1092 | tdir = runtestdir.replace(b'\\', b'/') | |
1092 | proc = Popen4(b'%s -c "%s/hghave %s"' % |
|
1093 | proc = Popen4(b'%s -c "%s/hghave %s"' % | |
1093 | (self._shell, tdir, b' '.join(reqs)), |
|
1094 | (self._shell, tdir, b' '.join(reqs)), | |
1094 | self._testtmp, 0, self._getenv()) |
|
1095 | self._testtmp, 0, self._getenv()) | |
1095 | stdout, stderr = proc.communicate() |
|
1096 | stdout, stderr = proc.communicate() | |
1096 | ret = proc.wait() |
|
1097 | ret = proc.wait() | |
1097 | if wifexited(ret): |
|
1098 | if wifexited(ret): | |
1098 | ret = os.WEXITSTATUS(ret) |
|
1099 | ret = os.WEXITSTATUS(ret) | |
1099 | if ret == 2: |
|
1100 | if ret == 2: | |
1100 | print(stdout.decode('utf-8')) |
|
1101 | print(stdout.decode('utf-8')) | |
1101 | sys.exit(1) |
|
1102 | sys.exit(1) | |
1102 |
|
1103 | |||
1103 | if ret != 0: |
|
1104 | if ret != 0: | |
1104 | return False, stdout |
|
1105 | return False, stdout | |
1105 |
|
1106 | |||
1106 | if 'slow' in reqs: |
|
1107 | if 'slow' in reqs: | |
1107 | self._timeout = self._slowtimeout |
|
1108 | self._timeout = self._slowtimeout | |
1108 | return True, None |
|
1109 | return True, None | |
1109 |
|
1110 | |||
1110 | def _parsetest(self, lines): |
|
1111 | def _parsetest(self, lines): | |
1111 | # We generate a shell script which outputs unique markers to line |
|
1112 | # We generate a shell script which outputs unique markers to line | |
1112 | # up script results with our source. These markers include input |
|
1113 | # up script results with our source. These markers include input | |
1113 | # line number and the last return code. |
|
1114 | # line number and the last return code. | |
1114 | salt = b"SALT%d" % time.time() |
|
1115 | salt = b"SALT%d" % time.time() | |
1115 | def addsalt(line, inpython): |
|
1116 | def addsalt(line, inpython): | |
1116 | if inpython: |
|
1117 | if inpython: | |
1117 | script.append(b'%s %d 0\n' % (salt, line)) |
|
1118 | script.append(b'%s %d 0\n' % (salt, line)) | |
1118 | else: |
|
1119 | else: | |
1119 | script.append(b'echo %s %d $?\n' % (salt, line)) |
|
1120 | script.append(b'echo %s %d $?\n' % (salt, line)) | |
1120 |
|
1121 | |||
1121 | script = [] |
|
1122 | script = [] | |
1122 |
|
1123 | |||
1123 | # After we run the shell script, we re-unify the script output |
|
1124 | # After we run the shell script, we re-unify the script output | |
1124 | # with non-active parts of the source, with synchronization by our |
|
1125 | # with non-active parts of the source, with synchronization by our | |
1125 | # SALT line number markers. The after table contains the non-active |
|
1126 | # SALT line number markers. The after table contains the non-active | |
1126 | # components, ordered by line number. |
|
1127 | # components, ordered by line number. | |
1127 | after = {} |
|
1128 | after = {} | |
1128 |
|
1129 | |||
1129 | # Expected shell script output. |
|
1130 | # Expected shell script output. | |
1130 | expected = {} |
|
1131 | expected = {} | |
1131 |
|
1132 | |||
1132 | pos = prepos = -1 |
|
1133 | pos = prepos = -1 | |
1133 |
|
1134 | |||
1134 | # True or False when in a true or false conditional section |
|
1135 | # True or False when in a true or false conditional section | |
1135 | skipping = None |
|
1136 | skipping = None | |
1136 |
|
1137 | |||
1137 | # We keep track of whether or not we're in a Python block so we |
|
1138 | # We keep track of whether or not we're in a Python block so we | |
1138 | # can generate the surrounding doctest magic. |
|
1139 | # can generate the surrounding doctest magic. | |
1139 | inpython = False |
|
1140 | inpython = False | |
1140 |
|
1141 | |||
1141 | if self._debug: |
|
1142 | if self._debug: | |
1142 | script.append(b'set -x\n') |
|
1143 | script.append(b'set -x\n') | |
1143 | if self._hgcommand != b'hg': |
|
1144 | if self._hgcommand != b'hg': | |
1144 | script.append(b'alias hg="%s"\n' % self._hgcommand) |
|
1145 | script.append(b'alias hg="%s"\n' % self._hgcommand) | |
1145 | if os.getenv('MSYSTEM'): |
|
1146 | if os.getenv('MSYSTEM'): | |
1146 | script.append(b'alias pwd="pwd -W"\n') |
|
1147 | script.append(b'alias pwd="pwd -W"\n') | |
1147 |
|
1148 | |||
1148 | n = 0 |
|
1149 | n = 0 | |
1149 | for n, l in enumerate(lines): |
|
1150 | for n, l in enumerate(lines): | |
1150 | if not l.endswith(b'\n'): |
|
1151 | if not l.endswith(b'\n'): | |
1151 | l += b'\n' |
|
1152 | l += b'\n' | |
1152 | if l.startswith(b'#require'): |
|
1153 | if l.startswith(b'#require'): | |
1153 | lsplit = l.split() |
|
1154 | lsplit = l.split() | |
1154 | if len(lsplit) < 2 or lsplit[0] != b'#require': |
|
1155 | if len(lsplit) < 2 or lsplit[0] != b'#require': | |
1155 | after.setdefault(pos, []).append(' !!! invalid #require\n') |
|
1156 | after.setdefault(pos, []).append(' !!! invalid #require\n') | |
1156 | haveresult, message = self._hghave(lsplit[1:]) |
|
1157 | haveresult, message = self._hghave(lsplit[1:]) | |
1157 | if not haveresult: |
|
1158 | if not haveresult: | |
1158 | script = [b'echo "%s"\nexit 80\n' % message] |
|
1159 | script = [b'echo "%s"\nexit 80\n' % message] | |
1159 | break |
|
1160 | break | |
1160 | after.setdefault(pos, []).append(l) |
|
1161 | after.setdefault(pos, []).append(l) | |
1161 | elif l.startswith(b'#if'): |
|
1162 | elif l.startswith(b'#if'): | |
1162 | lsplit = l.split() |
|
1163 | lsplit = l.split() | |
1163 | if len(lsplit) < 2 or lsplit[0] != b'#if': |
|
1164 | if len(lsplit) < 2 or lsplit[0] != b'#if': | |
1164 | after.setdefault(pos, []).append(' !!! invalid #if\n') |
|
1165 | after.setdefault(pos, []).append(' !!! invalid #if\n') | |
1165 | if skipping is not None: |
|
1166 | if skipping is not None: | |
1166 | after.setdefault(pos, []).append(' !!! nested #if\n') |
|
1167 | after.setdefault(pos, []).append(' !!! nested #if\n') | |
1167 | skipping = not self._hghave(lsplit[1:])[0] |
|
1168 | skipping = not self._hghave(lsplit[1:])[0] | |
1168 | after.setdefault(pos, []).append(l) |
|
1169 | after.setdefault(pos, []).append(l) | |
1169 | elif l.startswith(b'#else'): |
|
1170 | elif l.startswith(b'#else'): | |
1170 | if skipping is None: |
|
1171 | if skipping is None: | |
1171 | after.setdefault(pos, []).append(' !!! missing #if\n') |
|
1172 | after.setdefault(pos, []).append(' !!! missing #if\n') | |
1172 | skipping = not skipping |
|
1173 | skipping = not skipping | |
1173 | after.setdefault(pos, []).append(l) |
|
1174 | after.setdefault(pos, []).append(l) | |
1174 | elif l.startswith(b'#endif'): |
|
1175 | elif l.startswith(b'#endif'): | |
1175 | if skipping is None: |
|
1176 | if skipping is None: | |
1176 | after.setdefault(pos, []).append(' !!! missing #if\n') |
|
1177 | after.setdefault(pos, []).append(' !!! missing #if\n') | |
1177 | skipping = None |
|
1178 | skipping = None | |
1178 | after.setdefault(pos, []).append(l) |
|
1179 | after.setdefault(pos, []).append(l) | |
1179 | elif skipping: |
|
1180 | elif skipping: | |
1180 | after.setdefault(pos, []).append(l) |
|
1181 | after.setdefault(pos, []).append(l) | |
1181 | elif l.startswith(b' >>> '): # python inlines |
|
1182 | elif l.startswith(b' >>> '): # python inlines | |
1182 | after.setdefault(pos, []).append(l) |
|
1183 | after.setdefault(pos, []).append(l) | |
1183 | prepos = pos |
|
1184 | prepos = pos | |
1184 | pos = n |
|
1185 | pos = n | |
1185 | if not inpython: |
|
1186 | if not inpython: | |
1186 | # We've just entered a Python block. Add the header. |
|
1187 | # We've just entered a Python block. Add the header. | |
1187 | inpython = True |
|
1188 | inpython = True | |
1188 | addsalt(prepos, False) # Make sure we report the exit code. |
|
1189 | addsalt(prepos, False) # Make sure we report the exit code. | |
1189 | script.append(b'%s -m heredoctest <<EOF\n' % PYTHON) |
|
1190 | script.append(b'%s -m heredoctest <<EOF\n' % PYTHON) | |
1190 | addsalt(n, True) |
|
1191 | addsalt(n, True) | |
1191 | script.append(l[2:]) |
|
1192 | script.append(l[2:]) | |
1192 | elif l.startswith(b' ... '): # python inlines |
|
1193 | elif l.startswith(b' ... '): # python inlines | |
1193 | after.setdefault(prepos, []).append(l) |
|
1194 | after.setdefault(prepos, []).append(l) | |
1194 | script.append(l[2:]) |
|
1195 | script.append(l[2:]) | |
1195 | elif l.startswith(b' $ '): # commands |
|
1196 | elif l.startswith(b' $ '): # commands | |
1196 | if inpython: |
|
1197 | if inpython: | |
1197 | script.append(b'EOF\n') |
|
1198 | script.append(b'EOF\n') | |
1198 | inpython = False |
|
1199 | inpython = False | |
1199 | after.setdefault(pos, []).append(l) |
|
1200 | after.setdefault(pos, []).append(l) | |
1200 | prepos = pos |
|
1201 | prepos = pos | |
1201 | pos = n |
|
1202 | pos = n | |
1202 | addsalt(n, False) |
|
1203 | addsalt(n, False) | |
1203 | cmd = l[4:].split() |
|
1204 | cmd = l[4:].split() | |
1204 | if len(cmd) == 2 and cmd[0] == b'cd': |
|
1205 | if len(cmd) == 2 and cmd[0] == b'cd': | |
1205 | l = b' $ cd %s || exit 1\n' % cmd[1] |
|
1206 | l = b' $ cd %s || exit 1\n' % cmd[1] | |
1206 | script.append(l[4:]) |
|
1207 | script.append(l[4:]) | |
1207 | elif l.startswith(b' > '): # continuations |
|
1208 | elif l.startswith(b' > '): # continuations | |
1208 | after.setdefault(prepos, []).append(l) |
|
1209 | after.setdefault(prepos, []).append(l) | |
1209 | script.append(l[4:]) |
|
1210 | script.append(l[4:]) | |
1210 | elif l.startswith(b' '): # results |
|
1211 | elif l.startswith(b' '): # results | |
1211 | # Queue up a list of expected results. |
|
1212 | # Queue up a list of expected results. | |
1212 | expected.setdefault(pos, []).append(l[2:]) |
|
1213 | expected.setdefault(pos, []).append(l[2:]) | |
1213 | else: |
|
1214 | else: | |
1214 | if inpython: |
|
1215 | if inpython: | |
1215 | script.append(b'EOF\n') |
|
1216 | script.append(b'EOF\n') | |
1216 | inpython = False |
|
1217 | inpython = False | |
1217 | # Non-command/result. Queue up for merged output. |
|
1218 | # Non-command/result. Queue up for merged output. | |
1218 | after.setdefault(pos, []).append(l) |
|
1219 | after.setdefault(pos, []).append(l) | |
1219 |
|
1220 | |||
1220 | if inpython: |
|
1221 | if inpython: | |
1221 | script.append(b'EOF\n') |
|
1222 | script.append(b'EOF\n') | |
1222 | if skipping is not None: |
|
1223 | if skipping is not None: | |
1223 | after.setdefault(pos, []).append(' !!! missing #endif\n') |
|
1224 | after.setdefault(pos, []).append(' !!! missing #endif\n') | |
1224 | addsalt(n + 1, False) |
|
1225 | addsalt(n + 1, False) | |
1225 |
|
1226 | |||
1226 | return salt, script, after, expected |
|
1227 | return salt, script, after, expected | |
1227 |
|
1228 | |||
1228 | def _processoutput(self, exitcode, output, salt, after, expected): |
|
1229 | def _processoutput(self, exitcode, output, salt, after, expected): | |
1229 | # Merge the script output back into a unified test. |
|
1230 | # Merge the script output back into a unified test. | |
1230 | warnonly = 1 # 1: not yet; 2: yes; 3: for sure not |
|
1231 | warnonly = 1 # 1: not yet; 2: yes; 3: for sure not | |
1231 | if exitcode != 0: |
|
1232 | if exitcode != 0: | |
1232 | warnonly = 3 |
|
1233 | warnonly = 3 | |
1233 |
|
1234 | |||
1234 | pos = -1 |
|
1235 | pos = -1 | |
1235 | postout = [] |
|
1236 | postout = [] | |
1236 | for l in output: |
|
1237 | for l in output: | |
1237 | lout, lcmd = l, None |
|
1238 | lout, lcmd = l, None | |
1238 | if salt in l: |
|
1239 | if salt in l: | |
1239 | lout, lcmd = l.split(salt, 1) |
|
1240 | lout, lcmd = l.split(salt, 1) | |
1240 |
|
1241 | |||
1241 | while lout: |
|
1242 | while lout: | |
1242 | if not lout.endswith(b'\n'): |
|
1243 | if not lout.endswith(b'\n'): | |
1243 | lout += b' (no-eol)\n' |
|
1244 | lout += b' (no-eol)\n' | |
1244 |
|
1245 | |||
1245 | # Find the expected output at the current position. |
|
1246 | # Find the expected output at the current position. | |
1246 | els = [None] |
|
1247 | els = [None] | |
1247 | if expected.get(pos, None): |
|
1248 | if expected.get(pos, None): | |
1248 | els = expected[pos] |
|
1249 | els = expected[pos] | |
1249 |
|
1250 | |||
1250 | i = 0 |
|
1251 | i = 0 | |
1251 | optional = [] |
|
1252 | optional = [] | |
1252 | while i < len(els): |
|
1253 | while i < len(els): | |
1253 | el = els[i] |
|
1254 | el = els[i] | |
1254 |
|
1255 | |||
1255 | r = TTest.linematch(el, lout) |
|
1256 | r = TTest.linematch(el, lout) | |
1256 | if isinstance(r, str): |
|
1257 | if isinstance(r, str): | |
1257 | if r == '+glob': |
|
1258 | if r == '+glob': | |
1258 | lout = el[:-1] + ' (glob)\n' |
|
1259 | lout = el[:-1] + ' (glob)\n' | |
1259 | r = '' # Warn only this line. |
|
1260 | r = '' # Warn only this line. | |
1260 | elif r == '-glob': |
|
1261 | elif r == '-glob': | |
1261 | lout = ''.join(el.rsplit(' (glob)', 1)) |
|
1262 | lout = ''.join(el.rsplit(' (glob)', 1)) | |
1262 | r = '' # Warn only this line. |
|
1263 | r = '' # Warn only this line. | |
1263 | elif r == "retry": |
|
1264 | elif r == "retry": | |
1264 | postout.append(b' ' + el) |
|
1265 | postout.append(b' ' + el) | |
1265 | els.pop(i) |
|
1266 | els.pop(i) | |
1266 | break |
|
1267 | break | |
1267 | else: |
|
1268 | else: | |
1268 | log('\ninfo, unknown linematch result: %r\n' % r) |
|
1269 | log('\ninfo, unknown linematch result: %r\n' % r) | |
1269 | r = False |
|
1270 | r = False | |
1270 | if r: |
|
1271 | if r: | |
1271 | els.pop(i) |
|
1272 | els.pop(i) | |
1272 | break |
|
1273 | break | |
1273 | if el and el.endswith(b" (?)\n"): |
|
1274 | if el and el.endswith(b" (?)\n"): | |
1274 | optional.append(i) |
|
1275 | optional.append(i) | |
1275 | i += 1 |
|
1276 | i += 1 | |
1276 |
|
1277 | |||
1277 | if r: |
|
1278 | if r: | |
1278 | if r == "retry": |
|
1279 | if r == "retry": | |
1279 | continue |
|
1280 | continue | |
1280 | # clean up any optional leftovers |
|
1281 | # clean up any optional leftovers | |
1281 | for i in optional: |
|
1282 | for i in optional: | |
1282 | postout.append(b' ' + els[i]) |
|
1283 | postout.append(b' ' + els[i]) | |
1283 | for i in reversed(optional): |
|
1284 | for i in reversed(optional): | |
1284 | del els[i] |
|
1285 | del els[i] | |
1285 | postout.append(b' ' + el) |
|
1286 | postout.append(b' ' + el) | |
1286 | else: |
|
1287 | else: | |
1287 | if self.NEEDESCAPE(lout): |
|
1288 | if self.NEEDESCAPE(lout): | |
1288 | lout = TTest._stringescape(b'%s (esc)\n' % |
|
1289 | lout = TTest._stringescape(b'%s (esc)\n' % | |
1289 | lout.rstrip(b'\n')) |
|
1290 | lout.rstrip(b'\n')) | |
1290 | postout.append(b' ' + lout) # Let diff deal with it. |
|
1291 | postout.append(b' ' + lout) # Let diff deal with it. | |
1291 | if r != '': # If line failed. |
|
1292 | if r != '': # If line failed. | |
1292 | warnonly = 3 # for sure not |
|
1293 | warnonly = 3 # for sure not | |
1293 | elif warnonly == 1: # Is "not yet" and line is warn only. |
|
1294 | elif warnonly == 1: # Is "not yet" and line is warn only. | |
1294 | warnonly = 2 # Yes do warn. |
|
1295 | warnonly = 2 # Yes do warn. | |
1295 | break |
|
1296 | break | |
1296 | else: |
|
1297 | else: | |
1297 | # clean up any optional leftovers |
|
1298 | # clean up any optional leftovers | |
1298 | while expected.get(pos, None): |
|
1299 | while expected.get(pos, None): | |
1299 | el = expected[pos].pop(0) |
|
1300 | el = expected[pos].pop(0) | |
1300 | if el and not el.endswith(b" (?)\n"): |
|
1301 | if el and not el.endswith(b" (?)\n"): | |
1301 | break |
|
1302 | break | |
1302 | postout.append(b' ' + el) |
|
1303 | postout.append(b' ' + el) | |
1303 |
|
1304 | |||
1304 | if lcmd: |
|
1305 | if lcmd: | |
1305 | # Add on last return code. |
|
1306 | # Add on last return code. | |
1306 | ret = int(lcmd.split()[1]) |
|
1307 | ret = int(lcmd.split()[1]) | |
1307 | if ret != 0: |
|
1308 | if ret != 0: | |
1308 | postout.append(b' [%d]\n' % ret) |
|
1309 | postout.append(b' [%d]\n' % ret) | |
1309 | if pos in after: |
|
1310 | if pos in after: | |
1310 | # Merge in non-active test bits. |
|
1311 | # Merge in non-active test bits. | |
1311 | postout += after.pop(pos) |
|
1312 | postout += after.pop(pos) | |
1312 | pos = int(lcmd.split()[0]) |
|
1313 | pos = int(lcmd.split()[0]) | |
1313 |
|
1314 | |||
1314 | if pos in after: |
|
1315 | if pos in after: | |
1315 | postout += after.pop(pos) |
|
1316 | postout += after.pop(pos) | |
1316 |
|
1317 | |||
1317 | if warnonly == 2: |
|
1318 | if warnonly == 2: | |
1318 | exitcode = False # Set exitcode to warned. |
|
1319 | exitcode = False # Set exitcode to warned. | |
1319 |
|
1320 | |||
1320 | return exitcode, postout |
|
1321 | return exitcode, postout | |
1321 |
|
1322 | |||
1322 | @staticmethod |
|
1323 | @staticmethod | |
1323 | def rematch(el, l): |
|
1324 | def rematch(el, l): | |
1324 | try: |
|
1325 | try: | |
1325 | # use \Z to ensure that the regex matches to the end of the string |
|
1326 | # use \Z to ensure that the regex matches to the end of the string | |
1326 | if os.name == 'nt': |
|
1327 | if os.name == 'nt': | |
1327 | return re.match(el + br'\r?\n\Z', l) |
|
1328 | return re.match(el + br'\r?\n\Z', l) | |
1328 | return re.match(el + br'\n\Z', l) |
|
1329 | return re.match(el + br'\n\Z', l) | |
1329 | except re.error: |
|
1330 | except re.error: | |
1330 | # el is an invalid regex |
|
1331 | # el is an invalid regex | |
1331 | return False |
|
1332 | return False | |
1332 |
|
1333 | |||
1333 | @staticmethod |
|
1334 | @staticmethod | |
1334 | def globmatch(el, l): |
|
1335 | def globmatch(el, l): | |
1335 | # The only supported special characters are * and ? plus / which also |
|
1336 | # The only supported special characters are * and ? plus / which also | |
1336 | # matches \ on windows. Escaping of these characters is supported. |
|
1337 | # matches \ on windows. Escaping of these characters is supported. | |
1337 | if el + b'\n' == l: |
|
1338 | if el + b'\n' == l: | |
1338 | if os.altsep: |
|
1339 | if os.altsep: | |
1339 | # matching on "/" is not needed for this line |
|
1340 | # matching on "/" is not needed for this line | |
1340 | for pat in checkcodeglobpats: |
|
1341 | for pat in checkcodeglobpats: | |
1341 | if pat.match(el): |
|
1342 | if pat.match(el): | |
1342 | return True |
|
1343 | return True | |
1343 | return b'-glob' |
|
1344 | return b'-glob' | |
1344 | return True |
|
1345 | return True | |
1345 | el = el.replace(b'$LOCALIP', b'*') |
|
1346 | el = el.replace(b'$LOCALIP', b'*') | |
1346 | i, n = 0, len(el) |
|
1347 | i, n = 0, len(el) | |
1347 | res = b'' |
|
1348 | res = b'' | |
1348 | while i < n: |
|
1349 | while i < n: | |
1349 | c = el[i:i + 1] |
|
1350 | c = el[i:i + 1] | |
1350 | i += 1 |
|
1351 | i += 1 | |
1351 | if c == b'\\' and i < n and el[i:i + 1] in b'*?\\/': |
|
1352 | if c == b'\\' and i < n and el[i:i + 1] in b'*?\\/': | |
1352 | res += el[i - 1:i + 1] |
|
1353 | res += el[i - 1:i + 1] | |
1353 | i += 1 |
|
1354 | i += 1 | |
1354 | elif c == b'*': |
|
1355 | elif c == b'*': | |
1355 | res += b'.*' |
|
1356 | res += b'.*' | |
1356 | elif c == b'?': |
|
1357 | elif c == b'?': | |
1357 | res += b'.' |
|
1358 | res += b'.' | |
1358 | elif c == b'/' and os.altsep: |
|
1359 | elif c == b'/' and os.altsep: | |
1359 | res += b'[/\\\\]' |
|
1360 | res += b'[/\\\\]' | |
1360 | else: |
|
1361 | else: | |
1361 | res += re.escape(c) |
|
1362 | res += re.escape(c) | |
1362 | return TTest.rematch(res, l) |
|
1363 | return TTest.rematch(res, l) | |
1363 |
|
1364 | |||
1364 | @staticmethod |
|
1365 | @staticmethod | |
1365 | def linematch(el, l): |
|
1366 | def linematch(el, l): | |
1366 | retry = False |
|
1367 | retry = False | |
1367 | if el == l: # perfect match (fast) |
|
1368 | if el == l: # perfect match (fast) | |
1368 | return True |
|
1369 | return True | |
1369 | if el: |
|
1370 | if el: | |
1370 | if el.endswith(b" (?)\n"): |
|
1371 | if el.endswith(b" (?)\n"): | |
1371 | retry = "retry" |
|
1372 | retry = "retry" | |
1372 | el = el[:-5] + b"\n" |
|
1373 | el = el[:-5] + b"\n" | |
1373 | if el.endswith(b" (esc)\n"): |
|
1374 | if el.endswith(b" (esc)\n"): | |
1374 | if PYTHON3: |
|
1375 | if PYTHON3: | |
1375 | el = el[:-7].decode('unicode_escape') + '\n' |
|
1376 | el = el[:-7].decode('unicode_escape') + '\n' | |
1376 | el = el.encode('utf-8') |
|
1377 | el = el.encode('utf-8') | |
1377 | else: |
|
1378 | else: | |
1378 | el = el[:-7].decode('string-escape') + '\n' |
|
1379 | el = el[:-7].decode('string-escape') + '\n' | |
1379 | if el == l or os.name == 'nt' and el[:-1] + b'\r\n' == l: |
|
1380 | if el == l or os.name == 'nt' and el[:-1] + b'\r\n' == l: | |
1380 | return True |
|
1381 | return True | |
1381 | if el.endswith(b" (re)\n"): |
|
1382 | if el.endswith(b" (re)\n"): | |
1382 | return TTest.rematch(el[:-6], l) or retry |
|
1383 | return TTest.rematch(el[:-6], l) or retry | |
1383 | if el.endswith(b" (glob)\n"): |
|
1384 | if el.endswith(b" (glob)\n"): | |
1384 | # ignore '(glob)' added to l by 'replacements' |
|
1385 | # ignore '(glob)' added to l by 'replacements' | |
1385 | if l.endswith(b" (glob)\n"): |
|
1386 | if l.endswith(b" (glob)\n"): | |
1386 | l = l[:-8] + b"\n" |
|
1387 | l = l[:-8] + b"\n" | |
1387 | return TTest.globmatch(el[:-8], l) |
|
1388 | return TTest.globmatch(el[:-8], l) | |
1388 | if os.altsep and l.replace(b'\\', b'/') == el: |
|
1389 | if os.altsep and l.replace(b'\\', b'/') == el: | |
1389 | return b'+glob' |
|
1390 | return b'+glob' | |
1390 | return retry |
|
1391 | return retry | |
1391 |
|
1392 | |||
1392 | @staticmethod |
|
1393 | @staticmethod | |
1393 | def parsehghaveoutput(lines): |
|
1394 | def parsehghaveoutput(lines): | |
1394 | '''Parse hghave log lines. |
|
1395 | '''Parse hghave log lines. | |
1395 |
|
1396 | |||
1396 | Return tuple of lists (missing, failed): |
|
1397 | Return tuple of lists (missing, failed): | |
1397 | * the missing/unknown features |
|
1398 | * the missing/unknown features | |
1398 | * the features for which existence check failed''' |
|
1399 | * the features for which existence check failed''' | |
1399 | missing = [] |
|
1400 | missing = [] | |
1400 | failed = [] |
|
1401 | failed = [] | |
1401 | for line in lines: |
|
1402 | for line in lines: | |
1402 | if line.startswith(TTest.SKIPPED_PREFIX): |
|
1403 | if line.startswith(TTest.SKIPPED_PREFIX): | |
1403 | line = line.splitlines()[0] |
|
1404 | line = line.splitlines()[0] | |
1404 | missing.append(line[len(TTest.SKIPPED_PREFIX):].decode('utf-8')) |
|
1405 | missing.append(line[len(TTest.SKIPPED_PREFIX):].decode('utf-8')) | |
1405 | elif line.startswith(TTest.FAILED_PREFIX): |
|
1406 | elif line.startswith(TTest.FAILED_PREFIX): | |
1406 | line = line.splitlines()[0] |
|
1407 | line = line.splitlines()[0] | |
1407 | failed.append(line[len(TTest.FAILED_PREFIX):].decode('utf-8')) |
|
1408 | failed.append(line[len(TTest.FAILED_PREFIX):].decode('utf-8')) | |
1408 |
|
1409 | |||
1409 | return missing, failed |
|
1410 | return missing, failed | |
1410 |
|
1411 | |||
1411 | @staticmethod |
|
1412 | @staticmethod | |
1412 | def _escapef(m): |
|
1413 | def _escapef(m): | |
1413 | return TTest.ESCAPEMAP[m.group(0)] |
|
1414 | return TTest.ESCAPEMAP[m.group(0)] | |
1414 |
|
1415 | |||
1415 | @staticmethod |
|
1416 | @staticmethod | |
1416 | def _stringescape(s): |
|
1417 | def _stringescape(s): | |
1417 | return TTest.ESCAPESUB(TTest._escapef, s) |
|
1418 | return TTest.ESCAPESUB(TTest._escapef, s) | |
1418 |
|
1419 | |||
1419 | iolock = threading.RLock() |
|
1420 | iolock = threading.RLock() | |
1420 |
|
1421 | |||
1421 | class SkipTest(Exception): |
|
1422 | class SkipTest(Exception): | |
1422 | """Raised to indicate that a test is to be skipped.""" |
|
1423 | """Raised to indicate that a test is to be skipped.""" | |
1423 |
|
1424 | |||
1424 | class IgnoreTest(Exception): |
|
1425 | class IgnoreTest(Exception): | |
1425 | """Raised to indicate that a test is to be ignored.""" |
|
1426 | """Raised to indicate that a test is to be ignored.""" | |
1426 |
|
1427 | |||
1427 | class WarnTest(Exception): |
|
1428 | class WarnTest(Exception): | |
1428 | """Raised to indicate that a test warned.""" |
|
1429 | """Raised to indicate that a test warned.""" | |
1429 |
|
1430 | |||
1430 | class ReportedTest(Exception): |
|
1431 | class ReportedTest(Exception): | |
1431 | """Raised to indicate that a test already reported.""" |
|
1432 | """Raised to indicate that a test already reported.""" | |
1432 |
|
1433 | |||
1433 | class TestResult(unittest._TextTestResult): |
|
1434 | class TestResult(unittest._TextTestResult): | |
1434 | """Holds results when executing via unittest.""" |
|
1435 | """Holds results when executing via unittest.""" | |
1435 | # Don't worry too much about accessing the non-public _TextTestResult. |
|
1436 | # Don't worry too much about accessing the non-public _TextTestResult. | |
1436 | # It is relatively common in Python testing tools. |
|
1437 | # It is relatively common in Python testing tools. | |
1437 | def __init__(self, options, *args, **kwargs): |
|
1438 | def __init__(self, options, *args, **kwargs): | |
1438 | super(TestResult, self).__init__(*args, **kwargs) |
|
1439 | super(TestResult, self).__init__(*args, **kwargs) | |
1439 |
|
1440 | |||
1440 | self._options = options |
|
1441 | self._options = options | |
1441 |
|
1442 | |||
1442 | # unittest.TestResult didn't have skipped until 2.7. We need to |
|
1443 | # unittest.TestResult didn't have skipped until 2.7. We need to | |
1443 | # polyfill it. |
|
1444 | # polyfill it. | |
1444 | self.skipped = [] |
|
1445 | self.skipped = [] | |
1445 |
|
1446 | |||
1446 | # We have a custom "ignored" result that isn't present in any Python |
|
1447 | # We have a custom "ignored" result that isn't present in any Python | |
1447 | # unittest implementation. It is very similar to skipped. It may make |
|
1448 | # unittest implementation. It is very similar to skipped. It may make | |
1448 | # sense to map it into skip some day. |
|
1449 | # sense to map it into skip some day. | |
1449 | self.ignored = [] |
|
1450 | self.ignored = [] | |
1450 |
|
1451 | |||
1451 | # We have a custom "warned" result that isn't present in any Python |
|
1452 | # We have a custom "warned" result that isn't present in any Python | |
1452 | # unittest implementation. It is very similar to failed. It may make |
|
1453 | # unittest implementation. It is very similar to failed. It may make | |
1453 | # sense to map it into fail some day. |
|
1454 | # sense to map it into fail some day. | |
1454 | self.warned = [] |
|
1455 | self.warned = [] | |
1455 |
|
1456 | |||
1456 | self.times = [] |
|
1457 | self.times = [] | |
1457 | self._firststarttime = None |
|
1458 | self._firststarttime = None | |
1458 | # Data stored for the benefit of generating xunit reports. |
|
1459 | # Data stored for the benefit of generating xunit reports. | |
1459 | self.successes = [] |
|
1460 | self.successes = [] | |
1460 | self.faildata = {} |
|
1461 | self.faildata = {} | |
1461 |
|
1462 | |||
1462 | def addFailure(self, test, reason): |
|
1463 | def addFailure(self, test, reason): | |
1463 | self.failures.append((test, reason)) |
|
1464 | self.failures.append((test, reason)) | |
1464 |
|
1465 | |||
1465 | if self._options.first: |
|
1466 | if self._options.first: | |
1466 | self.stop() |
|
1467 | self.stop() | |
1467 | else: |
|
1468 | else: | |
1468 | with iolock: |
|
1469 | with iolock: | |
1469 | if reason == "timed out": |
|
1470 | if reason == "timed out": | |
1470 | self.stream.write('t') |
|
1471 | self.stream.write('t') | |
1471 | else: |
|
1472 | else: | |
1472 | if not self._options.nodiff: |
|
1473 | if not self._options.nodiff: | |
1473 | self.stream.write('\nERROR: %s output changed\n' % test) |
|
1474 | self.stream.write('\nERROR: %s output changed\n' % test) | |
1474 | self.stream.write('!') |
|
1475 | self.stream.write('!') | |
1475 |
|
1476 | |||
1476 | self.stream.flush() |
|
1477 | self.stream.flush() | |
1477 |
|
1478 | |||
1478 | def addSuccess(self, test): |
|
1479 | def addSuccess(self, test): | |
1479 | with iolock: |
|
1480 | with iolock: | |
1480 | super(TestResult, self).addSuccess(test) |
|
1481 | super(TestResult, self).addSuccess(test) | |
1481 | self.successes.append(test) |
|
1482 | self.successes.append(test) | |
1482 |
|
1483 | |||
1483 | def addError(self, test, err): |
|
1484 | def addError(self, test, err): | |
1484 | super(TestResult, self).addError(test, err) |
|
1485 | super(TestResult, self).addError(test, err) | |
1485 | if self._options.first: |
|
1486 | if self._options.first: | |
1486 | self.stop() |
|
1487 | self.stop() | |
1487 |
|
1488 | |||
1488 | # Polyfill. |
|
1489 | # Polyfill. | |
1489 | def addSkip(self, test, reason): |
|
1490 | def addSkip(self, test, reason): | |
1490 | self.skipped.append((test, reason)) |
|
1491 | self.skipped.append((test, reason)) | |
1491 | with iolock: |
|
1492 | with iolock: | |
1492 | if self.showAll: |
|
1493 | if self.showAll: | |
1493 | self.stream.writeln('skipped %s' % reason) |
|
1494 | self.stream.writeln('skipped %s' % reason) | |
1494 | else: |
|
1495 | else: | |
1495 | self.stream.write('s') |
|
1496 | self.stream.write('s') | |
1496 | self.stream.flush() |
|
1497 | self.stream.flush() | |
1497 |
|
1498 | |||
1498 | def addIgnore(self, test, reason): |
|
1499 | def addIgnore(self, test, reason): | |
1499 | self.ignored.append((test, reason)) |
|
1500 | self.ignored.append((test, reason)) | |
1500 | with iolock: |
|
1501 | with iolock: | |
1501 | if self.showAll: |
|
1502 | if self.showAll: | |
1502 | self.stream.writeln('ignored %s' % reason) |
|
1503 | self.stream.writeln('ignored %s' % reason) | |
1503 | else: |
|
1504 | else: | |
1504 | if reason not in ('not retesting', "doesn't match keyword"): |
|
1505 | if reason not in ('not retesting', "doesn't match keyword"): | |
1505 | self.stream.write('i') |
|
1506 | self.stream.write('i') | |
1506 | else: |
|
1507 | else: | |
1507 | self.testsRun += 1 |
|
1508 | self.testsRun += 1 | |
1508 | self.stream.flush() |
|
1509 | self.stream.flush() | |
1509 |
|
1510 | |||
1510 | def addWarn(self, test, reason): |
|
1511 | def addWarn(self, test, reason): | |
1511 | self.warned.append((test, reason)) |
|
1512 | self.warned.append((test, reason)) | |
1512 |
|
1513 | |||
1513 | if self._options.first: |
|
1514 | if self._options.first: | |
1514 | self.stop() |
|
1515 | self.stop() | |
1515 |
|
1516 | |||
1516 | with iolock: |
|
1517 | with iolock: | |
1517 | if self.showAll: |
|
1518 | if self.showAll: | |
1518 | self.stream.writeln('warned %s' % reason) |
|
1519 | self.stream.writeln('warned %s' % reason) | |
1519 | else: |
|
1520 | else: | |
1520 | self.stream.write('~') |
|
1521 | self.stream.write('~') | |
1521 | self.stream.flush() |
|
1522 | self.stream.flush() | |
1522 |
|
1523 | |||
1523 | def addOutputMismatch(self, test, ret, got, expected): |
|
1524 | def addOutputMismatch(self, test, ret, got, expected): | |
1524 | """Record a mismatch in test output for a particular test.""" |
|
1525 | """Record a mismatch in test output for a particular test.""" | |
1525 | if self.shouldStop: |
|
1526 | if self.shouldStop: | |
1526 | # don't print, some other test case already failed and |
|
1527 | # don't print, some other test case already failed and | |
1527 | # printed, we're just stale and probably failed due to our |
|
1528 | # printed, we're just stale and probably failed due to our | |
1528 | # temp dir getting cleaned up. |
|
1529 | # temp dir getting cleaned up. | |
1529 | return |
|
1530 | return | |
1530 |
|
1531 | |||
1531 | accepted = False |
|
1532 | accepted = False | |
1532 | lines = [] |
|
1533 | lines = [] | |
1533 |
|
1534 | |||
1534 | with iolock: |
|
1535 | with iolock: | |
1535 | if self._options.nodiff: |
|
1536 | if self._options.nodiff: | |
1536 | pass |
|
1537 | pass | |
1537 | elif self._options.view: |
|
1538 | elif self._options.view: | |
1538 | v = self._options.view |
|
1539 | v = self._options.view | |
1539 | if PYTHON3: |
|
1540 | if PYTHON3: | |
1540 | v = _bytespath(v) |
|
1541 | v = _bytespath(v) | |
1541 | os.system(b"%s %s %s" % |
|
1542 | os.system(b"%s %s %s" % | |
1542 | (v, test.refpath, test.errpath)) |
|
1543 | (v, test.refpath, test.errpath)) | |
1543 | else: |
|
1544 | else: | |
1544 | servefail, lines = getdiff(expected, got, |
|
1545 | servefail, lines = getdiff(expected, got, | |
1545 | test.refpath, test.errpath) |
|
1546 | test.refpath, test.errpath) | |
1546 | if servefail: |
|
1547 | if servefail: | |
1547 | self.addFailure( |
|
1548 | self.addFailure( | |
1548 | test, |
|
1549 | test, | |
1549 | 'server failed to start (HGPORT=%s)' % test._startport) |
|
1550 | 'server failed to start (HGPORT=%s)' % test._startport) | |
1550 | raise ReportedTest('server failed to start') |
|
1551 | raise ReportedTest('server failed to start') | |
1551 | else: |
|
1552 | else: | |
1552 | self.stream.write('\n') |
|
1553 | self.stream.write('\n') | |
1553 | for line in lines: |
|
1554 | for line in lines: | |
1554 | if PYTHON3: |
|
1555 | if PYTHON3: | |
1555 | self.stream.flush() |
|
1556 | self.stream.flush() | |
1556 | self.stream.buffer.write(line) |
|
1557 | self.stream.buffer.write(line) | |
1557 | self.stream.buffer.flush() |
|
1558 | self.stream.buffer.flush() | |
1558 | else: |
|
1559 | else: | |
1559 | self.stream.write(line) |
|
1560 | self.stream.write(line) | |
1560 | self.stream.flush() |
|
1561 | self.stream.flush() | |
1561 |
|
1562 | |||
1562 | # handle interactive prompt without releasing iolock |
|
1563 | # handle interactive prompt without releasing iolock | |
1563 | if self._options.interactive: |
|
1564 | if self._options.interactive: | |
1564 | self.stream.write('Accept this change? [n] ') |
|
1565 | self.stream.write('Accept this change? [n] ') | |
1565 | answer = sys.stdin.readline().strip() |
|
1566 | answer = sys.stdin.readline().strip() | |
1566 | if answer.lower() in ('y', 'yes'): |
|
1567 | if answer.lower() in ('y', 'yes'): | |
1567 | if test.name.endswith('.t'): |
|
1568 | if test.name.endswith('.t'): | |
1568 | rename(test.errpath, test.path) |
|
1569 | rename(test.errpath, test.path) | |
1569 | else: |
|
1570 | else: | |
1570 | rename(test.errpath, '%s.out' % test.path) |
|
1571 | rename(test.errpath, '%s.out' % test.path) | |
1571 | accepted = True |
|
1572 | accepted = True | |
1572 | if not accepted: |
|
1573 | if not accepted: | |
1573 | self.faildata[test.name] = b''.join(lines) |
|
1574 | self.faildata[test.name] = b''.join(lines) | |
1574 |
|
1575 | |||
1575 | return accepted |
|
1576 | return accepted | |
1576 |
|
1577 | |||
1577 | def startTest(self, test): |
|
1578 | def startTest(self, test): | |
1578 | super(TestResult, self).startTest(test) |
|
1579 | super(TestResult, self).startTest(test) | |
1579 |
|
1580 | |||
1580 | # os.times module computes the user time and system time spent by |
|
1581 | # os.times module computes the user time and system time spent by | |
1581 | # child's processes along with real elapsed time taken by a process. |
|
1582 | # child's processes along with real elapsed time taken by a process. | |
1582 | # This module has one limitation. It can only work for Linux user |
|
1583 | # This module has one limitation. It can only work for Linux user | |
1583 | # and not for Windows. |
|
1584 | # and not for Windows. | |
1584 | test.started = os.times() |
|
1585 | test.started = os.times() | |
1585 | if self._firststarttime is None: # thread racy but irrelevant |
|
1586 | if self._firststarttime is None: # thread racy but irrelevant | |
1586 | self._firststarttime = test.started[4] |
|
1587 | self._firststarttime = test.started[4] | |
1587 |
|
1588 | |||
1588 | def stopTest(self, test, interrupted=False): |
|
1589 | def stopTest(self, test, interrupted=False): | |
1589 | super(TestResult, self).stopTest(test) |
|
1590 | super(TestResult, self).stopTest(test) | |
1590 |
|
1591 | |||
1591 | test.stopped = os.times() |
|
1592 | test.stopped = os.times() | |
1592 |
|
1593 | |||
1593 | starttime = test.started |
|
1594 | starttime = test.started | |
1594 | endtime = test.stopped |
|
1595 | endtime = test.stopped | |
1595 | origin = self._firststarttime |
|
1596 | origin = self._firststarttime | |
1596 | self.times.append((test.name, |
|
1597 | self.times.append((test.name, | |
1597 | endtime[2] - starttime[2], # user space CPU time |
|
1598 | endtime[2] - starttime[2], # user space CPU time | |
1598 | endtime[3] - starttime[3], # sys space CPU time |
|
1599 | endtime[3] - starttime[3], # sys space CPU time | |
1599 | endtime[4] - starttime[4], # real time |
|
1600 | endtime[4] - starttime[4], # real time | |
1600 | starttime[4] - origin, # start date in run context |
|
1601 | starttime[4] - origin, # start date in run context | |
1601 | endtime[4] - origin, # end date in run context |
|
1602 | endtime[4] - origin, # end date in run context | |
1602 | )) |
|
1603 | )) | |
1603 |
|
1604 | |||
1604 | if interrupted: |
|
1605 | if interrupted: | |
1605 | with iolock: |
|
1606 | with iolock: | |
1606 | self.stream.writeln('INTERRUPTED: %s (after %d seconds)' % ( |
|
1607 | self.stream.writeln('INTERRUPTED: %s (after %d seconds)' % ( | |
1607 | test.name, self.times[-1][3])) |
|
1608 | test.name, self.times[-1][3])) | |
1608 |
|
1609 | |||
1609 | class TestSuite(unittest.TestSuite): |
|
1610 | class TestSuite(unittest.TestSuite): | |
1610 | """Custom unittest TestSuite that knows how to execute Mercurial tests.""" |
|
1611 | """Custom unittest TestSuite that knows how to execute Mercurial tests.""" | |
1611 |
|
1612 | |||
1612 | def __init__(self, testdir, jobs=1, whitelist=None, blacklist=None, |
|
1613 | def __init__(self, testdir, jobs=1, whitelist=None, blacklist=None, | |
1613 | retest=False, keywords=None, loop=False, runs_per_test=1, |
|
1614 | retest=False, keywords=None, loop=False, runs_per_test=1, | |
1614 | loadtest=None, showchannels=False, |
|
1615 | loadtest=None, showchannels=False, | |
1615 | *args, **kwargs): |
|
1616 | *args, **kwargs): | |
1616 | """Create a new instance that can run tests with a configuration. |
|
1617 | """Create a new instance that can run tests with a configuration. | |
1617 |
|
1618 | |||
1618 | testdir specifies the directory where tests are executed from. This |
|
1619 | testdir specifies the directory where tests are executed from. This | |
1619 | is typically the ``tests`` directory from Mercurial's source |
|
1620 | is typically the ``tests`` directory from Mercurial's source | |
1620 | repository. |
|
1621 | repository. | |
1621 |
|
1622 | |||
1622 | jobs specifies the number of jobs to run concurrently. Each test |
|
1623 | jobs specifies the number of jobs to run concurrently. Each test | |
1623 | executes on its own thread. Tests actually spawn new processes, so |
|
1624 | executes on its own thread. Tests actually spawn new processes, so | |
1624 | state mutation should not be an issue. |
|
1625 | state mutation should not be an issue. | |
1625 |
|
1626 | |||
1626 | If there is only one job, it will use the main thread. |
|
1627 | If there is only one job, it will use the main thread. | |
1627 |
|
1628 | |||
1628 | whitelist and blacklist denote tests that have been whitelisted and |
|
1629 | whitelist and blacklist denote tests that have been whitelisted and | |
1629 | blacklisted, respectively. These arguments don't belong in TestSuite. |
|
1630 | blacklisted, respectively. These arguments don't belong in TestSuite. | |
1630 | Instead, whitelist and blacklist should be handled by the thing that |
|
1631 | Instead, whitelist and blacklist should be handled by the thing that | |
1631 | populates the TestSuite with tests. They are present to preserve |
|
1632 | populates the TestSuite with tests. They are present to preserve | |
1632 | backwards compatible behavior which reports skipped tests as part |
|
1633 | backwards compatible behavior which reports skipped tests as part | |
1633 | of the results. |
|
1634 | of the results. | |
1634 |
|
1635 | |||
1635 | retest denotes whether to retest failed tests. This arguably belongs |
|
1636 | retest denotes whether to retest failed tests. This arguably belongs | |
1636 | outside of TestSuite. |
|
1637 | outside of TestSuite. | |
1637 |
|
1638 | |||
1638 | keywords denotes key words that will be used to filter which tests |
|
1639 | keywords denotes key words that will be used to filter which tests | |
1639 | to execute. This arguably belongs outside of TestSuite. |
|
1640 | to execute. This arguably belongs outside of TestSuite. | |
1640 |
|
1641 | |||
1641 | loop denotes whether to loop over tests forever. |
|
1642 | loop denotes whether to loop over tests forever. | |
1642 | """ |
|
1643 | """ | |
1643 | super(TestSuite, self).__init__(*args, **kwargs) |
|
1644 | super(TestSuite, self).__init__(*args, **kwargs) | |
1644 |
|
1645 | |||
1645 | self._jobs = jobs |
|
1646 | self._jobs = jobs | |
1646 | self._whitelist = whitelist |
|
1647 | self._whitelist = whitelist | |
1647 | self._blacklist = blacklist |
|
1648 | self._blacklist = blacklist | |
1648 | self._retest = retest |
|
1649 | self._retest = retest | |
1649 | self._keywords = keywords |
|
1650 | self._keywords = keywords | |
1650 | self._loop = loop |
|
1651 | self._loop = loop | |
1651 | self._runs_per_test = runs_per_test |
|
1652 | self._runs_per_test = runs_per_test | |
1652 | self._loadtest = loadtest |
|
1653 | self._loadtest = loadtest | |
1653 | self._showchannels = showchannels |
|
1654 | self._showchannels = showchannels | |
1654 |
|
1655 | |||
1655 | def run(self, result): |
|
1656 | def run(self, result): | |
1656 | # We have a number of filters that need to be applied. We do this |
|
1657 | # We have a number of filters that need to be applied. We do this | |
1657 | # here instead of inside Test because it makes the running logic for |
|
1658 | # here instead of inside Test because it makes the running logic for | |
1658 | # Test simpler. |
|
1659 | # Test simpler. | |
1659 | tests = [] |
|
1660 | tests = [] | |
1660 | num_tests = [0] |
|
1661 | num_tests = [0] | |
1661 | for test in self._tests: |
|
1662 | for test in self._tests: | |
1662 | def get(): |
|
1663 | def get(): | |
1663 | num_tests[0] += 1 |
|
1664 | num_tests[0] += 1 | |
1664 | if getattr(test, 'should_reload', False): |
|
1665 | if getattr(test, 'should_reload', False): | |
1665 | return self._loadtest(test.path, num_tests[0]) |
|
1666 | return self._loadtest(test.path, num_tests[0]) | |
1666 | return test |
|
1667 | return test | |
1667 | if not os.path.exists(test.path): |
|
1668 | if not os.path.exists(test.path): | |
1668 | result.addSkip(test, "Doesn't exist") |
|
1669 | result.addSkip(test, "Doesn't exist") | |
1669 | continue |
|
1670 | continue | |
1670 |
|
1671 | |||
1671 | if not (self._whitelist and test.name in self._whitelist): |
|
1672 | if not (self._whitelist and test.name in self._whitelist): | |
1672 | if self._blacklist and test.bname in self._blacklist: |
|
1673 | if self._blacklist and test.bname in self._blacklist: | |
1673 | result.addSkip(test, 'blacklisted') |
|
1674 | result.addSkip(test, 'blacklisted') | |
1674 | continue |
|
1675 | continue | |
1675 |
|
1676 | |||
1676 | if self._retest and not os.path.exists(test.errpath): |
|
1677 | if self._retest and not os.path.exists(test.errpath): | |
1677 | result.addIgnore(test, 'not retesting') |
|
1678 | result.addIgnore(test, 'not retesting') | |
1678 | continue |
|
1679 | continue | |
1679 |
|
1680 | |||
1680 | if self._keywords: |
|
1681 | if self._keywords: | |
1681 | f = open(test.path, 'rb') |
|
1682 | f = open(test.path, 'rb') | |
1682 | t = f.read().lower() + test.bname.lower() |
|
1683 | t = f.read().lower() + test.bname.lower() | |
1683 | f.close() |
|
1684 | f.close() | |
1684 | ignored = False |
|
1685 | ignored = False | |
1685 | for k in self._keywords.lower().split(): |
|
1686 | for k in self._keywords.lower().split(): | |
1686 | if k not in t: |
|
1687 | if k not in t: | |
1687 | result.addIgnore(test, "doesn't match keyword") |
|
1688 | result.addIgnore(test, "doesn't match keyword") | |
1688 | ignored = True |
|
1689 | ignored = True | |
1689 | break |
|
1690 | break | |
1690 |
|
1691 | |||
1691 | if ignored: |
|
1692 | if ignored: | |
1692 | continue |
|
1693 | continue | |
1693 | for _ in xrange(self._runs_per_test): |
|
1694 | for _ in xrange(self._runs_per_test): | |
1694 | tests.append(get()) |
|
1695 | tests.append(get()) | |
1695 |
|
1696 | |||
1696 | runtests = list(tests) |
|
1697 | runtests = list(tests) | |
1697 | done = queue.Queue() |
|
1698 | done = queue.Queue() | |
1698 | running = 0 |
|
1699 | running = 0 | |
1699 |
|
1700 | |||
1700 | channels = [""] * self._jobs |
|
1701 | channels = [""] * self._jobs | |
1701 |
|
1702 | |||
1702 | def job(test, result): |
|
1703 | def job(test, result): | |
1703 | for n, v in enumerate(channels): |
|
1704 | for n, v in enumerate(channels): | |
1704 | if not v: |
|
1705 | if not v: | |
1705 | channel = n |
|
1706 | channel = n | |
1706 | break |
|
1707 | break | |
1707 | channels[channel] = "=" + test.name[5:].split(".")[0] |
|
1708 | channels[channel] = "=" + test.name[5:].split(".")[0] | |
1708 | try: |
|
1709 | try: | |
1709 | test(result) |
|
1710 | test(result) | |
1710 | done.put(None) |
|
1711 | done.put(None) | |
1711 | except KeyboardInterrupt: |
|
1712 | except KeyboardInterrupt: | |
1712 | pass |
|
1713 | pass | |
1713 | except: # re-raises |
|
1714 | except: # re-raises | |
1714 | done.put(('!', test, 'run-test raised an error, see traceback')) |
|
1715 | done.put(('!', test, 'run-test raised an error, see traceback')) | |
1715 | raise |
|
1716 | raise | |
1716 | try: |
|
1717 | try: | |
1717 | channels[channel] = '' |
|
1718 | channels[channel] = '' | |
1718 | except IndexError: |
|
1719 | except IndexError: | |
1719 | pass |
|
1720 | pass | |
1720 |
|
1721 | |||
1721 | def stat(): |
|
1722 | def stat(): | |
1722 | count = 0 |
|
1723 | count = 0 | |
1723 | while channels: |
|
1724 | while channels: | |
1724 | d = '\n%03s ' % count |
|
1725 | d = '\n%03s ' % count | |
1725 | for n, v in enumerate(channels): |
|
1726 | for n, v in enumerate(channels): | |
1726 | if v: |
|
1727 | if v: | |
1727 | d += v[0] |
|
1728 | d += v[0] | |
1728 | channels[n] = v[1:] or '.' |
|
1729 | channels[n] = v[1:] or '.' | |
1729 | else: |
|
1730 | else: | |
1730 | d += ' ' |
|
1731 | d += ' ' | |
1731 | d += ' ' |
|
1732 | d += ' ' | |
1732 | with iolock: |
|
1733 | with iolock: | |
1733 | sys.stdout.write(d + ' ') |
|
1734 | sys.stdout.write(d + ' ') | |
1734 | sys.stdout.flush() |
|
1735 | sys.stdout.flush() | |
1735 | for x in xrange(10): |
|
1736 | for x in xrange(10): | |
1736 | if channels: |
|
1737 | if channels: | |
1737 | time.sleep(.1) |
|
1738 | time.sleep(.1) | |
1738 | count += 1 |
|
1739 | count += 1 | |
1739 |
|
1740 | |||
1740 | stoppedearly = False |
|
1741 | stoppedearly = False | |
1741 |
|
1742 | |||
1742 | if self._showchannels: |
|
1743 | if self._showchannels: | |
1743 | statthread = threading.Thread(target=stat, name="stat") |
|
1744 | statthread = threading.Thread(target=stat, name="stat") | |
1744 | statthread.start() |
|
1745 | statthread.start() | |
1745 |
|
1746 | |||
1746 | try: |
|
1747 | try: | |
1747 | while tests or running: |
|
1748 | while tests or running: | |
1748 | if not done.empty() or running == self._jobs or not tests: |
|
1749 | if not done.empty() or running == self._jobs or not tests: | |
1749 | try: |
|
1750 | try: | |
1750 | done.get(True, 1) |
|
1751 | done.get(True, 1) | |
1751 | running -= 1 |
|
1752 | running -= 1 | |
1752 | if result and result.shouldStop: |
|
1753 | if result and result.shouldStop: | |
1753 | stoppedearly = True |
|
1754 | stoppedearly = True | |
1754 | break |
|
1755 | break | |
1755 | except queue.Empty: |
|
1756 | except queue.Empty: | |
1756 | continue |
|
1757 | continue | |
1757 | if tests and not running == self._jobs: |
|
1758 | if tests and not running == self._jobs: | |
1758 | test = tests.pop(0) |
|
1759 | test = tests.pop(0) | |
1759 | if self._loop: |
|
1760 | if self._loop: | |
1760 | if getattr(test, 'should_reload', False): |
|
1761 | if getattr(test, 'should_reload', False): | |
1761 | num_tests[0] += 1 |
|
1762 | num_tests[0] += 1 | |
1762 | tests.append( |
|
1763 | tests.append( | |
1763 | self._loadtest(test.name, num_tests[0])) |
|
1764 | self._loadtest(test.name, num_tests[0])) | |
1764 | else: |
|
1765 | else: | |
1765 | tests.append(test) |
|
1766 | tests.append(test) | |
1766 | if self._jobs == 1: |
|
1767 | if self._jobs == 1: | |
1767 | job(test, result) |
|
1768 | job(test, result) | |
1768 | else: |
|
1769 | else: | |
1769 | t = threading.Thread(target=job, name=test.name, |
|
1770 | t = threading.Thread(target=job, name=test.name, | |
1770 | args=(test, result)) |
|
1771 | args=(test, result)) | |
1771 | t.start() |
|
1772 | t.start() | |
1772 | running += 1 |
|
1773 | running += 1 | |
1773 |
|
1774 | |||
1774 | # If we stop early we still need to wait on started tests to |
|
1775 | # If we stop early we still need to wait on started tests to | |
1775 | # finish. Otherwise, there is a race between the test completing |
|
1776 | # finish. Otherwise, there is a race between the test completing | |
1776 | # and the test's cleanup code running. This could result in the |
|
1777 | # and the test's cleanup code running. This could result in the | |
1777 | # test reporting incorrect. |
|
1778 | # test reporting incorrect. | |
1778 | if stoppedearly: |
|
1779 | if stoppedearly: | |
1779 | while running: |
|
1780 | while running: | |
1780 | try: |
|
1781 | try: | |
1781 | done.get(True, 1) |
|
1782 | done.get(True, 1) | |
1782 | running -= 1 |
|
1783 | running -= 1 | |
1783 | except queue.Empty: |
|
1784 | except queue.Empty: | |
1784 | continue |
|
1785 | continue | |
1785 | except KeyboardInterrupt: |
|
1786 | except KeyboardInterrupt: | |
1786 | for test in runtests: |
|
1787 | for test in runtests: | |
1787 | test.abort() |
|
1788 | test.abort() | |
1788 |
|
1789 | |||
1789 | channels = [] |
|
1790 | channels = [] | |
1790 |
|
1791 | |||
1791 | return result |
|
1792 | return result | |
1792 |
|
1793 | |||
1793 | # Save the most recent 5 wall-clock runtimes of each test to a |
|
1794 | # Save the most recent 5 wall-clock runtimes of each test to a | |
1794 | # human-readable text file named .testtimes. Tests are sorted |
|
1795 | # human-readable text file named .testtimes. Tests are sorted | |
1795 | # alphabetically, while times for each test are listed from oldest to |
|
1796 | # alphabetically, while times for each test are listed from oldest to | |
1796 | # newest. |
|
1797 | # newest. | |
1797 |
|
1798 | |||
1798 | def loadtimes(testdir): |
|
1799 | def loadtimes(testdir): | |
1799 | times = [] |
|
1800 | times = [] | |
1800 | try: |
|
1801 | try: | |
1801 | with open(os.path.join(testdir, b'.testtimes-')) as fp: |
|
1802 | with open(os.path.join(testdir, b'.testtimes-')) as fp: | |
1802 | for line in fp: |
|
1803 | for line in fp: | |
1803 | ts = line.split() |
|
1804 | ts = line.split() | |
1804 | times.append((ts[0], [float(t) for t in ts[1:]])) |
|
1805 | times.append((ts[0], [float(t) for t in ts[1:]])) | |
1805 | except IOError as err: |
|
1806 | except IOError as err: | |
1806 | if err.errno != errno.ENOENT: |
|
1807 | if err.errno != errno.ENOENT: | |
1807 | raise |
|
1808 | raise | |
1808 | return times |
|
1809 | return times | |
1809 |
|
1810 | |||
1810 | def savetimes(testdir, result): |
|
1811 | def savetimes(testdir, result): | |
1811 | saved = dict(loadtimes(testdir)) |
|
1812 | saved = dict(loadtimes(testdir)) | |
1812 | maxruns = 5 |
|
1813 | maxruns = 5 | |
1813 | skipped = set([str(t[0]) for t in result.skipped]) |
|
1814 | skipped = set([str(t[0]) for t in result.skipped]) | |
1814 | for tdata in result.times: |
|
1815 | for tdata in result.times: | |
1815 | test, real = tdata[0], tdata[3] |
|
1816 | test, real = tdata[0], tdata[3] | |
1816 | if test not in skipped: |
|
1817 | if test not in skipped: | |
1817 | ts = saved.setdefault(test, []) |
|
1818 | ts = saved.setdefault(test, []) | |
1818 | ts.append(real) |
|
1819 | ts.append(real) | |
1819 | ts[:] = ts[-maxruns:] |
|
1820 | ts[:] = ts[-maxruns:] | |
1820 |
|
1821 | |||
1821 | fd, tmpname = tempfile.mkstemp(prefix=b'.testtimes', |
|
1822 | fd, tmpname = tempfile.mkstemp(prefix=b'.testtimes', | |
1822 | dir=testdir, text=True) |
|
1823 | dir=testdir, text=True) | |
1823 | with os.fdopen(fd, 'w') as fp: |
|
1824 | with os.fdopen(fd, 'w') as fp: | |
1824 | for name, ts in sorted(saved.items()): |
|
1825 | for name, ts in sorted(saved.items()): | |
1825 | fp.write('%s %s\n' % (name, ' '.join(['%.3f' % (t,) for t in ts]))) |
|
1826 | fp.write('%s %s\n' % (name, ' '.join(['%.3f' % (t,) for t in ts]))) | |
1826 | timepath = os.path.join(testdir, b'.testtimes') |
|
1827 | timepath = os.path.join(testdir, b'.testtimes') | |
1827 | try: |
|
1828 | try: | |
1828 | os.unlink(timepath) |
|
1829 | os.unlink(timepath) | |
1829 | except OSError: |
|
1830 | except OSError: | |
1830 | pass |
|
1831 | pass | |
1831 | try: |
|
1832 | try: | |
1832 | os.rename(tmpname, timepath) |
|
1833 | os.rename(tmpname, timepath) | |
1833 | except OSError: |
|
1834 | except OSError: | |
1834 | pass |
|
1835 | pass | |
1835 |
|
1836 | |||
1836 | class TextTestRunner(unittest.TextTestRunner): |
|
1837 | class TextTestRunner(unittest.TextTestRunner): | |
1837 | """Custom unittest test runner that uses appropriate settings.""" |
|
1838 | """Custom unittest test runner that uses appropriate settings.""" | |
1838 |
|
1839 | |||
1839 | def __init__(self, runner, *args, **kwargs): |
|
1840 | def __init__(self, runner, *args, **kwargs): | |
1840 | super(TextTestRunner, self).__init__(*args, **kwargs) |
|
1841 | super(TextTestRunner, self).__init__(*args, **kwargs) | |
1841 |
|
1842 | |||
1842 | self._runner = runner |
|
1843 | self._runner = runner | |
1843 |
|
1844 | |||
1844 | def run(self, test): |
|
1845 | def run(self, test): | |
1845 | result = TestResult(self._runner.options, self.stream, |
|
1846 | result = TestResult(self._runner.options, self.stream, | |
1846 | self.descriptions, self.verbosity) |
|
1847 | self.descriptions, self.verbosity) | |
1847 |
|
1848 | |||
1848 | test(result) |
|
1849 | test(result) | |
1849 |
|
1850 | |||
1850 | failed = len(result.failures) |
|
1851 | failed = len(result.failures) | |
1851 | warned = len(result.warned) |
|
1852 | warned = len(result.warned) | |
1852 | skipped = len(result.skipped) |
|
1853 | skipped = len(result.skipped) | |
1853 | ignored = len(result.ignored) |
|
1854 | ignored = len(result.ignored) | |
1854 |
|
1855 | |||
1855 | with iolock: |
|
1856 | with iolock: | |
1856 | self.stream.writeln('') |
|
1857 | self.stream.writeln('') | |
1857 |
|
1858 | |||
1858 | if not self._runner.options.noskips: |
|
1859 | if not self._runner.options.noskips: | |
1859 | for test, msg in result.skipped: |
|
1860 | for test, msg in result.skipped: | |
1860 | self.stream.writeln('Skipped %s: %s' % (test.name, msg)) |
|
1861 | self.stream.writeln('Skipped %s: %s' % (test.name, msg)) | |
1861 | for test, msg in result.warned: |
|
1862 | for test, msg in result.warned: | |
1862 | self.stream.writeln('Warned %s: %s' % (test.name, msg)) |
|
1863 | self.stream.writeln('Warned %s: %s' % (test.name, msg)) | |
1863 | for test, msg in result.failures: |
|
1864 | for test, msg in result.failures: | |
1864 | self.stream.writeln('Failed %s: %s' % (test.name, msg)) |
|
1865 | self.stream.writeln('Failed %s: %s' % (test.name, msg)) | |
1865 | for test, msg in result.errors: |
|
1866 | for test, msg in result.errors: | |
1866 | self.stream.writeln('Errored %s: %s' % (test.name, msg)) |
|
1867 | self.stream.writeln('Errored %s: %s' % (test.name, msg)) | |
1867 |
|
1868 | |||
1868 | if self._runner.options.xunit: |
|
1869 | if self._runner.options.xunit: | |
1869 | with open(self._runner.options.xunit, 'wb') as xuf: |
|
1870 | with open(self._runner.options.xunit, 'wb') as xuf: | |
1870 | timesd = dict((t[0], t[3]) for t in result.times) |
|
1871 | timesd = dict((t[0], t[3]) for t in result.times) | |
1871 | doc = minidom.Document() |
|
1872 | doc = minidom.Document() | |
1872 | s = doc.createElement('testsuite') |
|
1873 | s = doc.createElement('testsuite') | |
1873 | s.setAttribute('name', 'run-tests') |
|
1874 | s.setAttribute('name', 'run-tests') | |
1874 | s.setAttribute('tests', str(result.testsRun)) |
|
1875 | s.setAttribute('tests', str(result.testsRun)) | |
1875 | s.setAttribute('errors', "0") # TODO |
|
1876 | s.setAttribute('errors', "0") # TODO | |
1876 | s.setAttribute('failures', str(failed)) |
|
1877 | s.setAttribute('failures', str(failed)) | |
1877 | s.setAttribute('skipped', str(skipped + ignored)) |
|
1878 | s.setAttribute('skipped', str(skipped + ignored)) | |
1878 | doc.appendChild(s) |
|
1879 | doc.appendChild(s) | |
1879 | for tc in result.successes: |
|
1880 | for tc in result.successes: | |
1880 | t = doc.createElement('testcase') |
|
1881 | t = doc.createElement('testcase') | |
1881 | t.setAttribute('name', tc.name) |
|
1882 | t.setAttribute('name', tc.name) | |
1882 | t.setAttribute('time', '%.3f' % timesd[tc.name]) |
|
1883 | t.setAttribute('time', '%.3f' % timesd[tc.name]) | |
1883 | s.appendChild(t) |
|
1884 | s.appendChild(t) | |
1884 | for tc, err in sorted(result.faildata.items()): |
|
1885 | for tc, err in sorted(result.faildata.items()): | |
1885 | t = doc.createElement('testcase') |
|
1886 | t = doc.createElement('testcase') | |
1886 | t.setAttribute('name', tc) |
|
1887 | t.setAttribute('name', tc) | |
1887 | t.setAttribute('time', '%.3f' % timesd[tc]) |
|
1888 | t.setAttribute('time', '%.3f' % timesd[tc]) | |
1888 | # createCDATASection expects a unicode or it will |
|
1889 | # createCDATASection expects a unicode or it will | |
1889 | # convert using default conversion rules, which will |
|
1890 | # convert using default conversion rules, which will | |
1890 | # fail if string isn't ASCII. |
|
1891 | # fail if string isn't ASCII. | |
1891 | err = cdatasafe(err).decode('utf-8', 'replace') |
|
1892 | err = cdatasafe(err).decode('utf-8', 'replace') | |
1892 | cd = doc.createCDATASection(err) |
|
1893 | cd = doc.createCDATASection(err) | |
1893 | t.appendChild(cd) |
|
1894 | t.appendChild(cd) | |
1894 | s.appendChild(t) |
|
1895 | s.appendChild(t) | |
1895 | xuf.write(doc.toprettyxml(indent=' ', encoding='utf-8')) |
|
1896 | xuf.write(doc.toprettyxml(indent=' ', encoding='utf-8')) | |
1896 |
|
1897 | |||
1897 | if self._runner.options.json: |
|
1898 | if self._runner.options.json: | |
1898 | jsonpath = os.path.join(self._runner._testdir, b'report.json') |
|
1899 | jsonpath = os.path.join(self._runner._testdir, b'report.json') | |
1899 | with open(jsonpath, 'w') as fp: |
|
1900 | with open(jsonpath, 'w') as fp: | |
1900 | timesd = {} |
|
1901 | timesd = {} | |
1901 | for tdata in result.times: |
|
1902 | for tdata in result.times: | |
1902 | test = tdata[0] |
|
1903 | test = tdata[0] | |
1903 | timesd[test] = tdata[1:] |
|
1904 | timesd[test] = tdata[1:] | |
1904 |
|
1905 | |||
1905 | outcome = {} |
|
1906 | outcome = {} | |
1906 | groups = [('success', ((tc, None) |
|
1907 | groups = [('success', ((tc, None) | |
1907 | for tc in result.successes)), |
|
1908 | for tc in result.successes)), | |
1908 | ('failure', result.failures), |
|
1909 | ('failure', result.failures), | |
1909 | ('skip', result.skipped)] |
|
1910 | ('skip', result.skipped)] | |
1910 | for res, testcases in groups: |
|
1911 | for res, testcases in groups: | |
1911 | for tc, __ in testcases: |
|
1912 | for tc, __ in testcases: | |
1912 | if tc.name in timesd: |
|
1913 | if tc.name in timesd: | |
1913 | diff = result.faildata.get(tc.name, b'') |
|
1914 | diff = result.faildata.get(tc.name, b'') | |
1914 | tres = {'result': res, |
|
1915 | tres = {'result': res, | |
1915 | 'time': ('%0.3f' % timesd[tc.name][2]), |
|
1916 | 'time': ('%0.3f' % timesd[tc.name][2]), | |
1916 | 'cuser': ('%0.3f' % timesd[tc.name][0]), |
|
1917 | 'cuser': ('%0.3f' % timesd[tc.name][0]), | |
1917 | 'csys': ('%0.3f' % timesd[tc.name][1]), |
|
1918 | 'csys': ('%0.3f' % timesd[tc.name][1]), | |
1918 | 'start': ('%0.3f' % timesd[tc.name][3]), |
|
1919 | 'start': ('%0.3f' % timesd[tc.name][3]), | |
1919 | 'end': ('%0.3f' % timesd[tc.name][4]), |
|
1920 | 'end': ('%0.3f' % timesd[tc.name][4]), | |
1920 | 'diff': diff.decode('unicode_escape'), |
|
1921 | 'diff': diff.decode('unicode_escape'), | |
1921 | } |
|
1922 | } | |
1922 | else: |
|
1923 | else: | |
1923 | # blacklisted test |
|
1924 | # blacklisted test | |
1924 | tres = {'result': res} |
|
1925 | tres = {'result': res} | |
1925 |
|
1926 | |||
1926 | outcome[tc.name] = tres |
|
1927 | outcome[tc.name] = tres | |
1927 | jsonout = json.dumps(outcome, sort_keys=True, indent=4, |
|
1928 | jsonout = json.dumps(outcome, sort_keys=True, indent=4, | |
1928 | separators=(',', ': ')) |
|
1929 | separators=(',', ': ')) | |
1929 | fp.writelines(("testreport =", jsonout)) |
|
1930 | fp.writelines(("testreport =", jsonout)) | |
1930 |
|
1931 | |||
1931 | self._runner._checkhglib('Tested') |
|
1932 | self._runner._checkhglib('Tested') | |
1932 |
|
1933 | |||
1933 | savetimes(self._runner._testdir, result) |
|
1934 | savetimes(self._runner._testdir, result) | |
1934 |
|
1935 | |||
1935 | if failed and self._runner.options.known_good_rev: |
|
1936 | if failed and self._runner.options.known_good_rev: | |
1936 | def nooutput(args): |
|
1937 | def nooutput(args): | |
1937 | p = subprocess.Popen(args, stderr=subprocess.STDOUT, |
|
1938 | p = subprocess.Popen(args, stderr=subprocess.STDOUT, | |
1938 | stdout=subprocess.PIPE) |
|
1939 | stdout=subprocess.PIPE) | |
1939 | p.stdout.read() |
|
1940 | p.stdout.read() | |
1940 | p.wait() |
|
1941 | p.wait() | |
1941 | for test, msg in result.failures: |
|
1942 | for test, msg in result.failures: | |
1942 | nooutput(['hg', 'bisect', '--reset']), |
|
1943 | nooutput(['hg', 'bisect', '--reset']), | |
1943 | nooutput(['hg', 'bisect', '--bad', '.']) |
|
1944 | nooutput(['hg', 'bisect', '--bad', '.']) | |
1944 | nooutput(['hg', 'bisect', '--good', |
|
1945 | nooutput(['hg', 'bisect', '--good', | |
1945 | self._runner.options.known_good_rev]) |
|
1946 | self._runner.options.known_good_rev]) | |
1946 | # TODO: we probably need to forward some options |
|
1947 | # TODO: we probably need to forward some options | |
1947 | # that alter hg's behavior inside the tests. |
|
1948 | # that alter hg's behavior inside the tests. | |
1948 | rtc = '%s %s %s' % (sys.executable, sys.argv[0], test) |
|
1949 | rtc = '%s %s %s' % (sys.executable, sys.argv[0], test) | |
1949 | sub = subprocess.Popen(['hg', 'bisect', '--command', rtc], |
|
1950 | sub = subprocess.Popen(['hg', 'bisect', '--command', rtc], | |
1950 | stderr=subprocess.STDOUT, |
|
1951 | stderr=subprocess.STDOUT, | |
1951 | stdout=subprocess.PIPE) |
|
1952 | stdout=subprocess.PIPE) | |
1952 | data = sub.stdout.read() |
|
1953 | data = sub.stdout.read() | |
1953 | sub.wait() |
|
1954 | sub.wait() | |
1954 | m = re.search( |
|
1955 | m = re.search( | |
1955 | (r'\nThe first (?P<goodbad>bad|good) revision ' |
|
1956 | (r'\nThe first (?P<goodbad>bad|good) revision ' | |
1956 | r'is:\nchangeset: +\d+:(?P<node>[a-f0-9]+)\n.*\n' |
|
1957 | r'is:\nchangeset: +\d+:(?P<node>[a-f0-9]+)\n.*\n' | |
1957 | r'summary: +(?P<summary>[^\n]+)\n'), |
|
1958 | r'summary: +(?P<summary>[^\n]+)\n'), | |
1958 | data, (re.MULTILINE | re.DOTALL)) |
|
1959 | data, (re.MULTILINE | re.DOTALL)) | |
1959 | if m is None: |
|
1960 | if m is None: | |
1960 | self.stream.writeln( |
|
1961 | self.stream.writeln( | |
1961 | 'Failed to identify failure point for %s' % test) |
|
1962 | 'Failed to identify failure point for %s' % test) | |
1962 | continue |
|
1963 | continue | |
1963 | dat = m.groupdict() |
|
1964 | dat = m.groupdict() | |
1964 | verb = 'broken' if dat['goodbad'] == 'bad' else 'fixed' |
|
1965 | verb = 'broken' if dat['goodbad'] == 'bad' else 'fixed' | |
1965 | self.stream.writeln( |
|
1966 | self.stream.writeln( | |
1966 | '%s %s by %s (%s)' % ( |
|
1967 | '%s %s by %s (%s)' % ( | |
1967 | test, verb, dat['node'], dat['summary'])) |
|
1968 | test, verb, dat['node'], dat['summary'])) | |
1968 | self.stream.writeln( |
|
1969 | self.stream.writeln( | |
1969 | '# Ran %d tests, %d skipped, %d warned, %d failed.' |
|
1970 | '# Ran %d tests, %d skipped, %d warned, %d failed.' | |
1970 | % (result.testsRun, |
|
1971 | % (result.testsRun, | |
1971 | skipped + ignored, warned, failed)) |
|
1972 | skipped + ignored, warned, failed)) | |
1972 | if failed: |
|
1973 | if failed: | |
1973 | self.stream.writeln('python hash seed: %s' % |
|
1974 | self.stream.writeln('python hash seed: %s' % | |
1974 | os.environ['PYTHONHASHSEED']) |
|
1975 | os.environ['PYTHONHASHSEED']) | |
1975 | if self._runner.options.time: |
|
1976 | if self._runner.options.time: | |
1976 | self.printtimes(result.times) |
|
1977 | self.printtimes(result.times) | |
1977 |
|
1978 | |||
1978 | return result |
|
1979 | return result | |
1979 |
|
1980 | |||
1980 | def printtimes(self, times): |
|
1981 | def printtimes(self, times): | |
1981 | # iolock held by run |
|
1982 | # iolock held by run | |
1982 | self.stream.writeln('# Producing time report') |
|
1983 | self.stream.writeln('# Producing time report') | |
1983 | times.sort(key=lambda t: (t[3])) |
|
1984 | times.sort(key=lambda t: (t[3])) | |
1984 | cols = '%7.3f %7.3f %7.3f %7.3f %7.3f %s' |
|
1985 | cols = '%7.3f %7.3f %7.3f %7.3f %7.3f %s' | |
1985 | self.stream.writeln('%-7s %-7s %-7s %-7s %-7s %s' % |
|
1986 | self.stream.writeln('%-7s %-7s %-7s %-7s %-7s %s' % | |
1986 | ('start', 'end', 'cuser', 'csys', 'real', 'Test')) |
|
1987 | ('start', 'end', 'cuser', 'csys', 'real', 'Test')) | |
1987 | for tdata in times: |
|
1988 | for tdata in times: | |
1988 | test = tdata[0] |
|
1989 | test = tdata[0] | |
1989 | cuser, csys, real, start, end = tdata[1:6] |
|
1990 | cuser, csys, real, start, end = tdata[1:6] | |
1990 | self.stream.writeln(cols % (start, end, cuser, csys, real, test)) |
|
1991 | self.stream.writeln(cols % (start, end, cuser, csys, real, test)) | |
1991 |
|
1992 | |||
1992 | class TestRunner(object): |
|
1993 | class TestRunner(object): | |
1993 | """Holds context for executing tests. |
|
1994 | """Holds context for executing tests. | |
1994 |
|
1995 | |||
1995 | Tests rely on a lot of state. This object holds it for them. |
|
1996 | Tests rely on a lot of state. This object holds it for them. | |
1996 | """ |
|
1997 | """ | |
1997 |
|
1998 | |||
1998 | # Programs required to run tests. |
|
1999 | # Programs required to run tests. | |
1999 | REQUIREDTOOLS = [ |
|
2000 | REQUIREDTOOLS = [ | |
2000 | os.path.basename(_bytespath(sys.executable)), |
|
2001 | os.path.basename(_bytespath(sys.executable)), | |
2001 | b'diff', |
|
2002 | b'diff', | |
2002 | b'grep', |
|
2003 | b'grep', | |
2003 | b'unzip', |
|
2004 | b'unzip', | |
2004 | b'gunzip', |
|
2005 | b'gunzip', | |
2005 | b'bunzip2', |
|
2006 | b'bunzip2', | |
2006 | b'sed', |
|
2007 | b'sed', | |
2007 | ] |
|
2008 | ] | |
2008 |
|
2009 | |||
2009 | # Maps file extensions to test class. |
|
2010 | # Maps file extensions to test class. | |
2010 | TESTTYPES = [ |
|
2011 | TESTTYPES = [ | |
2011 | (b'.py', PythonTest), |
|
2012 | (b'.py', PythonTest), | |
2012 | (b'.t', TTest), |
|
2013 | (b'.t', TTest), | |
2013 | ] |
|
2014 | ] | |
2014 |
|
2015 | |||
2015 | def __init__(self): |
|
2016 | def __init__(self): | |
2016 | self.options = None |
|
2017 | self.options = None | |
2017 | self._hgroot = None |
|
2018 | self._hgroot = None | |
2018 | self._testdir = None |
|
2019 | self._testdir = None | |
2019 | self._hgtmp = None |
|
2020 | self._hgtmp = None | |
2020 | self._installdir = None |
|
2021 | self._installdir = None | |
2021 | self._bindir = None |
|
2022 | self._bindir = None | |
2022 | self._tmpbinddir = None |
|
2023 | self._tmpbinddir = None | |
2023 | self._pythondir = None |
|
2024 | self._pythondir = None | |
2024 | self._coveragefile = None |
|
2025 | self._coveragefile = None | |
2025 | self._createdfiles = [] |
|
2026 | self._createdfiles = [] | |
2026 | self._hgcommand = None |
|
2027 | self._hgcommand = None | |
2027 | self._hgpath = None |
|
2028 | self._hgpath = None | |
2028 | self._portoffset = 0 |
|
2029 | self._portoffset = 0 | |
2029 | self._ports = {} |
|
2030 | self._ports = {} | |
2030 |
|
2031 | |||
2031 | def run(self, args, parser=None): |
|
2032 | def run(self, args, parser=None): | |
2032 | """Run the test suite.""" |
|
2033 | """Run the test suite.""" | |
2033 | oldmask = os.umask(0o22) |
|
2034 | oldmask = os.umask(0o22) | |
2034 | try: |
|
2035 | try: | |
2035 | parser = parser or getparser() |
|
2036 | parser = parser or getparser() | |
2036 | options, args = parseargs(args, parser) |
|
2037 | options, args = parseargs(args, parser) | |
2037 | # positional arguments are paths to test files to run, so |
|
2038 | # positional arguments are paths to test files to run, so | |
2038 | # we make sure they're all bytestrings |
|
2039 | # we make sure they're all bytestrings | |
2039 | args = [_bytespath(a) for a in args] |
|
2040 | args = [_bytespath(a) for a in args] | |
2040 | self.options = options |
|
2041 | self.options = options | |
2041 |
|
2042 | |||
2042 | self._checktools() |
|
2043 | self._checktools() | |
2043 | tests = self.findtests(args) |
|
2044 | tests = self.findtests(args) | |
2044 | if options.profile_runner: |
|
2045 | if options.profile_runner: | |
2045 | import statprof |
|
2046 | import statprof | |
2046 | statprof.start() |
|
2047 | statprof.start() | |
2047 | result = self._run(tests) |
|
2048 | result = self._run(tests) | |
2048 | if options.profile_runner: |
|
2049 | if options.profile_runner: | |
2049 | statprof.stop() |
|
2050 | statprof.stop() | |
2050 | statprof.display() |
|
2051 | statprof.display() | |
2051 | return result |
|
2052 | return result | |
2052 |
|
2053 | |||
2053 | finally: |
|
2054 | finally: | |
2054 | os.umask(oldmask) |
|
2055 | os.umask(oldmask) | |
2055 |
|
2056 | |||
2056 | def _run(self, tests): |
|
2057 | def _run(self, tests): | |
2057 | if self.options.random: |
|
2058 | if self.options.random: | |
2058 | random.shuffle(tests) |
|
2059 | random.shuffle(tests) | |
2059 | else: |
|
2060 | else: | |
2060 | # keywords for slow tests |
|
2061 | # keywords for slow tests | |
2061 | slow = {b'svn': 10, |
|
2062 | slow = {b'svn': 10, | |
2062 | b'cvs': 10, |
|
2063 | b'cvs': 10, | |
2063 | b'hghave': 10, |
|
2064 | b'hghave': 10, | |
2064 | b'largefiles-update': 10, |
|
2065 | b'largefiles-update': 10, | |
2065 | b'run-tests': 10, |
|
2066 | b'run-tests': 10, | |
2066 | b'corruption': 10, |
|
2067 | b'corruption': 10, | |
2067 | b'race': 10, |
|
2068 | b'race': 10, | |
2068 | b'i18n': 10, |
|
2069 | b'i18n': 10, | |
2069 | b'check': 100, |
|
2070 | b'check': 100, | |
2070 | b'gendoc': 100, |
|
2071 | b'gendoc': 100, | |
2071 | b'contrib-perf': 200, |
|
2072 | b'contrib-perf': 200, | |
2072 | } |
|
2073 | } | |
2073 | perf = {} |
|
2074 | perf = {} | |
2074 | def sortkey(f): |
|
2075 | def sortkey(f): | |
2075 | # run largest tests first, as they tend to take the longest |
|
2076 | # run largest tests first, as they tend to take the longest | |
2076 | try: |
|
2077 | try: | |
2077 | return perf[f] |
|
2078 | return perf[f] | |
2078 | except KeyError: |
|
2079 | except KeyError: | |
2079 | try: |
|
2080 | try: | |
2080 | val = -os.stat(f).st_size |
|
2081 | val = -os.stat(f).st_size | |
2081 | except OSError as e: |
|
2082 | except OSError as e: | |
2082 | if e.errno != errno.ENOENT: |
|
2083 | if e.errno != errno.ENOENT: | |
2083 | raise |
|
2084 | raise | |
2084 | perf[f] = -1e9 # file does not exist, tell early |
|
2085 | perf[f] = -1e9 # file does not exist, tell early | |
2085 | return -1e9 |
|
2086 | return -1e9 | |
2086 | for kw, mul in slow.items(): |
|
2087 | for kw, mul in slow.items(): | |
2087 | if kw in f: |
|
2088 | if kw in f: | |
2088 | val *= mul |
|
2089 | val *= mul | |
2089 | if f.endswith(b'.py'): |
|
2090 | if f.endswith(b'.py'): | |
2090 | val /= 10.0 |
|
2091 | val /= 10.0 | |
2091 | perf[f] = val / 1000.0 |
|
2092 | perf[f] = val / 1000.0 | |
2092 | return perf[f] |
|
2093 | return perf[f] | |
2093 | tests.sort(key=sortkey) |
|
2094 | tests.sort(key=sortkey) | |
2094 |
|
2095 | |||
2095 | self._testdir = osenvironb[b'TESTDIR'] = getattr( |
|
2096 | self._testdir = osenvironb[b'TESTDIR'] = getattr( | |
2096 | os, 'getcwdb', os.getcwd)() |
|
2097 | os, 'getcwdb', os.getcwd)() | |
2097 |
|
2098 | |||
2098 | if 'PYTHONHASHSEED' not in os.environ: |
|
2099 | if 'PYTHONHASHSEED' not in os.environ: | |
2099 | # use a random python hash seed all the time |
|
2100 | # use a random python hash seed all the time | |
2100 | # we do the randomness ourself to know what seed is used |
|
2101 | # we do the randomness ourself to know what seed is used | |
2101 | os.environ['PYTHONHASHSEED'] = str(random.getrandbits(32)) |
|
2102 | os.environ['PYTHONHASHSEED'] = str(random.getrandbits(32)) | |
2102 |
|
2103 | |||
2103 | if self.options.tmpdir: |
|
2104 | if self.options.tmpdir: | |
2104 | self.options.keep_tmpdir = True |
|
2105 | self.options.keep_tmpdir = True | |
2105 | tmpdir = _bytespath(self.options.tmpdir) |
|
2106 | tmpdir = _bytespath(self.options.tmpdir) | |
2106 | if os.path.exists(tmpdir): |
|
2107 | if os.path.exists(tmpdir): | |
2107 | # Meaning of tmpdir has changed since 1.3: we used to create |
|
2108 | # Meaning of tmpdir has changed since 1.3: we used to create | |
2108 | # HGTMP inside tmpdir; now HGTMP is tmpdir. So fail if |
|
2109 | # HGTMP inside tmpdir; now HGTMP is tmpdir. So fail if | |
2109 | # tmpdir already exists. |
|
2110 | # tmpdir already exists. | |
2110 | print("error: temp dir %r already exists" % tmpdir) |
|
2111 | print("error: temp dir %r already exists" % tmpdir) | |
2111 | return 1 |
|
2112 | return 1 | |
2112 |
|
2113 | |||
2113 | # Automatically removing tmpdir sounds convenient, but could |
|
2114 | # Automatically removing tmpdir sounds convenient, but could | |
2114 | # really annoy anyone in the habit of using "--tmpdir=/tmp" |
|
2115 | # really annoy anyone in the habit of using "--tmpdir=/tmp" | |
2115 | # or "--tmpdir=$HOME". |
|
2116 | # or "--tmpdir=$HOME". | |
2116 | #vlog("# Removing temp dir", tmpdir) |
|
2117 | #vlog("# Removing temp dir", tmpdir) | |
2117 | #shutil.rmtree(tmpdir) |
|
2118 | #shutil.rmtree(tmpdir) | |
2118 | os.makedirs(tmpdir) |
|
2119 | os.makedirs(tmpdir) | |
2119 | else: |
|
2120 | else: | |
2120 | d = None |
|
2121 | d = None | |
2121 | if os.name == 'nt': |
|
2122 | if os.name == 'nt': | |
2122 | # without this, we get the default temp dir location, but |
|
2123 | # without this, we get the default temp dir location, but | |
2123 | # in all lowercase, which causes troubles with paths (issue3490) |
|
2124 | # in all lowercase, which causes troubles with paths (issue3490) | |
2124 | d = osenvironb.get(b'TMP', None) |
|
2125 | d = osenvironb.get(b'TMP', None) | |
2125 | tmpdir = tempfile.mkdtemp(b'', b'hgtests.', d) |
|
2126 | tmpdir = tempfile.mkdtemp(b'', b'hgtests.', d) | |
2126 |
|
2127 | |||
2127 | self._hgtmp = osenvironb[b'HGTMP'] = ( |
|
2128 | self._hgtmp = osenvironb[b'HGTMP'] = ( | |
2128 | os.path.realpath(tmpdir)) |
|
2129 | os.path.realpath(tmpdir)) | |
2129 |
|
2130 | |||
2130 | if self.options.with_hg: |
|
2131 | if self.options.with_hg: | |
2131 | self._installdir = None |
|
2132 | self._installdir = None | |
2132 | whg = self.options.with_hg |
|
2133 | whg = self.options.with_hg | |
2133 | self._bindir = os.path.dirname(os.path.realpath(whg)) |
|
2134 | self._bindir = os.path.dirname(os.path.realpath(whg)) | |
2134 | assert isinstance(self._bindir, bytes) |
|
2135 | assert isinstance(self._bindir, bytes) | |
2135 | self._hgcommand = os.path.basename(whg) |
|
2136 | self._hgcommand = os.path.basename(whg) | |
2136 | self._tmpbindir = os.path.join(self._hgtmp, b'install', b'bin') |
|
2137 | self._tmpbindir = os.path.join(self._hgtmp, b'install', b'bin') | |
2137 | os.makedirs(self._tmpbindir) |
|
2138 | os.makedirs(self._tmpbindir) | |
2138 |
|
2139 | |||
2139 | # This looks redundant with how Python initializes sys.path from |
|
2140 | # This looks redundant with how Python initializes sys.path from | |
2140 | # the location of the script being executed. Needed because the |
|
2141 | # the location of the script being executed. Needed because the | |
2141 | # "hg" specified by --with-hg is not the only Python script |
|
2142 | # "hg" specified by --with-hg is not the only Python script | |
2142 | # executed in the test suite that needs to import 'mercurial' |
|
2143 | # executed in the test suite that needs to import 'mercurial' | |
2143 | # ... which means it's not really redundant at all. |
|
2144 | # ... which means it's not really redundant at all. | |
2144 | self._pythondir = self._bindir |
|
2145 | self._pythondir = self._bindir | |
2145 | else: |
|
2146 | else: | |
2146 | self._installdir = os.path.join(self._hgtmp, b"install") |
|
2147 | self._installdir = os.path.join(self._hgtmp, b"install") | |
2147 | self._bindir = os.path.join(self._installdir, b"bin") |
|
2148 | self._bindir = os.path.join(self._installdir, b"bin") | |
2148 | self._hgcommand = b'hg' |
|
2149 | self._hgcommand = b'hg' | |
2149 | self._tmpbindir = self._bindir |
|
2150 | self._tmpbindir = self._bindir | |
2150 | self._pythondir = os.path.join(self._installdir, b"lib", b"python") |
|
2151 | self._pythondir = os.path.join(self._installdir, b"lib", b"python") | |
2151 |
|
2152 | |||
2152 | # set CHGHG, then replace "hg" command by "chg" |
|
2153 | # set CHGHG, then replace "hg" command by "chg" | |
2153 | chgbindir = self._bindir |
|
2154 | chgbindir = self._bindir | |
2154 | if self.options.chg or self.options.with_chg: |
|
2155 | if self.options.chg or self.options.with_chg: | |
2155 | osenvironb[b'CHGHG'] = os.path.join(self._bindir, self._hgcommand) |
|
2156 | osenvironb[b'CHGHG'] = os.path.join(self._bindir, self._hgcommand) | |
2156 | else: |
|
2157 | else: | |
2157 | osenvironb.pop(b'CHGHG', None) # drop flag for hghave |
|
2158 | osenvironb.pop(b'CHGHG', None) # drop flag for hghave | |
2158 | if self.options.chg: |
|
2159 | if self.options.chg: | |
2159 | self._hgcommand = b'chg' |
|
2160 | self._hgcommand = b'chg' | |
2160 | elif self.options.with_chg: |
|
2161 | elif self.options.with_chg: | |
2161 | chgbindir = os.path.dirname(os.path.realpath(self.options.with_chg)) |
|
2162 | chgbindir = os.path.dirname(os.path.realpath(self.options.with_chg)) | |
2162 | self._hgcommand = os.path.basename(self.options.with_chg) |
|
2163 | self._hgcommand = os.path.basename(self.options.with_chg) | |
2163 |
|
2164 | |||
2164 | osenvironb[b"BINDIR"] = self._bindir |
|
2165 | osenvironb[b"BINDIR"] = self._bindir | |
2165 | osenvironb[b"PYTHON"] = PYTHON |
|
2166 | osenvironb[b"PYTHON"] = PYTHON | |
2166 |
|
2167 | |||
2167 | if self.options.with_python3: |
|
2168 | if self.options.with_python3: | |
2168 | osenvironb[b'PYTHON3'] = self.options.with_python3 |
|
2169 | osenvironb[b'PYTHON3'] = self.options.with_python3 | |
2169 |
|
2170 | |||
2170 | fileb = _bytespath(__file__) |
|
2171 | fileb = _bytespath(__file__) | |
2171 | runtestdir = os.path.abspath(os.path.dirname(fileb)) |
|
2172 | runtestdir = os.path.abspath(os.path.dirname(fileb)) | |
2172 | osenvironb[b'RUNTESTDIR'] = runtestdir |
|
2173 | osenvironb[b'RUNTESTDIR'] = runtestdir | |
2173 | if PYTHON3: |
|
2174 | if PYTHON3: | |
2174 | sepb = _bytespath(os.pathsep) |
|
2175 | sepb = _bytespath(os.pathsep) | |
2175 | else: |
|
2176 | else: | |
2176 | sepb = os.pathsep |
|
2177 | sepb = os.pathsep | |
2177 | path = [self._bindir, runtestdir] + osenvironb[b"PATH"].split(sepb) |
|
2178 | path = [self._bindir, runtestdir] + osenvironb[b"PATH"].split(sepb) | |
2178 | if os.path.islink(__file__): |
|
2179 | if os.path.islink(__file__): | |
2179 | # test helper will likely be at the end of the symlink |
|
2180 | # test helper will likely be at the end of the symlink | |
2180 | realfile = os.path.realpath(fileb) |
|
2181 | realfile = os.path.realpath(fileb) | |
2181 | realdir = os.path.abspath(os.path.dirname(realfile)) |
|
2182 | realdir = os.path.abspath(os.path.dirname(realfile)) | |
2182 | path.insert(2, realdir) |
|
2183 | path.insert(2, realdir) | |
2183 | if chgbindir != self._bindir: |
|
2184 | if chgbindir != self._bindir: | |
2184 | path.insert(1, chgbindir) |
|
2185 | path.insert(1, chgbindir) | |
2185 | if self._testdir != runtestdir: |
|
2186 | if self._testdir != runtestdir: | |
2186 | path = [self._testdir] + path |
|
2187 | path = [self._testdir] + path | |
2187 | if self._tmpbindir != self._bindir: |
|
2188 | if self._tmpbindir != self._bindir: | |
2188 | path = [self._tmpbindir] + path |
|
2189 | path = [self._tmpbindir] + path | |
2189 | osenvironb[b"PATH"] = sepb.join(path) |
|
2190 | osenvironb[b"PATH"] = sepb.join(path) | |
2190 |
|
2191 | |||
2191 | # Include TESTDIR in PYTHONPATH so that out-of-tree extensions |
|
2192 | # Include TESTDIR in PYTHONPATH so that out-of-tree extensions | |
2192 | # can run .../tests/run-tests.py test-foo where test-foo |
|
2193 | # can run .../tests/run-tests.py test-foo where test-foo | |
2193 | # adds an extension to HGRC. Also include run-test.py directory to |
|
2194 | # adds an extension to HGRC. Also include run-test.py directory to | |
2194 | # import modules like heredoctest. |
|
2195 | # import modules like heredoctest. | |
2195 | pypath = [self._pythondir, self._testdir, runtestdir] |
|
2196 | pypath = [self._pythondir, self._testdir, runtestdir] | |
2196 | # We have to augment PYTHONPATH, rather than simply replacing |
|
2197 | # We have to augment PYTHONPATH, rather than simply replacing | |
2197 | # it, in case external libraries are only available via current |
|
2198 | # it, in case external libraries are only available via current | |
2198 | # PYTHONPATH. (In particular, the Subversion bindings on OS X |
|
2199 | # PYTHONPATH. (In particular, the Subversion bindings on OS X | |
2199 | # are in /opt/subversion.) |
|
2200 | # are in /opt/subversion.) | |
2200 | oldpypath = osenvironb.get(IMPL_PATH) |
|
2201 | oldpypath = osenvironb.get(IMPL_PATH) | |
2201 | if oldpypath: |
|
2202 | if oldpypath: | |
2202 | pypath.append(oldpypath) |
|
2203 | pypath.append(oldpypath) | |
2203 | osenvironb[IMPL_PATH] = sepb.join(pypath) |
|
2204 | osenvironb[IMPL_PATH] = sepb.join(pypath) | |
2204 |
|
2205 | |||
2205 | if self.options.pure: |
|
2206 | if self.options.pure: | |
2206 | os.environ["HGTEST_RUN_TESTS_PURE"] = "--pure" |
|
2207 | os.environ["HGTEST_RUN_TESTS_PURE"] = "--pure" | |
2207 | os.environ["HGMODULEPOLICY"] = "py" |
|
2208 | os.environ["HGMODULEPOLICY"] = "py" | |
2208 |
|
2209 | |||
2209 | if self.options.allow_slow_tests: |
|
2210 | if self.options.allow_slow_tests: | |
2210 | os.environ["HGTEST_SLOW"] = "slow" |
|
2211 | os.environ["HGTEST_SLOW"] = "slow" | |
2211 | elif 'HGTEST_SLOW' in os.environ: |
|
2212 | elif 'HGTEST_SLOW' in os.environ: | |
2212 | del os.environ['HGTEST_SLOW'] |
|
2213 | del os.environ['HGTEST_SLOW'] | |
2213 |
|
2214 | |||
2214 | self._coveragefile = os.path.join(self._testdir, b'.coverage') |
|
2215 | self._coveragefile = os.path.join(self._testdir, b'.coverage') | |
2215 |
|
2216 | |||
2216 | vlog("# Using TESTDIR", self._testdir) |
|
2217 | vlog("# Using TESTDIR", self._testdir) | |
2217 | vlog("# Using RUNTESTDIR", osenvironb[b'RUNTESTDIR']) |
|
2218 | vlog("# Using RUNTESTDIR", osenvironb[b'RUNTESTDIR']) | |
2218 | vlog("# Using HGTMP", self._hgtmp) |
|
2219 | vlog("# Using HGTMP", self._hgtmp) | |
2219 | vlog("# Using PATH", os.environ["PATH"]) |
|
2220 | vlog("# Using PATH", os.environ["PATH"]) | |
2220 | vlog("# Using", IMPL_PATH, osenvironb[IMPL_PATH]) |
|
2221 | vlog("# Using", IMPL_PATH, osenvironb[IMPL_PATH]) | |
2221 |
|
2222 | |||
2222 | try: |
|
2223 | try: | |
2223 | return self._runtests(tests) or 0 |
|
2224 | return self._runtests(tests) or 0 | |
2224 | finally: |
|
2225 | finally: | |
2225 | time.sleep(.1) |
|
2226 | time.sleep(.1) | |
2226 | self._cleanup() |
|
2227 | self._cleanup() | |
2227 |
|
2228 | |||
2228 | def findtests(self, args): |
|
2229 | def findtests(self, args): | |
2229 | """Finds possible test files from arguments. |
|
2230 | """Finds possible test files from arguments. | |
2230 |
|
2231 | |||
2231 | If you wish to inject custom tests into the test harness, this would |
|
2232 | If you wish to inject custom tests into the test harness, this would | |
2232 | be a good function to monkeypatch or override in a derived class. |
|
2233 | be a good function to monkeypatch or override in a derived class. | |
2233 | """ |
|
2234 | """ | |
2234 | if not args: |
|
2235 | if not args: | |
2235 | if self.options.changed: |
|
2236 | if self.options.changed: | |
2236 | proc = Popen4('hg st --rev "%s" -man0 .' % |
|
2237 | proc = Popen4('hg st --rev "%s" -man0 .' % | |
2237 | self.options.changed, None, 0) |
|
2238 | self.options.changed, None, 0) | |
2238 | stdout, stderr = proc.communicate() |
|
2239 | stdout, stderr = proc.communicate() | |
2239 | args = stdout.strip(b'\0').split(b'\0') |
|
2240 | args = stdout.strip(b'\0').split(b'\0') | |
2240 | else: |
|
2241 | else: | |
2241 | args = os.listdir(b'.') |
|
2242 | args = os.listdir(b'.') | |
2242 |
|
2243 | |||
2243 | return [t for t in args |
|
2244 | return [t for t in args | |
2244 | if os.path.basename(t).startswith(b'test-') |
|
2245 | if os.path.basename(t).startswith(b'test-') | |
2245 | and (t.endswith(b'.py') or t.endswith(b'.t'))] |
|
2246 | and (t.endswith(b'.py') or t.endswith(b'.t'))] | |
2246 |
|
2247 | |||
2247 | def _runtests(self, tests): |
|
2248 | def _runtests(self, tests): | |
2248 | try: |
|
2249 | try: | |
2249 | if self._installdir: |
|
2250 | if self._installdir: | |
2250 | self._installhg() |
|
2251 | self._installhg() | |
2251 | self._checkhglib("Testing") |
|
2252 | self._checkhglib("Testing") | |
2252 | else: |
|
2253 | else: | |
2253 | self._usecorrectpython() |
|
2254 | self._usecorrectpython() | |
2254 | if self.options.chg: |
|
2255 | if self.options.chg: | |
2255 | assert self._installdir |
|
2256 | assert self._installdir | |
2256 | self._installchg() |
|
2257 | self._installchg() | |
2257 |
|
2258 | |||
2258 | if self.options.restart: |
|
2259 | if self.options.restart: | |
2259 | orig = list(tests) |
|
2260 | orig = list(tests) | |
2260 | while tests: |
|
2261 | while tests: | |
2261 | if os.path.exists(tests[0] + ".err"): |
|
2262 | if os.path.exists(tests[0] + ".err"): | |
2262 | break |
|
2263 | break | |
2263 | tests.pop(0) |
|
2264 | tests.pop(0) | |
2264 | if not tests: |
|
2265 | if not tests: | |
2265 | print("running all tests") |
|
2266 | print("running all tests") | |
2266 | tests = orig |
|
2267 | tests = orig | |
2267 |
|
2268 | |||
2268 | tests = [self._gettest(t, i) for i, t in enumerate(tests)] |
|
2269 | tests = [self._gettest(t, i) for i, t in enumerate(tests)] | |
2269 |
|
2270 | |||
2270 | failed = False |
|
2271 | failed = False | |
2271 | warned = False |
|
2272 | warned = False | |
2272 | kws = self.options.keywords |
|
2273 | kws = self.options.keywords | |
2273 | if kws is not None and PYTHON3: |
|
2274 | if kws is not None and PYTHON3: | |
2274 | kws = kws.encode('utf-8') |
|
2275 | kws = kws.encode('utf-8') | |
2275 |
|
2276 | |||
2276 | suite = TestSuite(self._testdir, |
|
2277 | suite = TestSuite(self._testdir, | |
2277 | jobs=self.options.jobs, |
|
2278 | jobs=self.options.jobs, | |
2278 | whitelist=self.options.whitelisted, |
|
2279 | whitelist=self.options.whitelisted, | |
2279 | blacklist=self.options.blacklist, |
|
2280 | blacklist=self.options.blacklist, | |
2280 | retest=self.options.retest, |
|
2281 | retest=self.options.retest, | |
2281 | keywords=kws, |
|
2282 | keywords=kws, | |
2282 | loop=self.options.loop, |
|
2283 | loop=self.options.loop, | |
2283 | runs_per_test=self.options.runs_per_test, |
|
2284 | runs_per_test=self.options.runs_per_test, | |
2284 | showchannels=self.options.showchannels, |
|
2285 | showchannels=self.options.showchannels, | |
2285 | tests=tests, loadtest=self._gettest) |
|
2286 | tests=tests, loadtest=self._gettest) | |
2286 | verbosity = 1 |
|
2287 | verbosity = 1 | |
2287 | if self.options.verbose: |
|
2288 | if self.options.verbose: | |
2288 | verbosity = 2 |
|
2289 | verbosity = 2 | |
2289 | runner = TextTestRunner(self, verbosity=verbosity) |
|
2290 | runner = TextTestRunner(self, verbosity=verbosity) | |
2290 | result = runner.run(suite) |
|
2291 | result = runner.run(suite) | |
2291 |
|
2292 | |||
2292 | if result.failures: |
|
2293 | if result.failures: | |
2293 | failed = True |
|
2294 | failed = True | |
2294 | if result.warned: |
|
2295 | if result.warned: | |
2295 | warned = True |
|
2296 | warned = True | |
2296 |
|
2297 | |||
2297 | if self.options.anycoverage: |
|
2298 | if self.options.anycoverage: | |
2298 | self._outputcoverage() |
|
2299 | self._outputcoverage() | |
2299 | except KeyboardInterrupt: |
|
2300 | except KeyboardInterrupt: | |
2300 | failed = True |
|
2301 | failed = True | |
2301 | print("\ninterrupted!") |
|
2302 | print("\ninterrupted!") | |
2302 |
|
2303 | |||
2303 | if failed: |
|
2304 | if failed: | |
2304 | return 1 |
|
2305 | return 1 | |
2305 | if warned: |
|
2306 | if warned: | |
2306 | return 80 |
|
2307 | return 80 | |
2307 |
|
2308 | |||
2308 | def _getport(self, count): |
|
2309 | def _getport(self, count): | |
2309 | port = self._ports.get(count) # do we have a cached entry? |
|
2310 | port = self._ports.get(count) # do we have a cached entry? | |
2310 | if port is None: |
|
2311 | if port is None: | |
2311 | portneeded = 3 |
|
2312 | portneeded = 3 | |
2312 | # above 100 tries we just give up and let test reports failure |
|
2313 | # above 100 tries we just give up and let test reports failure | |
2313 | for tries in xrange(100): |
|
2314 | for tries in xrange(100): | |
2314 | allfree = True |
|
2315 | allfree = True | |
2315 | port = self.options.port + self._portoffset |
|
2316 | port = self.options.port + self._portoffset | |
2316 | for idx in xrange(portneeded): |
|
2317 | for idx in xrange(portneeded): | |
2317 | if not checkportisavailable(port + idx): |
|
2318 | if not checkportisavailable(port + idx): | |
2318 | allfree = False |
|
2319 | allfree = False | |
2319 | break |
|
2320 | break | |
2320 | self._portoffset += portneeded |
|
2321 | self._portoffset += portneeded | |
2321 | if allfree: |
|
2322 | if allfree: | |
2322 | break |
|
2323 | break | |
2323 | self._ports[count] = port |
|
2324 | self._ports[count] = port | |
2324 | return port |
|
2325 | return port | |
2325 |
|
2326 | |||
2326 | def _gettest(self, test, count): |
|
2327 | def _gettest(self, test, count): | |
2327 | """Obtain a Test by looking at its filename. |
|
2328 | """Obtain a Test by looking at its filename. | |
2328 |
|
2329 | |||
2329 | Returns a Test instance. The Test may not be runnable if it doesn't |
|
2330 | Returns a Test instance. The Test may not be runnable if it doesn't | |
2330 | map to a known type. |
|
2331 | map to a known type. | |
2331 | """ |
|
2332 | """ | |
2332 | lctest = test.lower() |
|
2333 | lctest = test.lower() | |
2333 | testcls = Test |
|
2334 | testcls = Test | |
2334 |
|
2335 | |||
2335 | for ext, cls in self.TESTTYPES: |
|
2336 | for ext, cls in self.TESTTYPES: | |
2336 | if lctest.endswith(ext): |
|
2337 | if lctest.endswith(ext): | |
2337 | testcls = cls |
|
2338 | testcls = cls | |
2338 | break |
|
2339 | break | |
2339 |
|
2340 | |||
2340 | refpath = os.path.join(self._testdir, test) |
|
2341 | refpath = os.path.join(self._testdir, test) | |
2341 | tmpdir = os.path.join(self._hgtmp, b'child%d' % count) |
|
2342 | tmpdir = os.path.join(self._hgtmp, b'child%d' % count) | |
2342 |
|
2343 | |||
2343 | t = testcls(refpath, tmpdir, |
|
2344 | t = testcls(refpath, tmpdir, | |
2344 | keeptmpdir=self.options.keep_tmpdir, |
|
2345 | keeptmpdir=self.options.keep_tmpdir, | |
2345 | debug=self.options.debug, |
|
2346 | debug=self.options.debug, | |
2346 | timeout=self.options.timeout, |
|
2347 | timeout=self.options.timeout, | |
2347 | startport=self._getport(count), |
|
2348 | startport=self._getport(count), | |
2348 | extraconfigopts=self.options.extra_config_opt, |
|
2349 | extraconfigopts=self.options.extra_config_opt, | |
2349 | py3kwarnings=self.options.py3k_warnings, |
|
2350 | py3kwarnings=self.options.py3k_warnings, | |
2350 | shell=self.options.shell, |
|
2351 | shell=self.options.shell, | |
2351 | hgcommand=self._hgcommand, |
|
2352 | hgcommand=self._hgcommand, | |
2352 | usechg=bool(self.options.with_chg or self.options.chg), |
|
2353 | usechg=bool(self.options.with_chg or self.options.chg), | |
2353 | useipv6=useipv6) |
|
2354 | useipv6=useipv6) | |
2354 | t.should_reload = True |
|
2355 | t.should_reload = True | |
2355 | return t |
|
2356 | return t | |
2356 |
|
2357 | |||
2357 | def _cleanup(self): |
|
2358 | def _cleanup(self): | |
2358 | """Clean up state from this test invocation.""" |
|
2359 | """Clean up state from this test invocation.""" | |
2359 | if self.options.keep_tmpdir: |
|
2360 | if self.options.keep_tmpdir: | |
2360 | return |
|
2361 | return | |
2361 |
|
2362 | |||
2362 | vlog("# Cleaning up HGTMP", self._hgtmp) |
|
2363 | vlog("# Cleaning up HGTMP", self._hgtmp) | |
2363 | shutil.rmtree(self._hgtmp, True) |
|
2364 | shutil.rmtree(self._hgtmp, True) | |
2364 | for f in self._createdfiles: |
|
2365 | for f in self._createdfiles: | |
2365 | try: |
|
2366 | try: | |
2366 | os.remove(f) |
|
2367 | os.remove(f) | |
2367 | except OSError: |
|
2368 | except OSError: | |
2368 | pass |
|
2369 | pass | |
2369 |
|
2370 | |||
2370 | def _usecorrectpython(self): |
|
2371 | def _usecorrectpython(self): | |
2371 | """Configure the environment to use the appropriate Python in tests.""" |
|
2372 | """Configure the environment to use the appropriate Python in tests.""" | |
2372 | # Tests must use the same interpreter as us or bad things will happen. |
|
2373 | # Tests must use the same interpreter as us or bad things will happen. | |
2373 | pyexename = sys.platform == 'win32' and b'python.exe' or b'python' |
|
2374 | pyexename = sys.platform == 'win32' and b'python.exe' or b'python' | |
2374 | if getattr(os, 'symlink', None): |
|
2375 | if getattr(os, 'symlink', None): | |
2375 | vlog("# Making python executable in test path a symlink to '%s'" % |
|
2376 | vlog("# Making python executable in test path a symlink to '%s'" % | |
2376 | sys.executable) |
|
2377 | sys.executable) | |
2377 | mypython = os.path.join(self._tmpbindir, pyexename) |
|
2378 | mypython = os.path.join(self._tmpbindir, pyexename) | |
2378 | try: |
|
2379 | try: | |
2379 | if os.readlink(mypython) == sys.executable: |
|
2380 | if os.readlink(mypython) == sys.executable: | |
2380 | return |
|
2381 | return | |
2381 | os.unlink(mypython) |
|
2382 | os.unlink(mypython) | |
2382 | except OSError as err: |
|
2383 | except OSError as err: | |
2383 | if err.errno != errno.ENOENT: |
|
2384 | if err.errno != errno.ENOENT: | |
2384 | raise |
|
2385 | raise | |
2385 | if self._findprogram(pyexename) != sys.executable: |
|
2386 | if self._findprogram(pyexename) != sys.executable: | |
2386 | try: |
|
2387 | try: | |
2387 | os.symlink(sys.executable, mypython) |
|
2388 | os.symlink(sys.executable, mypython) | |
2388 | self._createdfiles.append(mypython) |
|
2389 | self._createdfiles.append(mypython) | |
2389 | except OSError as err: |
|
2390 | except OSError as err: | |
2390 | # child processes may race, which is harmless |
|
2391 | # child processes may race, which is harmless | |
2391 | if err.errno != errno.EEXIST: |
|
2392 | if err.errno != errno.EEXIST: | |
2392 | raise |
|
2393 | raise | |
2393 | else: |
|
2394 | else: | |
2394 | exedir, exename = os.path.split(sys.executable) |
|
2395 | exedir, exename = os.path.split(sys.executable) | |
2395 | vlog("# Modifying search path to find %s as %s in '%s'" % |
|
2396 | vlog("# Modifying search path to find %s as %s in '%s'" % | |
2396 | (exename, pyexename, exedir)) |
|
2397 | (exename, pyexename, exedir)) | |
2397 | path = os.environ['PATH'].split(os.pathsep) |
|
2398 | path = os.environ['PATH'].split(os.pathsep) | |
2398 | while exedir in path: |
|
2399 | while exedir in path: | |
2399 | path.remove(exedir) |
|
2400 | path.remove(exedir) | |
2400 | os.environ['PATH'] = os.pathsep.join([exedir] + path) |
|
2401 | os.environ['PATH'] = os.pathsep.join([exedir] + path) | |
2401 | if not self._findprogram(pyexename): |
|
2402 | if not self._findprogram(pyexename): | |
2402 | print("WARNING: Cannot find %s in search path" % pyexename) |
|
2403 | print("WARNING: Cannot find %s in search path" % pyexename) | |
2403 |
|
2404 | |||
2404 | def _installhg(self): |
|
2405 | def _installhg(self): | |
2405 | """Install hg into the test environment. |
|
2406 | """Install hg into the test environment. | |
2406 |
|
2407 | |||
2407 | This will also configure hg with the appropriate testing settings. |
|
2408 | This will also configure hg with the appropriate testing settings. | |
2408 | """ |
|
2409 | """ | |
2409 | vlog("# Performing temporary installation of HG") |
|
2410 | vlog("# Performing temporary installation of HG") | |
2410 | installerrs = os.path.join(self._hgtmp, b"install.err") |
|
2411 | installerrs = os.path.join(self._hgtmp, b"install.err") | |
2411 | compiler = '' |
|
2412 | compiler = '' | |
2412 | if self.options.compiler: |
|
2413 | if self.options.compiler: | |
2413 | compiler = '--compiler ' + self.options.compiler |
|
2414 | compiler = '--compiler ' + self.options.compiler | |
2414 | if self.options.pure: |
|
2415 | if self.options.pure: | |
2415 | pure = b"--pure" |
|
2416 | pure = b"--pure" | |
2416 | else: |
|
2417 | else: | |
2417 | pure = b"" |
|
2418 | pure = b"" | |
2418 |
|
2419 | |||
2419 | # Run installer in hg root |
|
2420 | # Run installer in hg root | |
2420 | script = os.path.realpath(sys.argv[0]) |
|
2421 | script = os.path.realpath(sys.argv[0]) | |
2421 | exe = sys.executable |
|
2422 | exe = sys.executable | |
2422 | if PYTHON3: |
|
2423 | if PYTHON3: | |
2423 | compiler = _bytespath(compiler) |
|
2424 | compiler = _bytespath(compiler) | |
2424 | script = _bytespath(script) |
|
2425 | script = _bytespath(script) | |
2425 | exe = _bytespath(exe) |
|
2426 | exe = _bytespath(exe) | |
2426 | hgroot = os.path.dirname(os.path.dirname(script)) |
|
2427 | hgroot = os.path.dirname(os.path.dirname(script)) | |
2427 | self._hgroot = hgroot |
|
2428 | self._hgroot = hgroot | |
2428 | os.chdir(hgroot) |
|
2429 | os.chdir(hgroot) | |
2429 | nohome = b'--home=""' |
|
2430 | nohome = b'--home=""' | |
2430 | if os.name == 'nt': |
|
2431 | if os.name == 'nt': | |
2431 | # The --home="" trick works only on OS where os.sep == '/' |
|
2432 | # The --home="" trick works only on OS where os.sep == '/' | |
2432 | # because of a distutils convert_path() fast-path. Avoid it at |
|
2433 | # because of a distutils convert_path() fast-path. Avoid it at | |
2433 | # least on Windows for now, deal with .pydistutils.cfg bugs |
|
2434 | # least on Windows for now, deal with .pydistutils.cfg bugs | |
2434 | # when they happen. |
|
2435 | # when they happen. | |
2435 | nohome = b'' |
|
2436 | nohome = b'' | |
2436 | cmd = (b'%(exe)s setup.py %(pure)s clean --all' |
|
2437 | cmd = (b'%(exe)s setup.py %(pure)s clean --all' | |
2437 | b' build %(compiler)s --build-base="%(base)s"' |
|
2438 | b' build %(compiler)s --build-base="%(base)s"' | |
2438 | b' install --force --prefix="%(prefix)s"' |
|
2439 | b' install --force --prefix="%(prefix)s"' | |
2439 | b' --install-lib="%(libdir)s"' |
|
2440 | b' --install-lib="%(libdir)s"' | |
2440 | b' --install-scripts="%(bindir)s" %(nohome)s >%(logfile)s 2>&1' |
|
2441 | b' --install-scripts="%(bindir)s" %(nohome)s >%(logfile)s 2>&1' | |
2441 | % {b'exe': exe, b'pure': pure, |
|
2442 | % {b'exe': exe, b'pure': pure, | |
2442 | b'compiler': compiler, |
|
2443 | b'compiler': compiler, | |
2443 | b'base': os.path.join(self._hgtmp, b"build"), |
|
2444 | b'base': os.path.join(self._hgtmp, b"build"), | |
2444 | b'prefix': self._installdir, b'libdir': self._pythondir, |
|
2445 | b'prefix': self._installdir, b'libdir': self._pythondir, | |
2445 | b'bindir': self._bindir, |
|
2446 | b'bindir': self._bindir, | |
2446 | b'nohome': nohome, b'logfile': installerrs}) |
|
2447 | b'nohome': nohome, b'logfile': installerrs}) | |
2447 |
|
2448 | |||
2448 | # setuptools requires install directories to exist. |
|
2449 | # setuptools requires install directories to exist. | |
2449 | def makedirs(p): |
|
2450 | def makedirs(p): | |
2450 | try: |
|
2451 | try: | |
2451 | os.makedirs(p) |
|
2452 | os.makedirs(p) | |
2452 | except OSError as e: |
|
2453 | except OSError as e: | |
2453 | if e.errno != errno.EEXIST: |
|
2454 | if e.errno != errno.EEXIST: | |
2454 | raise |
|
2455 | raise | |
2455 | makedirs(self._pythondir) |
|
2456 | makedirs(self._pythondir) | |
2456 | makedirs(self._bindir) |
|
2457 | makedirs(self._bindir) | |
2457 |
|
2458 | |||
2458 | vlog("# Running", cmd) |
|
2459 | vlog("# Running", cmd) | |
2459 | if os.system(cmd) == 0: |
|
2460 | if os.system(cmd) == 0: | |
2460 | if not self.options.verbose: |
|
2461 | if not self.options.verbose: | |
2461 | try: |
|
2462 | try: | |
2462 | os.remove(installerrs) |
|
2463 | os.remove(installerrs) | |
2463 | except OSError as e: |
|
2464 | except OSError as e: | |
2464 | if e.errno != errno.ENOENT: |
|
2465 | if e.errno != errno.ENOENT: | |
2465 | raise |
|
2466 | raise | |
2466 | else: |
|
2467 | else: | |
2467 | f = open(installerrs, 'rb') |
|
2468 | f = open(installerrs, 'rb') | |
2468 | for line in f: |
|
2469 | for line in f: | |
2469 | if PYTHON3: |
|
2470 | if PYTHON3: | |
2470 | sys.stdout.buffer.write(line) |
|
2471 | sys.stdout.buffer.write(line) | |
2471 | else: |
|
2472 | else: | |
2472 | sys.stdout.write(line) |
|
2473 | sys.stdout.write(line) | |
2473 | f.close() |
|
2474 | f.close() | |
2474 | sys.exit(1) |
|
2475 | sys.exit(1) | |
2475 | os.chdir(self._testdir) |
|
2476 | os.chdir(self._testdir) | |
2476 |
|
2477 | |||
2477 | self._usecorrectpython() |
|
2478 | self._usecorrectpython() | |
2478 |
|
2479 | |||
2479 | if self.options.py3k_warnings and not self.options.anycoverage: |
|
2480 | if self.options.py3k_warnings and not self.options.anycoverage: | |
2480 | vlog("# Updating hg command to enable Py3k Warnings switch") |
|
2481 | vlog("# Updating hg command to enable Py3k Warnings switch") | |
2481 | f = open(os.path.join(self._bindir, 'hg'), 'rb') |
|
2482 | f = open(os.path.join(self._bindir, 'hg'), 'rb') | |
2482 | lines = [line.rstrip() for line in f] |
|
2483 | lines = [line.rstrip() for line in f] | |
2483 | lines[0] += ' -3' |
|
2484 | lines[0] += ' -3' | |
2484 | f.close() |
|
2485 | f.close() | |
2485 | f = open(os.path.join(self._bindir, 'hg'), 'wb') |
|
2486 | f = open(os.path.join(self._bindir, 'hg'), 'wb') | |
2486 | for line in lines: |
|
2487 | for line in lines: | |
2487 | f.write(line + '\n') |
|
2488 | f.write(line + '\n') | |
2488 | f.close() |
|
2489 | f.close() | |
2489 |
|
2490 | |||
2490 | hgbat = os.path.join(self._bindir, b'hg.bat') |
|
2491 | hgbat = os.path.join(self._bindir, b'hg.bat') | |
2491 | if os.path.isfile(hgbat): |
|
2492 | if os.path.isfile(hgbat): | |
2492 | # hg.bat expects to be put in bin/scripts while run-tests.py |
|
2493 | # hg.bat expects to be put in bin/scripts while run-tests.py | |
2493 | # installation layout put it in bin/ directly. Fix it |
|
2494 | # installation layout put it in bin/ directly. Fix it | |
2494 | f = open(hgbat, 'rb') |
|
2495 | f = open(hgbat, 'rb') | |
2495 | data = f.read() |
|
2496 | data = f.read() | |
2496 | f.close() |
|
2497 | f.close() | |
2497 | if b'"%~dp0..\python" "%~dp0hg" %*' in data: |
|
2498 | if b'"%~dp0..\python" "%~dp0hg" %*' in data: | |
2498 | data = data.replace(b'"%~dp0..\python" "%~dp0hg" %*', |
|
2499 | data = data.replace(b'"%~dp0..\python" "%~dp0hg" %*', | |
2499 | b'"%~dp0python" "%~dp0hg" %*') |
|
2500 | b'"%~dp0python" "%~dp0hg" %*') | |
2500 | f = open(hgbat, 'wb') |
|
2501 | f = open(hgbat, 'wb') | |
2501 | f.write(data) |
|
2502 | f.write(data) | |
2502 | f.close() |
|
2503 | f.close() | |
2503 | else: |
|
2504 | else: | |
2504 | print('WARNING: cannot fix hg.bat reference to python.exe') |
|
2505 | print('WARNING: cannot fix hg.bat reference to python.exe') | |
2505 |
|
2506 | |||
2506 | if self.options.anycoverage: |
|
2507 | if self.options.anycoverage: | |
2507 | custom = os.path.join(self._testdir, 'sitecustomize.py') |
|
2508 | custom = os.path.join(self._testdir, 'sitecustomize.py') | |
2508 | target = os.path.join(self._pythondir, 'sitecustomize.py') |
|
2509 | target = os.path.join(self._pythondir, 'sitecustomize.py') | |
2509 | vlog('# Installing coverage trigger to %s' % target) |
|
2510 | vlog('# Installing coverage trigger to %s' % target) | |
2510 | shutil.copyfile(custom, target) |
|
2511 | shutil.copyfile(custom, target) | |
2511 | rc = os.path.join(self._testdir, '.coveragerc') |
|
2512 | rc = os.path.join(self._testdir, '.coveragerc') | |
2512 | vlog('# Installing coverage rc to %s' % rc) |
|
2513 | vlog('# Installing coverage rc to %s' % rc) | |
2513 | os.environ['COVERAGE_PROCESS_START'] = rc |
|
2514 | os.environ['COVERAGE_PROCESS_START'] = rc | |
2514 | covdir = os.path.join(self._installdir, '..', 'coverage') |
|
2515 | covdir = os.path.join(self._installdir, '..', 'coverage') | |
2515 | try: |
|
2516 | try: | |
2516 | os.mkdir(covdir) |
|
2517 | os.mkdir(covdir) | |
2517 | except OSError as e: |
|
2518 | except OSError as e: | |
2518 | if e.errno != errno.EEXIST: |
|
2519 | if e.errno != errno.EEXIST: | |
2519 | raise |
|
2520 | raise | |
2520 |
|
2521 | |||
2521 | os.environ['COVERAGE_DIR'] = covdir |
|
2522 | os.environ['COVERAGE_DIR'] = covdir | |
2522 |
|
2523 | |||
2523 | def _checkhglib(self, verb): |
|
2524 | def _checkhglib(self, verb): | |
2524 | """Ensure that the 'mercurial' package imported by python is |
|
2525 | """Ensure that the 'mercurial' package imported by python is | |
2525 | the one we expect it to be. If not, print a warning to stderr.""" |
|
2526 | the one we expect it to be. If not, print a warning to stderr.""" | |
2526 | if ((self._bindir == self._pythondir) and |
|
2527 | if ((self._bindir == self._pythondir) and | |
2527 | (self._bindir != self._tmpbindir)): |
|
2528 | (self._bindir != self._tmpbindir)): | |
2528 | # The pythondir has been inferred from --with-hg flag. |
|
2529 | # The pythondir has been inferred from --with-hg flag. | |
2529 | # We cannot expect anything sensible here. |
|
2530 | # We cannot expect anything sensible here. | |
2530 | return |
|
2531 | return | |
2531 | expecthg = os.path.join(self._pythondir, b'mercurial') |
|
2532 | expecthg = os.path.join(self._pythondir, b'mercurial') | |
2532 | actualhg = self._gethgpath() |
|
2533 | actualhg = self._gethgpath() | |
2533 | if os.path.abspath(actualhg) != os.path.abspath(expecthg): |
|
2534 | if os.path.abspath(actualhg) != os.path.abspath(expecthg): | |
2534 | sys.stderr.write('warning: %s with unexpected mercurial lib: %s\n' |
|
2535 | sys.stderr.write('warning: %s with unexpected mercurial lib: %s\n' | |
2535 | ' (expected %s)\n' |
|
2536 | ' (expected %s)\n' | |
2536 | % (verb, actualhg, expecthg)) |
|
2537 | % (verb, actualhg, expecthg)) | |
2537 | def _gethgpath(self): |
|
2538 | def _gethgpath(self): | |
2538 | """Return the path to the mercurial package that is actually found by |
|
2539 | """Return the path to the mercurial package that is actually found by | |
2539 | the current Python interpreter.""" |
|
2540 | the current Python interpreter.""" | |
2540 | if self._hgpath is not None: |
|
2541 | if self._hgpath is not None: | |
2541 | return self._hgpath |
|
2542 | return self._hgpath | |
2542 |
|
2543 | |||
2543 | cmd = b'%s -c "import mercurial; print (mercurial.__path__[0])"' |
|
2544 | cmd = b'%s -c "import mercurial; print (mercurial.__path__[0])"' | |
2544 | cmd = cmd % PYTHON |
|
2545 | cmd = cmd % PYTHON | |
2545 | if PYTHON3: |
|
2546 | if PYTHON3: | |
2546 | cmd = _strpath(cmd) |
|
2547 | cmd = _strpath(cmd) | |
2547 | pipe = os.popen(cmd) |
|
2548 | pipe = os.popen(cmd) | |
2548 | try: |
|
2549 | try: | |
2549 | self._hgpath = _bytespath(pipe.read().strip()) |
|
2550 | self._hgpath = _bytespath(pipe.read().strip()) | |
2550 | finally: |
|
2551 | finally: | |
2551 | pipe.close() |
|
2552 | pipe.close() | |
2552 |
|
2553 | |||
2553 | return self._hgpath |
|
2554 | return self._hgpath | |
2554 |
|
2555 | |||
2555 | def _installchg(self): |
|
2556 | def _installchg(self): | |
2556 | """Install chg into the test environment""" |
|
2557 | """Install chg into the test environment""" | |
2557 | vlog('# Performing temporary installation of CHG') |
|
2558 | vlog('# Performing temporary installation of CHG') | |
2558 | assert os.path.dirname(self._bindir) == self._installdir |
|
2559 | assert os.path.dirname(self._bindir) == self._installdir | |
2559 | assert self._hgroot, 'must be called after _installhg()' |
|
2560 | assert self._hgroot, 'must be called after _installhg()' | |
2560 | cmd = (b'"%(make)s" clean install PREFIX="%(prefix)s"' |
|
2561 | cmd = (b'"%(make)s" clean install PREFIX="%(prefix)s"' | |
2561 | % {b'make': 'make', # TODO: switch by option or environment? |
|
2562 | % {b'make': 'make', # TODO: switch by option or environment? | |
2562 | b'prefix': self._installdir}) |
|
2563 | b'prefix': self._installdir}) | |
2563 | cwd = os.path.join(self._hgroot, b'contrib', b'chg') |
|
2564 | cwd = os.path.join(self._hgroot, b'contrib', b'chg') | |
2564 | vlog("# Running", cmd) |
|
2565 | vlog("# Running", cmd) | |
2565 | proc = subprocess.Popen(cmd, shell=True, cwd=cwd, |
|
2566 | proc = subprocess.Popen(cmd, shell=True, cwd=cwd, | |
2566 | stdin=subprocess.PIPE, stdout=subprocess.PIPE, |
|
2567 | stdin=subprocess.PIPE, stdout=subprocess.PIPE, | |
2567 | stderr=subprocess.STDOUT) |
|
2568 | stderr=subprocess.STDOUT) | |
2568 | out, _err = proc.communicate() |
|
2569 | out, _err = proc.communicate() | |
2569 | if proc.returncode != 0: |
|
2570 | if proc.returncode != 0: | |
2570 | if PYTHON3: |
|
2571 | if PYTHON3: | |
2571 | sys.stdout.buffer.write(out) |
|
2572 | sys.stdout.buffer.write(out) | |
2572 | else: |
|
2573 | else: | |
2573 | sys.stdout.write(out) |
|
2574 | sys.stdout.write(out) | |
2574 | sys.exit(1) |
|
2575 | sys.exit(1) | |
2575 |
|
2576 | |||
2576 | def _outputcoverage(self): |
|
2577 | def _outputcoverage(self): | |
2577 | """Produce code coverage output.""" |
|
2578 | """Produce code coverage output.""" | |
2578 | import coverage |
|
2579 | import coverage | |
2579 | coverage = coverage.coverage |
|
2580 | coverage = coverage.coverage | |
2580 |
|
2581 | |||
2581 | vlog('# Producing coverage report') |
|
2582 | vlog('# Producing coverage report') | |
2582 | # chdir is the easiest way to get short, relative paths in the |
|
2583 | # chdir is the easiest way to get short, relative paths in the | |
2583 | # output. |
|
2584 | # output. | |
2584 | os.chdir(self._hgroot) |
|
2585 | os.chdir(self._hgroot) | |
2585 | covdir = os.path.join(self._installdir, '..', 'coverage') |
|
2586 | covdir = os.path.join(self._installdir, '..', 'coverage') | |
2586 | cov = coverage(data_file=os.path.join(covdir, 'cov')) |
|
2587 | cov = coverage(data_file=os.path.join(covdir, 'cov')) | |
2587 |
|
2588 | |||
2588 | # Map install directory paths back to source directory. |
|
2589 | # Map install directory paths back to source directory. | |
2589 | cov.config.paths['srcdir'] = ['.', self._pythondir] |
|
2590 | cov.config.paths['srcdir'] = ['.', self._pythondir] | |
2590 |
|
2591 | |||
2591 | cov.combine() |
|
2592 | cov.combine() | |
2592 |
|
2593 | |||
2593 | omit = [os.path.join(x, '*') for x in [self._bindir, self._testdir]] |
|
2594 | omit = [os.path.join(x, '*') for x in [self._bindir, self._testdir]] | |
2594 | cov.report(ignore_errors=True, omit=omit) |
|
2595 | cov.report(ignore_errors=True, omit=omit) | |
2595 |
|
2596 | |||
2596 | if self.options.htmlcov: |
|
2597 | if self.options.htmlcov: | |
2597 | htmldir = os.path.join(self._testdir, 'htmlcov') |
|
2598 | htmldir = os.path.join(self._testdir, 'htmlcov') | |
2598 | cov.html_report(directory=htmldir, omit=omit) |
|
2599 | cov.html_report(directory=htmldir, omit=omit) | |
2599 | if self.options.annotate: |
|
2600 | if self.options.annotate: | |
2600 | adir = os.path.join(self._testdir, 'annotated') |
|
2601 | adir = os.path.join(self._testdir, 'annotated') | |
2601 | if not os.path.isdir(adir): |
|
2602 | if not os.path.isdir(adir): | |
2602 | os.mkdir(adir) |
|
2603 | os.mkdir(adir) | |
2603 | cov.annotate(directory=adir, omit=omit) |
|
2604 | cov.annotate(directory=adir, omit=omit) | |
2604 |
|
2605 | |||
2605 | def _findprogram(self, program): |
|
2606 | def _findprogram(self, program): | |
2606 | """Search PATH for a executable program""" |
|
2607 | """Search PATH for a executable program""" | |
2607 | dpb = _bytespath(os.defpath) |
|
2608 | dpb = _bytespath(os.defpath) | |
2608 | sepb = _bytespath(os.pathsep) |
|
2609 | sepb = _bytespath(os.pathsep) | |
2609 | for p in osenvironb.get(b'PATH', dpb).split(sepb): |
|
2610 | for p in osenvironb.get(b'PATH', dpb).split(sepb): | |
2610 | name = os.path.join(p, program) |
|
2611 | name = os.path.join(p, program) | |
2611 | if os.name == 'nt' or os.access(name, os.X_OK): |
|
2612 | if os.name == 'nt' or os.access(name, os.X_OK): | |
2612 | return name |
|
2613 | return name | |
2613 | return None |
|
2614 | return None | |
2614 |
|
2615 | |||
2615 | def _checktools(self): |
|
2616 | def _checktools(self): | |
2616 | """Ensure tools required to run tests are present.""" |
|
2617 | """Ensure tools required to run tests are present.""" | |
2617 | for p in self.REQUIREDTOOLS: |
|
2618 | for p in self.REQUIREDTOOLS: | |
2618 | if os.name == 'nt' and not p.endswith('.exe'): |
|
2619 | if os.name == 'nt' and not p.endswith('.exe'): | |
2619 | p += '.exe' |
|
2620 | p += '.exe' | |
2620 | found = self._findprogram(p) |
|
2621 | found = self._findprogram(p) | |
2621 | if found: |
|
2622 | if found: | |
2622 | vlog("# Found prerequisite", p, "at", found) |
|
2623 | vlog("# Found prerequisite", p, "at", found) | |
2623 | else: |
|
2624 | else: | |
2624 | print("WARNING: Did not find prerequisite tool: %s " % |
|
2625 | print("WARNING: Did not find prerequisite tool: %s " % | |
2625 | p.decode("utf-8")) |
|
2626 | p.decode("utf-8")) | |
2626 |
|
2627 | |||
2627 | if __name__ == '__main__': |
|
2628 | if __name__ == '__main__': | |
2628 | runner = TestRunner() |
|
2629 | runner = TestRunner() | |
2629 |
|
2630 | |||
2630 | try: |
|
2631 | try: | |
2631 | import msvcrt |
|
2632 | import msvcrt | |
2632 | msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) |
|
2633 | msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) | |
2633 | msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) |
|
2634 | msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) | |
2634 | msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY) |
|
2635 | msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY) | |
2635 | except ImportError: |
|
2636 | except ImportError: | |
2636 | pass |
|
2637 | pass | |
2637 |
|
2638 | |||
2638 | sys.exit(runner.run(sys.argv[1:])) |
|
2639 | sys.exit(runner.run(sys.argv[1:])) |
@@ -1,853 +1,853 b'' | |||||
1 |
|
1 | |||
2 | $ cat << EOF >> $HGRCPATH |
|
2 | $ cat << EOF >> $HGRCPATH | |
3 | > [format] |
|
3 | > [format] | |
4 | > usegeneraldelta=yes |
|
4 | > usegeneraldelta=yes | |
5 | > EOF |
|
5 | > EOF | |
6 |
|
6 | |||
7 | Setting up test |
|
7 | Setting up test | |
8 |
|
8 | |||
9 | $ hg init test |
|
9 | $ hg init test | |
10 | $ cd test |
|
10 | $ cd test | |
11 | $ echo 0 > afile |
|
11 | $ echo 0 > afile | |
12 | $ hg add afile |
|
12 | $ hg add afile | |
13 | $ hg commit -m "0.0" |
|
13 | $ hg commit -m "0.0" | |
14 | $ echo 1 >> afile |
|
14 | $ echo 1 >> afile | |
15 | $ hg commit -m "0.1" |
|
15 | $ hg commit -m "0.1" | |
16 | $ echo 2 >> afile |
|
16 | $ echo 2 >> afile | |
17 | $ hg commit -m "0.2" |
|
17 | $ hg commit -m "0.2" | |
18 | $ echo 3 >> afile |
|
18 | $ echo 3 >> afile | |
19 | $ hg commit -m "0.3" |
|
19 | $ hg commit -m "0.3" | |
20 | $ hg update -C 0 |
|
20 | $ hg update -C 0 | |
21 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
21 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
22 | $ echo 1 >> afile |
|
22 | $ echo 1 >> afile | |
23 | $ hg commit -m "1.1" |
|
23 | $ hg commit -m "1.1" | |
24 | created new head |
|
24 | created new head | |
25 | $ echo 2 >> afile |
|
25 | $ echo 2 >> afile | |
26 | $ hg commit -m "1.2" |
|
26 | $ hg commit -m "1.2" | |
27 | $ echo "a line" > fred |
|
27 | $ echo "a line" > fred | |
28 | $ echo 3 >> afile |
|
28 | $ echo 3 >> afile | |
29 | $ hg add fred |
|
29 | $ hg add fred | |
30 | $ hg commit -m "1.3" |
|
30 | $ hg commit -m "1.3" | |
31 | $ hg mv afile adifferentfile |
|
31 | $ hg mv afile adifferentfile | |
32 | $ hg commit -m "1.3m" |
|
32 | $ hg commit -m "1.3m" | |
33 | $ hg update -C 3 |
|
33 | $ hg update -C 3 | |
34 | 1 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
34 | 1 files updated, 0 files merged, 2 files removed, 0 files unresolved | |
35 | $ hg mv afile anotherfile |
|
35 | $ hg mv afile anotherfile | |
36 | $ hg commit -m "0.3m" |
|
36 | $ hg commit -m "0.3m" | |
37 | $ hg verify |
|
37 | $ hg verify | |
38 | checking changesets |
|
38 | checking changesets | |
39 | checking manifests |
|
39 | checking manifests | |
40 | crosschecking files in changesets and manifests |
|
40 | crosschecking files in changesets and manifests | |
41 | checking files |
|
41 | checking files | |
42 | 4 files, 9 changesets, 7 total revisions |
|
42 | 4 files, 9 changesets, 7 total revisions | |
43 | $ cd .. |
|
43 | $ cd .. | |
44 | $ hg init empty |
|
44 | $ hg init empty | |
45 |
|
45 | |||
46 | Bundle and phase |
|
46 | Bundle and phase | |
47 |
|
47 | |||
48 | $ hg -R test phase --force --secret 0 |
|
48 | $ hg -R test phase --force --secret 0 | |
49 | $ hg -R test bundle phase.hg empty |
|
49 | $ hg -R test bundle phase.hg empty | |
50 | searching for changes |
|
50 | searching for changes | |
51 | no changes found (ignored 9 secret changesets) |
|
51 | no changes found (ignored 9 secret changesets) | |
52 | [1] |
|
52 | [1] | |
53 | $ hg -R test phase --draft -r 'head()' |
|
53 | $ hg -R test phase --draft -r 'head()' | |
54 |
|
54 | |||
55 | Bundle --all |
|
55 | Bundle --all | |
56 |
|
56 | |||
57 | $ hg -R test bundle --all all.hg |
|
57 | $ hg -R test bundle --all all.hg | |
58 | 9 changesets found |
|
58 | 9 changesets found | |
59 |
|
59 | |||
60 | Bundle test to full.hg |
|
60 | Bundle test to full.hg | |
61 |
|
61 | |||
62 | $ hg -R test bundle full.hg empty |
|
62 | $ hg -R test bundle full.hg empty | |
63 | searching for changes |
|
63 | searching for changes | |
64 | 9 changesets found |
|
64 | 9 changesets found | |
65 |
|
65 | |||
66 | Unbundle full.hg in test |
|
66 | Unbundle full.hg in test | |
67 |
|
67 | |||
68 | $ hg -R test unbundle full.hg |
|
68 | $ hg -R test unbundle full.hg | |
69 | adding changesets |
|
69 | adding changesets | |
70 | adding manifests |
|
70 | adding manifests | |
71 | adding file changes |
|
71 | adding file changes | |
72 | added 0 changesets with 0 changes to 4 files |
|
72 | added 0 changesets with 0 changes to 4 files | |
73 | (run 'hg update' to get a working copy) |
|
73 | (run 'hg update' to get a working copy) | |
74 |
|
74 | |||
75 | Verify empty |
|
75 | Verify empty | |
76 |
|
76 | |||
77 | $ hg -R empty heads |
|
77 | $ hg -R empty heads | |
78 | [1] |
|
78 | [1] | |
79 | $ hg -R empty verify |
|
79 | $ hg -R empty verify | |
80 | checking changesets |
|
80 | checking changesets | |
81 | checking manifests |
|
81 | checking manifests | |
82 | crosschecking files in changesets and manifests |
|
82 | crosschecking files in changesets and manifests | |
83 | checking files |
|
83 | checking files | |
84 | 0 files, 0 changesets, 0 total revisions |
|
84 | 0 files, 0 changesets, 0 total revisions | |
85 |
|
85 | |||
86 | Pull full.hg into test (using --cwd) |
|
86 | Pull full.hg into test (using --cwd) | |
87 |
|
87 | |||
88 | $ hg --cwd test pull ../full.hg |
|
88 | $ hg --cwd test pull ../full.hg | |
89 | pulling from ../full.hg |
|
89 | pulling from ../full.hg | |
90 | searching for changes |
|
90 | searching for changes | |
91 | no changes found |
|
91 | no changes found | |
92 |
|
92 | |||
93 | Verify that there are no leaked temporary files after pull (issue2797) |
|
93 | Verify that there are no leaked temporary files after pull (issue2797) | |
94 |
|
94 | |||
95 | $ ls test/.hg | grep .hg10un |
|
95 | $ ls test/.hg | grep .hg10un | |
96 | [1] |
|
96 | [1] | |
97 |
|
97 | |||
98 | Pull full.hg into empty (using --cwd) |
|
98 | Pull full.hg into empty (using --cwd) | |
99 |
|
99 | |||
100 | $ hg --cwd empty pull ../full.hg |
|
100 | $ hg --cwd empty pull ../full.hg | |
101 | pulling from ../full.hg |
|
101 | pulling from ../full.hg | |
102 | requesting all changes |
|
102 | requesting all changes | |
103 | adding changesets |
|
103 | adding changesets | |
104 | adding manifests |
|
104 | adding manifests | |
105 | adding file changes |
|
105 | adding file changes | |
106 | added 9 changesets with 7 changes to 4 files (+1 heads) |
|
106 | added 9 changesets with 7 changes to 4 files (+1 heads) | |
107 | (run 'hg heads' to see heads, 'hg merge' to merge) |
|
107 | (run 'hg heads' to see heads, 'hg merge' to merge) | |
108 |
|
108 | |||
109 | Rollback empty |
|
109 | Rollback empty | |
110 |
|
110 | |||
111 | $ hg -R empty rollback |
|
111 | $ hg -R empty rollback | |
112 | repository tip rolled back to revision -1 (undo pull) |
|
112 | repository tip rolled back to revision -1 (undo pull) | |
113 |
|
113 | |||
114 | Pull full.hg into empty again (using --cwd) |
|
114 | Pull full.hg into empty again (using --cwd) | |
115 |
|
115 | |||
116 | $ hg --cwd empty pull ../full.hg |
|
116 | $ hg --cwd empty pull ../full.hg | |
117 | pulling from ../full.hg |
|
117 | pulling from ../full.hg | |
118 | requesting all changes |
|
118 | requesting all changes | |
119 | adding changesets |
|
119 | adding changesets | |
120 | adding manifests |
|
120 | adding manifests | |
121 | adding file changes |
|
121 | adding file changes | |
122 | added 9 changesets with 7 changes to 4 files (+1 heads) |
|
122 | added 9 changesets with 7 changes to 4 files (+1 heads) | |
123 | (run 'hg heads' to see heads, 'hg merge' to merge) |
|
123 | (run 'hg heads' to see heads, 'hg merge' to merge) | |
124 |
|
124 | |||
125 | Pull full.hg into test (using -R) |
|
125 | Pull full.hg into test (using -R) | |
126 |
|
126 | |||
127 | $ hg -R test pull full.hg |
|
127 | $ hg -R test pull full.hg | |
128 | pulling from full.hg |
|
128 | pulling from full.hg | |
129 | searching for changes |
|
129 | searching for changes | |
130 | no changes found |
|
130 | no changes found | |
131 |
|
131 | |||
132 | Pull full.hg into empty (using -R) |
|
132 | Pull full.hg into empty (using -R) | |
133 |
|
133 | |||
134 | $ hg -R empty pull full.hg |
|
134 | $ hg -R empty pull full.hg | |
135 | pulling from full.hg |
|
135 | pulling from full.hg | |
136 | searching for changes |
|
136 | searching for changes | |
137 | no changes found |
|
137 | no changes found | |
138 |
|
138 | |||
139 | Rollback empty |
|
139 | Rollback empty | |
140 |
|
140 | |||
141 | $ hg -R empty rollback |
|
141 | $ hg -R empty rollback | |
142 | repository tip rolled back to revision -1 (undo pull) |
|
142 | repository tip rolled back to revision -1 (undo pull) | |
143 |
|
143 | |||
144 | Pull full.hg into empty again (using -R) |
|
144 | Pull full.hg into empty again (using -R) | |
145 |
|
145 | |||
146 | $ hg -R empty pull full.hg |
|
146 | $ hg -R empty pull full.hg | |
147 | pulling from full.hg |
|
147 | pulling from full.hg | |
148 | requesting all changes |
|
148 | requesting all changes | |
149 | adding changesets |
|
149 | adding changesets | |
150 | adding manifests |
|
150 | adding manifests | |
151 | adding file changes |
|
151 | adding file changes | |
152 | added 9 changesets with 7 changes to 4 files (+1 heads) |
|
152 | added 9 changesets with 7 changes to 4 files (+1 heads) | |
153 | (run 'hg heads' to see heads, 'hg merge' to merge) |
|
153 | (run 'hg heads' to see heads, 'hg merge' to merge) | |
154 |
|
154 | |||
155 | Log -R full.hg in fresh empty |
|
155 | Log -R full.hg in fresh empty | |
156 |
|
156 | |||
157 | $ rm -r empty |
|
157 | $ rm -r empty | |
158 | $ hg init empty |
|
158 | $ hg init empty | |
159 | $ cd empty |
|
159 | $ cd empty | |
160 | $ hg -R bundle://../full.hg log |
|
160 | $ hg -R bundle://../full.hg log | |
161 | changeset: 8:aa35859c02ea |
|
161 | changeset: 8:aa35859c02ea | |
162 | tag: tip |
|
162 | tag: tip | |
163 | parent: 3:eebf5a27f8ca |
|
163 | parent: 3:eebf5a27f8ca | |
164 | user: test |
|
164 | user: test | |
165 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
165 | date: Thu Jan 01 00:00:00 1970 +0000 | |
166 | summary: 0.3m |
|
166 | summary: 0.3m | |
167 |
|
167 | |||
168 | changeset: 7:a6a34bfa0076 |
|
168 | changeset: 7:a6a34bfa0076 | |
169 | user: test |
|
169 | user: test | |
170 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
170 | date: Thu Jan 01 00:00:00 1970 +0000 | |
171 | summary: 1.3m |
|
171 | summary: 1.3m | |
172 |
|
172 | |||
173 | changeset: 6:7373c1169842 |
|
173 | changeset: 6:7373c1169842 | |
174 | user: test |
|
174 | user: test | |
175 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
175 | date: Thu Jan 01 00:00:00 1970 +0000 | |
176 | summary: 1.3 |
|
176 | summary: 1.3 | |
177 |
|
177 | |||
178 | changeset: 5:1bb50a9436a7 |
|
178 | changeset: 5:1bb50a9436a7 | |
179 | user: test |
|
179 | user: test | |
180 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
180 | date: Thu Jan 01 00:00:00 1970 +0000 | |
181 | summary: 1.2 |
|
181 | summary: 1.2 | |
182 |
|
182 | |||
183 | changeset: 4:095197eb4973 |
|
183 | changeset: 4:095197eb4973 | |
184 | parent: 0:f9ee2f85a263 |
|
184 | parent: 0:f9ee2f85a263 | |
185 | user: test |
|
185 | user: test | |
186 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
186 | date: Thu Jan 01 00:00:00 1970 +0000 | |
187 | summary: 1.1 |
|
187 | summary: 1.1 | |
188 |
|
188 | |||
189 | changeset: 3:eebf5a27f8ca |
|
189 | changeset: 3:eebf5a27f8ca | |
190 | user: test |
|
190 | user: test | |
191 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
191 | date: Thu Jan 01 00:00:00 1970 +0000 | |
192 | summary: 0.3 |
|
192 | summary: 0.3 | |
193 |
|
193 | |||
194 | changeset: 2:e38ba6f5b7e0 |
|
194 | changeset: 2:e38ba6f5b7e0 | |
195 | user: test |
|
195 | user: test | |
196 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
196 | date: Thu Jan 01 00:00:00 1970 +0000 | |
197 | summary: 0.2 |
|
197 | summary: 0.2 | |
198 |
|
198 | |||
199 | changeset: 1:34c2bf6b0626 |
|
199 | changeset: 1:34c2bf6b0626 | |
200 | user: test |
|
200 | user: test | |
201 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
201 | date: Thu Jan 01 00:00:00 1970 +0000 | |
202 | summary: 0.1 |
|
202 | summary: 0.1 | |
203 |
|
203 | |||
204 | changeset: 0:f9ee2f85a263 |
|
204 | changeset: 0:f9ee2f85a263 | |
205 | user: test |
|
205 | user: test | |
206 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
206 | date: Thu Jan 01 00:00:00 1970 +0000 | |
207 | summary: 0.0 |
|
207 | summary: 0.0 | |
208 |
|
208 | |||
209 | Make sure bundlerepo doesn't leak tempfiles (issue2491) |
|
209 | Make sure bundlerepo doesn't leak tempfiles (issue2491) | |
210 |
|
210 | |||
211 | $ ls .hg |
|
211 | $ ls .hg | |
212 | 00changelog.i |
|
212 | 00changelog.i | |
213 | cache |
|
213 | cache | |
214 | requires |
|
214 | requires | |
215 | store |
|
215 | store | |
216 |
|
216 | |||
217 | Pull ../full.hg into empty (with hook) |
|
217 | Pull ../full.hg into empty (with hook) | |
218 |
|
218 | |||
219 | $ cat >> .hg/hgrc <<EOF |
|
219 | $ cat >> .hg/hgrc <<EOF | |
220 | > [hooks] |
|
220 | > [hooks] | |
221 | > changegroup = sh -c "printenv.py changegroup" |
|
221 | > changegroup = sh -c "printenv.py changegroup" | |
222 | > EOF |
|
222 | > EOF | |
223 |
|
223 | |||
224 | doesn't work (yet ?) |
|
224 | doesn't work (yet ?) | |
225 |
|
225 | |||
226 | hg -R bundle://../full.hg verify |
|
226 | hg -R bundle://../full.hg verify | |
227 |
|
227 | |||
228 | $ hg pull bundle://../full.hg |
|
228 | $ hg pull bundle://../full.hg | |
229 | pulling from bundle:../full.hg |
|
229 | pulling from bundle:../full.hg | |
230 | requesting all changes |
|
230 | requesting all changes | |
231 | adding changesets |
|
231 | adding changesets | |
232 | adding manifests |
|
232 | adding manifests | |
233 | adding file changes |
|
233 | adding file changes | |
234 | added 9 changesets with 7 changes to 4 files (+1 heads) |
|
234 | added 9 changesets with 7 changes to 4 files (+1 heads) | |
235 |
changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull HG_TXNID=TXN: |
|
235 | changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=bundle:../full.hg | |
236 | (run 'hg heads' to see heads, 'hg merge' to merge) |
|
236 | (run 'hg heads' to see heads, 'hg merge' to merge) | |
237 |
|
237 | |||
238 | Rollback empty |
|
238 | Rollback empty | |
239 |
|
239 | |||
240 | $ hg rollback |
|
240 | $ hg rollback | |
241 | repository tip rolled back to revision -1 (undo pull) |
|
241 | repository tip rolled back to revision -1 (undo pull) | |
242 | $ cd .. |
|
242 | $ cd .. | |
243 |
|
243 | |||
244 | Log -R bundle:empty+full.hg |
|
244 | Log -R bundle:empty+full.hg | |
245 |
|
245 | |||
246 | $ hg -R bundle:empty+full.hg log --template="{rev} "; echo "" |
|
246 | $ hg -R bundle:empty+full.hg log --template="{rev} "; echo "" | |
247 | 8 7 6 5 4 3 2 1 0 |
|
247 | 8 7 6 5 4 3 2 1 0 | |
248 |
|
248 | |||
249 | Pull full.hg into empty again (using -R; with hook) |
|
249 | Pull full.hg into empty again (using -R; with hook) | |
250 |
|
250 | |||
251 | $ hg -R empty pull full.hg |
|
251 | $ hg -R empty pull full.hg | |
252 | pulling from full.hg |
|
252 | pulling from full.hg | |
253 | requesting all changes |
|
253 | requesting all changes | |
254 | adding changesets |
|
254 | adding changesets | |
255 | adding manifests |
|
255 | adding manifests | |
256 | adding file changes |
|
256 | adding file changes | |
257 | added 9 changesets with 7 changes to 4 files (+1 heads) |
|
257 | added 9 changesets with 7 changes to 4 files (+1 heads) | |
258 |
changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull HG_TXNID=TXN: |
|
258 | changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg | |
259 | (run 'hg heads' to see heads, 'hg merge' to merge) |
|
259 | (run 'hg heads' to see heads, 'hg merge' to merge) | |
260 |
|
260 | |||
261 | Cannot produce streaming clone bundles with "hg bundle" |
|
261 | Cannot produce streaming clone bundles with "hg bundle" | |
262 |
|
262 | |||
263 | $ hg -R test bundle -t packed1 packed.hg |
|
263 | $ hg -R test bundle -t packed1 packed.hg | |
264 | abort: packed bundles cannot be produced by "hg bundle" |
|
264 | abort: packed bundles cannot be produced by "hg bundle" | |
265 | (use 'hg debugcreatestreamclonebundle') |
|
265 | (use 'hg debugcreatestreamclonebundle') | |
266 | [255] |
|
266 | [255] | |
267 |
|
267 | |||
268 | packed1 is produced properly |
|
268 | packed1 is produced properly | |
269 |
|
269 | |||
270 | $ hg -R test debugcreatestreamclonebundle packed.hg |
|
270 | $ hg -R test debugcreatestreamclonebundle packed.hg | |
271 | writing 2664 bytes for 6 files |
|
271 | writing 2664 bytes for 6 files | |
272 | bundle requirements: generaldelta, revlogv1 |
|
272 | bundle requirements: generaldelta, revlogv1 | |
273 |
|
273 | |||
274 | $ f -B 64 --size --sha1 --hexdump packed.hg |
|
274 | $ f -B 64 --size --sha1 --hexdump packed.hg | |
275 | packed.hg: size=2827, sha1=9d14cb90c66a21462d915ab33656f38b9deed686 |
|
275 | packed.hg: size=2827, sha1=9d14cb90c66a21462d915ab33656f38b9deed686 | |
276 | 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 06 00 00 |HGS1UN..........| |
|
276 | 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 06 00 00 |HGS1UN..........| | |
277 | 0010: 00 00 00 00 0a 68 00 16 67 65 6e 65 72 61 6c 64 |.....h..generald| |
|
277 | 0010: 00 00 00 00 0a 68 00 16 67 65 6e 65 72 61 6c 64 |.....h..generald| | |
278 | 0020: 65 6c 74 61 2c 72 65 76 6c 6f 67 76 31 00 64 61 |elta,revlogv1.da| |
|
278 | 0020: 65 6c 74 61 2c 72 65 76 6c 6f 67 76 31 00 64 61 |elta,revlogv1.da| | |
279 | 0030: 74 61 2f 61 64 69 66 66 65 72 65 6e 74 66 69 6c |ta/adifferentfil| |
|
279 | 0030: 74 61 2f 61 64 69 66 66 65 72 65 6e 74 66 69 6c |ta/adifferentfil| | |
280 |
|
280 | |||
281 | $ hg debugbundle --spec packed.hg |
|
281 | $ hg debugbundle --spec packed.hg | |
282 | none-packed1;requirements%3Dgeneraldelta%2Crevlogv1 |
|
282 | none-packed1;requirements%3Dgeneraldelta%2Crevlogv1 | |
283 |
|
283 | |||
284 | generaldelta requirement is not listed in stream clone bundles unless used |
|
284 | generaldelta requirement is not listed in stream clone bundles unless used | |
285 |
|
285 | |||
286 | $ hg --config format.usegeneraldelta=false init testnongd |
|
286 | $ hg --config format.usegeneraldelta=false init testnongd | |
287 | $ cd testnongd |
|
287 | $ cd testnongd | |
288 | $ touch foo |
|
288 | $ touch foo | |
289 | $ hg -q commit -A -m initial |
|
289 | $ hg -q commit -A -m initial | |
290 | $ cd .. |
|
290 | $ cd .. | |
291 | $ hg -R testnongd debugcreatestreamclonebundle packednongd.hg |
|
291 | $ hg -R testnongd debugcreatestreamclonebundle packednongd.hg | |
292 | writing 301 bytes for 3 files |
|
292 | writing 301 bytes for 3 files | |
293 | bundle requirements: revlogv1 |
|
293 | bundle requirements: revlogv1 | |
294 |
|
294 | |||
295 | $ f -B 64 --size --sha1 --hexdump packednongd.hg |
|
295 | $ f -B 64 --size --sha1 --hexdump packednongd.hg | |
296 | packednongd.hg: size=383, sha1=1d9c230238edd5d38907100b729ba72b1831fe6f |
|
296 | packednongd.hg: size=383, sha1=1d9c230238edd5d38907100b729ba72b1831fe6f | |
297 | 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 03 00 00 |HGS1UN..........| |
|
297 | 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 03 00 00 |HGS1UN..........| | |
298 | 0010: 00 00 00 00 01 2d 00 09 72 65 76 6c 6f 67 76 31 |.....-..revlogv1| |
|
298 | 0010: 00 00 00 00 01 2d 00 09 72 65 76 6c 6f 67 76 31 |.....-..revlogv1| | |
299 | 0020: 00 64 61 74 61 2f 66 6f 6f 2e 69 00 36 34 0a 00 |.data/foo.i.64..| |
|
299 | 0020: 00 64 61 74 61 2f 66 6f 6f 2e 69 00 36 34 0a 00 |.data/foo.i.64..| | |
300 | 0030: 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
|
300 | 0030: 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| | |
301 |
|
301 | |||
302 | $ hg debugbundle --spec packednongd.hg |
|
302 | $ hg debugbundle --spec packednongd.hg | |
303 | none-packed1;requirements%3Drevlogv1 |
|
303 | none-packed1;requirements%3Drevlogv1 | |
304 |
|
304 | |||
305 | Unpacking packed1 bundles with "hg unbundle" isn't allowed |
|
305 | Unpacking packed1 bundles with "hg unbundle" isn't allowed | |
306 |
|
306 | |||
307 | $ hg init packed |
|
307 | $ hg init packed | |
308 | $ hg -R packed unbundle packed.hg |
|
308 | $ hg -R packed unbundle packed.hg | |
309 | abort: packed bundles cannot be applied with "hg unbundle" |
|
309 | abort: packed bundles cannot be applied with "hg unbundle" | |
310 | (use "hg debugapplystreamclonebundle") |
|
310 | (use "hg debugapplystreamclonebundle") | |
311 | [255] |
|
311 | [255] | |
312 |
|
312 | |||
313 | packed1 can be consumed from debug command |
|
313 | packed1 can be consumed from debug command | |
314 |
|
314 | |||
315 | (this also confirms that streamclone-ed changes are visible via |
|
315 | (this also confirms that streamclone-ed changes are visible via | |
316 | @filecache properties to in-process procedures before closing |
|
316 | @filecache properties to in-process procedures before closing | |
317 | transaction) |
|
317 | transaction) | |
318 |
|
318 | |||
319 | $ cat > $TESTTMP/showtip.py <<EOF |
|
319 | $ cat > $TESTTMP/showtip.py <<EOF | |
320 | > from __future__ import absolute_import |
|
320 | > from __future__ import absolute_import | |
321 | > |
|
321 | > | |
322 | > def showtip(ui, repo, hooktype, **kwargs): |
|
322 | > def showtip(ui, repo, hooktype, **kwargs): | |
323 | > ui.warn('%s: %s\n' % (hooktype, repo['tip'].hex()[:12])) |
|
323 | > ui.warn('%s: %s\n' % (hooktype, repo['tip'].hex()[:12])) | |
324 | > |
|
324 | > | |
325 | > def reposetup(ui, repo): |
|
325 | > def reposetup(ui, repo): | |
326 | > # this confirms (and ensures) that (empty) 00changelog.i |
|
326 | > # this confirms (and ensures) that (empty) 00changelog.i | |
327 | > # before streamclone is already cached as repo.changelog |
|
327 | > # before streamclone is already cached as repo.changelog | |
328 | > ui.setconfig('hooks', 'pretxnopen.showtip', showtip) |
|
328 | > ui.setconfig('hooks', 'pretxnopen.showtip', showtip) | |
329 | > |
|
329 | > | |
330 | > # this confirms that streamclone-ed changes are visible to |
|
330 | > # this confirms that streamclone-ed changes are visible to | |
331 | > # in-process procedures before closing transaction |
|
331 | > # in-process procedures before closing transaction | |
332 | > ui.setconfig('hooks', 'pretxnclose.showtip', showtip) |
|
332 | > ui.setconfig('hooks', 'pretxnclose.showtip', showtip) | |
333 | > |
|
333 | > | |
334 | > # this confirms that streamclone-ed changes are still visible |
|
334 | > # this confirms that streamclone-ed changes are still visible | |
335 | > # after closing transaction |
|
335 | > # after closing transaction | |
336 | > ui.setconfig('hooks', 'txnclose.showtip', showtip) |
|
336 | > ui.setconfig('hooks', 'txnclose.showtip', showtip) | |
337 | > EOF |
|
337 | > EOF | |
338 | $ cat >> $HGRCPATH <<EOF |
|
338 | $ cat >> $HGRCPATH <<EOF | |
339 | > [extensions] |
|
339 | > [extensions] | |
340 | > showtip = $TESTTMP/showtip.py |
|
340 | > showtip = $TESTTMP/showtip.py | |
341 | > EOF |
|
341 | > EOF | |
342 |
|
342 | |||
343 | $ hg -R packed debugapplystreamclonebundle packed.hg |
|
343 | $ hg -R packed debugapplystreamclonebundle packed.hg | |
344 | 6 files to transfer, 2.60 KB of data |
|
344 | 6 files to transfer, 2.60 KB of data | |
345 | pretxnopen: 000000000000 |
|
345 | pretxnopen: 000000000000 | |
346 | pretxnclose: aa35859c02ea |
|
346 | pretxnclose: aa35859c02ea | |
347 | transferred 2.60 KB in *.* seconds (* */sec) (glob) |
|
347 | transferred 2.60 KB in *.* seconds (* */sec) (glob) | |
348 | txnclose: aa35859c02ea |
|
348 | txnclose: aa35859c02ea | |
349 |
|
349 | |||
350 | (for safety, confirm visibility of streamclone-ed changes by another |
|
350 | (for safety, confirm visibility of streamclone-ed changes by another | |
351 | process, too) |
|
351 | process, too) | |
352 |
|
352 | |||
353 | $ hg -R packed tip -T "{node|short}\n" |
|
353 | $ hg -R packed tip -T "{node|short}\n" | |
354 | aa35859c02ea |
|
354 | aa35859c02ea | |
355 |
|
355 | |||
356 | $ cat >> $HGRCPATH <<EOF |
|
356 | $ cat >> $HGRCPATH <<EOF | |
357 | > [extensions] |
|
357 | > [extensions] | |
358 | > showtip = ! |
|
358 | > showtip = ! | |
359 | > EOF |
|
359 | > EOF | |
360 |
|
360 | |||
361 | Does not work on non-empty repo |
|
361 | Does not work on non-empty repo | |
362 |
|
362 | |||
363 | $ hg -R packed debugapplystreamclonebundle packed.hg |
|
363 | $ hg -R packed debugapplystreamclonebundle packed.hg | |
364 | abort: cannot apply stream clone bundle on non-empty repo |
|
364 | abort: cannot apply stream clone bundle on non-empty repo | |
365 | [255] |
|
365 | [255] | |
366 |
|
366 | |||
367 | Create partial clones |
|
367 | Create partial clones | |
368 |
|
368 | |||
369 | $ rm -r empty |
|
369 | $ rm -r empty | |
370 | $ hg init empty |
|
370 | $ hg init empty | |
371 | $ hg clone -r 3 test partial |
|
371 | $ hg clone -r 3 test partial | |
372 | adding changesets |
|
372 | adding changesets | |
373 | adding manifests |
|
373 | adding manifests | |
374 | adding file changes |
|
374 | adding file changes | |
375 | added 4 changesets with 4 changes to 1 files |
|
375 | added 4 changesets with 4 changes to 1 files | |
376 | updating to branch default |
|
376 | updating to branch default | |
377 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
377 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
378 | $ hg clone partial partial2 |
|
378 | $ hg clone partial partial2 | |
379 | updating to branch default |
|
379 | updating to branch default | |
380 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
380 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
381 | $ cd partial |
|
381 | $ cd partial | |
382 |
|
382 | |||
383 | Log -R full.hg in partial |
|
383 | Log -R full.hg in partial | |
384 |
|
384 | |||
385 | $ hg -R bundle://../full.hg log -T phases |
|
385 | $ hg -R bundle://../full.hg log -T phases | |
386 | changeset: 8:aa35859c02ea |
|
386 | changeset: 8:aa35859c02ea | |
387 | tag: tip |
|
387 | tag: tip | |
388 | phase: draft |
|
388 | phase: draft | |
389 | parent: 3:eebf5a27f8ca |
|
389 | parent: 3:eebf5a27f8ca | |
390 | user: test |
|
390 | user: test | |
391 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
391 | date: Thu Jan 01 00:00:00 1970 +0000 | |
392 | summary: 0.3m |
|
392 | summary: 0.3m | |
393 |
|
393 | |||
394 | changeset: 7:a6a34bfa0076 |
|
394 | changeset: 7:a6a34bfa0076 | |
395 | phase: draft |
|
395 | phase: draft | |
396 | user: test |
|
396 | user: test | |
397 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
397 | date: Thu Jan 01 00:00:00 1970 +0000 | |
398 | summary: 1.3m |
|
398 | summary: 1.3m | |
399 |
|
399 | |||
400 | changeset: 6:7373c1169842 |
|
400 | changeset: 6:7373c1169842 | |
401 | phase: draft |
|
401 | phase: draft | |
402 | user: test |
|
402 | user: test | |
403 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
403 | date: Thu Jan 01 00:00:00 1970 +0000 | |
404 | summary: 1.3 |
|
404 | summary: 1.3 | |
405 |
|
405 | |||
406 | changeset: 5:1bb50a9436a7 |
|
406 | changeset: 5:1bb50a9436a7 | |
407 | phase: draft |
|
407 | phase: draft | |
408 | user: test |
|
408 | user: test | |
409 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
409 | date: Thu Jan 01 00:00:00 1970 +0000 | |
410 | summary: 1.2 |
|
410 | summary: 1.2 | |
411 |
|
411 | |||
412 | changeset: 4:095197eb4973 |
|
412 | changeset: 4:095197eb4973 | |
413 | phase: draft |
|
413 | phase: draft | |
414 | parent: 0:f9ee2f85a263 |
|
414 | parent: 0:f9ee2f85a263 | |
415 | user: test |
|
415 | user: test | |
416 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
416 | date: Thu Jan 01 00:00:00 1970 +0000 | |
417 | summary: 1.1 |
|
417 | summary: 1.1 | |
418 |
|
418 | |||
419 | changeset: 3:eebf5a27f8ca |
|
419 | changeset: 3:eebf5a27f8ca | |
420 | phase: public |
|
420 | phase: public | |
421 | user: test |
|
421 | user: test | |
422 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
422 | date: Thu Jan 01 00:00:00 1970 +0000 | |
423 | summary: 0.3 |
|
423 | summary: 0.3 | |
424 |
|
424 | |||
425 | changeset: 2:e38ba6f5b7e0 |
|
425 | changeset: 2:e38ba6f5b7e0 | |
426 | phase: public |
|
426 | phase: public | |
427 | user: test |
|
427 | user: test | |
428 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
428 | date: Thu Jan 01 00:00:00 1970 +0000 | |
429 | summary: 0.2 |
|
429 | summary: 0.2 | |
430 |
|
430 | |||
431 | changeset: 1:34c2bf6b0626 |
|
431 | changeset: 1:34c2bf6b0626 | |
432 | phase: public |
|
432 | phase: public | |
433 | user: test |
|
433 | user: test | |
434 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
434 | date: Thu Jan 01 00:00:00 1970 +0000 | |
435 | summary: 0.1 |
|
435 | summary: 0.1 | |
436 |
|
436 | |||
437 | changeset: 0:f9ee2f85a263 |
|
437 | changeset: 0:f9ee2f85a263 | |
438 | phase: public |
|
438 | phase: public | |
439 | user: test |
|
439 | user: test | |
440 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
440 | date: Thu Jan 01 00:00:00 1970 +0000 | |
441 | summary: 0.0 |
|
441 | summary: 0.0 | |
442 |
|
442 | |||
443 |
|
443 | |||
444 | Incoming full.hg in partial |
|
444 | Incoming full.hg in partial | |
445 |
|
445 | |||
446 | $ hg incoming bundle://../full.hg |
|
446 | $ hg incoming bundle://../full.hg | |
447 | comparing with bundle:../full.hg |
|
447 | comparing with bundle:../full.hg | |
448 | searching for changes |
|
448 | searching for changes | |
449 | changeset: 4:095197eb4973 |
|
449 | changeset: 4:095197eb4973 | |
450 | parent: 0:f9ee2f85a263 |
|
450 | parent: 0:f9ee2f85a263 | |
451 | user: test |
|
451 | user: test | |
452 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
452 | date: Thu Jan 01 00:00:00 1970 +0000 | |
453 | summary: 1.1 |
|
453 | summary: 1.1 | |
454 |
|
454 | |||
455 | changeset: 5:1bb50a9436a7 |
|
455 | changeset: 5:1bb50a9436a7 | |
456 | user: test |
|
456 | user: test | |
457 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
457 | date: Thu Jan 01 00:00:00 1970 +0000 | |
458 | summary: 1.2 |
|
458 | summary: 1.2 | |
459 |
|
459 | |||
460 | changeset: 6:7373c1169842 |
|
460 | changeset: 6:7373c1169842 | |
461 | user: test |
|
461 | user: test | |
462 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
462 | date: Thu Jan 01 00:00:00 1970 +0000 | |
463 | summary: 1.3 |
|
463 | summary: 1.3 | |
464 |
|
464 | |||
465 | changeset: 7:a6a34bfa0076 |
|
465 | changeset: 7:a6a34bfa0076 | |
466 | user: test |
|
466 | user: test | |
467 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
467 | date: Thu Jan 01 00:00:00 1970 +0000 | |
468 | summary: 1.3m |
|
468 | summary: 1.3m | |
469 |
|
469 | |||
470 | changeset: 8:aa35859c02ea |
|
470 | changeset: 8:aa35859c02ea | |
471 | tag: tip |
|
471 | tag: tip | |
472 | parent: 3:eebf5a27f8ca |
|
472 | parent: 3:eebf5a27f8ca | |
473 | user: test |
|
473 | user: test | |
474 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
474 | date: Thu Jan 01 00:00:00 1970 +0000 | |
475 | summary: 0.3m |
|
475 | summary: 0.3m | |
476 |
|
476 | |||
477 |
|
477 | |||
478 | Outgoing -R full.hg vs partial2 in partial |
|
478 | Outgoing -R full.hg vs partial2 in partial | |
479 |
|
479 | |||
480 | $ hg -R bundle://../full.hg outgoing ../partial2 |
|
480 | $ hg -R bundle://../full.hg outgoing ../partial2 | |
481 | comparing with ../partial2 |
|
481 | comparing with ../partial2 | |
482 | searching for changes |
|
482 | searching for changes | |
483 | changeset: 4:095197eb4973 |
|
483 | changeset: 4:095197eb4973 | |
484 | parent: 0:f9ee2f85a263 |
|
484 | parent: 0:f9ee2f85a263 | |
485 | user: test |
|
485 | user: test | |
486 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
486 | date: Thu Jan 01 00:00:00 1970 +0000 | |
487 | summary: 1.1 |
|
487 | summary: 1.1 | |
488 |
|
488 | |||
489 | changeset: 5:1bb50a9436a7 |
|
489 | changeset: 5:1bb50a9436a7 | |
490 | user: test |
|
490 | user: test | |
491 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
491 | date: Thu Jan 01 00:00:00 1970 +0000 | |
492 | summary: 1.2 |
|
492 | summary: 1.2 | |
493 |
|
493 | |||
494 | changeset: 6:7373c1169842 |
|
494 | changeset: 6:7373c1169842 | |
495 | user: test |
|
495 | user: test | |
496 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
496 | date: Thu Jan 01 00:00:00 1970 +0000 | |
497 | summary: 1.3 |
|
497 | summary: 1.3 | |
498 |
|
498 | |||
499 | changeset: 7:a6a34bfa0076 |
|
499 | changeset: 7:a6a34bfa0076 | |
500 | user: test |
|
500 | user: test | |
501 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
501 | date: Thu Jan 01 00:00:00 1970 +0000 | |
502 | summary: 1.3m |
|
502 | summary: 1.3m | |
503 |
|
503 | |||
504 | changeset: 8:aa35859c02ea |
|
504 | changeset: 8:aa35859c02ea | |
505 | tag: tip |
|
505 | tag: tip | |
506 | parent: 3:eebf5a27f8ca |
|
506 | parent: 3:eebf5a27f8ca | |
507 | user: test |
|
507 | user: test | |
508 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
508 | date: Thu Jan 01 00:00:00 1970 +0000 | |
509 | summary: 0.3m |
|
509 | summary: 0.3m | |
510 |
|
510 | |||
511 |
|
511 | |||
512 | Outgoing -R does-not-exist.hg vs partial2 in partial |
|
512 | Outgoing -R does-not-exist.hg vs partial2 in partial | |
513 |
|
513 | |||
514 | $ hg -R bundle://../does-not-exist.hg outgoing ../partial2 |
|
514 | $ hg -R bundle://../does-not-exist.hg outgoing ../partial2 | |
515 | abort: *../does-not-exist.hg* (glob) |
|
515 | abort: *../does-not-exist.hg* (glob) | |
516 | [255] |
|
516 | [255] | |
517 | $ cd .. |
|
517 | $ cd .. | |
518 |
|
518 | |||
519 | hide outer repo |
|
519 | hide outer repo | |
520 | $ hg init |
|
520 | $ hg init | |
521 |
|
521 | |||
522 | Direct clone from bundle (all-history) |
|
522 | Direct clone from bundle (all-history) | |
523 |
|
523 | |||
524 | $ hg clone full.hg full-clone |
|
524 | $ hg clone full.hg full-clone | |
525 | requesting all changes |
|
525 | requesting all changes | |
526 | adding changesets |
|
526 | adding changesets | |
527 | adding manifests |
|
527 | adding manifests | |
528 | adding file changes |
|
528 | adding file changes | |
529 | added 9 changesets with 7 changes to 4 files (+1 heads) |
|
529 | added 9 changesets with 7 changes to 4 files (+1 heads) | |
530 | updating to branch default |
|
530 | updating to branch default | |
531 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
531 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
532 | $ hg -R full-clone heads |
|
532 | $ hg -R full-clone heads | |
533 | changeset: 8:aa35859c02ea |
|
533 | changeset: 8:aa35859c02ea | |
534 | tag: tip |
|
534 | tag: tip | |
535 | parent: 3:eebf5a27f8ca |
|
535 | parent: 3:eebf5a27f8ca | |
536 | user: test |
|
536 | user: test | |
537 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
537 | date: Thu Jan 01 00:00:00 1970 +0000 | |
538 | summary: 0.3m |
|
538 | summary: 0.3m | |
539 |
|
539 | |||
540 | changeset: 7:a6a34bfa0076 |
|
540 | changeset: 7:a6a34bfa0076 | |
541 | user: test |
|
541 | user: test | |
542 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
542 | date: Thu Jan 01 00:00:00 1970 +0000 | |
543 | summary: 1.3m |
|
543 | summary: 1.3m | |
544 |
|
544 | |||
545 | $ rm -r full-clone |
|
545 | $ rm -r full-clone | |
546 |
|
546 | |||
547 | When cloning from a non-copiable repository into '', do not |
|
547 | When cloning from a non-copiable repository into '', do not | |
548 | recurse infinitely (issue2528) |
|
548 | recurse infinitely (issue2528) | |
549 |
|
549 | |||
550 | $ hg clone full.hg '' |
|
550 | $ hg clone full.hg '' | |
551 | abort: empty destination path is not valid |
|
551 | abort: empty destination path is not valid | |
552 | [255] |
|
552 | [255] | |
553 |
|
553 | |||
554 | test for https://bz.mercurial-scm.org/216 |
|
554 | test for https://bz.mercurial-scm.org/216 | |
555 |
|
555 | |||
556 | Unbundle incremental bundles into fresh empty in one go |
|
556 | Unbundle incremental bundles into fresh empty in one go | |
557 |
|
557 | |||
558 | $ rm -r empty |
|
558 | $ rm -r empty | |
559 | $ hg init empty |
|
559 | $ hg init empty | |
560 | $ hg -R test bundle --base null -r 0 ../0.hg |
|
560 | $ hg -R test bundle --base null -r 0 ../0.hg | |
561 | 1 changesets found |
|
561 | 1 changesets found | |
562 | $ hg -R test bundle --base 0 -r 1 ../1.hg |
|
562 | $ hg -R test bundle --base 0 -r 1 ../1.hg | |
563 | 1 changesets found |
|
563 | 1 changesets found | |
564 | $ hg -R empty unbundle -u ../0.hg ../1.hg |
|
564 | $ hg -R empty unbundle -u ../0.hg ../1.hg | |
565 | adding changesets |
|
565 | adding changesets | |
566 | adding manifests |
|
566 | adding manifests | |
567 | adding file changes |
|
567 | adding file changes | |
568 | added 1 changesets with 1 changes to 1 files |
|
568 | added 1 changesets with 1 changes to 1 files | |
569 | adding changesets |
|
569 | adding changesets | |
570 | adding manifests |
|
570 | adding manifests | |
571 | adding file changes |
|
571 | adding file changes | |
572 | added 1 changesets with 1 changes to 1 files |
|
572 | added 1 changesets with 1 changes to 1 files | |
573 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
573 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
574 |
|
574 | |||
575 | View full contents of the bundle |
|
575 | View full contents of the bundle | |
576 | $ hg -R test bundle --base null -r 3 ../partial.hg |
|
576 | $ hg -R test bundle --base null -r 3 ../partial.hg | |
577 | 4 changesets found |
|
577 | 4 changesets found | |
578 | $ cd test |
|
578 | $ cd test | |
579 | $ hg -R ../../partial.hg log -r "bundle()" |
|
579 | $ hg -R ../../partial.hg log -r "bundle()" | |
580 | changeset: 0:f9ee2f85a263 |
|
580 | changeset: 0:f9ee2f85a263 | |
581 | user: test |
|
581 | user: test | |
582 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
582 | date: Thu Jan 01 00:00:00 1970 +0000 | |
583 | summary: 0.0 |
|
583 | summary: 0.0 | |
584 |
|
584 | |||
585 | changeset: 1:34c2bf6b0626 |
|
585 | changeset: 1:34c2bf6b0626 | |
586 | user: test |
|
586 | user: test | |
587 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
587 | date: Thu Jan 01 00:00:00 1970 +0000 | |
588 | summary: 0.1 |
|
588 | summary: 0.1 | |
589 |
|
589 | |||
590 | changeset: 2:e38ba6f5b7e0 |
|
590 | changeset: 2:e38ba6f5b7e0 | |
591 | user: test |
|
591 | user: test | |
592 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
592 | date: Thu Jan 01 00:00:00 1970 +0000 | |
593 | summary: 0.2 |
|
593 | summary: 0.2 | |
594 |
|
594 | |||
595 | changeset: 3:eebf5a27f8ca |
|
595 | changeset: 3:eebf5a27f8ca | |
596 | user: test |
|
596 | user: test | |
597 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
597 | date: Thu Jan 01 00:00:00 1970 +0000 | |
598 | summary: 0.3 |
|
598 | summary: 0.3 | |
599 |
|
599 | |||
600 | $ cd .. |
|
600 | $ cd .. | |
601 |
|
601 | |||
602 | test for 540d1059c802 |
|
602 | test for 540d1059c802 | |
603 |
|
603 | |||
604 | test for 540d1059c802 |
|
604 | test for 540d1059c802 | |
605 |
|
605 | |||
606 | $ hg init orig |
|
606 | $ hg init orig | |
607 | $ cd orig |
|
607 | $ cd orig | |
608 | $ echo foo > foo |
|
608 | $ echo foo > foo | |
609 | $ hg add foo |
|
609 | $ hg add foo | |
610 | $ hg ci -m 'add foo' |
|
610 | $ hg ci -m 'add foo' | |
611 |
|
611 | |||
612 | $ hg clone . ../copy |
|
612 | $ hg clone . ../copy | |
613 | updating to branch default |
|
613 | updating to branch default | |
614 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
614 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
615 | $ hg tag foo |
|
615 | $ hg tag foo | |
616 |
|
616 | |||
617 | $ cd ../copy |
|
617 | $ cd ../copy | |
618 | $ echo >> foo |
|
618 | $ echo >> foo | |
619 | $ hg ci -m 'change foo' |
|
619 | $ hg ci -m 'change foo' | |
620 | $ hg bundle ../bundle.hg ../orig |
|
620 | $ hg bundle ../bundle.hg ../orig | |
621 | searching for changes |
|
621 | searching for changes | |
622 | 1 changesets found |
|
622 | 1 changesets found | |
623 |
|
623 | |||
624 | $ cd ../orig |
|
624 | $ cd ../orig | |
625 | $ hg incoming ../bundle.hg |
|
625 | $ hg incoming ../bundle.hg | |
626 | comparing with ../bundle.hg |
|
626 | comparing with ../bundle.hg | |
627 | searching for changes |
|
627 | searching for changes | |
628 | changeset: 2:ed1b79f46b9a |
|
628 | changeset: 2:ed1b79f46b9a | |
629 | tag: tip |
|
629 | tag: tip | |
630 | parent: 0:bbd179dfa0a7 |
|
630 | parent: 0:bbd179dfa0a7 | |
631 | user: test |
|
631 | user: test | |
632 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
632 | date: Thu Jan 01 00:00:00 1970 +0000 | |
633 | summary: change foo |
|
633 | summary: change foo | |
634 |
|
634 | |||
635 | $ cd .. |
|
635 | $ cd .. | |
636 |
|
636 | |||
637 | test bundle with # in the filename (issue2154): |
|
637 | test bundle with # in the filename (issue2154): | |
638 |
|
638 | |||
639 | $ cp bundle.hg 'test#bundle.hg' |
|
639 | $ cp bundle.hg 'test#bundle.hg' | |
640 | $ cd orig |
|
640 | $ cd orig | |
641 | $ hg incoming '../test#bundle.hg' |
|
641 | $ hg incoming '../test#bundle.hg' | |
642 | comparing with ../test |
|
642 | comparing with ../test | |
643 | abort: unknown revision 'bundle.hg'! |
|
643 | abort: unknown revision 'bundle.hg'! | |
644 | [255] |
|
644 | [255] | |
645 |
|
645 | |||
646 | note that percent encoding is not handled: |
|
646 | note that percent encoding is not handled: | |
647 |
|
647 | |||
648 | $ hg incoming ../test%23bundle.hg |
|
648 | $ hg incoming ../test%23bundle.hg | |
649 | abort: repository ../test%23bundle.hg not found! |
|
649 | abort: repository ../test%23bundle.hg not found! | |
650 | [255] |
|
650 | [255] | |
651 | $ cd .. |
|
651 | $ cd .. | |
652 |
|
652 | |||
653 | test to bundle revisions on the newly created branch (issue3828): |
|
653 | test to bundle revisions on the newly created branch (issue3828): | |
654 |
|
654 | |||
655 | $ hg -q clone -U test test-clone |
|
655 | $ hg -q clone -U test test-clone | |
656 | $ cd test |
|
656 | $ cd test | |
657 |
|
657 | |||
658 | $ hg -q branch foo |
|
658 | $ hg -q branch foo | |
659 | $ hg commit -m "create foo branch" |
|
659 | $ hg commit -m "create foo branch" | |
660 | $ hg -q outgoing ../test-clone |
|
660 | $ hg -q outgoing ../test-clone | |
661 | 9:b4f5acb1ee27 |
|
661 | 9:b4f5acb1ee27 | |
662 | $ hg -q bundle --branch foo foo.hg ../test-clone |
|
662 | $ hg -q bundle --branch foo foo.hg ../test-clone | |
663 | $ hg -R foo.hg -q log -r "bundle()" |
|
663 | $ hg -R foo.hg -q log -r "bundle()" | |
664 | 9:b4f5acb1ee27 |
|
664 | 9:b4f5acb1ee27 | |
665 |
|
665 | |||
666 | $ cd .. |
|
666 | $ cd .. | |
667 |
|
667 | |||
668 | test for https://bz.mercurial-scm.org/1144 |
|
668 | test for https://bz.mercurial-scm.org/1144 | |
669 |
|
669 | |||
670 | test that verify bundle does not traceback |
|
670 | test that verify bundle does not traceback | |
671 |
|
671 | |||
672 | partial history bundle, fails w/ unknown parent |
|
672 | partial history bundle, fails w/ unknown parent | |
673 |
|
673 | |||
674 | $ hg -R bundle.hg verify |
|
674 | $ hg -R bundle.hg verify | |
675 | abort: 00changelog.i@bbd179dfa0a7: unknown parent! |
|
675 | abort: 00changelog.i@bbd179dfa0a7: unknown parent! | |
676 | [255] |
|
676 | [255] | |
677 |
|
677 | |||
678 | full history bundle, refuses to verify non-local repo |
|
678 | full history bundle, refuses to verify non-local repo | |
679 |
|
679 | |||
680 | $ hg -R all.hg verify |
|
680 | $ hg -R all.hg verify | |
681 | abort: cannot verify bundle or remote repos |
|
681 | abort: cannot verify bundle or remote repos | |
682 | [255] |
|
682 | [255] | |
683 |
|
683 | |||
684 | but, regular verify must continue to work |
|
684 | but, regular verify must continue to work | |
685 |
|
685 | |||
686 | $ hg -R orig verify |
|
686 | $ hg -R orig verify | |
687 | checking changesets |
|
687 | checking changesets | |
688 | checking manifests |
|
688 | checking manifests | |
689 | crosschecking files in changesets and manifests |
|
689 | crosschecking files in changesets and manifests | |
690 | checking files |
|
690 | checking files | |
691 | 2 files, 2 changesets, 2 total revisions |
|
691 | 2 files, 2 changesets, 2 total revisions | |
692 |
|
692 | |||
693 | diff against bundle |
|
693 | diff against bundle | |
694 |
|
694 | |||
695 | $ hg init b |
|
695 | $ hg init b | |
696 | $ cd b |
|
696 | $ cd b | |
697 | $ hg -R ../all.hg diff -r tip |
|
697 | $ hg -R ../all.hg diff -r tip | |
698 | diff -r aa35859c02ea anotherfile |
|
698 | diff -r aa35859c02ea anotherfile | |
699 | --- a/anotherfile Thu Jan 01 00:00:00 1970 +0000 |
|
699 | --- a/anotherfile Thu Jan 01 00:00:00 1970 +0000 | |
700 | +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 |
|
700 | +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 | |
701 | @@ -1,4 +0,0 @@ |
|
701 | @@ -1,4 +0,0 @@ | |
702 | -0 |
|
702 | -0 | |
703 | -1 |
|
703 | -1 | |
704 | -2 |
|
704 | -2 | |
705 | -3 |
|
705 | -3 | |
706 | $ cd .. |
|
706 | $ cd .. | |
707 |
|
707 | |||
708 | bundle single branch |
|
708 | bundle single branch | |
709 |
|
709 | |||
710 | $ hg init branchy |
|
710 | $ hg init branchy | |
711 | $ cd branchy |
|
711 | $ cd branchy | |
712 | $ echo a >a |
|
712 | $ echo a >a | |
713 | $ echo x >x |
|
713 | $ echo x >x | |
714 | $ hg ci -Ama |
|
714 | $ hg ci -Ama | |
715 | adding a |
|
715 | adding a | |
716 | adding x |
|
716 | adding x | |
717 | $ echo c >c |
|
717 | $ echo c >c | |
718 | $ echo xx >x |
|
718 | $ echo xx >x | |
719 | $ hg ci -Amc |
|
719 | $ hg ci -Amc | |
720 | adding c |
|
720 | adding c | |
721 | $ echo c1 >c1 |
|
721 | $ echo c1 >c1 | |
722 | $ hg ci -Amc1 |
|
722 | $ hg ci -Amc1 | |
723 | adding c1 |
|
723 | adding c1 | |
724 | $ hg up 0 |
|
724 | $ hg up 0 | |
725 | 1 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
725 | 1 files updated, 0 files merged, 2 files removed, 0 files unresolved | |
726 | $ echo b >b |
|
726 | $ echo b >b | |
727 | $ hg ci -Amb |
|
727 | $ hg ci -Amb | |
728 | adding b |
|
728 | adding b | |
729 | created new head |
|
729 | created new head | |
730 | $ echo b1 >b1 |
|
730 | $ echo b1 >b1 | |
731 | $ echo xx >x |
|
731 | $ echo xx >x | |
732 | $ hg ci -Amb1 |
|
732 | $ hg ci -Amb1 | |
733 | adding b1 |
|
733 | adding b1 | |
734 | $ hg clone -q -r2 . part |
|
734 | $ hg clone -q -r2 . part | |
735 |
|
735 | |||
736 | == bundling via incoming |
|
736 | == bundling via incoming | |
737 |
|
737 | |||
738 | $ hg in -R part --bundle incoming.hg --template "{node}\n" . |
|
738 | $ hg in -R part --bundle incoming.hg --template "{node}\n" . | |
739 | comparing with . |
|
739 | comparing with . | |
740 | searching for changes |
|
740 | searching for changes | |
741 | 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a |
|
741 | 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a | |
742 | 057f4db07f61970e1c11e83be79e9d08adc4dc31 |
|
742 | 057f4db07f61970e1c11e83be79e9d08adc4dc31 | |
743 |
|
743 | |||
744 | == bundling |
|
744 | == bundling | |
745 |
|
745 | |||
746 | $ hg bundle bundle.hg part --debug --config progress.debug=true |
|
746 | $ hg bundle bundle.hg part --debug --config progress.debug=true | |
747 | query 1; heads |
|
747 | query 1; heads | |
748 | searching for changes |
|
748 | searching for changes | |
749 | all remote heads known locally |
|
749 | all remote heads known locally | |
750 | 2 changesets found |
|
750 | 2 changesets found | |
751 | list of changesets: |
|
751 | list of changesets: | |
752 | 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a |
|
752 | 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a | |
753 | 057f4db07f61970e1c11e83be79e9d08adc4dc31 |
|
753 | 057f4db07f61970e1c11e83be79e9d08adc4dc31 | |
754 | bundle2-output-bundle: "HG20", (1 params) 1 parts total |
|
754 | bundle2-output-bundle: "HG20", (1 params) 1 parts total | |
755 | bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload |
|
755 | bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload | |
756 | bundling: 1/2 changesets (50.00%) |
|
756 | bundling: 1/2 changesets (50.00%) | |
757 | bundling: 2/2 changesets (100.00%) |
|
757 | bundling: 2/2 changesets (100.00%) | |
758 | bundling: 1/2 manifests (50.00%) |
|
758 | bundling: 1/2 manifests (50.00%) | |
759 | bundling: 2/2 manifests (100.00%) |
|
759 | bundling: 2/2 manifests (100.00%) | |
760 | bundling: b 1/3 files (33.33%) |
|
760 | bundling: b 1/3 files (33.33%) | |
761 | bundling: b1 2/3 files (66.67%) |
|
761 | bundling: b1 2/3 files (66.67%) | |
762 | bundling: x 3/3 files (100.00%) |
|
762 | bundling: x 3/3 files (100.00%) | |
763 |
|
763 | |||
764 | == Test for issue3441 |
|
764 | == Test for issue3441 | |
765 |
|
765 | |||
766 | $ hg clone -q -r0 . part2 |
|
766 | $ hg clone -q -r0 . part2 | |
767 | $ hg -q -R part2 pull bundle.hg |
|
767 | $ hg -q -R part2 pull bundle.hg | |
768 | $ hg -R part2 verify |
|
768 | $ hg -R part2 verify | |
769 | checking changesets |
|
769 | checking changesets | |
770 | checking manifests |
|
770 | checking manifests | |
771 | crosschecking files in changesets and manifests |
|
771 | crosschecking files in changesets and manifests | |
772 | checking files |
|
772 | checking files | |
773 | 4 files, 3 changesets, 5 total revisions |
|
773 | 4 files, 3 changesets, 5 total revisions | |
774 |
|
774 | |||
775 | == Test bundling no commits |
|
775 | == Test bundling no commits | |
776 |
|
776 | |||
777 | $ hg bundle -r 'public()' no-output.hg |
|
777 | $ hg bundle -r 'public()' no-output.hg | |
778 | abort: no commits to bundle |
|
778 | abort: no commits to bundle | |
779 | [255] |
|
779 | [255] | |
780 |
|
780 | |||
781 | $ cd .. |
|
781 | $ cd .. | |
782 |
|
782 | |||
783 | When user merges to the revision existing only in the bundle, |
|
783 | When user merges to the revision existing only in the bundle, | |
784 | it should show warning that second parent of the working |
|
784 | it should show warning that second parent of the working | |
785 | directory does not exist |
|
785 | directory does not exist | |
786 |
|
786 | |||
787 | $ hg init update2bundled |
|
787 | $ hg init update2bundled | |
788 | $ cd update2bundled |
|
788 | $ cd update2bundled | |
789 | $ cat <<EOF >> .hg/hgrc |
|
789 | $ cat <<EOF >> .hg/hgrc | |
790 | > [extensions] |
|
790 | > [extensions] | |
791 | > strip = |
|
791 | > strip = | |
792 | > EOF |
|
792 | > EOF | |
793 | $ echo "aaa" >> a |
|
793 | $ echo "aaa" >> a | |
794 | $ hg commit -A -m 0 |
|
794 | $ hg commit -A -m 0 | |
795 | adding a |
|
795 | adding a | |
796 | $ echo "bbb" >> b |
|
796 | $ echo "bbb" >> b | |
797 | $ hg commit -A -m 1 |
|
797 | $ hg commit -A -m 1 | |
798 | adding b |
|
798 | adding b | |
799 | $ echo "ccc" >> c |
|
799 | $ echo "ccc" >> c | |
800 | $ hg commit -A -m 2 |
|
800 | $ hg commit -A -m 2 | |
801 | adding c |
|
801 | adding c | |
802 | $ hg update -r 1 |
|
802 | $ hg update -r 1 | |
803 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
803 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved | |
804 | $ echo "ddd" >> d |
|
804 | $ echo "ddd" >> d | |
805 | $ hg commit -A -m 3 |
|
805 | $ hg commit -A -m 3 | |
806 | adding d |
|
806 | adding d | |
807 | created new head |
|
807 | created new head | |
808 | $ hg update -r 2 |
|
808 | $ hg update -r 2 | |
809 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
809 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved | |
810 | $ hg log -G |
|
810 | $ hg log -G | |
811 | o changeset: 3:8bd3e1f196af |
|
811 | o changeset: 3:8bd3e1f196af | |
812 | | tag: tip |
|
812 | | tag: tip | |
813 | | parent: 1:a01eca7af26d |
|
813 | | parent: 1:a01eca7af26d | |
814 | | user: test |
|
814 | | user: test | |
815 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
815 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
816 | | summary: 3 |
|
816 | | summary: 3 | |
817 | | |
|
817 | | | |
818 | | @ changeset: 2:4652c276ac4f |
|
818 | | @ changeset: 2:4652c276ac4f | |
819 | |/ user: test |
|
819 | |/ user: test | |
820 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
820 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
821 | | summary: 2 |
|
821 | | summary: 2 | |
822 | | |
|
822 | | | |
823 | o changeset: 1:a01eca7af26d |
|
823 | o changeset: 1:a01eca7af26d | |
824 | | user: test |
|
824 | | user: test | |
825 | | date: Thu Jan 01 00:00:00 1970 +0000 |
|
825 | | date: Thu Jan 01 00:00:00 1970 +0000 | |
826 | | summary: 1 |
|
826 | | summary: 1 | |
827 | | |
|
827 | | | |
828 | o changeset: 0:4fe08cd4693e |
|
828 | o changeset: 0:4fe08cd4693e | |
829 | user: test |
|
829 | user: test | |
830 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
830 | date: Thu Jan 01 00:00:00 1970 +0000 | |
831 | summary: 0 |
|
831 | summary: 0 | |
832 |
|
832 | |||
833 | $ hg bundle --base 1 -r 3 ../update2bundled.hg |
|
833 | $ hg bundle --base 1 -r 3 ../update2bundled.hg | |
834 | 1 changesets found |
|
834 | 1 changesets found | |
835 | $ hg strip -r 3 |
|
835 | $ hg strip -r 3 | |
836 | saved backup bundle to $TESTTMP/update2bundled/.hg/strip-backup/8bd3e1f196af-017e56d8-backup.hg (glob) |
|
836 | saved backup bundle to $TESTTMP/update2bundled/.hg/strip-backup/8bd3e1f196af-017e56d8-backup.hg (glob) | |
837 | $ hg merge -R ../update2bundled.hg -r 3 |
|
837 | $ hg merge -R ../update2bundled.hg -r 3 | |
838 | setting parent to node 8bd3e1f196af289b2b121be08031e76d7ae92098 that only exists in the bundle |
|
838 | setting parent to node 8bd3e1f196af289b2b121be08031e76d7ae92098 that only exists in the bundle | |
839 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
839 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
840 | (branch merge, don't forget to commit) |
|
840 | (branch merge, don't forget to commit) | |
841 |
|
841 | |||
842 | When user updates to the revision existing only in the bundle, |
|
842 | When user updates to the revision existing only in the bundle, | |
843 | it should show warning |
|
843 | it should show warning | |
844 |
|
844 | |||
845 | $ hg update -R ../update2bundled.hg --clean -r 3 |
|
845 | $ hg update -R ../update2bundled.hg --clean -r 3 | |
846 | setting parent to node 8bd3e1f196af289b2b121be08031e76d7ae92098 that only exists in the bundle |
|
846 | setting parent to node 8bd3e1f196af289b2b121be08031e76d7ae92098 that only exists in the bundle | |
847 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
847 | 1 files updated, 0 files merged, 1 files removed, 0 files unresolved | |
848 |
|
848 | |||
849 | When user updates to the revision existing in the local repository |
|
849 | When user updates to the revision existing in the local repository | |
850 | the warning shouldn't be emitted |
|
850 | the warning shouldn't be emitted | |
851 |
|
851 | |||
852 | $ hg update -R ../update2bundled.hg -r 0 |
|
852 | $ hg update -R ../update2bundled.hg -r 0 | |
853 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
853 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved |
@@ -1,1136 +1,1136 b'' | |||||
1 | Test exchange of common information using bundle2 |
|
1 | Test exchange of common information using bundle2 | |
2 |
|
2 | |||
3 |
|
3 | |||
4 | $ getmainid() { |
|
4 | $ getmainid() { | |
5 | > hg -R main log --template '{node}\n' --rev "$1" |
|
5 | > hg -R main log --template '{node}\n' --rev "$1" | |
6 | > } |
|
6 | > } | |
7 |
|
7 | |||
8 | enable obsolescence |
|
8 | enable obsolescence | |
9 |
|
9 | |||
10 | $ cp $HGRCPATH $TESTTMP/hgrc.orig |
|
10 | $ cp $HGRCPATH $TESTTMP/hgrc.orig | |
11 | $ cat > $TESTTMP/bundle2-pushkey-hook.sh << EOF |
|
11 | $ cat > $TESTTMP/bundle2-pushkey-hook.sh << EOF | |
12 | > echo pushkey: lock state after \"\$HG_NAMESPACE\" |
|
12 | > echo pushkey: lock state after \"\$HG_NAMESPACE\" | |
13 | > hg debuglock |
|
13 | > hg debuglock | |
14 | > EOF |
|
14 | > EOF | |
15 |
|
15 | |||
16 | $ cat >> $HGRCPATH << EOF |
|
16 | $ cat >> $HGRCPATH << EOF | |
17 | > [experimental] |
|
17 | > [experimental] | |
18 | > evolution=createmarkers,exchange |
|
18 | > evolution=createmarkers,exchange | |
19 | > bundle2-output-capture=True |
|
19 | > bundle2-output-capture=True | |
20 | > [ui] |
|
20 | > [ui] | |
21 | > ssh=python "$TESTDIR/dummyssh" |
|
21 | > ssh=python "$TESTDIR/dummyssh" | |
22 | > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline} |
|
22 | > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline} | |
23 | > [web] |
|
23 | > [web] | |
24 | > push_ssl = false |
|
24 | > push_ssl = false | |
25 | > allow_push = * |
|
25 | > allow_push = * | |
26 | > [phases] |
|
26 | > [phases] | |
27 | > publish=False |
|
27 | > publish=False | |
28 | > [hooks] |
|
28 | > [hooks] | |
29 | > pretxnclose.tip = hg log -r tip -T "pre-close-tip:{node|short} {phase} {bookmarks}\n" |
|
29 | > pretxnclose.tip = hg log -r tip -T "pre-close-tip:{node|short} {phase} {bookmarks}\n" | |
30 | > txnclose.tip = hg log -r tip -T "postclose-tip:{node|short} {phase} {bookmarks}\n" |
|
30 | > txnclose.tip = hg log -r tip -T "postclose-tip:{node|short} {phase} {bookmarks}\n" | |
31 | > txnclose.env = sh -c "HG_LOCAL= printenv.py txnclose" |
|
31 | > txnclose.env = sh -c "HG_LOCAL= printenv.py txnclose" | |
32 | > pushkey= sh "$TESTTMP/bundle2-pushkey-hook.sh" |
|
32 | > pushkey= sh "$TESTTMP/bundle2-pushkey-hook.sh" | |
33 | > EOF |
|
33 | > EOF | |
34 |
|
34 | |||
35 | The extension requires a repo (currently unused) |
|
35 | The extension requires a repo (currently unused) | |
36 |
|
36 | |||
37 | $ hg init main |
|
37 | $ hg init main | |
38 | $ cd main |
|
38 | $ cd main | |
39 | $ touch a |
|
39 | $ touch a | |
40 | $ hg add a |
|
40 | $ hg add a | |
41 | $ hg commit -m 'a' |
|
41 | $ hg commit -m 'a' | |
42 | pre-close-tip:3903775176ed draft |
|
42 | pre-close-tip:3903775176ed draft | |
43 | postclose-tip:3903775176ed draft |
|
43 | postclose-tip:3903775176ed draft | |
44 |
txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN: |
|
44 | txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
45 |
|
45 | |||
46 | $ hg unbundle $TESTDIR/bundles/rebase.hg |
|
46 | $ hg unbundle $TESTDIR/bundles/rebase.hg | |
47 | adding changesets |
|
47 | adding changesets | |
48 | adding manifests |
|
48 | adding manifests | |
49 | adding file changes |
|
49 | adding file changes | |
50 | added 8 changesets with 7 changes to 7 files (+3 heads) |
|
50 | added 8 changesets with 7 changes to 7 files (+3 heads) | |
51 | pre-close-tip:02de42196ebe draft |
|
51 | pre-close-tip:02de42196ebe draft | |
52 | postclose-tip:02de42196ebe draft |
|
52 | postclose-tip:02de42196ebe draft | |
53 |
txnclose hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=unbundle HG_TXNID=TXN: |
|
53 | txnclose hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=unbundle HG_TXNID=TXN:$ID$ HG_TXNNAME=unbundle | |
54 | bundle:*/tests/bundles/rebase.hg HG_URL=bundle:*/tests/bundles/rebase.hg (glob) |
|
54 | bundle:*/tests/bundles/rebase.hg HG_URL=bundle:*/tests/bundles/rebase.hg (glob) | |
55 | (run 'hg heads' to see heads, 'hg merge' to merge) |
|
55 | (run 'hg heads' to see heads, 'hg merge' to merge) | |
56 |
|
56 | |||
57 | $ cd .. |
|
57 | $ cd .. | |
58 |
|
58 | |||
59 | Real world exchange |
|
59 | Real world exchange | |
60 | ===================== |
|
60 | ===================== | |
61 |
|
61 | |||
62 | Add more obsolescence information |
|
62 | Add more obsolescence information | |
63 |
|
63 | |||
64 | $ hg -R main debugobsolete -d '0 0' 1111111111111111111111111111111111111111 `getmainid 9520eea781bc` |
|
64 | $ hg -R main debugobsolete -d '0 0' 1111111111111111111111111111111111111111 `getmainid 9520eea781bc` | |
65 | pre-close-tip:02de42196ebe draft |
|
65 | pre-close-tip:02de42196ebe draft | |
66 | postclose-tip:02de42196ebe draft |
|
66 | postclose-tip:02de42196ebe draft | |
67 |
txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN: |
|
67 | txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete | |
68 | $ hg -R main debugobsolete -d '0 0' 2222222222222222222222222222222222222222 `getmainid 24b6387c8c8c` |
|
68 | $ hg -R main debugobsolete -d '0 0' 2222222222222222222222222222222222222222 `getmainid 24b6387c8c8c` | |
69 | pre-close-tip:02de42196ebe draft |
|
69 | pre-close-tip:02de42196ebe draft | |
70 | postclose-tip:02de42196ebe draft |
|
70 | postclose-tip:02de42196ebe draft | |
71 |
txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN: |
|
71 | txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete | |
72 |
|
72 | |||
73 | clone --pull |
|
73 | clone --pull | |
74 |
|
74 | |||
75 | $ hg -R main phase --public cd010b8cd998 |
|
75 | $ hg -R main phase --public cd010b8cd998 | |
76 | pre-close-tip:02de42196ebe draft |
|
76 | pre-close-tip:02de42196ebe draft | |
77 | postclose-tip:02de42196ebe draft |
|
77 | postclose-tip:02de42196ebe draft | |
78 |
txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN: |
|
78 | txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase | |
79 | $ hg clone main other --pull --rev 9520eea781bc |
|
79 | $ hg clone main other --pull --rev 9520eea781bc | |
80 | adding changesets |
|
80 | adding changesets | |
81 | adding manifests |
|
81 | adding manifests | |
82 | adding file changes |
|
82 | adding file changes | |
83 | added 2 changesets with 2 changes to 2 files |
|
83 | added 2 changesets with 2 changes to 2 files | |
84 | 1 new obsolescence markers |
|
84 | 1 new obsolescence markers | |
85 | pre-close-tip:9520eea781bc draft |
|
85 | pre-close-tip:9520eea781bc draft | |
86 | postclose-tip:9520eea781bc draft |
|
86 | postclose-tip:9520eea781bc draft | |
87 |
txnclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_NODE_LAST=9520eea781bcca16c1e15acc0ba14335a0e8e5ba HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
87 | txnclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_NODE_LAST=9520eea781bcca16c1e15acc0ba14335a0e8e5ba HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull | |
88 | file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob) |
|
88 | file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob) | |
89 | updating to branch default |
|
89 | updating to branch default | |
90 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
90 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
91 | $ hg -R other log -G |
|
91 | $ hg -R other log -G | |
92 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E |
|
92 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E | |
93 | | |
|
93 | | | |
94 | o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A |
|
94 | o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A | |
95 |
|
95 | |||
96 | $ hg -R other debugobsolete |
|
96 | $ hg -R other debugobsolete | |
97 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
97 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
98 |
|
98 | |||
99 | pull |
|
99 | pull | |
100 |
|
100 | |||
101 | $ hg -R main phase --public 9520eea781bc |
|
101 | $ hg -R main phase --public 9520eea781bc | |
102 | pre-close-tip:02de42196ebe draft |
|
102 | pre-close-tip:02de42196ebe draft | |
103 | postclose-tip:02de42196ebe draft |
|
103 | postclose-tip:02de42196ebe draft | |
104 |
txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN: |
|
104 | txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase | |
105 | $ hg -R other pull -r 24b6387c8c8c |
|
105 | $ hg -R other pull -r 24b6387c8c8c | |
106 | pulling from $TESTTMP/main (glob) |
|
106 | pulling from $TESTTMP/main (glob) | |
107 | searching for changes |
|
107 | searching for changes | |
108 | adding changesets |
|
108 | adding changesets | |
109 | adding manifests |
|
109 | adding manifests | |
110 | adding file changes |
|
110 | adding file changes | |
111 | added 1 changesets with 1 changes to 1 files (+1 heads) |
|
111 | added 1 changesets with 1 changes to 1 files (+1 heads) | |
112 | 1 new obsolescence markers |
|
112 | 1 new obsolescence markers | |
113 | pre-close-tip:24b6387c8c8c draft |
|
113 | pre-close-tip:24b6387c8c8c draft | |
114 | postclose-tip:24b6387c8c8c draft |
|
114 | postclose-tip:24b6387c8c8c draft | |
115 |
txnclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_NODE_LAST=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
115 | txnclose hook: HG_NEW_OBSMARKERS=1 HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_NODE_LAST=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull | |
116 | file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob) |
|
116 | file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob) | |
117 | (run 'hg heads' to see heads, 'hg merge' to merge) |
|
117 | (run 'hg heads' to see heads, 'hg merge' to merge) | |
118 | $ hg -R other log -G |
|
118 | $ hg -R other log -G | |
119 | o 2:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F |
|
119 | o 2:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F | |
120 | | |
|
120 | | | |
121 | | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E |
|
121 | | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E | |
122 | |/ |
|
122 | |/ | |
123 | o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A |
|
123 | o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A | |
124 |
|
124 | |||
125 | $ hg -R other debugobsolete |
|
125 | $ hg -R other debugobsolete | |
126 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
126 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
127 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
127 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
128 |
|
128 | |||
129 | pull empty (with phase movement) |
|
129 | pull empty (with phase movement) | |
130 |
|
130 | |||
131 | $ hg -R main phase --public 24b6387c8c8c |
|
131 | $ hg -R main phase --public 24b6387c8c8c | |
132 | pre-close-tip:02de42196ebe draft |
|
132 | pre-close-tip:02de42196ebe draft | |
133 | postclose-tip:02de42196ebe draft |
|
133 | postclose-tip:02de42196ebe draft | |
134 |
txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN: |
|
134 | txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase | |
135 | $ hg -R other pull -r 24b6387c8c8c |
|
135 | $ hg -R other pull -r 24b6387c8c8c | |
136 | pulling from $TESTTMP/main (glob) |
|
136 | pulling from $TESTTMP/main (glob) | |
137 | no changes found |
|
137 | no changes found | |
138 | pre-close-tip:24b6387c8c8c public |
|
138 | pre-close-tip:24b6387c8c8c public | |
139 | postclose-tip:24b6387c8c8c public |
|
139 | postclose-tip:24b6387c8c8c public | |
140 |
txnclose hook: HG_NEW_OBSMARKERS=0 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
140 | txnclose hook: HG_NEW_OBSMARKERS=0 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull | |
141 | file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob) |
|
141 | file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob) | |
142 | $ hg -R other log -G |
|
142 | $ hg -R other log -G | |
143 | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F |
|
143 | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F | |
144 | | |
|
144 | | | |
145 | | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E |
|
145 | | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E | |
146 | |/ |
|
146 | |/ | |
147 | o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A |
|
147 | o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A | |
148 |
|
148 | |||
149 | $ hg -R other debugobsolete |
|
149 | $ hg -R other debugobsolete | |
150 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
150 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
151 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
151 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
152 |
|
152 | |||
153 | pull empty |
|
153 | pull empty | |
154 |
|
154 | |||
155 | $ hg -R other pull -r 24b6387c8c8c |
|
155 | $ hg -R other pull -r 24b6387c8c8c | |
156 | pulling from $TESTTMP/main (glob) |
|
156 | pulling from $TESTTMP/main (glob) | |
157 | no changes found |
|
157 | no changes found | |
158 | pre-close-tip:24b6387c8c8c public |
|
158 | pre-close-tip:24b6387c8c8c public | |
159 | postclose-tip:24b6387c8c8c public |
|
159 | postclose-tip:24b6387c8c8c public | |
160 |
txnclose hook: HG_NEW_OBSMARKERS=0 HG_SOURCE=pull HG_TXNID=TXN: |
|
160 | txnclose hook: HG_NEW_OBSMARKERS=0 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull | |
161 | file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob) |
|
161 | file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob) | |
162 | $ hg -R other log -G |
|
162 | $ hg -R other log -G | |
163 | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F |
|
163 | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F | |
164 | | |
|
164 | | | |
165 | | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E |
|
165 | | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E | |
166 | |/ |
|
166 | |/ | |
167 | o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A |
|
167 | o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A | |
168 |
|
168 | |||
169 | $ hg -R other debugobsolete |
|
169 | $ hg -R other debugobsolete | |
170 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
170 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
171 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
171 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
172 |
|
172 | |||
173 | add extra data to test their exchange during push |
|
173 | add extra data to test their exchange during push | |
174 |
|
174 | |||
175 | $ hg -R main bookmark --rev eea13746799a book_eea1 |
|
175 | $ hg -R main bookmark --rev eea13746799a book_eea1 | |
176 | pre-close-tip:02de42196ebe draft |
|
176 | pre-close-tip:02de42196ebe draft | |
177 | postclose-tip:02de42196ebe draft |
|
177 | postclose-tip:02de42196ebe draft | |
178 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN: |
|
178 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
179 | $ hg -R main debugobsolete -d '0 0' 3333333333333333333333333333333333333333 `getmainid eea13746799a` |
|
179 | $ hg -R main debugobsolete -d '0 0' 3333333333333333333333333333333333333333 `getmainid eea13746799a` | |
180 | pre-close-tip:02de42196ebe draft |
|
180 | pre-close-tip:02de42196ebe draft | |
181 | postclose-tip:02de42196ebe draft |
|
181 | postclose-tip:02de42196ebe draft | |
182 |
txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN: |
|
182 | txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete | |
183 | $ hg -R main bookmark --rev 02de42196ebe book_02de |
|
183 | $ hg -R main bookmark --rev 02de42196ebe book_02de | |
184 | pre-close-tip:02de42196ebe draft book_02de |
|
184 | pre-close-tip:02de42196ebe draft book_02de | |
185 | postclose-tip:02de42196ebe draft book_02de |
|
185 | postclose-tip:02de42196ebe draft book_02de | |
186 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN: |
|
186 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
187 | $ hg -R main debugobsolete -d '0 0' 4444444444444444444444444444444444444444 `getmainid 02de42196ebe` |
|
187 | $ hg -R main debugobsolete -d '0 0' 4444444444444444444444444444444444444444 `getmainid 02de42196ebe` | |
188 | pre-close-tip:02de42196ebe draft book_02de |
|
188 | pre-close-tip:02de42196ebe draft book_02de | |
189 | postclose-tip:02de42196ebe draft book_02de |
|
189 | postclose-tip:02de42196ebe draft book_02de | |
190 |
txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN: |
|
190 | txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete | |
191 | $ hg -R main bookmark --rev 42ccdea3bb16 book_42cc |
|
191 | $ hg -R main bookmark --rev 42ccdea3bb16 book_42cc | |
192 | pre-close-tip:02de42196ebe draft book_02de |
|
192 | pre-close-tip:02de42196ebe draft book_02de | |
193 | postclose-tip:02de42196ebe draft book_02de |
|
193 | postclose-tip:02de42196ebe draft book_02de | |
194 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN: |
|
194 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
195 | $ hg -R main debugobsolete -d '0 0' 5555555555555555555555555555555555555555 `getmainid 42ccdea3bb16` |
|
195 | $ hg -R main debugobsolete -d '0 0' 5555555555555555555555555555555555555555 `getmainid 42ccdea3bb16` | |
196 | pre-close-tip:02de42196ebe draft book_02de |
|
196 | pre-close-tip:02de42196ebe draft book_02de | |
197 | postclose-tip:02de42196ebe draft book_02de |
|
197 | postclose-tip:02de42196ebe draft book_02de | |
198 |
txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN: |
|
198 | txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete | |
199 | $ hg -R main bookmark --rev 5fddd98957c8 book_5fdd |
|
199 | $ hg -R main bookmark --rev 5fddd98957c8 book_5fdd | |
200 | pre-close-tip:02de42196ebe draft book_02de |
|
200 | pre-close-tip:02de42196ebe draft book_02de | |
201 | postclose-tip:02de42196ebe draft book_02de |
|
201 | postclose-tip:02de42196ebe draft book_02de | |
202 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN: |
|
202 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
203 | $ hg -R main debugobsolete -d '0 0' 6666666666666666666666666666666666666666 `getmainid 5fddd98957c8` |
|
203 | $ hg -R main debugobsolete -d '0 0' 6666666666666666666666666666666666666666 `getmainid 5fddd98957c8` | |
204 | pre-close-tip:02de42196ebe draft book_02de |
|
204 | pre-close-tip:02de42196ebe draft book_02de | |
205 | postclose-tip:02de42196ebe draft book_02de |
|
205 | postclose-tip:02de42196ebe draft book_02de | |
206 |
txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN: |
|
206 | txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete | |
207 | $ hg -R main bookmark --rev 32af7686d403 book_32af |
|
207 | $ hg -R main bookmark --rev 32af7686d403 book_32af | |
208 | pre-close-tip:02de42196ebe draft book_02de |
|
208 | pre-close-tip:02de42196ebe draft book_02de | |
209 | postclose-tip:02de42196ebe draft book_02de |
|
209 | postclose-tip:02de42196ebe draft book_02de | |
210 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN: |
|
210 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
211 | $ hg -R main debugobsolete -d '0 0' 7777777777777777777777777777777777777777 `getmainid 32af7686d403` |
|
211 | $ hg -R main debugobsolete -d '0 0' 7777777777777777777777777777777777777777 `getmainid 32af7686d403` | |
212 | pre-close-tip:02de42196ebe draft book_02de |
|
212 | pre-close-tip:02de42196ebe draft book_02de | |
213 | postclose-tip:02de42196ebe draft book_02de |
|
213 | postclose-tip:02de42196ebe draft book_02de | |
214 |
txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN: |
|
214 | txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete | |
215 |
|
215 | |||
216 | $ hg -R other bookmark --rev cd010b8cd998 book_eea1 |
|
216 | $ hg -R other bookmark --rev cd010b8cd998 book_eea1 | |
217 | pre-close-tip:24b6387c8c8c public |
|
217 | pre-close-tip:24b6387c8c8c public | |
218 | postclose-tip:24b6387c8c8c public |
|
218 | postclose-tip:24b6387c8c8c public | |
219 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN: |
|
219 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
220 | $ hg -R other bookmark --rev cd010b8cd998 book_02de |
|
220 | $ hg -R other bookmark --rev cd010b8cd998 book_02de | |
221 | pre-close-tip:24b6387c8c8c public |
|
221 | pre-close-tip:24b6387c8c8c public | |
222 | postclose-tip:24b6387c8c8c public |
|
222 | postclose-tip:24b6387c8c8c public | |
223 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN: |
|
223 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
224 | $ hg -R other bookmark --rev cd010b8cd998 book_42cc |
|
224 | $ hg -R other bookmark --rev cd010b8cd998 book_42cc | |
225 | pre-close-tip:24b6387c8c8c public |
|
225 | pre-close-tip:24b6387c8c8c public | |
226 | postclose-tip:24b6387c8c8c public |
|
226 | postclose-tip:24b6387c8c8c public | |
227 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN: |
|
227 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
228 | $ hg -R other bookmark --rev cd010b8cd998 book_5fdd |
|
228 | $ hg -R other bookmark --rev cd010b8cd998 book_5fdd | |
229 | pre-close-tip:24b6387c8c8c public |
|
229 | pre-close-tip:24b6387c8c8c public | |
230 | postclose-tip:24b6387c8c8c public |
|
230 | postclose-tip:24b6387c8c8c public | |
231 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN: |
|
231 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
232 | $ hg -R other bookmark --rev cd010b8cd998 book_32af |
|
232 | $ hg -R other bookmark --rev cd010b8cd998 book_32af | |
233 | pre-close-tip:24b6387c8c8c public |
|
233 | pre-close-tip:24b6387c8c8c public | |
234 | postclose-tip:24b6387c8c8c public |
|
234 | postclose-tip:24b6387c8c8c public | |
235 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN: |
|
235 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
236 |
|
236 | |||
237 | $ hg -R main phase --public eea13746799a |
|
237 | $ hg -R main phase --public eea13746799a | |
238 | pre-close-tip:02de42196ebe draft book_02de |
|
238 | pre-close-tip:02de42196ebe draft book_02de | |
239 | postclose-tip:02de42196ebe draft book_02de |
|
239 | postclose-tip:02de42196ebe draft book_02de | |
240 |
txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN: |
|
240 | txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase | |
241 |
|
241 | |||
242 | push |
|
242 | push | |
243 | $ hg -R main push other --rev eea13746799a --bookmark book_eea1 |
|
243 | $ hg -R main push other --rev eea13746799a --bookmark book_eea1 | |
244 | pushing to other |
|
244 | pushing to other | |
245 | searching for changes |
|
245 | searching for changes | |
246 | remote: adding changesets |
|
246 | remote: adding changesets | |
247 | remote: adding manifests |
|
247 | remote: adding manifests | |
248 | remote: adding file changes |
|
248 | remote: adding file changes | |
249 | remote: added 1 changesets with 0 changes to 0 files (-1 heads) |
|
249 | remote: added 1 changesets with 0 changes to 0 files (-1 heads) | |
250 | remote: 1 new obsolescence markers |
|
250 | remote: 1 new obsolescence markers | |
251 | remote: pre-close-tip:eea13746799a public book_eea1 |
|
251 | remote: pre-close-tip:eea13746799a public book_eea1 | |
252 | remote: pushkey: lock state after "phases" |
|
252 | remote: pushkey: lock state after "phases" | |
253 | remote: lock: free |
|
253 | remote: lock: free | |
254 | remote: wlock: free |
|
254 | remote: wlock: free | |
255 | remote: pushkey: lock state after "bookmarks" |
|
255 | remote: pushkey: lock state after "bookmarks" | |
256 | remote: lock: free |
|
256 | remote: lock: free | |
257 | remote: wlock: free |
|
257 | remote: wlock: free | |
258 | remote: postclose-tip:eea13746799a public book_eea1 |
|
258 | remote: postclose-tip:eea13746799a public book_eea1 | |
259 |
remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_NEW_OBSMARKERS=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_NODE_LAST=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_PHASES_MOVED=1 HG_SOURCE=push HG_TXNID=TXN: |
|
259 | remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_NEW_OBSMARKERS=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_NODE_LAST=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_PHASES_MOVED=1 HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/other | |
260 | updating bookmark book_eea1 |
|
260 | updating bookmark book_eea1 | |
261 | pre-close-tip:02de42196ebe draft book_02de |
|
261 | pre-close-tip:02de42196ebe draft book_02de | |
262 | postclose-tip:02de42196ebe draft book_02de |
|
262 | postclose-tip:02de42196ebe draft book_02de | |
263 |
txnclose hook: HG_SOURCE=push-response HG_TXNID=TXN: |
|
263 | txnclose hook: HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response | |
264 | file:/*/$TESTTMP/other HG_URL=file:$TESTTMP/other (glob) |
|
264 | file:/*/$TESTTMP/other HG_URL=file:$TESTTMP/other (glob) | |
265 | $ hg -R other log -G |
|
265 | $ hg -R other log -G | |
266 | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G |
|
266 | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G | |
267 | |\ |
|
267 | |\ | |
268 | | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F |
|
268 | | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F | |
269 | | | |
|
269 | | | | |
270 | @ | 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E |
|
270 | @ | 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E | |
271 | |/ |
|
271 | |/ | |
272 | o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de book_32af book_42cc book_5fdd A |
|
272 | o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de book_32af book_42cc book_5fdd A | |
273 |
|
273 | |||
274 | $ hg -R other debugobsolete |
|
274 | $ hg -R other debugobsolete | |
275 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
275 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
276 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
276 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
277 | 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
277 | 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
278 |
|
278 | |||
279 | pull over ssh |
|
279 | pull over ssh | |
280 |
|
280 | |||
281 | $ hg -R other pull ssh://user@dummy/main -r 02de42196ebe --bookmark book_02de |
|
281 | $ hg -R other pull ssh://user@dummy/main -r 02de42196ebe --bookmark book_02de | |
282 | pulling from ssh://user@dummy/main |
|
282 | pulling from ssh://user@dummy/main | |
283 | searching for changes |
|
283 | searching for changes | |
284 | adding changesets |
|
284 | adding changesets | |
285 | adding manifests |
|
285 | adding manifests | |
286 | adding file changes |
|
286 | adding file changes | |
287 | added 1 changesets with 1 changes to 1 files (+1 heads) |
|
287 | added 1 changesets with 1 changes to 1 files (+1 heads) | |
288 | 1 new obsolescence markers |
|
288 | 1 new obsolescence markers | |
289 | updating bookmark book_02de |
|
289 | updating bookmark book_02de | |
290 | pre-close-tip:02de42196ebe draft book_02de |
|
290 | pre-close-tip:02de42196ebe draft book_02de | |
291 | postclose-tip:02de42196ebe draft book_02de |
|
291 | postclose-tip:02de42196ebe draft book_02de | |
292 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_NEW_OBSMARKERS=1 HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
292 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_NEW_OBSMARKERS=1 HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull | |
293 | ssh://user@dummy/main HG_URL=ssh://user@dummy/main |
|
293 | ssh://user@dummy/main HG_URL=ssh://user@dummy/main | |
294 | (run 'hg heads' to see heads, 'hg merge' to merge) |
|
294 | (run 'hg heads' to see heads, 'hg merge' to merge) | |
295 | $ hg -R other debugobsolete |
|
295 | $ hg -R other debugobsolete | |
296 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
296 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
297 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
297 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
298 | 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
298 | 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
299 | 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
299 | 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
300 |
|
300 | |||
301 | pull over http |
|
301 | pull over http | |
302 |
|
302 | |||
303 | $ hg serve -R main -p $HGPORT -d --pid-file=main.pid -E main-error.log |
|
303 | $ hg serve -R main -p $HGPORT -d --pid-file=main.pid -E main-error.log | |
304 | $ cat main.pid >> $DAEMON_PIDS |
|
304 | $ cat main.pid >> $DAEMON_PIDS | |
305 |
|
305 | |||
306 | $ hg -R other pull http://localhost:$HGPORT/ -r 42ccdea3bb16 --bookmark book_42cc |
|
306 | $ hg -R other pull http://localhost:$HGPORT/ -r 42ccdea3bb16 --bookmark book_42cc | |
307 | pulling from http://localhost:$HGPORT/ |
|
307 | pulling from http://localhost:$HGPORT/ | |
308 | searching for changes |
|
308 | searching for changes | |
309 | adding changesets |
|
309 | adding changesets | |
310 | adding manifests |
|
310 | adding manifests | |
311 | adding file changes |
|
311 | adding file changes | |
312 | added 1 changesets with 1 changes to 1 files (+1 heads) |
|
312 | added 1 changesets with 1 changes to 1 files (+1 heads) | |
313 | 1 new obsolescence markers |
|
313 | 1 new obsolescence markers | |
314 | updating bookmark book_42cc |
|
314 | updating bookmark book_42cc | |
315 | pre-close-tip:42ccdea3bb16 draft book_42cc |
|
315 | pre-close-tip:42ccdea3bb16 draft book_42cc | |
316 | postclose-tip:42ccdea3bb16 draft book_42cc |
|
316 | postclose-tip:42ccdea3bb16 draft book_42cc | |
317 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_NEW_OBSMARKERS=1 HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_NODE_LAST=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
317 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_NEW_OBSMARKERS=1 HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_NODE_LAST=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull | |
318 | http://localhost:$HGPORT/ HG_URL=http://localhost:$HGPORT/ |
|
318 | http://localhost:$HGPORT/ HG_URL=http://localhost:$HGPORT/ | |
319 | (run 'hg heads .' to see heads, 'hg merge' to merge) |
|
319 | (run 'hg heads .' to see heads, 'hg merge' to merge) | |
320 | $ cat main-error.log |
|
320 | $ cat main-error.log | |
321 | $ hg -R other debugobsolete |
|
321 | $ hg -R other debugobsolete | |
322 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
322 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
323 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
323 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
324 | 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
324 | 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
325 | 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
325 | 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
326 | 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
326 | 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
327 |
|
327 | |||
328 | push over ssh |
|
328 | push over ssh | |
329 |
|
329 | |||
330 | $ hg -R main push ssh://user@dummy/other -r 5fddd98957c8 --bookmark book_5fdd |
|
330 | $ hg -R main push ssh://user@dummy/other -r 5fddd98957c8 --bookmark book_5fdd | |
331 | pushing to ssh://user@dummy/other |
|
331 | pushing to ssh://user@dummy/other | |
332 | searching for changes |
|
332 | searching for changes | |
333 | remote: adding changesets |
|
333 | remote: adding changesets | |
334 | remote: adding manifests |
|
334 | remote: adding manifests | |
335 | remote: adding file changes |
|
335 | remote: adding file changes | |
336 | remote: added 1 changesets with 1 changes to 1 files |
|
336 | remote: added 1 changesets with 1 changes to 1 files | |
337 | remote: 1 new obsolescence markers |
|
337 | remote: 1 new obsolescence markers | |
338 | remote: pre-close-tip:5fddd98957c8 draft book_5fdd |
|
338 | remote: pre-close-tip:5fddd98957c8 draft book_5fdd | |
339 | remote: pushkey: lock state after "bookmarks" |
|
339 | remote: pushkey: lock state after "bookmarks" | |
340 | remote: lock: free |
|
340 | remote: lock: free | |
341 | remote: wlock: free |
|
341 | remote: wlock: free | |
342 | remote: postclose-tip:5fddd98957c8 draft book_5fdd |
|
342 | remote: postclose-tip:5fddd98957c8 draft book_5fdd | |
343 |
remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_NEW_OBSMARKERS=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_NODE_LAST=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_TXNID=TXN: |
|
343 | remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_NEW_OBSMARKERS=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_NODE_LAST=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_TXNNAME=serve HG_URL=remote:ssh:$LOCALIP | |
344 | updating bookmark book_5fdd |
|
344 | updating bookmark book_5fdd | |
345 | pre-close-tip:02de42196ebe draft book_02de |
|
345 | pre-close-tip:02de42196ebe draft book_02de | |
346 | postclose-tip:02de42196ebe draft book_02de |
|
346 | postclose-tip:02de42196ebe draft book_02de | |
347 |
txnclose hook: HG_SOURCE=push-response HG_TXNID=TXN: |
|
347 | txnclose hook: HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response | |
348 | ssh://user@dummy/other HG_URL=ssh://user@dummy/other |
|
348 | ssh://user@dummy/other HG_URL=ssh://user@dummy/other | |
349 | $ hg -R other log -G |
|
349 | $ hg -R other log -G | |
350 | o 6:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C |
|
350 | o 6:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C | |
351 | | |
|
351 | | | |
352 | o 5:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B |
|
352 | o 5:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B | |
353 | | |
|
353 | | | |
354 | | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H |
|
354 | | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H | |
355 | | | |
|
355 | | | | |
356 | | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G |
|
356 | | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G | |
357 | | |/| |
|
357 | | |/| | |
358 | | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F |
|
358 | | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F | |
359 | |/ / |
|
359 | |/ / | |
360 | | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E |
|
360 | | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E | |
361 | |/ |
|
361 | |/ | |
362 | o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af A |
|
362 | o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af A | |
363 |
|
363 | |||
364 | $ hg -R other debugobsolete |
|
364 | $ hg -R other debugobsolete | |
365 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
365 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
366 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
366 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
367 | 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
367 | 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
368 | 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
368 | 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
369 | 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
369 | 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
370 | 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
370 | 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
371 |
|
371 | |||
372 | push over http |
|
372 | push over http | |
373 |
|
373 | |||
374 | $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log |
|
374 | $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log | |
375 | $ cat other.pid >> $DAEMON_PIDS |
|
375 | $ cat other.pid >> $DAEMON_PIDS | |
376 |
|
376 | |||
377 | $ hg -R main phase --public 32af7686d403 |
|
377 | $ hg -R main phase --public 32af7686d403 | |
378 | pre-close-tip:02de42196ebe draft book_02de |
|
378 | pre-close-tip:02de42196ebe draft book_02de | |
379 | postclose-tip:02de42196ebe draft book_02de |
|
379 | postclose-tip:02de42196ebe draft book_02de | |
380 |
txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN: |
|
380 | txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase | |
381 | $ hg -R main push http://localhost:$HGPORT2/ -r 32af7686d403 --bookmark book_32af |
|
381 | $ hg -R main push http://localhost:$HGPORT2/ -r 32af7686d403 --bookmark book_32af | |
382 | pushing to http://localhost:$HGPORT2/ |
|
382 | pushing to http://localhost:$HGPORT2/ | |
383 | searching for changes |
|
383 | searching for changes | |
384 | remote: adding changesets |
|
384 | remote: adding changesets | |
385 | remote: adding manifests |
|
385 | remote: adding manifests | |
386 | remote: adding file changes |
|
386 | remote: adding file changes | |
387 | remote: added 1 changesets with 1 changes to 1 files |
|
387 | remote: added 1 changesets with 1 changes to 1 files | |
388 | remote: 1 new obsolescence markers |
|
388 | remote: 1 new obsolescence markers | |
389 | remote: pre-close-tip:32af7686d403 public book_32af |
|
389 | remote: pre-close-tip:32af7686d403 public book_32af | |
390 | remote: pushkey: lock state after "phases" |
|
390 | remote: pushkey: lock state after "phases" | |
391 | remote: lock: free |
|
391 | remote: lock: free | |
392 | remote: wlock: free |
|
392 | remote: wlock: free | |
393 | remote: pushkey: lock state after "bookmarks" |
|
393 | remote: pushkey: lock state after "bookmarks" | |
394 | remote: lock: free |
|
394 | remote: lock: free | |
395 | remote: wlock: free |
|
395 | remote: wlock: free | |
396 | remote: postclose-tip:32af7686d403 public book_32af |
|
396 | remote: postclose-tip:32af7686d403 public book_32af | |
397 |
remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_NEW_OBSMARKERS=1 HG_NODE=32af7686d403cf45b5d95f2d70cebea587ac806a HG_NODE_LAST=32af7686d403cf45b5d95f2d70cebea587ac806a HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN: |
|
397 | remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_NEW_OBSMARKERS=1 HG_NODE=32af7686d403cf45b5d95f2d70cebea587ac806a HG_NODE_LAST=32af7686d403cf45b5d95f2d70cebea587ac806a HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_TXNNAME=serve HG_URL=remote:http:$LOCALIP: | |
398 | updating bookmark book_32af |
|
398 | updating bookmark book_32af | |
399 | pre-close-tip:02de42196ebe draft book_02de |
|
399 | pre-close-tip:02de42196ebe draft book_02de | |
400 | postclose-tip:02de42196ebe draft book_02de |
|
400 | postclose-tip:02de42196ebe draft book_02de | |
401 |
txnclose hook: HG_SOURCE=push-response HG_TXNID=TXN: |
|
401 | txnclose hook: HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response | |
402 | http://localhost:$HGPORT2/ HG_URL=http://localhost:$HGPORT2/ |
|
402 | http://localhost:$HGPORT2/ HG_URL=http://localhost:$HGPORT2/ | |
403 | $ cat other-error.log |
|
403 | $ cat other-error.log | |
404 |
|
404 | |||
405 | Check final content. |
|
405 | Check final content. | |
406 |
|
406 | |||
407 | $ hg -R other log -G |
|
407 | $ hg -R other log -G | |
408 | o 7:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af D |
|
408 | o 7:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af D | |
409 | | |
|
409 | | | |
410 | o 6:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C |
|
410 | o 6:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C | |
411 | | |
|
411 | | | |
412 | o 5:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B |
|
412 | o 5:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B | |
413 | | |
|
413 | | | |
414 | | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H |
|
414 | | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H | |
415 | | | |
|
415 | | | | |
416 | | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G |
|
416 | | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G | |
417 | | |/| |
|
417 | | |/| | |
418 | | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F |
|
418 | | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F | |
419 | |/ / |
|
419 | |/ / | |
420 | | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E |
|
420 | | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E | |
421 | |/ |
|
421 | |/ | |
422 | o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A |
|
422 | o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A | |
423 |
|
423 | |||
424 | $ hg -R other debugobsolete |
|
424 | $ hg -R other debugobsolete | |
425 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
425 | 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
426 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
426 | 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
427 | 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
427 | 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
428 | 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
428 | 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
429 | 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
429 | 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
430 | 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
430 | 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
431 | 7777777777777777777777777777777777777777 32af7686d403cf45b5d95f2d70cebea587ac806a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} |
|
431 | 7777777777777777777777777777777777777777 32af7686d403cf45b5d95f2d70cebea587ac806a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} | |
432 |
|
432 | |||
433 | (check that no 'pending' files remain) |
|
433 | (check that no 'pending' files remain) | |
434 |
|
434 | |||
435 | $ ls -1 other/.hg/bookmarks* |
|
435 | $ ls -1 other/.hg/bookmarks* | |
436 | other/.hg/bookmarks |
|
436 | other/.hg/bookmarks | |
437 | $ ls -1 other/.hg/store/phaseroots* |
|
437 | $ ls -1 other/.hg/store/phaseroots* | |
438 | other/.hg/store/phaseroots |
|
438 | other/.hg/store/phaseroots | |
439 | $ ls -1 other/.hg/store/00changelog.i* |
|
439 | $ ls -1 other/.hg/store/00changelog.i* | |
440 | other/.hg/store/00changelog.i |
|
440 | other/.hg/store/00changelog.i | |
441 |
|
441 | |||
442 | Error Handling |
|
442 | Error Handling | |
443 | ============== |
|
443 | ============== | |
444 |
|
444 | |||
445 | Check that errors are properly returned to the client during push. |
|
445 | Check that errors are properly returned to the client during push. | |
446 |
|
446 | |||
447 | Setting up |
|
447 | Setting up | |
448 |
|
448 | |||
449 | $ cat > failpush.py << EOF |
|
449 | $ cat > failpush.py << EOF | |
450 | > """A small extension that makes push fails when using bundle2 |
|
450 | > """A small extension that makes push fails when using bundle2 | |
451 | > |
|
451 | > | |
452 | > used to test error handling in bundle2 |
|
452 | > used to test error handling in bundle2 | |
453 | > """ |
|
453 | > """ | |
454 | > |
|
454 | > | |
455 | > from mercurial import error |
|
455 | > from mercurial import error | |
456 | > from mercurial import bundle2 |
|
456 | > from mercurial import bundle2 | |
457 | > from mercurial import exchange |
|
457 | > from mercurial import exchange | |
458 | > from mercurial import extensions |
|
458 | > from mercurial import extensions | |
459 | > |
|
459 | > | |
460 | > def _pushbundle2failpart(pushop, bundler): |
|
460 | > def _pushbundle2failpart(pushop, bundler): | |
461 | > reason = pushop.ui.config('failpush', 'reason', None) |
|
461 | > reason = pushop.ui.config('failpush', 'reason', None) | |
462 | > part = None |
|
462 | > part = None | |
463 | > if reason == 'abort': |
|
463 | > if reason == 'abort': | |
464 | > bundler.newpart('test:abort') |
|
464 | > bundler.newpart('test:abort') | |
465 | > if reason == 'unknown': |
|
465 | > if reason == 'unknown': | |
466 | > bundler.newpart('test:unknown') |
|
466 | > bundler.newpart('test:unknown') | |
467 | > if reason == 'race': |
|
467 | > if reason == 'race': | |
468 | > # 20 Bytes of crap |
|
468 | > # 20 Bytes of crap | |
469 | > bundler.newpart('check:heads', data='01234567890123456789') |
|
469 | > bundler.newpart('check:heads', data='01234567890123456789') | |
470 | > |
|
470 | > | |
471 | > @bundle2.parthandler("test:abort") |
|
471 | > @bundle2.parthandler("test:abort") | |
472 | > def handleabort(op, part): |
|
472 | > def handleabort(op, part): | |
473 | > raise error.Abort('Abandon ship!', hint="don't panic") |
|
473 | > raise error.Abort('Abandon ship!', hint="don't panic") | |
474 | > |
|
474 | > | |
475 | > def uisetup(ui): |
|
475 | > def uisetup(ui): | |
476 | > exchange.b2partsgenmapping['failpart'] = _pushbundle2failpart |
|
476 | > exchange.b2partsgenmapping['failpart'] = _pushbundle2failpart | |
477 | > exchange.b2partsgenorder.insert(0, 'failpart') |
|
477 | > exchange.b2partsgenorder.insert(0, 'failpart') | |
478 | > |
|
478 | > | |
479 | > EOF |
|
479 | > EOF | |
480 |
|
480 | |||
481 | $ cd main |
|
481 | $ cd main | |
482 | $ hg up tip |
|
482 | $ hg up tip | |
483 | 3 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
483 | 3 files updated, 0 files merged, 1 files removed, 0 files unresolved | |
484 | $ echo 'I' > I |
|
484 | $ echo 'I' > I | |
485 | $ hg add I |
|
485 | $ hg add I | |
486 | $ hg ci -m 'I' |
|
486 | $ hg ci -m 'I' | |
487 | pre-close-tip:e7ec4e813ba6 draft |
|
487 | pre-close-tip:e7ec4e813ba6 draft | |
488 | postclose-tip:e7ec4e813ba6 draft |
|
488 | postclose-tip:e7ec4e813ba6 draft | |
489 |
txnclose hook: HG_TXNID=TXN: |
|
489 | txnclose hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
490 | $ hg id |
|
490 | $ hg id | |
491 | e7ec4e813ba6 tip |
|
491 | e7ec4e813ba6 tip | |
492 | $ cd .. |
|
492 | $ cd .. | |
493 |
|
493 | |||
494 | $ cat << EOF >> $HGRCPATH |
|
494 | $ cat << EOF >> $HGRCPATH | |
495 | > [extensions] |
|
495 | > [extensions] | |
496 | > failpush=$TESTTMP/failpush.py |
|
496 | > failpush=$TESTTMP/failpush.py | |
497 | > EOF |
|
497 | > EOF | |
498 |
|
498 | |||
499 | $ killdaemons.py |
|
499 | $ killdaemons.py | |
500 | $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log |
|
500 | $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log | |
501 | $ cat other.pid >> $DAEMON_PIDS |
|
501 | $ cat other.pid >> $DAEMON_PIDS | |
502 |
|
502 | |||
503 | Doing the actual push: Abort error |
|
503 | Doing the actual push: Abort error | |
504 |
|
504 | |||
505 | $ cat << EOF >> $HGRCPATH |
|
505 | $ cat << EOF >> $HGRCPATH | |
506 | > [failpush] |
|
506 | > [failpush] | |
507 | > reason = abort |
|
507 | > reason = abort | |
508 | > EOF |
|
508 | > EOF | |
509 |
|
509 | |||
510 | $ hg -R main push other -r e7ec4e813ba6 |
|
510 | $ hg -R main push other -r e7ec4e813ba6 | |
511 | pushing to other |
|
511 | pushing to other | |
512 | searching for changes |
|
512 | searching for changes | |
513 | abort: Abandon ship! |
|
513 | abort: Abandon ship! | |
514 | (don't panic) |
|
514 | (don't panic) | |
515 | [255] |
|
515 | [255] | |
516 |
|
516 | |||
517 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 |
|
517 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 | |
518 | pushing to ssh://user@dummy/other |
|
518 | pushing to ssh://user@dummy/other | |
519 | searching for changes |
|
519 | searching for changes | |
520 | remote: Abandon ship! |
|
520 | remote: Abandon ship! | |
521 | remote: (don't panic) |
|
521 | remote: (don't panic) | |
522 | abort: push failed on remote |
|
522 | abort: push failed on remote | |
523 | [255] |
|
523 | [255] | |
524 |
|
524 | |||
525 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 |
|
525 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 | |
526 | pushing to http://localhost:$HGPORT2/ |
|
526 | pushing to http://localhost:$HGPORT2/ | |
527 | searching for changes |
|
527 | searching for changes | |
528 | remote: Abandon ship! |
|
528 | remote: Abandon ship! | |
529 | remote: (don't panic) |
|
529 | remote: (don't panic) | |
530 | abort: push failed on remote |
|
530 | abort: push failed on remote | |
531 | [255] |
|
531 | [255] | |
532 |
|
532 | |||
533 |
|
533 | |||
534 | Doing the actual push: unknown mandatory parts |
|
534 | Doing the actual push: unknown mandatory parts | |
535 |
|
535 | |||
536 | $ cat << EOF >> $HGRCPATH |
|
536 | $ cat << EOF >> $HGRCPATH | |
537 | > [failpush] |
|
537 | > [failpush] | |
538 | > reason = unknown |
|
538 | > reason = unknown | |
539 | > EOF |
|
539 | > EOF | |
540 |
|
540 | |||
541 | $ hg -R main push other -r e7ec4e813ba6 |
|
541 | $ hg -R main push other -r e7ec4e813ba6 | |
542 | pushing to other |
|
542 | pushing to other | |
543 | searching for changes |
|
543 | searching for changes | |
544 | abort: missing support for test:unknown |
|
544 | abort: missing support for test:unknown | |
545 | [255] |
|
545 | [255] | |
546 |
|
546 | |||
547 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 |
|
547 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 | |
548 | pushing to ssh://user@dummy/other |
|
548 | pushing to ssh://user@dummy/other | |
549 | searching for changes |
|
549 | searching for changes | |
550 | abort: missing support for test:unknown |
|
550 | abort: missing support for test:unknown | |
551 | [255] |
|
551 | [255] | |
552 |
|
552 | |||
553 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 |
|
553 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 | |
554 | pushing to http://localhost:$HGPORT2/ |
|
554 | pushing to http://localhost:$HGPORT2/ | |
555 | searching for changes |
|
555 | searching for changes | |
556 | abort: missing support for test:unknown |
|
556 | abort: missing support for test:unknown | |
557 | [255] |
|
557 | [255] | |
558 |
|
558 | |||
559 | Doing the actual push: race |
|
559 | Doing the actual push: race | |
560 |
|
560 | |||
561 | $ cat << EOF >> $HGRCPATH |
|
561 | $ cat << EOF >> $HGRCPATH | |
562 | > [failpush] |
|
562 | > [failpush] | |
563 | > reason = race |
|
563 | > reason = race | |
564 | > EOF |
|
564 | > EOF | |
565 |
|
565 | |||
566 | $ hg -R main push other -r e7ec4e813ba6 |
|
566 | $ hg -R main push other -r e7ec4e813ba6 | |
567 | pushing to other |
|
567 | pushing to other | |
568 | searching for changes |
|
568 | searching for changes | |
569 | abort: push failed: |
|
569 | abort: push failed: | |
570 | 'repository changed while pushing - please try again' |
|
570 | 'repository changed while pushing - please try again' | |
571 | [255] |
|
571 | [255] | |
572 |
|
572 | |||
573 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 |
|
573 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 | |
574 | pushing to ssh://user@dummy/other |
|
574 | pushing to ssh://user@dummy/other | |
575 | searching for changes |
|
575 | searching for changes | |
576 | abort: push failed: |
|
576 | abort: push failed: | |
577 | 'repository changed while pushing - please try again' |
|
577 | 'repository changed while pushing - please try again' | |
578 | [255] |
|
578 | [255] | |
579 |
|
579 | |||
580 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 |
|
580 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 | |
581 | pushing to http://localhost:$HGPORT2/ |
|
581 | pushing to http://localhost:$HGPORT2/ | |
582 | searching for changes |
|
582 | searching for changes | |
583 | abort: push failed: |
|
583 | abort: push failed: | |
584 | 'repository changed while pushing - please try again' |
|
584 | 'repository changed while pushing - please try again' | |
585 | [255] |
|
585 | [255] | |
586 |
|
586 | |||
587 | Doing the actual push: hook abort |
|
587 | Doing the actual push: hook abort | |
588 |
|
588 | |||
589 | $ cat << EOF >> $HGRCPATH |
|
589 | $ cat << EOF >> $HGRCPATH | |
590 | > [failpush] |
|
590 | > [failpush] | |
591 | > reason = |
|
591 | > reason = | |
592 | > [hooks] |
|
592 | > [hooks] | |
593 | > pretxnclose.failpush = sh -c "echo 'You shall not pass!'; false" |
|
593 | > pretxnclose.failpush = sh -c "echo 'You shall not pass!'; false" | |
594 | > txnabort.failpush = sh -c "echo 'Cleaning up the mess...'" |
|
594 | > txnabort.failpush = sh -c "echo 'Cleaning up the mess...'" | |
595 | > EOF |
|
595 | > EOF | |
596 |
|
596 | |||
597 | $ killdaemons.py |
|
597 | $ killdaemons.py | |
598 | $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log |
|
598 | $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log | |
599 | $ cat other.pid >> $DAEMON_PIDS |
|
599 | $ cat other.pid >> $DAEMON_PIDS | |
600 |
|
600 | |||
601 | $ hg -R main push other -r e7ec4e813ba6 |
|
601 | $ hg -R main push other -r e7ec4e813ba6 | |
602 | pushing to other |
|
602 | pushing to other | |
603 | searching for changes |
|
603 | searching for changes | |
604 | remote: adding changesets |
|
604 | remote: adding changesets | |
605 | remote: adding manifests |
|
605 | remote: adding manifests | |
606 | remote: adding file changes |
|
606 | remote: adding file changes | |
607 | remote: added 1 changesets with 1 changes to 1 files |
|
607 | remote: added 1 changesets with 1 changes to 1 files | |
608 | remote: pre-close-tip:e7ec4e813ba6 draft |
|
608 | remote: pre-close-tip:e7ec4e813ba6 draft | |
609 | remote: You shall not pass! |
|
609 | remote: You shall not pass! | |
610 | remote: transaction abort! |
|
610 | remote: transaction abort! | |
611 | remote: Cleaning up the mess... |
|
611 | remote: Cleaning up the mess... | |
612 | remote: rollback completed |
|
612 | remote: rollback completed | |
613 | abort: pretxnclose.failpush hook exited with status 1 |
|
613 | abort: pretxnclose.failpush hook exited with status 1 | |
614 | [255] |
|
614 | [255] | |
615 |
|
615 | |||
616 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 |
|
616 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 | |
617 | pushing to ssh://user@dummy/other |
|
617 | pushing to ssh://user@dummy/other | |
618 | searching for changes |
|
618 | searching for changes | |
619 | remote: adding changesets |
|
619 | remote: adding changesets | |
620 | remote: adding manifests |
|
620 | remote: adding manifests | |
621 | remote: adding file changes |
|
621 | remote: adding file changes | |
622 | remote: added 1 changesets with 1 changes to 1 files |
|
622 | remote: added 1 changesets with 1 changes to 1 files | |
623 | remote: pre-close-tip:e7ec4e813ba6 draft |
|
623 | remote: pre-close-tip:e7ec4e813ba6 draft | |
624 | remote: You shall not pass! |
|
624 | remote: You shall not pass! | |
625 | remote: transaction abort! |
|
625 | remote: transaction abort! | |
626 | remote: Cleaning up the mess... |
|
626 | remote: Cleaning up the mess... | |
627 | remote: rollback completed |
|
627 | remote: rollback completed | |
628 | remote: pretxnclose.failpush hook exited with status 1 |
|
628 | remote: pretxnclose.failpush hook exited with status 1 | |
629 | abort: push failed on remote |
|
629 | abort: push failed on remote | |
630 | [255] |
|
630 | [255] | |
631 |
|
631 | |||
632 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 |
|
632 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 | |
633 | pushing to http://localhost:$HGPORT2/ |
|
633 | pushing to http://localhost:$HGPORT2/ | |
634 | searching for changes |
|
634 | searching for changes | |
635 | remote: adding changesets |
|
635 | remote: adding changesets | |
636 | remote: adding manifests |
|
636 | remote: adding manifests | |
637 | remote: adding file changes |
|
637 | remote: adding file changes | |
638 | remote: added 1 changesets with 1 changes to 1 files |
|
638 | remote: added 1 changesets with 1 changes to 1 files | |
639 | remote: pre-close-tip:e7ec4e813ba6 draft |
|
639 | remote: pre-close-tip:e7ec4e813ba6 draft | |
640 | remote: You shall not pass! |
|
640 | remote: You shall not pass! | |
641 | remote: transaction abort! |
|
641 | remote: transaction abort! | |
642 | remote: Cleaning up the mess... |
|
642 | remote: Cleaning up the mess... | |
643 | remote: rollback completed |
|
643 | remote: rollback completed | |
644 | remote: pretxnclose.failpush hook exited with status 1 |
|
644 | remote: pretxnclose.failpush hook exited with status 1 | |
645 | abort: push failed on remote |
|
645 | abort: push failed on remote | |
646 | [255] |
|
646 | [255] | |
647 |
|
647 | |||
648 | (check that no 'pending' files remain) |
|
648 | (check that no 'pending' files remain) | |
649 |
|
649 | |||
650 | $ ls -1 other/.hg/bookmarks* |
|
650 | $ ls -1 other/.hg/bookmarks* | |
651 | other/.hg/bookmarks |
|
651 | other/.hg/bookmarks | |
652 | $ ls -1 other/.hg/store/phaseroots* |
|
652 | $ ls -1 other/.hg/store/phaseroots* | |
653 | other/.hg/store/phaseroots |
|
653 | other/.hg/store/phaseroots | |
654 | $ ls -1 other/.hg/store/00changelog.i* |
|
654 | $ ls -1 other/.hg/store/00changelog.i* | |
655 | other/.hg/store/00changelog.i |
|
655 | other/.hg/store/00changelog.i | |
656 |
|
656 | |||
657 | Check error from hook during the unbundling process itself |
|
657 | Check error from hook during the unbundling process itself | |
658 |
|
658 | |||
659 | $ cat << EOF >> $HGRCPATH |
|
659 | $ cat << EOF >> $HGRCPATH | |
660 | > pretxnchangegroup = sh -c "echo 'Fail early!'; false" |
|
660 | > pretxnchangegroup = sh -c "echo 'Fail early!'; false" | |
661 | > EOF |
|
661 | > EOF | |
662 | $ killdaemons.py # reload http config |
|
662 | $ killdaemons.py # reload http config | |
663 | $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log |
|
663 | $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log | |
664 | $ cat other.pid >> $DAEMON_PIDS |
|
664 | $ cat other.pid >> $DAEMON_PIDS | |
665 |
|
665 | |||
666 | $ hg -R main push other -r e7ec4e813ba6 |
|
666 | $ hg -R main push other -r e7ec4e813ba6 | |
667 | pushing to other |
|
667 | pushing to other | |
668 | searching for changes |
|
668 | searching for changes | |
669 | remote: adding changesets |
|
669 | remote: adding changesets | |
670 | remote: adding manifests |
|
670 | remote: adding manifests | |
671 | remote: adding file changes |
|
671 | remote: adding file changes | |
672 | remote: added 1 changesets with 1 changes to 1 files |
|
672 | remote: added 1 changesets with 1 changes to 1 files | |
673 | remote: Fail early! |
|
673 | remote: Fail early! | |
674 | remote: transaction abort! |
|
674 | remote: transaction abort! | |
675 | remote: Cleaning up the mess... |
|
675 | remote: Cleaning up the mess... | |
676 | remote: rollback completed |
|
676 | remote: rollback completed | |
677 | abort: pretxnchangegroup hook exited with status 1 |
|
677 | abort: pretxnchangegroup hook exited with status 1 | |
678 | [255] |
|
678 | [255] | |
679 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 |
|
679 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 | |
680 | pushing to ssh://user@dummy/other |
|
680 | pushing to ssh://user@dummy/other | |
681 | searching for changes |
|
681 | searching for changes | |
682 | remote: adding changesets |
|
682 | remote: adding changesets | |
683 | remote: adding manifests |
|
683 | remote: adding manifests | |
684 | remote: adding file changes |
|
684 | remote: adding file changes | |
685 | remote: added 1 changesets with 1 changes to 1 files |
|
685 | remote: added 1 changesets with 1 changes to 1 files | |
686 | remote: Fail early! |
|
686 | remote: Fail early! | |
687 | remote: transaction abort! |
|
687 | remote: transaction abort! | |
688 | remote: Cleaning up the mess... |
|
688 | remote: Cleaning up the mess... | |
689 | remote: rollback completed |
|
689 | remote: rollback completed | |
690 | remote: pretxnchangegroup hook exited with status 1 |
|
690 | remote: pretxnchangegroup hook exited with status 1 | |
691 | abort: push failed on remote |
|
691 | abort: push failed on remote | |
692 | [255] |
|
692 | [255] | |
693 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 |
|
693 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 | |
694 | pushing to http://localhost:$HGPORT2/ |
|
694 | pushing to http://localhost:$HGPORT2/ | |
695 | searching for changes |
|
695 | searching for changes | |
696 | remote: adding changesets |
|
696 | remote: adding changesets | |
697 | remote: adding manifests |
|
697 | remote: adding manifests | |
698 | remote: adding file changes |
|
698 | remote: adding file changes | |
699 | remote: added 1 changesets with 1 changes to 1 files |
|
699 | remote: added 1 changesets with 1 changes to 1 files | |
700 | remote: Fail early! |
|
700 | remote: Fail early! | |
701 | remote: transaction abort! |
|
701 | remote: transaction abort! | |
702 | remote: Cleaning up the mess... |
|
702 | remote: Cleaning up the mess... | |
703 | remote: rollback completed |
|
703 | remote: rollback completed | |
704 | remote: pretxnchangegroup hook exited with status 1 |
|
704 | remote: pretxnchangegroup hook exited with status 1 | |
705 | abort: push failed on remote |
|
705 | abort: push failed on remote | |
706 | [255] |
|
706 | [255] | |
707 |
|
707 | |||
708 | Check output capture control. |
|
708 | Check output capture control. | |
709 |
|
709 | |||
710 | (should be still forced for http, disabled for local and ssh) |
|
710 | (should be still forced for http, disabled for local and ssh) | |
711 |
|
711 | |||
712 | $ cat >> $HGRCPATH << EOF |
|
712 | $ cat >> $HGRCPATH << EOF | |
713 | > [experimental] |
|
713 | > [experimental] | |
714 | > bundle2-output-capture=False |
|
714 | > bundle2-output-capture=False | |
715 | > EOF |
|
715 | > EOF | |
716 |
|
716 | |||
717 | $ hg -R main push other -r e7ec4e813ba6 |
|
717 | $ hg -R main push other -r e7ec4e813ba6 | |
718 | pushing to other |
|
718 | pushing to other | |
719 | searching for changes |
|
719 | searching for changes | |
720 | adding changesets |
|
720 | adding changesets | |
721 | adding manifests |
|
721 | adding manifests | |
722 | adding file changes |
|
722 | adding file changes | |
723 | added 1 changesets with 1 changes to 1 files |
|
723 | added 1 changesets with 1 changes to 1 files | |
724 | Fail early! |
|
724 | Fail early! | |
725 | transaction abort! |
|
725 | transaction abort! | |
726 | Cleaning up the mess... |
|
726 | Cleaning up the mess... | |
727 | rollback completed |
|
727 | rollback completed | |
728 | abort: pretxnchangegroup hook exited with status 1 |
|
728 | abort: pretxnchangegroup hook exited with status 1 | |
729 | [255] |
|
729 | [255] | |
730 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 |
|
730 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 | |
731 | pushing to ssh://user@dummy/other |
|
731 | pushing to ssh://user@dummy/other | |
732 | searching for changes |
|
732 | searching for changes | |
733 | remote: adding changesets |
|
733 | remote: adding changesets | |
734 | remote: adding manifests |
|
734 | remote: adding manifests | |
735 | remote: adding file changes |
|
735 | remote: adding file changes | |
736 | remote: added 1 changesets with 1 changes to 1 files |
|
736 | remote: added 1 changesets with 1 changes to 1 files | |
737 | remote: Fail early! |
|
737 | remote: Fail early! | |
738 | remote: transaction abort! |
|
738 | remote: transaction abort! | |
739 | remote: Cleaning up the mess... |
|
739 | remote: Cleaning up the mess... | |
740 | remote: rollback completed |
|
740 | remote: rollback completed | |
741 | remote: pretxnchangegroup hook exited with status 1 |
|
741 | remote: pretxnchangegroup hook exited with status 1 | |
742 | abort: push failed on remote |
|
742 | abort: push failed on remote | |
743 | [255] |
|
743 | [255] | |
744 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 |
|
744 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 | |
745 | pushing to http://localhost:$HGPORT2/ |
|
745 | pushing to http://localhost:$HGPORT2/ | |
746 | searching for changes |
|
746 | searching for changes | |
747 | remote: adding changesets |
|
747 | remote: adding changesets | |
748 | remote: adding manifests |
|
748 | remote: adding manifests | |
749 | remote: adding file changes |
|
749 | remote: adding file changes | |
750 | remote: added 1 changesets with 1 changes to 1 files |
|
750 | remote: added 1 changesets with 1 changes to 1 files | |
751 | remote: Fail early! |
|
751 | remote: Fail early! | |
752 | remote: transaction abort! |
|
752 | remote: transaction abort! | |
753 | remote: Cleaning up the mess... |
|
753 | remote: Cleaning up the mess... | |
754 | remote: rollback completed |
|
754 | remote: rollback completed | |
755 | remote: pretxnchangegroup hook exited with status 1 |
|
755 | remote: pretxnchangegroup hook exited with status 1 | |
756 | abort: push failed on remote |
|
756 | abort: push failed on remote | |
757 | [255] |
|
757 | [255] | |
758 |
|
758 | |||
759 | Check abort from mandatory pushkey |
|
759 | Check abort from mandatory pushkey | |
760 |
|
760 | |||
761 | $ cat > mandatorypart.py << EOF |
|
761 | $ cat > mandatorypart.py << EOF | |
762 | > from mercurial import exchange |
|
762 | > from mercurial import exchange | |
763 | > from mercurial import pushkey |
|
763 | > from mercurial import pushkey | |
764 | > from mercurial import node |
|
764 | > from mercurial import node | |
765 | > from mercurial import error |
|
765 | > from mercurial import error | |
766 | > @exchange.b2partsgenerator('failingpuskey') |
|
766 | > @exchange.b2partsgenerator('failingpuskey') | |
767 | > def addfailingpushey(pushop, bundler): |
|
767 | > def addfailingpushey(pushop, bundler): | |
768 | > enc = pushkey.encode |
|
768 | > enc = pushkey.encode | |
769 | > part = bundler.newpart('pushkey') |
|
769 | > part = bundler.newpart('pushkey') | |
770 | > part.addparam('namespace', enc('phases')) |
|
770 | > part.addparam('namespace', enc('phases')) | |
771 | > part.addparam('key', enc(pushop.repo['cd010b8cd998'].hex())) |
|
771 | > part.addparam('key', enc(pushop.repo['cd010b8cd998'].hex())) | |
772 | > part.addparam('old', enc(str(0))) # successful update |
|
772 | > part.addparam('old', enc(str(0))) # successful update | |
773 | > part.addparam('new', enc(str(0))) |
|
773 | > part.addparam('new', enc(str(0))) | |
774 | > def fail(pushop, exc): |
|
774 | > def fail(pushop, exc): | |
775 | > raise error.Abort('Correct phase push failed (because hooks)') |
|
775 | > raise error.Abort('Correct phase push failed (because hooks)') | |
776 | > pushop.pkfailcb[part.id] = fail |
|
776 | > pushop.pkfailcb[part.id] = fail | |
777 | > EOF |
|
777 | > EOF | |
778 | $ cat >> $HGRCPATH << EOF |
|
778 | $ cat >> $HGRCPATH << EOF | |
779 | > [hooks] |
|
779 | > [hooks] | |
780 | > pretxnchangegroup= |
|
780 | > pretxnchangegroup= | |
781 | > pretxnclose.failpush= |
|
781 | > pretxnclose.failpush= | |
782 | > prepushkey.failpush = sh -c "echo 'do not push the key !'; false" |
|
782 | > prepushkey.failpush = sh -c "echo 'do not push the key !'; false" | |
783 | > [extensions] |
|
783 | > [extensions] | |
784 | > mandatorypart=$TESTTMP/mandatorypart.py |
|
784 | > mandatorypart=$TESTTMP/mandatorypart.py | |
785 | > EOF |
|
785 | > EOF | |
786 | $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config |
|
786 | $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config | |
787 | $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log |
|
787 | $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log | |
788 | $ cat other.pid >> $DAEMON_PIDS |
|
788 | $ cat other.pid >> $DAEMON_PIDS | |
789 |
|
789 | |||
790 | (Failure from a hook) |
|
790 | (Failure from a hook) | |
791 |
|
791 | |||
792 | $ hg -R main push other -r e7ec4e813ba6 |
|
792 | $ hg -R main push other -r e7ec4e813ba6 | |
793 | pushing to other |
|
793 | pushing to other | |
794 | searching for changes |
|
794 | searching for changes | |
795 | adding changesets |
|
795 | adding changesets | |
796 | adding manifests |
|
796 | adding manifests | |
797 | adding file changes |
|
797 | adding file changes | |
798 | added 1 changesets with 1 changes to 1 files |
|
798 | added 1 changesets with 1 changes to 1 files | |
799 | do not push the key ! |
|
799 | do not push the key ! | |
800 | pushkey-abort: prepushkey.failpush hook exited with status 1 |
|
800 | pushkey-abort: prepushkey.failpush hook exited with status 1 | |
801 | transaction abort! |
|
801 | transaction abort! | |
802 | Cleaning up the mess... |
|
802 | Cleaning up the mess... | |
803 | rollback completed |
|
803 | rollback completed | |
804 | abort: Correct phase push failed (because hooks) |
|
804 | abort: Correct phase push failed (because hooks) | |
805 | [255] |
|
805 | [255] | |
806 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 |
|
806 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 | |
807 | pushing to ssh://user@dummy/other |
|
807 | pushing to ssh://user@dummy/other | |
808 | searching for changes |
|
808 | searching for changes | |
809 | remote: adding changesets |
|
809 | remote: adding changesets | |
810 | remote: adding manifests |
|
810 | remote: adding manifests | |
811 | remote: adding file changes |
|
811 | remote: adding file changes | |
812 | remote: added 1 changesets with 1 changes to 1 files |
|
812 | remote: added 1 changesets with 1 changes to 1 files | |
813 | remote: do not push the key ! |
|
813 | remote: do not push the key ! | |
814 | remote: pushkey-abort: prepushkey.failpush hook exited with status 1 |
|
814 | remote: pushkey-abort: prepushkey.failpush hook exited with status 1 | |
815 | remote: transaction abort! |
|
815 | remote: transaction abort! | |
816 | remote: Cleaning up the mess... |
|
816 | remote: Cleaning up the mess... | |
817 | remote: rollback completed |
|
817 | remote: rollback completed | |
818 | abort: Correct phase push failed (because hooks) |
|
818 | abort: Correct phase push failed (because hooks) | |
819 | [255] |
|
819 | [255] | |
820 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 |
|
820 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 | |
821 | pushing to http://localhost:$HGPORT2/ |
|
821 | pushing to http://localhost:$HGPORT2/ | |
822 | searching for changes |
|
822 | searching for changes | |
823 | remote: adding changesets |
|
823 | remote: adding changesets | |
824 | remote: adding manifests |
|
824 | remote: adding manifests | |
825 | remote: adding file changes |
|
825 | remote: adding file changes | |
826 | remote: added 1 changesets with 1 changes to 1 files |
|
826 | remote: added 1 changesets with 1 changes to 1 files | |
827 | remote: do not push the key ! |
|
827 | remote: do not push the key ! | |
828 | remote: pushkey-abort: prepushkey.failpush hook exited with status 1 |
|
828 | remote: pushkey-abort: prepushkey.failpush hook exited with status 1 | |
829 | remote: transaction abort! |
|
829 | remote: transaction abort! | |
830 | remote: Cleaning up the mess... |
|
830 | remote: Cleaning up the mess... | |
831 | remote: rollback completed |
|
831 | remote: rollback completed | |
832 | abort: Correct phase push failed (because hooks) |
|
832 | abort: Correct phase push failed (because hooks) | |
833 | [255] |
|
833 | [255] | |
834 |
|
834 | |||
835 | (Failure from a the pushkey) |
|
835 | (Failure from a the pushkey) | |
836 |
|
836 | |||
837 | $ cat > mandatorypart.py << EOF |
|
837 | $ cat > mandatorypart.py << EOF | |
838 | > from mercurial import exchange |
|
838 | > from mercurial import exchange | |
839 | > from mercurial import pushkey |
|
839 | > from mercurial import pushkey | |
840 | > from mercurial import node |
|
840 | > from mercurial import node | |
841 | > from mercurial import error |
|
841 | > from mercurial import error | |
842 | > @exchange.b2partsgenerator('failingpuskey') |
|
842 | > @exchange.b2partsgenerator('failingpuskey') | |
843 | > def addfailingpushey(pushop, bundler): |
|
843 | > def addfailingpushey(pushop, bundler): | |
844 | > enc = pushkey.encode |
|
844 | > enc = pushkey.encode | |
845 | > part = bundler.newpart('pushkey') |
|
845 | > part = bundler.newpart('pushkey') | |
846 | > part.addparam('namespace', enc('phases')) |
|
846 | > part.addparam('namespace', enc('phases')) | |
847 | > part.addparam('key', enc(pushop.repo['cd010b8cd998'].hex())) |
|
847 | > part.addparam('key', enc(pushop.repo['cd010b8cd998'].hex())) | |
848 | > part.addparam('old', enc(str(4))) # will fail |
|
848 | > part.addparam('old', enc(str(4))) # will fail | |
849 | > part.addparam('new', enc(str(3))) |
|
849 | > part.addparam('new', enc(str(3))) | |
850 | > def fail(pushop, exc): |
|
850 | > def fail(pushop, exc): | |
851 | > raise error.Abort('Clown phase push failed') |
|
851 | > raise error.Abort('Clown phase push failed') | |
852 | > pushop.pkfailcb[part.id] = fail |
|
852 | > pushop.pkfailcb[part.id] = fail | |
853 | > EOF |
|
853 | > EOF | |
854 | $ cat >> $HGRCPATH << EOF |
|
854 | $ cat >> $HGRCPATH << EOF | |
855 | > [hooks] |
|
855 | > [hooks] | |
856 | > prepushkey.failpush = |
|
856 | > prepushkey.failpush = | |
857 | > EOF |
|
857 | > EOF | |
858 | $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config |
|
858 | $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config | |
859 | $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log |
|
859 | $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log | |
860 | $ cat other.pid >> $DAEMON_PIDS |
|
860 | $ cat other.pid >> $DAEMON_PIDS | |
861 |
|
861 | |||
862 | $ hg -R main push other -r e7ec4e813ba6 |
|
862 | $ hg -R main push other -r e7ec4e813ba6 | |
863 | pushing to other |
|
863 | pushing to other | |
864 | searching for changes |
|
864 | searching for changes | |
865 | adding changesets |
|
865 | adding changesets | |
866 | adding manifests |
|
866 | adding manifests | |
867 | adding file changes |
|
867 | adding file changes | |
868 | added 1 changesets with 1 changes to 1 files |
|
868 | added 1 changesets with 1 changes to 1 files | |
869 | transaction abort! |
|
869 | transaction abort! | |
870 | Cleaning up the mess... |
|
870 | Cleaning up the mess... | |
871 | rollback completed |
|
871 | rollback completed | |
872 | pushkey: lock state after "phases" |
|
872 | pushkey: lock state after "phases" | |
873 | lock: free |
|
873 | lock: free | |
874 | wlock: free |
|
874 | wlock: free | |
875 | abort: Clown phase push failed |
|
875 | abort: Clown phase push failed | |
876 | [255] |
|
876 | [255] | |
877 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 |
|
877 | $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 | |
878 | pushing to ssh://user@dummy/other |
|
878 | pushing to ssh://user@dummy/other | |
879 | searching for changes |
|
879 | searching for changes | |
880 | remote: adding changesets |
|
880 | remote: adding changesets | |
881 | remote: adding manifests |
|
881 | remote: adding manifests | |
882 | remote: adding file changes |
|
882 | remote: adding file changes | |
883 | remote: added 1 changesets with 1 changes to 1 files |
|
883 | remote: added 1 changesets with 1 changes to 1 files | |
884 | remote: transaction abort! |
|
884 | remote: transaction abort! | |
885 | remote: Cleaning up the mess... |
|
885 | remote: Cleaning up the mess... | |
886 | remote: rollback completed |
|
886 | remote: rollback completed | |
887 | remote: pushkey: lock state after "phases" |
|
887 | remote: pushkey: lock state after "phases" | |
888 | remote: lock: free |
|
888 | remote: lock: free | |
889 | remote: wlock: free |
|
889 | remote: wlock: free | |
890 | abort: Clown phase push failed |
|
890 | abort: Clown phase push failed | |
891 | [255] |
|
891 | [255] | |
892 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 |
|
892 | $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 | |
893 | pushing to http://localhost:$HGPORT2/ |
|
893 | pushing to http://localhost:$HGPORT2/ | |
894 | searching for changes |
|
894 | searching for changes | |
895 | remote: adding changesets |
|
895 | remote: adding changesets | |
896 | remote: adding manifests |
|
896 | remote: adding manifests | |
897 | remote: adding file changes |
|
897 | remote: adding file changes | |
898 | remote: added 1 changesets with 1 changes to 1 files |
|
898 | remote: added 1 changesets with 1 changes to 1 files | |
899 | remote: transaction abort! |
|
899 | remote: transaction abort! | |
900 | remote: Cleaning up the mess... |
|
900 | remote: Cleaning up the mess... | |
901 | remote: rollback completed |
|
901 | remote: rollback completed | |
902 | remote: pushkey: lock state after "phases" |
|
902 | remote: pushkey: lock state after "phases" | |
903 | remote: lock: free |
|
903 | remote: lock: free | |
904 | remote: wlock: free |
|
904 | remote: wlock: free | |
905 | abort: Clown phase push failed |
|
905 | abort: Clown phase push failed | |
906 | [255] |
|
906 | [255] | |
907 |
|
907 | |||
908 | Test lazily acquiring the lock during unbundle |
|
908 | Test lazily acquiring the lock during unbundle | |
909 | $ cp $TESTTMP/hgrc.orig $HGRCPATH |
|
909 | $ cp $TESTTMP/hgrc.orig $HGRCPATH | |
910 | $ cat >> $HGRCPATH <<EOF |
|
910 | $ cat >> $HGRCPATH <<EOF | |
911 | > [ui] |
|
911 | > [ui] | |
912 | > ssh=python "$TESTDIR/dummyssh" |
|
912 | > ssh=python "$TESTDIR/dummyssh" | |
913 | > EOF |
|
913 | > EOF | |
914 |
|
914 | |||
915 | $ cat >> $TESTTMP/locktester.py <<EOF |
|
915 | $ cat >> $TESTTMP/locktester.py <<EOF | |
916 | > import os |
|
916 | > import os | |
917 | > from mercurial import extensions, bundle2, util |
|
917 | > from mercurial import extensions, bundle2, util | |
918 | > def checklock(orig, repo, *args, **kwargs): |
|
918 | > def checklock(orig, repo, *args, **kwargs): | |
919 | > if repo.svfs.lexists("lock"): |
|
919 | > if repo.svfs.lexists("lock"): | |
920 | > raise util.Abort("Lock should not be taken") |
|
920 | > raise util.Abort("Lock should not be taken") | |
921 | > return orig(repo, *args, **kwargs) |
|
921 | > return orig(repo, *args, **kwargs) | |
922 | > def extsetup(ui): |
|
922 | > def extsetup(ui): | |
923 | > extensions.wrapfunction(bundle2, 'processbundle', checklock) |
|
923 | > extensions.wrapfunction(bundle2, 'processbundle', checklock) | |
924 | > EOF |
|
924 | > EOF | |
925 |
|
925 | |||
926 | $ hg init lazylock |
|
926 | $ hg init lazylock | |
927 | $ cat >> lazylock/.hg/hgrc <<EOF |
|
927 | $ cat >> lazylock/.hg/hgrc <<EOF | |
928 | > [extensions] |
|
928 | > [extensions] | |
929 | > locktester=$TESTTMP/locktester.py |
|
929 | > locktester=$TESTTMP/locktester.py | |
930 | > EOF |
|
930 | > EOF | |
931 |
|
931 | |||
932 | $ hg clone -q ssh://user@dummy/lazylock lazylockclient |
|
932 | $ hg clone -q ssh://user@dummy/lazylock lazylockclient | |
933 | $ cd lazylockclient |
|
933 | $ cd lazylockclient | |
934 | $ touch a && hg ci -Aqm a |
|
934 | $ touch a && hg ci -Aqm a | |
935 | $ hg push |
|
935 | $ hg push | |
936 | pushing to ssh://user@dummy/lazylock |
|
936 | pushing to ssh://user@dummy/lazylock | |
937 | searching for changes |
|
937 | searching for changes | |
938 | remote: Lock should not be taken |
|
938 | remote: Lock should not be taken | |
939 | abort: push failed on remote |
|
939 | abort: push failed on remote | |
940 | [255] |
|
940 | [255] | |
941 |
|
941 | |||
942 | $ cat >> ../lazylock/.hg/hgrc <<EOF |
|
942 | $ cat >> ../lazylock/.hg/hgrc <<EOF | |
943 | > [experimental] |
|
943 | > [experimental] | |
944 | > bundle2lazylocking=True |
|
944 | > bundle2lazylocking=True | |
945 | > EOF |
|
945 | > EOF | |
946 | $ hg push |
|
946 | $ hg push | |
947 | pushing to ssh://user@dummy/lazylock |
|
947 | pushing to ssh://user@dummy/lazylock | |
948 | searching for changes |
|
948 | searching for changes | |
949 | remote: adding changesets |
|
949 | remote: adding changesets | |
950 | remote: adding manifests |
|
950 | remote: adding manifests | |
951 | remote: adding file changes |
|
951 | remote: adding file changes | |
952 | remote: added 1 changesets with 1 changes to 1 files |
|
952 | remote: added 1 changesets with 1 changes to 1 files | |
953 |
|
953 | |||
954 | $ cd .. |
|
954 | $ cd .. | |
955 |
|
955 | |||
956 | Servers can disable bundle1 for clone/pull operations |
|
956 | Servers can disable bundle1 for clone/pull operations | |
957 |
|
957 | |||
958 | $ killdaemons.py |
|
958 | $ killdaemons.py | |
959 | $ hg init bundle2onlyserver |
|
959 | $ hg init bundle2onlyserver | |
960 | $ cd bundle2onlyserver |
|
960 | $ cd bundle2onlyserver | |
961 | $ cat > .hg/hgrc << EOF |
|
961 | $ cat > .hg/hgrc << EOF | |
962 | > [server] |
|
962 | > [server] | |
963 | > bundle1.pull = false |
|
963 | > bundle1.pull = false | |
964 | > EOF |
|
964 | > EOF | |
965 |
|
965 | |||
966 | $ touch foo |
|
966 | $ touch foo | |
967 | $ hg -q commit -A -m initial |
|
967 | $ hg -q commit -A -m initial | |
968 |
|
968 | |||
969 | $ hg serve -p $HGPORT -d --pid-file=hg.pid |
|
969 | $ hg serve -p $HGPORT -d --pid-file=hg.pid | |
970 | $ cat hg.pid >> $DAEMON_PIDS |
|
970 | $ cat hg.pid >> $DAEMON_PIDS | |
971 |
|
971 | |||
972 | $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2 |
|
972 | $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2 | |
973 | requesting all changes |
|
973 | requesting all changes | |
974 | abort: remote error: |
|
974 | abort: remote error: | |
975 | incompatible Mercurial client; bundle2 required |
|
975 | incompatible Mercurial client; bundle2 required | |
976 | (see https://www.mercurial-scm.org/wiki/IncompatibleClient) |
|
976 | (see https://www.mercurial-scm.org/wiki/IncompatibleClient) | |
977 | [255] |
|
977 | [255] | |
978 | $ killdaemons.py |
|
978 | $ killdaemons.py | |
979 | $ cd .. |
|
979 | $ cd .. | |
980 |
|
980 | |||
981 | bundle1 can still pull non-generaldelta repos when generaldelta bundle1 disabled |
|
981 | bundle1 can still pull non-generaldelta repos when generaldelta bundle1 disabled | |
982 |
|
982 | |||
983 | $ hg --config format.usegeneraldelta=false init notgdserver |
|
983 | $ hg --config format.usegeneraldelta=false init notgdserver | |
984 | $ cd notgdserver |
|
984 | $ cd notgdserver | |
985 | $ cat > .hg/hgrc << EOF |
|
985 | $ cat > .hg/hgrc << EOF | |
986 | > [server] |
|
986 | > [server] | |
987 | > bundle1gd.pull = false |
|
987 | > bundle1gd.pull = false | |
988 | > EOF |
|
988 | > EOF | |
989 |
|
989 | |||
990 | $ touch foo |
|
990 | $ touch foo | |
991 | $ hg -q commit -A -m initial |
|
991 | $ hg -q commit -A -m initial | |
992 | $ hg serve -p $HGPORT -d --pid-file=hg.pid |
|
992 | $ hg serve -p $HGPORT -d --pid-file=hg.pid | |
993 | $ cat hg.pid >> $DAEMON_PIDS |
|
993 | $ cat hg.pid >> $DAEMON_PIDS | |
994 |
|
994 | |||
995 | $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2-1 |
|
995 | $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2-1 | |
996 | requesting all changes |
|
996 | requesting all changes | |
997 | adding changesets |
|
997 | adding changesets | |
998 | adding manifests |
|
998 | adding manifests | |
999 | adding file changes |
|
999 | adding file changes | |
1000 | added 1 changesets with 1 changes to 1 files |
|
1000 | added 1 changesets with 1 changes to 1 files | |
1001 | updating to branch default |
|
1001 | updating to branch default | |
1002 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
1002 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
1003 |
|
1003 | |||
1004 | $ killdaemons.py |
|
1004 | $ killdaemons.py | |
1005 | $ cd ../bundle2onlyserver |
|
1005 | $ cd ../bundle2onlyserver | |
1006 |
|
1006 | |||
1007 | bundle1 pull can be disabled for generaldelta repos only |
|
1007 | bundle1 pull can be disabled for generaldelta repos only | |
1008 |
|
1008 | |||
1009 | $ cat > .hg/hgrc << EOF |
|
1009 | $ cat > .hg/hgrc << EOF | |
1010 | > [server] |
|
1010 | > [server] | |
1011 | > bundle1gd.pull = false |
|
1011 | > bundle1gd.pull = false | |
1012 | > EOF |
|
1012 | > EOF | |
1013 |
|
1013 | |||
1014 | $ hg serve -p $HGPORT -d --pid-file=hg.pid |
|
1014 | $ hg serve -p $HGPORT -d --pid-file=hg.pid | |
1015 | $ cat hg.pid >> $DAEMON_PIDS |
|
1015 | $ cat hg.pid >> $DAEMON_PIDS | |
1016 | $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2 |
|
1016 | $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2 | |
1017 | requesting all changes |
|
1017 | requesting all changes | |
1018 | abort: remote error: |
|
1018 | abort: remote error: | |
1019 | incompatible Mercurial client; bundle2 required |
|
1019 | incompatible Mercurial client; bundle2 required | |
1020 | (see https://www.mercurial-scm.org/wiki/IncompatibleClient) |
|
1020 | (see https://www.mercurial-scm.org/wiki/IncompatibleClient) | |
1021 | [255] |
|
1021 | [255] | |
1022 |
|
1022 | |||
1023 | $ killdaemons.py |
|
1023 | $ killdaemons.py | |
1024 |
|
1024 | |||
1025 | Verify the global server.bundle1 option works |
|
1025 | Verify the global server.bundle1 option works | |
1026 |
|
1026 | |||
1027 | $ cd .. |
|
1027 | $ cd .. | |
1028 | $ cat > bundle2onlyserver/.hg/hgrc << EOF |
|
1028 | $ cat > bundle2onlyserver/.hg/hgrc << EOF | |
1029 | > [server] |
|
1029 | > [server] | |
1030 | > bundle1 = false |
|
1030 | > bundle1 = false | |
1031 | > EOF |
|
1031 | > EOF | |
1032 | $ hg -R bundle2onlyserver serve -p $HGPORT -d --pid-file=hg.pid |
|
1032 | $ hg -R bundle2onlyserver serve -p $HGPORT -d --pid-file=hg.pid | |
1033 | $ cat hg.pid >> $DAEMON_PIDS |
|
1033 | $ cat hg.pid >> $DAEMON_PIDS | |
1034 | $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT not-bundle2 |
|
1034 | $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT not-bundle2 | |
1035 | requesting all changes |
|
1035 | requesting all changes | |
1036 | abort: remote error: |
|
1036 | abort: remote error: | |
1037 | incompatible Mercurial client; bundle2 required |
|
1037 | incompatible Mercurial client; bundle2 required | |
1038 | (see https://www.mercurial-scm.org/wiki/IncompatibleClient) |
|
1038 | (see https://www.mercurial-scm.org/wiki/IncompatibleClient) | |
1039 | [255] |
|
1039 | [255] | |
1040 | $ killdaemons.py |
|
1040 | $ killdaemons.py | |
1041 |
|
1041 | |||
1042 | $ hg --config devel.legacy.exchange=bundle1 clone ssh://user@dummy/bundle2onlyserver not-bundle2-ssh |
|
1042 | $ hg --config devel.legacy.exchange=bundle1 clone ssh://user@dummy/bundle2onlyserver not-bundle2-ssh | |
1043 | requesting all changes |
|
1043 | requesting all changes | |
1044 | adding changesets |
|
1044 | adding changesets | |
1045 | remote: abort: incompatible Mercurial client; bundle2 required |
|
1045 | remote: abort: incompatible Mercurial client; bundle2 required | |
1046 | remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient) |
|
1046 | remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient) | |
1047 | transaction abort! |
|
1047 | transaction abort! | |
1048 | rollback completed |
|
1048 | rollback completed | |
1049 | abort: stream ended unexpectedly (got 0 bytes, expected 4) |
|
1049 | abort: stream ended unexpectedly (got 0 bytes, expected 4) | |
1050 | [255] |
|
1050 | [255] | |
1051 |
|
1051 | |||
1052 | $ cat > bundle2onlyserver/.hg/hgrc << EOF |
|
1052 | $ cat > bundle2onlyserver/.hg/hgrc << EOF | |
1053 | > [server] |
|
1053 | > [server] | |
1054 | > bundle1gd = false |
|
1054 | > bundle1gd = false | |
1055 | > EOF |
|
1055 | > EOF | |
1056 | $ hg -R bundle2onlyserver serve -p $HGPORT -d --pid-file=hg.pid |
|
1056 | $ hg -R bundle2onlyserver serve -p $HGPORT -d --pid-file=hg.pid | |
1057 | $ cat hg.pid >> $DAEMON_PIDS |
|
1057 | $ cat hg.pid >> $DAEMON_PIDS | |
1058 |
|
1058 | |||
1059 | $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2 |
|
1059 | $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2 | |
1060 | requesting all changes |
|
1060 | requesting all changes | |
1061 | abort: remote error: |
|
1061 | abort: remote error: | |
1062 | incompatible Mercurial client; bundle2 required |
|
1062 | incompatible Mercurial client; bundle2 required | |
1063 | (see https://www.mercurial-scm.org/wiki/IncompatibleClient) |
|
1063 | (see https://www.mercurial-scm.org/wiki/IncompatibleClient) | |
1064 | [255] |
|
1064 | [255] | |
1065 |
|
1065 | |||
1066 | $ killdaemons.py |
|
1066 | $ killdaemons.py | |
1067 |
|
1067 | |||
1068 | $ cd notgdserver |
|
1068 | $ cd notgdserver | |
1069 | $ cat > .hg/hgrc << EOF |
|
1069 | $ cat > .hg/hgrc << EOF | |
1070 | > [server] |
|
1070 | > [server] | |
1071 | > bundle1gd = false |
|
1071 | > bundle1gd = false | |
1072 | > EOF |
|
1072 | > EOF | |
1073 | $ hg serve -p $HGPORT -d --pid-file=hg.pid |
|
1073 | $ hg serve -p $HGPORT -d --pid-file=hg.pid | |
1074 | $ cat hg.pid >> $DAEMON_PIDS |
|
1074 | $ cat hg.pid >> $DAEMON_PIDS | |
1075 |
|
1075 | |||
1076 | $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2-2 |
|
1076 | $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2-2 | |
1077 | requesting all changes |
|
1077 | requesting all changes | |
1078 | adding changesets |
|
1078 | adding changesets | |
1079 | adding manifests |
|
1079 | adding manifests | |
1080 | adding file changes |
|
1080 | adding file changes | |
1081 | added 1 changesets with 1 changes to 1 files |
|
1081 | added 1 changesets with 1 changes to 1 files | |
1082 | updating to branch default |
|
1082 | updating to branch default | |
1083 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
1083 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
1084 |
|
1084 | |||
1085 | $ killdaemons.py |
|
1085 | $ killdaemons.py | |
1086 | $ cd ../bundle2onlyserver |
|
1086 | $ cd ../bundle2onlyserver | |
1087 |
|
1087 | |||
1088 | Verify bundle1 pushes can be disabled |
|
1088 | Verify bundle1 pushes can be disabled | |
1089 |
|
1089 | |||
1090 | $ cat > .hg/hgrc << EOF |
|
1090 | $ cat > .hg/hgrc << EOF | |
1091 | > [server] |
|
1091 | > [server] | |
1092 | > bundle1.push = false |
|
1092 | > bundle1.push = false | |
1093 | > [web] |
|
1093 | > [web] | |
1094 | > allow_push = * |
|
1094 | > allow_push = * | |
1095 | > push_ssl = false |
|
1095 | > push_ssl = false | |
1096 | > EOF |
|
1096 | > EOF | |
1097 |
|
1097 | |||
1098 | $ hg serve -p $HGPORT -d --pid-file=hg.pid -E error.log |
|
1098 | $ hg serve -p $HGPORT -d --pid-file=hg.pid -E error.log | |
1099 | $ cat hg.pid >> $DAEMON_PIDS |
|
1099 | $ cat hg.pid >> $DAEMON_PIDS | |
1100 | $ cd .. |
|
1100 | $ cd .. | |
1101 |
|
1101 | |||
1102 | $ hg clone http://localhost:$HGPORT bundle2-only |
|
1102 | $ hg clone http://localhost:$HGPORT bundle2-only | |
1103 | requesting all changes |
|
1103 | requesting all changes | |
1104 | adding changesets |
|
1104 | adding changesets | |
1105 | adding manifests |
|
1105 | adding manifests | |
1106 | adding file changes |
|
1106 | adding file changes | |
1107 | added 1 changesets with 1 changes to 1 files |
|
1107 | added 1 changesets with 1 changes to 1 files | |
1108 | updating to branch default |
|
1108 | updating to branch default | |
1109 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
1109 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
1110 | $ cd bundle2-only |
|
1110 | $ cd bundle2-only | |
1111 | $ echo commit > foo |
|
1111 | $ echo commit > foo | |
1112 | $ hg commit -m commit |
|
1112 | $ hg commit -m commit | |
1113 | $ hg --config devel.legacy.exchange=bundle1 push |
|
1113 | $ hg --config devel.legacy.exchange=bundle1 push | |
1114 | pushing to http://localhost:$HGPORT/ |
|
1114 | pushing to http://localhost:$HGPORT/ | |
1115 | searching for changes |
|
1115 | searching for changes | |
1116 | abort: remote error: |
|
1116 | abort: remote error: | |
1117 | incompatible Mercurial client; bundle2 required |
|
1117 | incompatible Mercurial client; bundle2 required | |
1118 | (see https://www.mercurial-scm.org/wiki/IncompatibleClient) |
|
1118 | (see https://www.mercurial-scm.org/wiki/IncompatibleClient) | |
1119 | [255] |
|
1119 | [255] | |
1120 |
|
1120 | |||
1121 | (also check with ssh) |
|
1121 | (also check with ssh) | |
1122 |
|
1122 | |||
1123 | $ hg --config devel.legacy.exchange=bundle1 push ssh://user@dummy/bundle2onlyserver |
|
1123 | $ hg --config devel.legacy.exchange=bundle1 push ssh://user@dummy/bundle2onlyserver | |
1124 | pushing to ssh://user@dummy/bundle2onlyserver |
|
1124 | pushing to ssh://user@dummy/bundle2onlyserver | |
1125 | searching for changes |
|
1125 | searching for changes | |
1126 | remote: abort: incompatible Mercurial client; bundle2 required |
|
1126 | remote: abort: incompatible Mercurial client; bundle2 required | |
1127 | remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient) |
|
1127 | remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient) | |
1128 | [1] |
|
1128 | [1] | |
1129 |
|
1129 | |||
1130 | $ hg push |
|
1130 | $ hg push | |
1131 | pushing to http://localhost:$HGPORT/ |
|
1131 | pushing to http://localhost:$HGPORT/ | |
1132 | searching for changes |
|
1132 | searching for changes | |
1133 | remote: adding changesets |
|
1133 | remote: adding changesets | |
1134 | remote: adding manifests |
|
1134 | remote: adding manifests | |
1135 | remote: adding file changes |
|
1135 | remote: adding file changes | |
1136 | remote: added 1 changesets with 1 changes to 1 files |
|
1136 | remote: added 1 changesets with 1 changes to 1 files |
@@ -1,260 +1,260 b'' | |||||
1 | Create an extension to test bundle2 with multiple changegroups |
|
1 | Create an extension to test bundle2 with multiple changegroups | |
2 |
|
2 | |||
3 | $ cat > bundle2.py <<EOF |
|
3 | $ cat > bundle2.py <<EOF | |
4 | > """ |
|
4 | > """ | |
5 | > """ |
|
5 | > """ | |
6 | > from mercurial import changegroup, discovery, exchange |
|
6 | > from mercurial import changegroup, discovery, exchange | |
7 | > |
|
7 | > | |
8 | > def _getbundlechangegrouppart(bundler, repo, source, bundlecaps=None, |
|
8 | > def _getbundlechangegrouppart(bundler, repo, source, bundlecaps=None, | |
9 | > b2caps=None, heads=None, common=None, |
|
9 | > b2caps=None, heads=None, common=None, | |
10 | > **kwargs): |
|
10 | > **kwargs): | |
11 | > # Create two changegroups given the common changesets and heads for the |
|
11 | > # Create two changegroups given the common changesets and heads for the | |
12 | > # changegroup part we are being requested. Use the parent of each head |
|
12 | > # changegroup part we are being requested. Use the parent of each head | |
13 | > # in 'heads' as intermediate heads for the first changegroup. |
|
13 | > # in 'heads' as intermediate heads for the first changegroup. | |
14 | > intermediates = [repo[r].p1().node() for r in heads] |
|
14 | > intermediates = [repo[r].p1().node() for r in heads] | |
15 | > outgoing = discovery.outgoing(repo, common, intermediates) |
|
15 | > outgoing = discovery.outgoing(repo, common, intermediates) | |
16 | > cg = changegroup.getchangegroup(repo, source, outgoing, |
|
16 | > cg = changegroup.getchangegroup(repo, source, outgoing, | |
17 | > bundlecaps=bundlecaps) |
|
17 | > bundlecaps=bundlecaps) | |
18 | > bundler.newpart('output', data='changegroup1') |
|
18 | > bundler.newpart('output', data='changegroup1') | |
19 | > bundler.newpart('changegroup', data=cg.getchunks()) |
|
19 | > bundler.newpart('changegroup', data=cg.getchunks()) | |
20 | > outgoing = discovery.outgoing(repo, common + intermediates, heads) |
|
20 | > outgoing = discovery.outgoing(repo, common + intermediates, heads) | |
21 | > cg = changegroup.getchangegroup(repo, source, outgoing, |
|
21 | > cg = changegroup.getchangegroup(repo, source, outgoing, | |
22 | > bundlecaps=bundlecaps) |
|
22 | > bundlecaps=bundlecaps) | |
23 | > bundler.newpart('output', data='changegroup2') |
|
23 | > bundler.newpart('output', data='changegroup2') | |
24 | > bundler.newpart('changegroup', data=cg.getchunks()) |
|
24 | > bundler.newpart('changegroup', data=cg.getchunks()) | |
25 | > |
|
25 | > | |
26 | > def _pull(repo, *args, **kwargs): |
|
26 | > def _pull(repo, *args, **kwargs): | |
27 | > pullop = _orig_pull(repo, *args, **kwargs) |
|
27 | > pullop = _orig_pull(repo, *args, **kwargs) | |
28 | > repo.ui.write('pullop.cgresult is %d\n' % pullop.cgresult) |
|
28 | > repo.ui.write('pullop.cgresult is %d\n' % pullop.cgresult) | |
29 | > return pullop |
|
29 | > return pullop | |
30 | > |
|
30 | > | |
31 | > _orig_pull = exchange.pull |
|
31 | > _orig_pull = exchange.pull | |
32 | > exchange.pull = _pull |
|
32 | > exchange.pull = _pull | |
33 | > exchange.getbundle2partsmapping['changegroup'] = _getbundlechangegrouppart |
|
33 | > exchange.getbundle2partsmapping['changegroup'] = _getbundlechangegrouppart | |
34 | > EOF |
|
34 | > EOF | |
35 |
|
35 | |||
36 | $ cat >> $HGRCPATH << EOF |
|
36 | $ cat >> $HGRCPATH << EOF | |
37 | > [ui] |
|
37 | > [ui] | |
38 | > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline} |
|
38 | > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline} | |
39 | > EOF |
|
39 | > EOF | |
40 |
|
40 | |||
41 | Start with a simple repository with a single commit |
|
41 | Start with a simple repository with a single commit | |
42 |
|
42 | |||
43 | $ hg init repo |
|
43 | $ hg init repo | |
44 | $ cd repo |
|
44 | $ cd repo | |
45 | $ cat > .hg/hgrc << EOF |
|
45 | $ cat > .hg/hgrc << EOF | |
46 | > [extensions] |
|
46 | > [extensions] | |
47 | > bundle2=$TESTTMP/bundle2.py |
|
47 | > bundle2=$TESTTMP/bundle2.py | |
48 | > EOF |
|
48 | > EOF | |
49 |
|
49 | |||
50 | $ echo A > A |
|
50 | $ echo A > A | |
51 | $ hg commit -A -m A -q |
|
51 | $ hg commit -A -m A -q | |
52 | $ cd .. |
|
52 | $ cd .. | |
53 |
|
53 | |||
54 | Clone |
|
54 | Clone | |
55 |
|
55 | |||
56 | $ hg clone -q repo clone |
|
56 | $ hg clone -q repo clone | |
57 |
|
57 | |||
58 | Add two linear commits |
|
58 | Add two linear commits | |
59 |
|
59 | |||
60 | $ cd repo |
|
60 | $ cd repo | |
61 | $ echo B > B |
|
61 | $ echo B > B | |
62 | $ hg commit -A -m B -q |
|
62 | $ hg commit -A -m B -q | |
63 | $ echo C > C |
|
63 | $ echo C > C | |
64 | $ hg commit -A -m C -q |
|
64 | $ hg commit -A -m C -q | |
65 |
|
65 | |||
66 | $ cd ../clone |
|
66 | $ cd ../clone | |
67 | $ cat >> .hg/hgrc <<EOF |
|
67 | $ cat >> .hg/hgrc <<EOF | |
68 | > [hooks] |
|
68 | > [hooks] | |
69 | > pretxnchangegroup = sh -c "printenv.py pretxnchangegroup" |
|
69 | > pretxnchangegroup = sh -c "printenv.py pretxnchangegroup" | |
70 | > changegroup = sh -c "printenv.py changegroup" |
|
70 | > changegroup = sh -c "printenv.py changegroup" | |
71 | > incoming = sh -c "printenv.py incoming" |
|
71 | > incoming = sh -c "printenv.py incoming" | |
72 | > EOF |
|
72 | > EOF | |
73 |
|
73 | |||
74 | Pull the new commits in the clone |
|
74 | Pull the new commits in the clone | |
75 |
|
75 | |||
76 | $ hg pull |
|
76 | $ hg pull | |
77 | pulling from $TESTTMP/repo (glob) |
|
77 | pulling from $TESTTMP/repo (glob) | |
78 | searching for changes |
|
78 | searching for changes | |
79 | remote: changegroup1 |
|
79 | remote: changegroup1 | |
80 | adding changesets |
|
80 | adding changesets | |
81 | adding manifests |
|
81 | adding manifests | |
82 | adding file changes |
|
82 | adding file changes | |
83 | added 1 changesets with 1 changes to 1 files |
|
83 | added 1 changesets with 1 changes to 1 files | |
84 |
pretxnchangegroup hook: HG_NODE=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_NODE_LAST=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_PENDING=$TESTTMP/clone HG_SOURCE=pull HG_TXNID=TXN: |
|
84 | pretxnchangegroup hook: HG_NODE=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_NODE_LAST=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_PENDING=$TESTTMP/clone HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
85 | remote: changegroup2 |
|
85 | remote: changegroup2 | |
86 | adding changesets |
|
86 | adding changesets | |
87 | adding manifests |
|
87 | adding manifests | |
88 | adding file changes |
|
88 | adding file changes | |
89 | added 1 changesets with 1 changes to 1 files |
|
89 | added 1 changesets with 1 changes to 1 files | |
90 |
pretxnchangegroup hook: HG_NODE=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_NODE_LAST=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_PENDING=$TESTTMP/clone HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
90 | pretxnchangegroup hook: HG_NODE=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_NODE_LAST=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_PENDING=$TESTTMP/clone HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
91 |
changegroup hook: HG_NODE=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_NODE_LAST=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_SOURCE=pull HG_TXNID=TXN: |
|
91 | changegroup hook: HG_NODE=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_NODE_LAST=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
92 |
incoming hook: HG_NODE=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_SOURCE=pull HG_TXNID=TXN: |
|
92 | incoming hook: HG_NODE=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
93 |
changegroup hook: HG_NODE=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_NODE_LAST=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
93 | changegroup hook: HG_NODE=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_NODE_LAST=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
94 |
incoming hook: HG_NODE=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
94 | incoming hook: HG_NODE=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
95 | pullop.cgresult is 1 |
|
95 | pullop.cgresult is 1 | |
96 | (run 'hg update' to get a working copy) |
|
96 | (run 'hg update' to get a working copy) | |
97 | $ hg update |
|
97 | $ hg update | |
98 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
98 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
99 | $ hg log -G |
|
99 | $ hg log -G | |
100 | @ 2:f838bfaca5c7 public test C |
|
100 | @ 2:f838bfaca5c7 public test C | |
101 | | |
|
101 | | | |
102 | o 1:27547f69f254 public test B |
|
102 | o 1:27547f69f254 public test B | |
103 | | |
|
103 | | | |
104 | o 0:4a2df7238c3b public test A |
|
104 | o 0:4a2df7238c3b public test A | |
105 |
|
105 | |||
106 | Add more changesets with multiple heads to the original repository |
|
106 | Add more changesets with multiple heads to the original repository | |
107 |
|
107 | |||
108 | $ cd ../repo |
|
108 | $ cd ../repo | |
109 | $ echo D > D |
|
109 | $ echo D > D | |
110 | $ hg commit -A -m D -q |
|
110 | $ hg commit -A -m D -q | |
111 | $ hg up -r 1 |
|
111 | $ hg up -r 1 | |
112 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
112 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved | |
113 | $ echo E > E |
|
113 | $ echo E > E | |
114 | $ hg commit -A -m E -q |
|
114 | $ hg commit -A -m E -q | |
115 | $ echo F > F |
|
115 | $ echo F > F | |
116 | $ hg commit -A -m F -q |
|
116 | $ hg commit -A -m F -q | |
117 | $ hg up -r 1 |
|
117 | $ hg up -r 1 | |
118 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
118 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved | |
119 | $ echo G > G |
|
119 | $ echo G > G | |
120 | $ hg commit -A -m G -q |
|
120 | $ hg commit -A -m G -q | |
121 | $ hg up -r 3 |
|
121 | $ hg up -r 3 | |
122 | 2 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
122 | 2 files updated, 0 files merged, 1 files removed, 0 files unresolved | |
123 | $ echo H > H |
|
123 | $ echo H > H | |
124 | $ hg commit -A -m H -q |
|
124 | $ hg commit -A -m H -q | |
125 | $ hg log -G |
|
125 | $ hg log -G | |
126 | @ 7:5cd59d311f65 draft test H |
|
126 | @ 7:5cd59d311f65 draft test H | |
127 | | |
|
127 | | | |
128 | | o 6:1d14c3ce6ac0 draft test G |
|
128 | | o 6:1d14c3ce6ac0 draft test G | |
129 | | | |
|
129 | | | | |
130 | | | o 5:7f219660301f draft test F |
|
130 | | | o 5:7f219660301f draft test F | |
131 | | | | |
|
131 | | | | | |
132 | | | o 4:8a5212ebc852 draft test E |
|
132 | | | o 4:8a5212ebc852 draft test E | |
133 | | |/ |
|
133 | | |/ | |
134 | o | 3:b3325c91a4d9 draft test D |
|
134 | o | 3:b3325c91a4d9 draft test D | |
135 | | | |
|
135 | | | | |
136 | o | 2:f838bfaca5c7 draft test C |
|
136 | o | 2:f838bfaca5c7 draft test C | |
137 | |/ |
|
137 | |/ | |
138 | o 1:27547f69f254 draft test B |
|
138 | o 1:27547f69f254 draft test B | |
139 | | |
|
139 | | | |
140 | o 0:4a2df7238c3b draft test A |
|
140 | o 0:4a2df7238c3b draft test A | |
141 |
|
141 | |||
142 | New heads are reported during transfer and properly accounted for in |
|
142 | New heads are reported during transfer and properly accounted for in | |
143 | pullop.cgresult |
|
143 | pullop.cgresult | |
144 |
|
144 | |||
145 | $ cd ../clone |
|
145 | $ cd ../clone | |
146 | $ hg pull |
|
146 | $ hg pull | |
147 | pulling from $TESTTMP/repo (glob) |
|
147 | pulling from $TESTTMP/repo (glob) | |
148 | searching for changes |
|
148 | searching for changes | |
149 | remote: changegroup1 |
|
149 | remote: changegroup1 | |
150 | adding changesets |
|
150 | adding changesets | |
151 | adding manifests |
|
151 | adding manifests | |
152 | adding file changes |
|
152 | adding file changes | |
153 | added 2 changesets with 2 changes to 2 files (+1 heads) |
|
153 | added 2 changesets with 2 changes to 2 files (+1 heads) | |
154 |
pretxnchangegroup hook: HG_NODE=b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e HG_NODE_LAST=8a5212ebc8527f9fb821601504794e3eb11a1ed3 HG_PENDING=$TESTTMP/clone HG_SOURCE=pull HG_TXNID=TXN: |
|
154 | pretxnchangegroup hook: HG_NODE=b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e HG_NODE_LAST=8a5212ebc8527f9fb821601504794e3eb11a1ed3 HG_PENDING=$TESTTMP/clone HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
155 | remote: changegroup2 |
|
155 | remote: changegroup2 | |
156 | adding changesets |
|
156 | adding changesets | |
157 | adding manifests |
|
157 | adding manifests | |
158 | adding file changes |
|
158 | adding file changes | |
159 | added 3 changesets with 3 changes to 3 files (+1 heads) |
|
159 | added 3 changesets with 3 changes to 3 files (+1 heads) | |
160 |
pretxnchangegroup hook: HG_NODE=7f219660301fe4c8a116f714df5e769695cc2b46 HG_NODE_LAST=5cd59d311f6508b8e0ed28a266756c859419c9f1 HG_PENDING=$TESTTMP/clone HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
160 | pretxnchangegroup hook: HG_NODE=7f219660301fe4c8a116f714df5e769695cc2b46 HG_NODE_LAST=5cd59d311f6508b8e0ed28a266756c859419c9f1 HG_PENDING=$TESTTMP/clone HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
161 |
changegroup hook: HG_NODE=b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e HG_NODE_LAST=8a5212ebc8527f9fb821601504794e3eb11a1ed3 HG_SOURCE=pull HG_TXNID=TXN: |
|
161 | changegroup hook: HG_NODE=b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e HG_NODE_LAST=8a5212ebc8527f9fb821601504794e3eb11a1ed3 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
162 |
incoming hook: HG_NODE=b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e HG_SOURCE=pull HG_TXNID=TXN: |
|
162 | incoming hook: HG_NODE=b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
163 |
incoming hook: HG_NODE=8a5212ebc8527f9fb821601504794e3eb11a1ed3 HG_SOURCE=pull HG_TXNID=TXN: |
|
163 | incoming hook: HG_NODE=8a5212ebc8527f9fb821601504794e3eb11a1ed3 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
164 |
changegroup hook: HG_NODE=7f219660301fe4c8a116f714df5e769695cc2b46 HG_NODE_LAST=5cd59d311f6508b8e0ed28a266756c859419c9f1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
164 | changegroup hook: HG_NODE=7f219660301fe4c8a116f714df5e769695cc2b46 HG_NODE_LAST=5cd59d311f6508b8e0ed28a266756c859419c9f1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
165 |
incoming hook: HG_NODE=7f219660301fe4c8a116f714df5e769695cc2b46 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
165 | incoming hook: HG_NODE=7f219660301fe4c8a116f714df5e769695cc2b46 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
166 |
incoming hook: HG_NODE=1d14c3ce6ac0582d2809220d33e8cd7a696e0156 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
166 | incoming hook: HG_NODE=1d14c3ce6ac0582d2809220d33e8cd7a696e0156 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
167 |
incoming hook: HG_NODE=5cd59d311f6508b8e0ed28a266756c859419c9f1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
167 | incoming hook: HG_NODE=5cd59d311f6508b8e0ed28a266756c859419c9f1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
168 | pullop.cgresult is 3 |
|
168 | pullop.cgresult is 3 | |
169 | (run 'hg heads' to see heads, 'hg merge' to merge) |
|
169 | (run 'hg heads' to see heads, 'hg merge' to merge) | |
170 | $ hg log -G |
|
170 | $ hg log -G | |
171 | o 7:5cd59d311f65 public test H |
|
171 | o 7:5cd59d311f65 public test H | |
172 | | |
|
172 | | | |
173 | | o 6:1d14c3ce6ac0 public test G |
|
173 | | o 6:1d14c3ce6ac0 public test G | |
174 | | | |
|
174 | | | | |
175 | | | o 5:7f219660301f public test F |
|
175 | | | o 5:7f219660301f public test F | |
176 | | | | |
|
176 | | | | | |
177 | | | o 4:8a5212ebc852 public test E |
|
177 | | | o 4:8a5212ebc852 public test E | |
178 | | |/ |
|
178 | | |/ | |
179 | o | 3:b3325c91a4d9 public test D |
|
179 | o | 3:b3325c91a4d9 public test D | |
180 | | | |
|
180 | | | | |
181 | @ | 2:f838bfaca5c7 public test C |
|
181 | @ | 2:f838bfaca5c7 public test C | |
182 | |/ |
|
182 | |/ | |
183 | o 1:27547f69f254 public test B |
|
183 | o 1:27547f69f254 public test B | |
184 | | |
|
184 | | | |
185 | o 0:4a2df7238c3b public test A |
|
185 | o 0:4a2df7238c3b public test A | |
186 |
|
186 | |||
187 | Removing a head from the original repository by merging it |
|
187 | Removing a head from the original repository by merging it | |
188 |
|
188 | |||
189 | $ cd ../repo |
|
189 | $ cd ../repo | |
190 | $ hg merge -r 6 -q |
|
190 | $ hg merge -r 6 -q | |
191 | $ hg commit -m Merge |
|
191 | $ hg commit -m Merge | |
192 | $ echo I > I |
|
192 | $ echo I > I | |
193 | $ hg commit -A -m H -q |
|
193 | $ hg commit -A -m H -q | |
194 | $ hg log -G |
|
194 | $ hg log -G | |
195 | @ 9:9d18e5bd9ab0 draft test H |
|
195 | @ 9:9d18e5bd9ab0 draft test H | |
196 | | |
|
196 | | | |
197 | o 8:71bd7b46de72 draft test Merge |
|
197 | o 8:71bd7b46de72 draft test Merge | |
198 | |\ |
|
198 | |\ | |
199 | | o 7:5cd59d311f65 draft test H |
|
199 | | o 7:5cd59d311f65 draft test H | |
200 | | | |
|
200 | | | | |
201 | o | 6:1d14c3ce6ac0 draft test G |
|
201 | o | 6:1d14c3ce6ac0 draft test G | |
202 | | | |
|
202 | | | | |
203 | | | o 5:7f219660301f draft test F |
|
203 | | | o 5:7f219660301f draft test F | |
204 | | | | |
|
204 | | | | | |
205 | +---o 4:8a5212ebc852 draft test E |
|
205 | +---o 4:8a5212ebc852 draft test E | |
206 | | | |
|
206 | | | | |
207 | | o 3:b3325c91a4d9 draft test D |
|
207 | | o 3:b3325c91a4d9 draft test D | |
208 | | | |
|
208 | | | | |
209 | | o 2:f838bfaca5c7 draft test C |
|
209 | | o 2:f838bfaca5c7 draft test C | |
210 | |/ |
|
210 | |/ | |
211 | o 1:27547f69f254 draft test B |
|
211 | o 1:27547f69f254 draft test B | |
212 | | |
|
212 | | | |
213 | o 0:4a2df7238c3b draft test A |
|
213 | o 0:4a2df7238c3b draft test A | |
214 |
|
214 | |||
215 | Removed heads are reported during transfer and properly accounted for in |
|
215 | Removed heads are reported during transfer and properly accounted for in | |
216 | pullop.cgresult |
|
216 | pullop.cgresult | |
217 |
|
217 | |||
218 | $ cd ../clone |
|
218 | $ cd ../clone | |
219 | $ hg pull |
|
219 | $ hg pull | |
220 | pulling from $TESTTMP/repo (glob) |
|
220 | pulling from $TESTTMP/repo (glob) | |
221 | searching for changes |
|
221 | searching for changes | |
222 | remote: changegroup1 |
|
222 | remote: changegroup1 | |
223 | adding changesets |
|
223 | adding changesets | |
224 | adding manifests |
|
224 | adding manifests | |
225 | adding file changes |
|
225 | adding file changes | |
226 | added 1 changesets with 0 changes to 0 files (-1 heads) |
|
226 | added 1 changesets with 0 changes to 0 files (-1 heads) | |
227 |
pretxnchangegroup hook: HG_NODE=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_NODE_LAST=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_PENDING=$TESTTMP/clone HG_SOURCE=pull HG_TXNID=TXN: |
|
227 | pretxnchangegroup hook: HG_NODE=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_NODE_LAST=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_PENDING=$TESTTMP/clone HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
228 | remote: changegroup2 |
|
228 | remote: changegroup2 | |
229 | adding changesets |
|
229 | adding changesets | |
230 | adding manifests |
|
230 | adding manifests | |
231 | adding file changes |
|
231 | adding file changes | |
232 | added 1 changesets with 1 changes to 1 files |
|
232 | added 1 changesets with 1 changes to 1 files | |
233 |
pretxnchangegroup hook: HG_NODE=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_NODE_LAST=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_PENDING=$TESTTMP/clone HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
233 | pretxnchangegroup hook: HG_NODE=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_NODE_LAST=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_PENDING=$TESTTMP/clone HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
234 |
changegroup hook: HG_NODE=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_NODE_LAST=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_SOURCE=pull HG_TXNID=TXN: |
|
234 | changegroup hook: HG_NODE=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_NODE_LAST=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
235 |
incoming hook: HG_NODE=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_SOURCE=pull HG_TXNID=TXN: |
|
235 | incoming hook: HG_NODE=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
236 |
changegroup hook: HG_NODE=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_NODE_LAST=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
236 | changegroup hook: HG_NODE=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_NODE_LAST=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
237 |
incoming hook: HG_NODE=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN: |
|
237 | incoming hook: HG_NODE=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo | |
238 | pullop.cgresult is -2 |
|
238 | pullop.cgresult is -2 | |
239 | (run 'hg update' to get a working copy) |
|
239 | (run 'hg update' to get a working copy) | |
240 | $ hg log -G |
|
240 | $ hg log -G | |
241 | o 9:9d18e5bd9ab0 public test H |
|
241 | o 9:9d18e5bd9ab0 public test H | |
242 | | |
|
242 | | | |
243 | o 8:71bd7b46de72 public test Merge |
|
243 | o 8:71bd7b46de72 public test Merge | |
244 | |\ |
|
244 | |\ | |
245 | | o 7:5cd59d311f65 public test H |
|
245 | | o 7:5cd59d311f65 public test H | |
246 | | | |
|
246 | | | | |
247 | o | 6:1d14c3ce6ac0 public test G |
|
247 | o | 6:1d14c3ce6ac0 public test G | |
248 | | | |
|
248 | | | | |
249 | | | o 5:7f219660301f public test F |
|
249 | | | o 5:7f219660301f public test F | |
250 | | | | |
|
250 | | | | | |
251 | +---o 4:8a5212ebc852 public test E |
|
251 | +---o 4:8a5212ebc852 public test E | |
252 | | | |
|
252 | | | | |
253 | | o 3:b3325c91a4d9 public test D |
|
253 | | o 3:b3325c91a4d9 public test D | |
254 | | | |
|
254 | | | | |
255 | | @ 2:f838bfaca5c7 public test C |
|
255 | | @ 2:f838bfaca5c7 public test C | |
256 | |/ |
|
256 | |/ | |
257 | o 1:27547f69f254 public test B |
|
257 | o 1:27547f69f254 public test B | |
258 | | |
|
258 | | | |
259 | o 0:4a2df7238c3b public test A |
|
259 | o 0:4a2df7238c3b public test A | |
260 |
|
260 |
@@ -1,935 +1,935 b'' | |||||
1 | commit hooks can see env vars |
|
1 | commit hooks can see env vars | |
2 | (and post-transaction one are run unlocked) |
|
2 | (and post-transaction one are run unlocked) | |
3 |
|
3 | |||
4 |
|
4 | |||
5 | $ cat > $TESTTMP/txnabort.checkargs.py <<EOF |
|
5 | $ cat > $TESTTMP/txnabort.checkargs.py <<EOF | |
6 | > def showargs(ui, repo, hooktype, **kwargs): |
|
6 | > def showargs(ui, repo, hooktype, **kwargs): | |
7 | > ui.write('%s python hook: %s\n' % (hooktype, ','.join(sorted(kwargs)))) |
|
7 | > ui.write('%s python hook: %s\n' % (hooktype, ','.join(sorted(kwargs)))) | |
8 | > EOF |
|
8 | > EOF | |
9 |
|
9 | |||
10 | $ hg init a |
|
10 | $ hg init a | |
11 | $ cd a |
|
11 | $ cd a | |
12 | $ cat > .hg/hgrc <<EOF |
|
12 | $ cat > .hg/hgrc <<EOF | |
13 | > [hooks] |
|
13 | > [hooks] | |
14 | > commit = sh -c "HG_LOCAL= HG_TAG= printenv.py commit" |
|
14 | > commit = sh -c "HG_LOCAL= HG_TAG= printenv.py commit" | |
15 | > commit.b = sh -c "HG_LOCAL= HG_TAG= printenv.py commit.b" |
|
15 | > commit.b = sh -c "HG_LOCAL= HG_TAG= printenv.py commit.b" | |
16 | > precommit = sh -c "HG_LOCAL= HG_NODE= HG_TAG= printenv.py precommit" |
|
16 | > precommit = sh -c "HG_LOCAL= HG_NODE= HG_TAG= printenv.py precommit" | |
17 | > pretxncommit = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxncommit" |
|
17 | > pretxncommit = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxncommit" | |
18 | > pretxncommit.tip = hg -q tip |
|
18 | > pretxncommit.tip = hg -q tip | |
19 | > pre-identify = sh -c "printenv.py pre-identify 1" |
|
19 | > pre-identify = sh -c "printenv.py pre-identify 1" | |
20 | > pre-cat = sh -c "printenv.py pre-cat" |
|
20 | > pre-cat = sh -c "printenv.py pre-cat" | |
21 | > post-cat = sh -c "printenv.py post-cat" |
|
21 | > post-cat = sh -c "printenv.py post-cat" | |
22 | > pretxnopen = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxnopen" |
|
22 | > pretxnopen = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxnopen" | |
23 | > pretxnclose = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxnclose" |
|
23 | > pretxnclose = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxnclose" | |
24 | > txnclose = sh -c "HG_LOCAL= HG_TAG= printenv.py txnclose" |
|
24 | > txnclose = sh -c "HG_LOCAL= HG_TAG= printenv.py txnclose" | |
25 | > txnabort.0 = python:$TESTTMP/txnabort.checkargs.py:showargs |
|
25 | > txnabort.0 = python:$TESTTMP/txnabort.checkargs.py:showargs | |
26 | > txnabort.1 = sh -c "HG_LOCAL= HG_TAG= printenv.py txnabort" |
|
26 | > txnabort.1 = sh -c "HG_LOCAL= HG_TAG= printenv.py txnabort" | |
27 | > txnclose.checklock = sh -c "hg debuglock > /dev/null" |
|
27 | > txnclose.checklock = sh -c "hg debuglock > /dev/null" | |
28 | > EOF |
|
28 | > EOF | |
29 | $ echo a > a |
|
29 | $ echo a > a | |
30 | $ hg add a |
|
30 | $ hg add a | |
31 | $ hg commit -m a |
|
31 | $ hg commit -m a | |
32 | precommit hook: HG_PARENT1=0000000000000000000000000000000000000000 |
|
32 | precommit hook: HG_PARENT1=0000000000000000000000000000000000000000 | |
33 |
pretxnopen hook: HG_TXNID=TXN: |
|
33 | pretxnopen hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
34 | pretxncommit hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=$TESTTMP/a |
|
34 | pretxncommit hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=$TESTTMP/a | |
35 | 0:cb9a9f314b8b |
|
35 | 0:cb9a9f314b8b | |
36 |
pretxnclose hook: HG_PENDING=$TESTTMP/a HG_PHASES_MOVED=1 HG_TXNID=TXN: |
|
36 | pretxnclose hook: HG_PENDING=$TESTTMP/a HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
37 |
txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN: |
|
37 | txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
38 | commit hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000 |
|
38 | commit hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000 | |
39 | commit.b hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000 |
|
39 | commit.b hook: HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000 | |
40 |
|
40 | |||
41 | $ hg clone . ../b |
|
41 | $ hg clone . ../b | |
42 | updating to branch default |
|
42 | updating to branch default | |
43 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
43 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
44 | $ cd ../b |
|
44 | $ cd ../b | |
45 |
|
45 | |||
46 | changegroup hooks can see env vars |
|
46 | changegroup hooks can see env vars | |
47 |
|
47 | |||
48 | $ cat > .hg/hgrc <<EOF |
|
48 | $ cat > .hg/hgrc <<EOF | |
49 | > [hooks] |
|
49 | > [hooks] | |
50 | > prechangegroup = sh -c "printenv.py prechangegroup" |
|
50 | > prechangegroup = sh -c "printenv.py prechangegroup" | |
51 | > changegroup = sh -c "printenv.py changegroup" |
|
51 | > changegroup = sh -c "printenv.py changegroup" | |
52 | > incoming = sh -c "printenv.py incoming" |
|
52 | > incoming = sh -c "printenv.py incoming" | |
53 | > EOF |
|
53 | > EOF | |
54 |
|
54 | |||
55 | pretxncommit and commit hooks can see both parents of merge |
|
55 | pretxncommit and commit hooks can see both parents of merge | |
56 |
|
56 | |||
57 | $ cd ../a |
|
57 | $ cd ../a | |
58 | $ echo b >> a |
|
58 | $ echo b >> a | |
59 | $ hg commit -m a1 -d "1 0" |
|
59 | $ hg commit -m a1 -d "1 0" | |
60 | precommit hook: HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
60 | precommit hook: HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b | |
61 |
pretxnopen hook: HG_TXNID=TXN: |
|
61 | pretxnopen hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
62 | pretxncommit hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a |
|
62 | pretxncommit hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a | |
63 | 1:ab228980c14d |
|
63 | 1:ab228980c14d | |
64 |
pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN: |
|
64 | pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
65 |
txnclose hook: HG_TXNID=TXN: |
|
65 | txnclose hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
66 | commit hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
66 | commit hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b | |
67 | commit.b hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
67 | commit.b hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b | |
68 | $ hg update -C 0 |
|
68 | $ hg update -C 0 | |
69 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
69 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
70 | $ echo b > b |
|
70 | $ echo b > b | |
71 | $ hg add b |
|
71 | $ hg add b | |
72 | $ hg commit -m b -d '1 0' |
|
72 | $ hg commit -m b -d '1 0' | |
73 | precommit hook: HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
73 | precommit hook: HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b | |
74 |
pretxnopen hook: HG_TXNID=TXN: |
|
74 | pretxnopen hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
75 | pretxncommit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a |
|
75 | pretxncommit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a | |
76 | 2:ee9deb46ab31 |
|
76 | 2:ee9deb46ab31 | |
77 |
pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN: |
|
77 | pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
78 | created new head |
|
78 | created new head | |
79 |
txnclose hook: HG_TXNID=TXN: |
|
79 | txnclose hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
80 | commit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
80 | commit hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b | |
81 | commit.b hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b |
|
81 | commit.b hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b | |
82 | $ hg merge 1 |
|
82 | $ hg merge 1 | |
83 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
83 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
84 | (branch merge, don't forget to commit) |
|
84 | (branch merge, don't forget to commit) | |
85 | $ hg commit -m merge -d '2 0' |
|
85 | $ hg commit -m merge -d '2 0' | |
86 | precommit hook: HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd |
|
86 | precommit hook: HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd | |
87 |
pretxnopen hook: HG_TXNID=TXN: |
|
87 | pretxnopen hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
88 | pretxncommit hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd HG_PENDING=$TESTTMP/a |
|
88 | pretxncommit hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd HG_PENDING=$TESTTMP/a | |
89 | 3:07f3376c1e65 |
|
89 | 3:07f3376c1e65 | |
90 |
pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN: |
|
90 | pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
91 |
txnclose hook: HG_TXNID=TXN: |
|
91 | txnclose hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
92 | commit hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd |
|
92 | commit hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd | |
93 | commit.b hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd |
|
93 | commit.b hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd | |
94 |
|
94 | |||
95 | test generic hooks |
|
95 | test generic hooks | |
96 |
|
96 | |||
97 | $ hg id |
|
97 | $ hg id | |
98 | pre-identify hook: HG_ARGS=id HG_OPTS={'bookmarks': None, 'branch': None, 'id': None, 'insecure': None, 'num': None, 'remotecmd': '', 'rev': '', 'ssh': '', 'tags': None} HG_PATS=[] |
|
98 | pre-identify hook: HG_ARGS=id HG_OPTS={'bookmarks': None, 'branch': None, 'id': None, 'insecure': None, 'num': None, 'remotecmd': '', 'rev': '', 'ssh': '', 'tags': None} HG_PATS=[] | |
99 | abort: pre-identify hook exited with status 1 |
|
99 | abort: pre-identify hook exited with status 1 | |
100 | [255] |
|
100 | [255] | |
101 | $ hg cat b |
|
101 | $ hg cat b | |
102 | pre-cat hook: HG_ARGS=cat b HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b'] |
|
102 | pre-cat hook: HG_ARGS=cat b HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b'] | |
103 | b |
|
103 | b | |
104 | post-cat hook: HG_ARGS=cat b HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b'] HG_RESULT=0 |
|
104 | post-cat hook: HG_ARGS=cat b HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b'] HG_RESULT=0 | |
105 |
|
105 | |||
106 | $ cd ../b |
|
106 | $ cd ../b | |
107 | $ hg pull ../a |
|
107 | $ hg pull ../a | |
108 | pulling from ../a |
|
108 | pulling from ../a | |
109 | searching for changes |
|
109 | searching for changes | |
110 |
prechangegroup hook: HG_SOURCE=pull HG_TXNID=TXN: |
|
110 | prechangegroup hook: HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a | |
111 | adding changesets |
|
111 | adding changesets | |
112 | adding manifests |
|
112 | adding manifests | |
113 | adding file changes |
|
113 | adding file changes | |
114 | added 3 changesets with 2 changes to 2 files |
|
114 | added 3 changesets with 2 changes to 2 files | |
115 |
changegroup hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_NODE_LAST=07f3376c1e655977439df2a814e3cc14b27abac2 HG_SOURCE=pull HG_TXNID=TXN: |
|
115 | changegroup hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_NODE_LAST=07f3376c1e655977439df2a814e3cc14b27abac2 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a | |
116 |
incoming hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_SOURCE=pull HG_TXNID=TXN: |
|
116 | incoming hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a | |
117 |
incoming hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_SOURCE=pull HG_TXNID=TXN: |
|
117 | incoming hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a | |
118 |
incoming hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_SOURCE=pull HG_TXNID=TXN: |
|
118 | incoming hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a | |
119 | (run 'hg update' to get a working copy) |
|
119 | (run 'hg update' to get a working copy) | |
120 |
|
120 | |||
121 | tag hooks can see env vars |
|
121 | tag hooks can see env vars | |
122 |
|
122 | |||
123 | $ cd ../a |
|
123 | $ cd ../a | |
124 | $ cat >> .hg/hgrc <<EOF |
|
124 | $ cat >> .hg/hgrc <<EOF | |
125 | > pretag = sh -c "printenv.py pretag" |
|
125 | > pretag = sh -c "printenv.py pretag" | |
126 | > tag = sh -c "HG_PARENT1= HG_PARENT2= printenv.py tag" |
|
126 | > tag = sh -c "HG_PARENT1= HG_PARENT2= printenv.py tag" | |
127 | > EOF |
|
127 | > EOF | |
128 | $ hg tag -d '3 0' a |
|
128 | $ hg tag -d '3 0' a | |
129 | pretag hook: HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a |
|
129 | pretag hook: HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a | |
130 | precommit hook: HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 |
|
130 | precommit hook: HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 | |
131 |
pretxnopen hook: HG_TXNID=TXN: |
|
131 | pretxnopen hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
132 | pretxncommit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PENDING=$TESTTMP/a |
|
132 | pretxncommit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PENDING=$TESTTMP/a | |
133 | 4:539e4b31b6dc |
|
133 | 4:539e4b31b6dc | |
134 |
pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN: |
|
134 | pretxnclose hook: HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
135 | tag hook: HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a |
|
135 | tag hook: HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a | |
136 |
txnclose hook: HG_TXNID=TXN: |
|
136 | txnclose hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
137 | commit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 |
|
137 | commit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 | |
138 | commit.b hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 |
|
138 | commit.b hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 | |
139 | $ hg tag -l la |
|
139 | $ hg tag -l la | |
140 | pretag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la |
|
140 | pretag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la | |
141 | tag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la |
|
141 | tag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la | |
142 |
|
142 | |||
143 | pretag hook can forbid tagging |
|
143 | pretag hook can forbid tagging | |
144 |
|
144 | |||
145 | $ cat >> .hg/hgrc <<EOF |
|
145 | $ cat >> .hg/hgrc <<EOF | |
146 | > pretag.forbid = sh -c "printenv.py pretag.forbid 1" |
|
146 | > pretag.forbid = sh -c "printenv.py pretag.forbid 1" | |
147 | > EOF |
|
147 | > EOF | |
148 | $ hg tag -d '4 0' fa |
|
148 | $ hg tag -d '4 0' fa | |
149 | pretag hook: HG_LOCAL=0 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fa |
|
149 | pretag hook: HG_LOCAL=0 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fa | |
150 | pretag.forbid hook: HG_LOCAL=0 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fa |
|
150 | pretag.forbid hook: HG_LOCAL=0 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fa | |
151 | abort: pretag.forbid hook exited with status 1 |
|
151 | abort: pretag.forbid hook exited with status 1 | |
152 | [255] |
|
152 | [255] | |
153 | $ hg tag -l fla |
|
153 | $ hg tag -l fla | |
154 | pretag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fla |
|
154 | pretag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fla | |
155 | pretag.forbid hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fla |
|
155 | pretag.forbid hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fla | |
156 | abort: pretag.forbid hook exited with status 1 |
|
156 | abort: pretag.forbid hook exited with status 1 | |
157 | [255] |
|
157 | [255] | |
158 |
|
158 | |||
159 | pretxncommit hook can see changeset, can roll back txn, changeset no |
|
159 | pretxncommit hook can see changeset, can roll back txn, changeset no | |
160 | more there after |
|
160 | more there after | |
161 |
|
161 | |||
162 | $ cat >> .hg/hgrc <<EOF |
|
162 | $ cat >> .hg/hgrc <<EOF | |
163 | > pretxncommit.forbid0 = sh -c "hg tip -q" |
|
163 | > pretxncommit.forbid0 = sh -c "hg tip -q" | |
164 | > pretxncommit.forbid1 = sh -c "printenv.py pretxncommit.forbid 1" |
|
164 | > pretxncommit.forbid1 = sh -c "printenv.py pretxncommit.forbid 1" | |
165 | > EOF |
|
165 | > EOF | |
166 | $ echo z > z |
|
166 | $ echo z > z | |
167 | $ hg add z |
|
167 | $ hg add z | |
168 | $ hg -q tip |
|
168 | $ hg -q tip | |
169 | 4:539e4b31b6dc |
|
169 | 4:539e4b31b6dc | |
170 | $ hg commit -m 'fail' -d '4 0' |
|
170 | $ hg commit -m 'fail' -d '4 0' | |
171 | precommit hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
171 | precommit hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 | |
172 |
pretxnopen hook: HG_TXNID=TXN: |
|
172 | pretxnopen hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
173 | pretxncommit hook: HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/a |
|
173 | pretxncommit hook: HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/a | |
174 | 5:6f611f8018c1 |
|
174 | 5:6f611f8018c1 | |
175 | 5:6f611f8018c1 |
|
175 | 5:6f611f8018c1 | |
176 | pretxncommit.forbid hook: HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/a |
|
176 | pretxncommit.forbid hook: HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/a | |
177 | transaction abort! |
|
177 | transaction abort! | |
178 | txnabort python hook: txnid,txnname |
|
178 | txnabort python hook: txnid,txnname | |
179 |
txnabort hook: HG_TXNID=TXN: |
|
179 | txnabort hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=commit | |
180 | rollback completed |
|
180 | rollback completed | |
181 | abort: pretxncommit.forbid1 hook exited with status 1 |
|
181 | abort: pretxncommit.forbid1 hook exited with status 1 | |
182 | [255] |
|
182 | [255] | |
183 | $ hg -q tip |
|
183 | $ hg -q tip | |
184 | 4:539e4b31b6dc |
|
184 | 4:539e4b31b6dc | |
185 |
|
185 | |||
186 | (Check that no 'changelog.i.a' file were left behind) |
|
186 | (Check that no 'changelog.i.a' file were left behind) | |
187 |
|
187 | |||
188 | $ ls -1 .hg/store/ |
|
188 | $ ls -1 .hg/store/ | |
189 | 00changelog.i |
|
189 | 00changelog.i | |
190 | 00manifest.i |
|
190 | 00manifest.i | |
191 | data |
|
191 | data | |
192 | fncache |
|
192 | fncache | |
193 | journal.phaseroots |
|
193 | journal.phaseroots | |
194 | phaseroots |
|
194 | phaseroots | |
195 | undo |
|
195 | undo | |
196 | undo.backup.fncache |
|
196 | undo.backup.fncache | |
197 | undo.backupfiles |
|
197 | undo.backupfiles | |
198 | undo.phaseroots |
|
198 | undo.phaseroots | |
199 |
|
199 | |||
200 |
|
200 | |||
201 | precommit hook can prevent commit |
|
201 | precommit hook can prevent commit | |
202 |
|
202 | |||
203 | $ cat >> .hg/hgrc <<EOF |
|
203 | $ cat >> .hg/hgrc <<EOF | |
204 | > precommit.forbid = sh -c "printenv.py precommit.forbid 1" |
|
204 | > precommit.forbid = sh -c "printenv.py precommit.forbid 1" | |
205 | > EOF |
|
205 | > EOF | |
206 | $ hg commit -m 'fail' -d '4 0' |
|
206 | $ hg commit -m 'fail' -d '4 0' | |
207 | precommit hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
207 | precommit hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 | |
208 | precommit.forbid hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 |
|
208 | precommit.forbid hook: HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 | |
209 | abort: precommit.forbid hook exited with status 1 |
|
209 | abort: precommit.forbid hook exited with status 1 | |
210 | [255] |
|
210 | [255] | |
211 | $ hg -q tip |
|
211 | $ hg -q tip | |
212 | 4:539e4b31b6dc |
|
212 | 4:539e4b31b6dc | |
213 |
|
213 | |||
214 | preupdate hook can prevent update |
|
214 | preupdate hook can prevent update | |
215 |
|
215 | |||
216 | $ cat >> .hg/hgrc <<EOF |
|
216 | $ cat >> .hg/hgrc <<EOF | |
217 | > preupdate = sh -c "printenv.py preupdate" |
|
217 | > preupdate = sh -c "printenv.py preupdate" | |
218 | > EOF |
|
218 | > EOF | |
219 | $ hg update 1 |
|
219 | $ hg update 1 | |
220 | preupdate hook: HG_PARENT1=ab228980c14d |
|
220 | preupdate hook: HG_PARENT1=ab228980c14d | |
221 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
221 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved | |
222 |
|
222 | |||
223 | update hook |
|
223 | update hook | |
224 |
|
224 | |||
225 | $ cat >> .hg/hgrc <<EOF |
|
225 | $ cat >> .hg/hgrc <<EOF | |
226 | > update = sh -c "printenv.py update" |
|
226 | > update = sh -c "printenv.py update" | |
227 | > EOF |
|
227 | > EOF | |
228 | $ hg update |
|
228 | $ hg update | |
229 | preupdate hook: HG_PARENT1=539e4b31b6dc |
|
229 | preupdate hook: HG_PARENT1=539e4b31b6dc | |
230 | update hook: HG_ERROR=0 HG_PARENT1=539e4b31b6dc |
|
230 | update hook: HG_ERROR=0 HG_PARENT1=539e4b31b6dc | |
231 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
231 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
232 |
|
232 | |||
233 | pushkey hook |
|
233 | pushkey hook | |
234 |
|
234 | |||
235 | $ cat >> .hg/hgrc <<EOF |
|
235 | $ cat >> .hg/hgrc <<EOF | |
236 | > pushkey = sh -c "printenv.py pushkey" |
|
236 | > pushkey = sh -c "printenv.py pushkey" | |
237 | > EOF |
|
237 | > EOF | |
238 | $ cd ../b |
|
238 | $ cd ../b | |
239 | $ hg bookmark -r null foo |
|
239 | $ hg bookmark -r null foo | |
240 | $ hg push -B foo ../a |
|
240 | $ hg push -B foo ../a | |
241 | pushing to ../a |
|
241 | pushing to ../a | |
242 | searching for changes |
|
242 | searching for changes | |
243 | no changes found |
|
243 | no changes found | |
244 |
pretxnopen hook: HG_TXNID=TXN: |
|
244 | pretxnopen hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=push | |
245 |
pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_PENDING=$TESTTMP/a HG_SOURCE=push HG_TXNID=TXN: |
|
245 | pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_PENDING=$TESTTMP/a HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/a | |
246 | pushkey hook: HG_KEY=foo HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_RET=1 |
|
246 | pushkey hook: HG_KEY=foo HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_RET=1 | |
247 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_SOURCE=push HG_TXNID=TXN: |
|
247 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/a | |
248 | exporting bookmark foo |
|
248 | exporting bookmark foo | |
249 | [1] |
|
249 | [1] | |
250 | $ cd ../a |
|
250 | $ cd ../a | |
251 |
|
251 | |||
252 | listkeys hook |
|
252 | listkeys hook | |
253 |
|
253 | |||
254 | $ cat >> .hg/hgrc <<EOF |
|
254 | $ cat >> .hg/hgrc <<EOF | |
255 | > listkeys = sh -c "printenv.py listkeys" |
|
255 | > listkeys = sh -c "printenv.py listkeys" | |
256 | > EOF |
|
256 | > EOF | |
257 | $ hg bookmark -r null bar |
|
257 | $ hg bookmark -r null bar | |
258 |
pretxnopen hook: HG_TXNID=TXN: |
|
258 | pretxnopen hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
259 |
pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_PENDING=$TESTTMP/a HG_TXNID=TXN: |
|
259 | pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
260 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN: |
|
260 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
261 | $ cd ../b |
|
261 | $ cd ../b | |
262 | $ hg pull -B bar ../a |
|
262 | $ hg pull -B bar ../a | |
263 | pulling from ../a |
|
263 | pulling from ../a | |
264 | listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} |
|
264 | listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} | |
265 | no changes found |
|
265 | no changes found | |
266 | listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'} |
|
266 | listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'} | |
267 | adding remote bookmark bar |
|
267 | adding remote bookmark bar | |
268 | $ cd ../a |
|
268 | $ cd ../a | |
269 |
|
269 | |||
270 | test that prepushkey can prevent incoming keys |
|
270 | test that prepushkey can prevent incoming keys | |
271 |
|
271 | |||
272 | $ cat >> .hg/hgrc <<EOF |
|
272 | $ cat >> .hg/hgrc <<EOF | |
273 | > prepushkey = sh -c "printenv.py prepushkey.forbid 1" |
|
273 | > prepushkey = sh -c "printenv.py prepushkey.forbid 1" | |
274 | > EOF |
|
274 | > EOF | |
275 | $ cd ../b |
|
275 | $ cd ../b | |
276 | $ hg bookmark -r null baz |
|
276 | $ hg bookmark -r null baz | |
277 | $ hg push -B baz ../a |
|
277 | $ hg push -B baz ../a | |
278 | pushing to ../a |
|
278 | pushing to ../a | |
279 | searching for changes |
|
279 | searching for changes | |
280 | listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'} |
|
280 | listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'} | |
281 | listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} |
|
281 | listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} | |
282 | no changes found |
|
282 | no changes found | |
283 |
pretxnopen hook: HG_TXNID=TXN: |
|
283 | pretxnopen hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=push | |
284 |
prepushkey.forbid hook: HG_BUNDLE2=1 HG_KEY=baz HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_SOURCE=push HG_TXNID=TXN: |
|
284 | prepushkey.forbid hook: HG_BUNDLE2=1 HG_KEY=baz HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a | |
285 | pushkey-abort: prepushkey hook exited with status 1 |
|
285 | pushkey-abort: prepushkey hook exited with status 1 | |
286 | abort: exporting bookmark baz failed! |
|
286 | abort: exporting bookmark baz failed! | |
287 | [255] |
|
287 | [255] | |
288 | $ cd ../a |
|
288 | $ cd ../a | |
289 |
|
289 | |||
290 | test that prelistkeys can prevent listing keys |
|
290 | test that prelistkeys can prevent listing keys | |
291 |
|
291 | |||
292 | $ cat >> .hg/hgrc <<EOF |
|
292 | $ cat >> .hg/hgrc <<EOF | |
293 | > prelistkeys = sh -c "printenv.py prelistkeys.forbid 1" |
|
293 | > prelistkeys = sh -c "printenv.py prelistkeys.forbid 1" | |
294 | > EOF |
|
294 | > EOF | |
295 | $ hg bookmark -r null quux |
|
295 | $ hg bookmark -r null quux | |
296 |
pretxnopen hook: HG_TXNID=TXN: |
|
296 | pretxnopen hook: HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
297 |
pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_PENDING=$TESTTMP/a HG_TXNID=TXN: |
|
297 | pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
298 |
txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN: |
|
298 | txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark | |
299 | $ cd ../b |
|
299 | $ cd ../b | |
300 | $ hg pull -B quux ../a |
|
300 | $ hg pull -B quux ../a | |
301 | pulling from ../a |
|
301 | pulling from ../a | |
302 | prelistkeys.forbid hook: HG_NAMESPACE=bookmarks |
|
302 | prelistkeys.forbid hook: HG_NAMESPACE=bookmarks | |
303 | abort: prelistkeys hook exited with status 1 |
|
303 | abort: prelistkeys hook exited with status 1 | |
304 | [255] |
|
304 | [255] | |
305 | $ cd ../a |
|
305 | $ cd ../a | |
306 | $ rm .hg/hgrc |
|
306 | $ rm .hg/hgrc | |
307 |
|
307 | |||
308 | prechangegroup hook can prevent incoming changes |
|
308 | prechangegroup hook can prevent incoming changes | |
309 |
|
309 | |||
310 | $ cd ../b |
|
310 | $ cd ../b | |
311 | $ hg -q tip |
|
311 | $ hg -q tip | |
312 | 3:07f3376c1e65 |
|
312 | 3:07f3376c1e65 | |
313 | $ cat > .hg/hgrc <<EOF |
|
313 | $ cat > .hg/hgrc <<EOF | |
314 | > [hooks] |
|
314 | > [hooks] | |
315 | > prechangegroup.forbid = sh -c "printenv.py prechangegroup.forbid 1" |
|
315 | > prechangegroup.forbid = sh -c "printenv.py prechangegroup.forbid 1" | |
316 | > EOF |
|
316 | > EOF | |
317 | $ hg pull ../a |
|
317 | $ hg pull ../a | |
318 | pulling from ../a |
|
318 | pulling from ../a | |
319 | searching for changes |
|
319 | searching for changes | |
320 |
prechangegroup.forbid hook: HG_SOURCE=pull HG_TXNID=TXN: |
|
320 | prechangegroup.forbid hook: HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a | |
321 | abort: prechangegroup.forbid hook exited with status 1 |
|
321 | abort: prechangegroup.forbid hook exited with status 1 | |
322 | [255] |
|
322 | [255] | |
323 |
|
323 | |||
324 | pretxnchangegroup hook can see incoming changes, can roll back txn, |
|
324 | pretxnchangegroup hook can see incoming changes, can roll back txn, | |
325 | incoming changes no longer there after |
|
325 | incoming changes no longer there after | |
326 |
|
326 | |||
327 | $ cat > .hg/hgrc <<EOF |
|
327 | $ cat > .hg/hgrc <<EOF | |
328 | > [hooks] |
|
328 | > [hooks] | |
329 | > pretxnchangegroup.forbid0 = hg tip -q |
|
329 | > pretxnchangegroup.forbid0 = hg tip -q | |
330 | > pretxnchangegroup.forbid1 = sh -c "printenv.py pretxnchangegroup.forbid 1" |
|
330 | > pretxnchangegroup.forbid1 = sh -c "printenv.py pretxnchangegroup.forbid 1" | |
331 | > EOF |
|
331 | > EOF | |
332 | $ hg pull ../a |
|
332 | $ hg pull ../a | |
333 | pulling from ../a |
|
333 | pulling from ../a | |
334 | searching for changes |
|
334 | searching for changes | |
335 | adding changesets |
|
335 | adding changesets | |
336 | adding manifests |
|
336 | adding manifests | |
337 | adding file changes |
|
337 | adding file changes | |
338 | added 1 changesets with 1 changes to 1 files |
|
338 | added 1 changesets with 1 changes to 1 files | |
339 | 4:539e4b31b6dc |
|
339 | 4:539e4b31b6dc | |
340 |
pretxnchangegroup.forbid hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_NODE_LAST=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/b HG_SOURCE=pull HG_TXNID=TXN: |
|
340 | pretxnchangegroup.forbid hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_NODE_LAST=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/b HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a | |
341 | transaction abort! |
|
341 | transaction abort! | |
342 | rollback completed |
|
342 | rollback completed | |
343 | abort: pretxnchangegroup.forbid1 hook exited with status 1 |
|
343 | abort: pretxnchangegroup.forbid1 hook exited with status 1 | |
344 | [255] |
|
344 | [255] | |
345 | $ hg -q tip |
|
345 | $ hg -q tip | |
346 | 3:07f3376c1e65 |
|
346 | 3:07f3376c1e65 | |
347 |
|
347 | |||
348 | outgoing hooks can see env vars |
|
348 | outgoing hooks can see env vars | |
349 |
|
349 | |||
350 | $ rm .hg/hgrc |
|
350 | $ rm .hg/hgrc | |
351 | $ cat > ../a/.hg/hgrc <<EOF |
|
351 | $ cat > ../a/.hg/hgrc <<EOF | |
352 | > [hooks] |
|
352 | > [hooks] | |
353 | > preoutgoing = sh -c "printenv.py preoutgoing" |
|
353 | > preoutgoing = sh -c "printenv.py preoutgoing" | |
354 | > outgoing = sh -c "printenv.py outgoing" |
|
354 | > outgoing = sh -c "printenv.py outgoing" | |
355 | > EOF |
|
355 | > EOF | |
356 | $ hg pull ../a |
|
356 | $ hg pull ../a | |
357 | pulling from ../a |
|
357 | pulling from ../a | |
358 | searching for changes |
|
358 | searching for changes | |
359 | preoutgoing hook: HG_SOURCE=pull |
|
359 | preoutgoing hook: HG_SOURCE=pull | |
360 | outgoing hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_SOURCE=pull |
|
360 | outgoing hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_SOURCE=pull | |
361 | adding changesets |
|
361 | adding changesets | |
362 | adding manifests |
|
362 | adding manifests | |
363 | adding file changes |
|
363 | adding file changes | |
364 | added 1 changesets with 1 changes to 1 files |
|
364 | added 1 changesets with 1 changes to 1 files | |
365 | adding remote bookmark quux |
|
365 | adding remote bookmark quux | |
366 | (run 'hg update' to get a working copy) |
|
366 | (run 'hg update' to get a working copy) | |
367 | $ hg rollback |
|
367 | $ hg rollback | |
368 | repository tip rolled back to revision 3 (undo pull) |
|
368 | repository tip rolled back to revision 3 (undo pull) | |
369 |
|
369 | |||
370 | preoutgoing hook can prevent outgoing changes |
|
370 | preoutgoing hook can prevent outgoing changes | |
371 |
|
371 | |||
372 | $ cat >> ../a/.hg/hgrc <<EOF |
|
372 | $ cat >> ../a/.hg/hgrc <<EOF | |
373 | > preoutgoing.forbid = sh -c "printenv.py preoutgoing.forbid 1" |
|
373 | > preoutgoing.forbid = sh -c "printenv.py preoutgoing.forbid 1" | |
374 | > EOF |
|
374 | > EOF | |
375 | $ hg pull ../a |
|
375 | $ hg pull ../a | |
376 | pulling from ../a |
|
376 | pulling from ../a | |
377 | searching for changes |
|
377 | searching for changes | |
378 | preoutgoing hook: HG_SOURCE=pull |
|
378 | preoutgoing hook: HG_SOURCE=pull | |
379 | preoutgoing.forbid hook: HG_SOURCE=pull |
|
379 | preoutgoing.forbid hook: HG_SOURCE=pull | |
380 | abort: preoutgoing.forbid hook exited with status 1 |
|
380 | abort: preoutgoing.forbid hook exited with status 1 | |
381 | [255] |
|
381 | [255] | |
382 |
|
382 | |||
383 | outgoing hooks work for local clones |
|
383 | outgoing hooks work for local clones | |
384 |
|
384 | |||
385 | $ cd .. |
|
385 | $ cd .. | |
386 | $ cat > a/.hg/hgrc <<EOF |
|
386 | $ cat > a/.hg/hgrc <<EOF | |
387 | > [hooks] |
|
387 | > [hooks] | |
388 | > preoutgoing = sh -c "printenv.py preoutgoing" |
|
388 | > preoutgoing = sh -c "printenv.py preoutgoing" | |
389 | > outgoing = sh -c "printenv.py outgoing" |
|
389 | > outgoing = sh -c "printenv.py outgoing" | |
390 | > EOF |
|
390 | > EOF | |
391 | $ hg clone a c |
|
391 | $ hg clone a c | |
392 | preoutgoing hook: HG_SOURCE=clone |
|
392 | preoutgoing hook: HG_SOURCE=clone | |
393 | outgoing hook: HG_NODE=0000000000000000000000000000000000000000 HG_SOURCE=clone |
|
393 | outgoing hook: HG_NODE=0000000000000000000000000000000000000000 HG_SOURCE=clone | |
394 | updating to branch default |
|
394 | updating to branch default | |
395 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
395 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
396 | $ rm -rf c |
|
396 | $ rm -rf c | |
397 |
|
397 | |||
398 | preoutgoing hook can prevent outgoing changes for local clones |
|
398 | preoutgoing hook can prevent outgoing changes for local clones | |
399 |
|
399 | |||
400 | $ cat >> a/.hg/hgrc <<EOF |
|
400 | $ cat >> a/.hg/hgrc <<EOF | |
401 | > preoutgoing.forbid = sh -c "printenv.py preoutgoing.forbid 1" |
|
401 | > preoutgoing.forbid = sh -c "printenv.py preoutgoing.forbid 1" | |
402 | > EOF |
|
402 | > EOF | |
403 | $ hg clone a zzz |
|
403 | $ hg clone a zzz | |
404 | preoutgoing hook: HG_SOURCE=clone |
|
404 | preoutgoing hook: HG_SOURCE=clone | |
405 | preoutgoing.forbid hook: HG_SOURCE=clone |
|
405 | preoutgoing.forbid hook: HG_SOURCE=clone | |
406 | abort: preoutgoing.forbid hook exited with status 1 |
|
406 | abort: preoutgoing.forbid hook exited with status 1 | |
407 | [255] |
|
407 | [255] | |
408 |
|
408 | |||
409 | $ cd "$TESTTMP/b" |
|
409 | $ cd "$TESTTMP/b" | |
410 |
|
410 | |||
411 | $ cat > hooktests.py <<EOF |
|
411 | $ cat > hooktests.py <<EOF | |
412 | > from mercurial import error |
|
412 | > from mercurial import error | |
413 | > |
|
413 | > | |
414 | > uncallable = 0 |
|
414 | > uncallable = 0 | |
415 | > |
|
415 | > | |
416 | > def printargs(args): |
|
416 | > def printargs(args): | |
417 | > args.pop('ui', None) |
|
417 | > args.pop('ui', None) | |
418 | > args.pop('repo', None) |
|
418 | > args.pop('repo', None) | |
419 | > a = list(args.items()) |
|
419 | > a = list(args.items()) | |
420 | > a.sort() |
|
420 | > a.sort() | |
421 | > print 'hook args:' |
|
421 | > print 'hook args:' | |
422 | > for k, v in a: |
|
422 | > for k, v in a: | |
423 | > print ' ', k, v |
|
423 | > print ' ', k, v | |
424 | > |
|
424 | > | |
425 | > def passhook(**args): |
|
425 | > def passhook(**args): | |
426 | > printargs(args) |
|
426 | > printargs(args) | |
427 | > |
|
427 | > | |
428 | > def failhook(**args): |
|
428 | > def failhook(**args): | |
429 | > printargs(args) |
|
429 | > printargs(args) | |
430 | > return True |
|
430 | > return True | |
431 | > |
|
431 | > | |
432 | > class LocalException(Exception): |
|
432 | > class LocalException(Exception): | |
433 | > pass |
|
433 | > pass | |
434 | > |
|
434 | > | |
435 | > def raisehook(**args): |
|
435 | > def raisehook(**args): | |
436 | > raise LocalException('exception from hook') |
|
436 | > raise LocalException('exception from hook') | |
437 | > |
|
437 | > | |
438 | > def aborthook(**args): |
|
438 | > def aborthook(**args): | |
439 | > raise error.Abort('raise abort from hook') |
|
439 | > raise error.Abort('raise abort from hook') | |
440 | > |
|
440 | > | |
441 | > def brokenhook(**args): |
|
441 | > def brokenhook(**args): | |
442 | > return 1 + {} |
|
442 | > return 1 + {} | |
443 | > |
|
443 | > | |
444 | > def verbosehook(ui, **args): |
|
444 | > def verbosehook(ui, **args): | |
445 | > ui.note('verbose output from hook\n') |
|
445 | > ui.note('verbose output from hook\n') | |
446 | > |
|
446 | > | |
447 | > def printtags(ui, repo, **args): |
|
447 | > def printtags(ui, repo, **args): | |
448 | > print sorted(repo.tags()) |
|
448 | > print sorted(repo.tags()) | |
449 | > |
|
449 | > | |
450 | > class container: |
|
450 | > class container: | |
451 | > unreachable = 1 |
|
451 | > unreachable = 1 | |
452 | > EOF |
|
452 | > EOF | |
453 |
|
453 | |||
454 | $ cat > syntaxerror.py << EOF |
|
454 | $ cat > syntaxerror.py << EOF | |
455 | > (foo |
|
455 | > (foo | |
456 | > EOF |
|
456 | > EOF | |
457 |
|
457 | |||
458 | test python hooks |
|
458 | test python hooks | |
459 |
|
459 | |||
460 | #if windows |
|
460 | #if windows | |
461 | $ PYTHONPATH="$TESTTMP/b;$PYTHONPATH" |
|
461 | $ PYTHONPATH="$TESTTMP/b;$PYTHONPATH" | |
462 | #else |
|
462 | #else | |
463 | $ PYTHONPATH="$TESTTMP/b:$PYTHONPATH" |
|
463 | $ PYTHONPATH="$TESTTMP/b:$PYTHONPATH" | |
464 | #endif |
|
464 | #endif | |
465 | $ export PYTHONPATH |
|
465 | $ export PYTHONPATH | |
466 |
|
466 | |||
467 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
467 | $ echo '[hooks]' > ../a/.hg/hgrc | |
468 | $ echo 'preoutgoing.broken = python:hooktests.brokenhook' >> ../a/.hg/hgrc |
|
468 | $ echo 'preoutgoing.broken = python:hooktests.brokenhook' >> ../a/.hg/hgrc | |
469 | $ hg pull ../a 2>&1 | grep 'raised an exception' |
|
469 | $ hg pull ../a 2>&1 | grep 'raised an exception' | |
470 | error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict' |
|
470 | error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict' | |
471 |
|
471 | |||
472 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
472 | $ echo '[hooks]' > ../a/.hg/hgrc | |
473 | $ echo 'preoutgoing.raise = python:hooktests.raisehook' >> ../a/.hg/hgrc |
|
473 | $ echo 'preoutgoing.raise = python:hooktests.raisehook' >> ../a/.hg/hgrc | |
474 | $ hg pull ../a 2>&1 | grep 'raised an exception' |
|
474 | $ hg pull ../a 2>&1 | grep 'raised an exception' | |
475 | error: preoutgoing.raise hook raised an exception: exception from hook |
|
475 | error: preoutgoing.raise hook raised an exception: exception from hook | |
476 |
|
476 | |||
477 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
477 | $ echo '[hooks]' > ../a/.hg/hgrc | |
478 | $ echo 'preoutgoing.abort = python:hooktests.aborthook' >> ../a/.hg/hgrc |
|
478 | $ echo 'preoutgoing.abort = python:hooktests.aborthook' >> ../a/.hg/hgrc | |
479 | $ hg pull ../a |
|
479 | $ hg pull ../a | |
480 | pulling from ../a |
|
480 | pulling from ../a | |
481 | searching for changes |
|
481 | searching for changes | |
482 | error: preoutgoing.abort hook failed: raise abort from hook |
|
482 | error: preoutgoing.abort hook failed: raise abort from hook | |
483 | abort: raise abort from hook |
|
483 | abort: raise abort from hook | |
484 | [255] |
|
484 | [255] | |
485 |
|
485 | |||
486 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
486 | $ echo '[hooks]' > ../a/.hg/hgrc | |
487 | $ echo 'preoutgoing.fail = python:hooktests.failhook' >> ../a/.hg/hgrc |
|
487 | $ echo 'preoutgoing.fail = python:hooktests.failhook' >> ../a/.hg/hgrc | |
488 | $ hg pull ../a |
|
488 | $ hg pull ../a | |
489 | pulling from ../a |
|
489 | pulling from ../a | |
490 | searching for changes |
|
490 | searching for changes | |
491 | hook args: |
|
491 | hook args: | |
492 | hooktype preoutgoing |
|
492 | hooktype preoutgoing | |
493 | source pull |
|
493 | source pull | |
494 | abort: preoutgoing.fail hook failed |
|
494 | abort: preoutgoing.fail hook failed | |
495 | [255] |
|
495 | [255] | |
496 |
|
496 | |||
497 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
497 | $ echo '[hooks]' > ../a/.hg/hgrc | |
498 | $ echo 'preoutgoing.uncallable = python:hooktests.uncallable' >> ../a/.hg/hgrc |
|
498 | $ echo 'preoutgoing.uncallable = python:hooktests.uncallable' >> ../a/.hg/hgrc | |
499 | $ hg pull ../a |
|
499 | $ hg pull ../a | |
500 | pulling from ../a |
|
500 | pulling from ../a | |
501 | searching for changes |
|
501 | searching for changes | |
502 | abort: preoutgoing.uncallable hook is invalid: "hooktests.uncallable" is not callable |
|
502 | abort: preoutgoing.uncallable hook is invalid: "hooktests.uncallable" is not callable | |
503 | [255] |
|
503 | [255] | |
504 |
|
504 | |||
505 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
505 | $ echo '[hooks]' > ../a/.hg/hgrc | |
506 | $ echo 'preoutgoing.nohook = python:hooktests.nohook' >> ../a/.hg/hgrc |
|
506 | $ echo 'preoutgoing.nohook = python:hooktests.nohook' >> ../a/.hg/hgrc | |
507 | $ hg pull ../a |
|
507 | $ hg pull ../a | |
508 | pulling from ../a |
|
508 | pulling from ../a | |
509 | searching for changes |
|
509 | searching for changes | |
510 | abort: preoutgoing.nohook hook is invalid: "hooktests.nohook" is not defined |
|
510 | abort: preoutgoing.nohook hook is invalid: "hooktests.nohook" is not defined | |
511 | [255] |
|
511 | [255] | |
512 |
|
512 | |||
513 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
513 | $ echo '[hooks]' > ../a/.hg/hgrc | |
514 | $ echo 'preoutgoing.nomodule = python:nomodule' >> ../a/.hg/hgrc |
|
514 | $ echo 'preoutgoing.nomodule = python:nomodule' >> ../a/.hg/hgrc | |
515 | $ hg pull ../a |
|
515 | $ hg pull ../a | |
516 | pulling from ../a |
|
516 | pulling from ../a | |
517 | searching for changes |
|
517 | searching for changes | |
518 | abort: preoutgoing.nomodule hook is invalid: "nomodule" not in a module |
|
518 | abort: preoutgoing.nomodule hook is invalid: "nomodule" not in a module | |
519 | [255] |
|
519 | [255] | |
520 |
|
520 | |||
521 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
521 | $ echo '[hooks]' > ../a/.hg/hgrc | |
522 | $ echo 'preoutgoing.badmodule = python:nomodule.nowhere' >> ../a/.hg/hgrc |
|
522 | $ echo 'preoutgoing.badmodule = python:nomodule.nowhere' >> ../a/.hg/hgrc | |
523 | $ hg pull ../a |
|
523 | $ hg pull ../a | |
524 | pulling from ../a |
|
524 | pulling from ../a | |
525 | searching for changes |
|
525 | searching for changes | |
526 | abort: preoutgoing.badmodule hook is invalid: import of "nomodule" failed |
|
526 | abort: preoutgoing.badmodule hook is invalid: import of "nomodule" failed | |
527 | (run with --traceback for stack trace) |
|
527 | (run with --traceback for stack trace) | |
528 | [255] |
|
528 | [255] | |
529 |
|
529 | |||
530 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
530 | $ echo '[hooks]' > ../a/.hg/hgrc | |
531 | $ echo 'preoutgoing.unreachable = python:hooktests.container.unreachable' >> ../a/.hg/hgrc |
|
531 | $ echo 'preoutgoing.unreachable = python:hooktests.container.unreachable' >> ../a/.hg/hgrc | |
532 | $ hg pull ../a |
|
532 | $ hg pull ../a | |
533 | pulling from ../a |
|
533 | pulling from ../a | |
534 | searching for changes |
|
534 | searching for changes | |
535 | abort: preoutgoing.unreachable hook is invalid: import of "hooktests.container" failed |
|
535 | abort: preoutgoing.unreachable hook is invalid: import of "hooktests.container" failed | |
536 | (run with --traceback for stack trace) |
|
536 | (run with --traceback for stack trace) | |
537 | [255] |
|
537 | [255] | |
538 |
|
538 | |||
539 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
539 | $ echo '[hooks]' > ../a/.hg/hgrc | |
540 | $ echo 'preoutgoing.syntaxerror = python:syntaxerror.syntaxerror' >> ../a/.hg/hgrc |
|
540 | $ echo 'preoutgoing.syntaxerror = python:syntaxerror.syntaxerror' >> ../a/.hg/hgrc | |
541 | $ hg pull ../a |
|
541 | $ hg pull ../a | |
542 | pulling from ../a |
|
542 | pulling from ../a | |
543 | searching for changes |
|
543 | searching for changes | |
544 | abort: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed |
|
544 | abort: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed | |
545 | (run with --traceback for stack trace) |
|
545 | (run with --traceback for stack trace) | |
546 | [255] |
|
546 | [255] | |
547 |
|
547 | |||
548 | The second egrep is to filter out lines like ' ^', which are slightly |
|
548 | The second egrep is to filter out lines like ' ^', which are slightly | |
549 | different between Python 2.6 and Python 2.7. |
|
549 | different between Python 2.6 and Python 2.7. | |
550 | $ hg pull ../a --traceback 2>&1 | egrep -v '^( +File| [_a-zA-Z*(])' | egrep -v '^( )+(\^)?$' |
|
550 | $ hg pull ../a --traceback 2>&1 | egrep -v '^( +File| [_a-zA-Z*(])' | egrep -v '^( )+(\^)?$' | |
551 | pulling from ../a |
|
551 | pulling from ../a | |
552 | searching for changes |
|
552 | searching for changes | |
553 | exception from first failed import attempt: |
|
553 | exception from first failed import attempt: | |
554 | Traceback (most recent call last): |
|
554 | Traceback (most recent call last): | |
555 | SyntaxError: * (glob) |
|
555 | SyntaxError: * (glob) | |
556 | exception from second failed import attempt: |
|
556 | exception from second failed import attempt: | |
557 | Traceback (most recent call last): |
|
557 | Traceback (most recent call last): | |
558 | ImportError: No module named hgext_syntaxerror |
|
558 | ImportError: No module named hgext_syntaxerror | |
559 | Traceback (most recent call last): |
|
559 | Traceback (most recent call last): | |
560 | HookLoadError: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed |
|
560 | HookLoadError: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed | |
561 | abort: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed |
|
561 | abort: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed | |
562 |
|
562 | |||
563 | $ echo '[hooks]' > ../a/.hg/hgrc |
|
563 | $ echo '[hooks]' > ../a/.hg/hgrc | |
564 | $ echo 'preoutgoing.pass = python:hooktests.passhook' >> ../a/.hg/hgrc |
|
564 | $ echo 'preoutgoing.pass = python:hooktests.passhook' >> ../a/.hg/hgrc | |
565 | $ hg pull ../a |
|
565 | $ hg pull ../a | |
566 | pulling from ../a |
|
566 | pulling from ../a | |
567 | searching for changes |
|
567 | searching for changes | |
568 | hook args: |
|
568 | hook args: | |
569 | hooktype preoutgoing |
|
569 | hooktype preoutgoing | |
570 | source pull |
|
570 | source pull | |
571 | adding changesets |
|
571 | adding changesets | |
572 | adding manifests |
|
572 | adding manifests | |
573 | adding file changes |
|
573 | adding file changes | |
574 | added 1 changesets with 1 changes to 1 files |
|
574 | added 1 changesets with 1 changes to 1 files | |
575 | adding remote bookmark quux |
|
575 | adding remote bookmark quux | |
576 | (run 'hg update' to get a working copy) |
|
576 | (run 'hg update' to get a working copy) | |
577 |
|
577 | |||
578 | post- python hooks that fail to *run* don't cause an abort |
|
578 | post- python hooks that fail to *run* don't cause an abort | |
579 | $ rm ../a/.hg/hgrc |
|
579 | $ rm ../a/.hg/hgrc | |
580 | $ echo '[hooks]' > .hg/hgrc |
|
580 | $ echo '[hooks]' > .hg/hgrc | |
581 | $ echo 'post-pull.broken = python:hooktests.brokenhook' >> .hg/hgrc |
|
581 | $ echo 'post-pull.broken = python:hooktests.brokenhook' >> .hg/hgrc | |
582 | $ hg pull ../a |
|
582 | $ hg pull ../a | |
583 | pulling from ../a |
|
583 | pulling from ../a | |
584 | searching for changes |
|
584 | searching for changes | |
585 | no changes found |
|
585 | no changes found | |
586 | error: post-pull.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict' |
|
586 | error: post-pull.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict' | |
587 | (run with --traceback for stack trace) |
|
587 | (run with --traceback for stack trace) | |
588 |
|
588 | |||
589 | but post- python hooks that fail to *load* do |
|
589 | but post- python hooks that fail to *load* do | |
590 | $ echo '[hooks]' > .hg/hgrc |
|
590 | $ echo '[hooks]' > .hg/hgrc | |
591 | $ echo 'post-pull.nomodule = python:nomodule' >> .hg/hgrc |
|
591 | $ echo 'post-pull.nomodule = python:nomodule' >> .hg/hgrc | |
592 | $ hg pull ../a |
|
592 | $ hg pull ../a | |
593 | pulling from ../a |
|
593 | pulling from ../a | |
594 | searching for changes |
|
594 | searching for changes | |
595 | no changes found |
|
595 | no changes found | |
596 | abort: post-pull.nomodule hook is invalid: "nomodule" not in a module |
|
596 | abort: post-pull.nomodule hook is invalid: "nomodule" not in a module | |
597 | [255] |
|
597 | [255] | |
598 |
|
598 | |||
599 | $ echo '[hooks]' > .hg/hgrc |
|
599 | $ echo '[hooks]' > .hg/hgrc | |
600 | $ echo 'post-pull.badmodule = python:nomodule.nowhere' >> .hg/hgrc |
|
600 | $ echo 'post-pull.badmodule = python:nomodule.nowhere' >> .hg/hgrc | |
601 | $ hg pull ../a |
|
601 | $ hg pull ../a | |
602 | pulling from ../a |
|
602 | pulling from ../a | |
603 | searching for changes |
|
603 | searching for changes | |
604 | no changes found |
|
604 | no changes found | |
605 | abort: post-pull.badmodule hook is invalid: import of "nomodule" failed |
|
605 | abort: post-pull.badmodule hook is invalid: import of "nomodule" failed | |
606 | (run with --traceback for stack trace) |
|
606 | (run with --traceback for stack trace) | |
607 | [255] |
|
607 | [255] | |
608 |
|
608 | |||
609 | $ echo '[hooks]' > .hg/hgrc |
|
609 | $ echo '[hooks]' > .hg/hgrc | |
610 | $ echo 'post-pull.nohook = python:hooktests.nohook' >> .hg/hgrc |
|
610 | $ echo 'post-pull.nohook = python:hooktests.nohook' >> .hg/hgrc | |
611 | $ hg pull ../a |
|
611 | $ hg pull ../a | |
612 | pulling from ../a |
|
612 | pulling from ../a | |
613 | searching for changes |
|
613 | searching for changes | |
614 | no changes found |
|
614 | no changes found | |
615 | abort: post-pull.nohook hook is invalid: "hooktests.nohook" is not defined |
|
615 | abort: post-pull.nohook hook is invalid: "hooktests.nohook" is not defined | |
616 | [255] |
|
616 | [255] | |
617 |
|
617 | |||
618 | make sure --traceback works |
|
618 | make sure --traceback works | |
619 |
|
619 | |||
620 | $ echo '[hooks]' > .hg/hgrc |
|
620 | $ echo '[hooks]' > .hg/hgrc | |
621 | $ echo 'commit.abort = python:hooktests.aborthook' >> .hg/hgrc |
|
621 | $ echo 'commit.abort = python:hooktests.aborthook' >> .hg/hgrc | |
622 |
|
622 | |||
623 | $ echo aa > a |
|
623 | $ echo aa > a | |
624 | $ hg --traceback commit -d '0 0' -ma 2>&1 | grep '^Traceback' |
|
624 | $ hg --traceback commit -d '0 0' -ma 2>&1 | grep '^Traceback' | |
625 | Traceback (most recent call last): |
|
625 | Traceback (most recent call last): | |
626 |
|
626 | |||
627 | $ cd .. |
|
627 | $ cd .. | |
628 | $ hg init c |
|
628 | $ hg init c | |
629 | $ cd c |
|
629 | $ cd c | |
630 |
|
630 | |||
631 | $ cat > hookext.py <<EOF |
|
631 | $ cat > hookext.py <<EOF | |
632 | > def autohook(**args): |
|
632 | > def autohook(**args): | |
633 | > print "Automatically installed hook" |
|
633 | > print "Automatically installed hook" | |
634 | > |
|
634 | > | |
635 | > def reposetup(ui, repo): |
|
635 | > def reposetup(ui, repo): | |
636 | > repo.ui.setconfig("hooks", "commit.auto", autohook) |
|
636 | > repo.ui.setconfig("hooks", "commit.auto", autohook) | |
637 | > EOF |
|
637 | > EOF | |
638 | $ echo '[extensions]' >> .hg/hgrc |
|
638 | $ echo '[extensions]' >> .hg/hgrc | |
639 | $ echo 'hookext = hookext.py' >> .hg/hgrc |
|
639 | $ echo 'hookext = hookext.py' >> .hg/hgrc | |
640 |
|
640 | |||
641 | $ touch foo |
|
641 | $ touch foo | |
642 | $ hg add foo |
|
642 | $ hg add foo | |
643 | $ hg ci -d '0 0' -m 'add foo' |
|
643 | $ hg ci -d '0 0' -m 'add foo' | |
644 | Automatically installed hook |
|
644 | Automatically installed hook | |
645 | $ echo >> foo |
|
645 | $ echo >> foo | |
646 | $ hg ci --debug -d '0 0' -m 'change foo' |
|
646 | $ hg ci --debug -d '0 0' -m 'change foo' | |
647 | committing files: |
|
647 | committing files: | |
648 | foo |
|
648 | foo | |
649 | committing manifest |
|
649 | committing manifest | |
650 | committing changelog |
|
650 | committing changelog | |
651 | committed changeset 1:52998019f6252a2b893452765fcb0a47351a5708 |
|
651 | committed changeset 1:52998019f6252a2b893452765fcb0a47351a5708 | |
652 | calling hook commit.auto: hgext_hookext.autohook |
|
652 | calling hook commit.auto: hgext_hookext.autohook | |
653 | Automatically installed hook |
|
653 | Automatically installed hook | |
654 |
|
654 | |||
655 | $ hg showconfig hooks |
|
655 | $ hg showconfig hooks | |
656 | hooks.commit.auto=<function autohook at *> (glob) |
|
656 | hooks.commit.auto=<function autohook at *> (glob) | |
657 |
|
657 | |||
658 | test python hook configured with python:[file]:[hook] syntax |
|
658 | test python hook configured with python:[file]:[hook] syntax | |
659 |
|
659 | |||
660 | $ cd .. |
|
660 | $ cd .. | |
661 | $ mkdir d |
|
661 | $ mkdir d | |
662 | $ cd d |
|
662 | $ cd d | |
663 | $ hg init repo |
|
663 | $ hg init repo | |
664 | $ mkdir hooks |
|
664 | $ mkdir hooks | |
665 |
|
665 | |||
666 | $ cd hooks |
|
666 | $ cd hooks | |
667 | $ cat > testhooks.py <<EOF |
|
667 | $ cat > testhooks.py <<EOF | |
668 | > def testhook(**args): |
|
668 | > def testhook(**args): | |
669 | > print 'hook works' |
|
669 | > print 'hook works' | |
670 | > EOF |
|
670 | > EOF | |
671 | $ echo '[hooks]' > ../repo/.hg/hgrc |
|
671 | $ echo '[hooks]' > ../repo/.hg/hgrc | |
672 | $ echo "pre-commit.test = python:`pwd`/testhooks.py:testhook" >> ../repo/.hg/hgrc |
|
672 | $ echo "pre-commit.test = python:`pwd`/testhooks.py:testhook" >> ../repo/.hg/hgrc | |
673 |
|
673 | |||
674 | $ cd ../repo |
|
674 | $ cd ../repo | |
675 | $ hg commit -d '0 0' |
|
675 | $ hg commit -d '0 0' | |
676 | hook works |
|
676 | hook works | |
677 | nothing changed |
|
677 | nothing changed | |
678 | [1] |
|
678 | [1] | |
679 |
|
679 | |||
680 | $ echo '[hooks]' > .hg/hgrc |
|
680 | $ echo '[hooks]' > .hg/hgrc | |
681 | $ echo "update.ne = python:`pwd`/nonexistent.py:testhook" >> .hg/hgrc |
|
681 | $ echo "update.ne = python:`pwd`/nonexistent.py:testhook" >> .hg/hgrc | |
682 | $ echo "pre-identify.npmd = python:`pwd`/:no_python_module_dir" >> .hg/hgrc |
|
682 | $ echo "pre-identify.npmd = python:`pwd`/:no_python_module_dir" >> .hg/hgrc | |
683 |
|
683 | |||
684 | $ hg up null |
|
684 | $ hg up null | |
685 | loading update.ne hook failed: |
|
685 | loading update.ne hook failed: | |
686 | abort: No such file or directory: $TESTTMP/d/repo/nonexistent.py |
|
686 | abort: No such file or directory: $TESTTMP/d/repo/nonexistent.py | |
687 | [255] |
|
687 | [255] | |
688 |
|
688 | |||
689 | $ hg id |
|
689 | $ hg id | |
690 | loading pre-identify.npmd hook failed: |
|
690 | loading pre-identify.npmd hook failed: | |
691 | abort: No module named repo! |
|
691 | abort: No module named repo! | |
692 | [255] |
|
692 | [255] | |
693 |
|
693 | |||
694 | $ cd ../../b |
|
694 | $ cd ../../b | |
695 |
|
695 | |||
696 | make sure --traceback works on hook import failure |
|
696 | make sure --traceback works on hook import failure | |
697 |
|
697 | |||
698 | $ cat > importfail.py <<EOF |
|
698 | $ cat > importfail.py <<EOF | |
699 | > import somebogusmodule |
|
699 | > import somebogusmodule | |
700 | > # dereference something in the module to force demandimport to load it |
|
700 | > # dereference something in the module to force demandimport to load it | |
701 | > somebogusmodule.whatever |
|
701 | > somebogusmodule.whatever | |
702 | > EOF |
|
702 | > EOF | |
703 |
|
703 | |||
704 | $ echo '[hooks]' > .hg/hgrc |
|
704 | $ echo '[hooks]' > .hg/hgrc | |
705 | $ echo 'precommit.importfail = python:importfail.whatever' >> .hg/hgrc |
|
705 | $ echo 'precommit.importfail = python:importfail.whatever' >> .hg/hgrc | |
706 |
|
706 | |||
707 | $ echo a >> a |
|
707 | $ echo a >> a | |
708 | $ hg --traceback commit -ma 2>&1 | egrep -v '^( +File| [a-zA-Z(])' |
|
708 | $ hg --traceback commit -ma 2>&1 | egrep -v '^( +File| [a-zA-Z(])' | |
709 | exception from first failed import attempt: |
|
709 | exception from first failed import attempt: | |
710 | Traceback (most recent call last): |
|
710 | Traceback (most recent call last): | |
711 | ImportError: No module named somebogusmodule |
|
711 | ImportError: No module named somebogusmodule | |
712 | exception from second failed import attempt: |
|
712 | exception from second failed import attempt: | |
713 | Traceback (most recent call last): |
|
713 | Traceback (most recent call last): | |
714 | ImportError: No module named hgext_importfail |
|
714 | ImportError: No module named hgext_importfail | |
715 | Traceback (most recent call last): |
|
715 | Traceback (most recent call last): | |
716 | HookLoadError: precommit.importfail hook is invalid: import of "importfail" failed |
|
716 | HookLoadError: precommit.importfail hook is invalid: import of "importfail" failed | |
717 | abort: precommit.importfail hook is invalid: import of "importfail" failed |
|
717 | abort: precommit.importfail hook is invalid: import of "importfail" failed | |
718 |
|
718 | |||
719 | Issue1827: Hooks Update & Commit not completely post operation |
|
719 | Issue1827: Hooks Update & Commit not completely post operation | |
720 |
|
720 | |||
721 | commit and update hooks should run after command completion. The largefiles |
|
721 | commit and update hooks should run after command completion. The largefiles | |
722 | use demonstrates a recursive wlock, showing the hook doesn't run until the |
|
722 | use demonstrates a recursive wlock, showing the hook doesn't run until the | |
723 | final release (and dirstate flush). |
|
723 | final release (and dirstate flush). | |
724 |
|
724 | |||
725 | $ echo '[hooks]' > .hg/hgrc |
|
725 | $ echo '[hooks]' > .hg/hgrc | |
726 | $ echo 'commit = hg id' >> .hg/hgrc |
|
726 | $ echo 'commit = hg id' >> .hg/hgrc | |
727 | $ echo 'update = hg id' >> .hg/hgrc |
|
727 | $ echo 'update = hg id' >> .hg/hgrc | |
728 | $ echo bb > a |
|
728 | $ echo bb > a | |
729 | $ hg ci -ma |
|
729 | $ hg ci -ma | |
730 | 223eafe2750c tip |
|
730 | 223eafe2750c tip | |
731 | $ hg up 0 --config extensions.largefiles= |
|
731 | $ hg up 0 --config extensions.largefiles= | |
732 | cb9a9f314b8b |
|
732 | cb9a9f314b8b | |
733 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
733 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
734 |
|
734 | |||
735 | make sure --verbose (and --quiet/--debug etc.) are propagated to the local ui |
|
735 | make sure --verbose (and --quiet/--debug etc.) are propagated to the local ui | |
736 | that is passed to pre/post hooks |
|
736 | that is passed to pre/post hooks | |
737 |
|
737 | |||
738 | $ echo '[hooks]' > .hg/hgrc |
|
738 | $ echo '[hooks]' > .hg/hgrc | |
739 | $ echo 'pre-identify = python:hooktests.verbosehook' >> .hg/hgrc |
|
739 | $ echo 'pre-identify = python:hooktests.verbosehook' >> .hg/hgrc | |
740 | $ hg id |
|
740 | $ hg id | |
741 | cb9a9f314b8b |
|
741 | cb9a9f314b8b | |
742 | $ hg id --verbose |
|
742 | $ hg id --verbose | |
743 | calling hook pre-identify: hooktests.verbosehook |
|
743 | calling hook pre-identify: hooktests.verbosehook | |
744 | verbose output from hook |
|
744 | verbose output from hook | |
745 | cb9a9f314b8b |
|
745 | cb9a9f314b8b | |
746 |
|
746 | |||
747 | Ensure hooks can be prioritized |
|
747 | Ensure hooks can be prioritized | |
748 |
|
748 | |||
749 | $ echo '[hooks]' > .hg/hgrc |
|
749 | $ echo '[hooks]' > .hg/hgrc | |
750 | $ echo 'pre-identify.a = python:hooktests.verbosehook' >> .hg/hgrc |
|
750 | $ echo 'pre-identify.a = python:hooktests.verbosehook' >> .hg/hgrc | |
751 | $ echo 'pre-identify.b = python:hooktests.verbosehook' >> .hg/hgrc |
|
751 | $ echo 'pre-identify.b = python:hooktests.verbosehook' >> .hg/hgrc | |
752 | $ echo 'priority.pre-identify.b = 1' >> .hg/hgrc |
|
752 | $ echo 'priority.pre-identify.b = 1' >> .hg/hgrc | |
753 | $ echo 'pre-identify.c = python:hooktests.verbosehook' >> .hg/hgrc |
|
753 | $ echo 'pre-identify.c = python:hooktests.verbosehook' >> .hg/hgrc | |
754 | $ hg id --verbose |
|
754 | $ hg id --verbose | |
755 | calling hook pre-identify.b: hooktests.verbosehook |
|
755 | calling hook pre-identify.b: hooktests.verbosehook | |
756 | verbose output from hook |
|
756 | verbose output from hook | |
757 | calling hook pre-identify.a: hooktests.verbosehook |
|
757 | calling hook pre-identify.a: hooktests.verbosehook | |
758 | verbose output from hook |
|
758 | verbose output from hook | |
759 | calling hook pre-identify.c: hooktests.verbosehook |
|
759 | calling hook pre-identify.c: hooktests.verbosehook | |
760 | verbose output from hook |
|
760 | verbose output from hook | |
761 | cb9a9f314b8b |
|
761 | cb9a9f314b8b | |
762 |
|
762 | |||
763 | new tags must be visible in pretxncommit (issue3210) |
|
763 | new tags must be visible in pretxncommit (issue3210) | |
764 |
|
764 | |||
765 | $ echo 'pretxncommit.printtags = python:hooktests.printtags' >> .hg/hgrc |
|
765 | $ echo 'pretxncommit.printtags = python:hooktests.printtags' >> .hg/hgrc | |
766 | $ hg tag -f foo |
|
766 | $ hg tag -f foo | |
767 | ['a', 'foo', 'tip'] |
|
767 | ['a', 'foo', 'tip'] | |
768 |
|
768 | |||
769 | post-init hooks must not crash (issue4983) |
|
769 | post-init hooks must not crash (issue4983) | |
770 | This also creates the `to` repo for the next test block. |
|
770 | This also creates the `to` repo for the next test block. | |
771 |
|
771 | |||
772 | $ cd .. |
|
772 | $ cd .. | |
773 | $ cat << EOF >> hgrc-with-post-init-hook |
|
773 | $ cat << EOF >> hgrc-with-post-init-hook | |
774 | > [hooks] |
|
774 | > [hooks] | |
775 | > post-init = sh -c "printenv.py post-init" |
|
775 | > post-init = sh -c "printenv.py post-init" | |
776 | > EOF |
|
776 | > EOF | |
777 | $ HGRCPATH=hgrc-with-post-init-hook hg init to |
|
777 | $ HGRCPATH=hgrc-with-post-init-hook hg init to | |
778 | post-init hook: HG_ARGS=init to HG_OPTS={'insecure': None, 'remotecmd': '', 'ssh': ''} HG_PATS=['to'] HG_RESULT=0 |
|
778 | post-init hook: HG_ARGS=init to HG_OPTS={'insecure': None, 'remotecmd': '', 'ssh': ''} HG_PATS=['to'] HG_RESULT=0 | |
779 |
|
779 | |||
780 | new commits must be visible in pretxnchangegroup (issue3428) |
|
780 | new commits must be visible in pretxnchangegroup (issue3428) | |
781 |
|
781 | |||
782 | $ echo '[hooks]' >> to/.hg/hgrc |
|
782 | $ echo '[hooks]' >> to/.hg/hgrc | |
783 | $ echo 'prechangegroup = hg --traceback tip' >> to/.hg/hgrc |
|
783 | $ echo 'prechangegroup = hg --traceback tip' >> to/.hg/hgrc | |
784 | $ echo 'pretxnchangegroup = hg --traceback tip' >> to/.hg/hgrc |
|
784 | $ echo 'pretxnchangegroup = hg --traceback tip' >> to/.hg/hgrc | |
785 | $ echo a >> to/a |
|
785 | $ echo a >> to/a | |
786 | $ hg --cwd to ci -Ama |
|
786 | $ hg --cwd to ci -Ama | |
787 | adding a |
|
787 | adding a | |
788 | $ hg clone to from |
|
788 | $ hg clone to from | |
789 | updating to branch default |
|
789 | updating to branch default | |
790 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
790 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
791 | $ echo aa >> from/a |
|
791 | $ echo aa >> from/a | |
792 | $ hg --cwd from ci -mb |
|
792 | $ hg --cwd from ci -mb | |
793 | $ hg --cwd from push |
|
793 | $ hg --cwd from push | |
794 | pushing to $TESTTMP/to (glob) |
|
794 | pushing to $TESTTMP/to (glob) | |
795 | searching for changes |
|
795 | searching for changes | |
796 | changeset: 0:cb9a9f314b8b |
|
796 | changeset: 0:cb9a9f314b8b | |
797 | tag: tip |
|
797 | tag: tip | |
798 | user: test |
|
798 | user: test | |
799 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
799 | date: Thu Jan 01 00:00:00 1970 +0000 | |
800 | summary: a |
|
800 | summary: a | |
801 |
|
801 | |||
802 | adding changesets |
|
802 | adding changesets | |
803 | adding manifests |
|
803 | adding manifests | |
804 | adding file changes |
|
804 | adding file changes | |
805 | added 1 changesets with 1 changes to 1 files |
|
805 | added 1 changesets with 1 changes to 1 files | |
806 | changeset: 1:9836a07b9b9d |
|
806 | changeset: 1:9836a07b9b9d | |
807 | tag: tip |
|
807 | tag: tip | |
808 | user: test |
|
808 | user: test | |
809 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
809 | date: Thu Jan 01 00:00:00 1970 +0000 | |
810 | summary: b |
|
810 | summary: b | |
811 |
|
811 | |||
812 |
|
812 | |||
813 | pretxnclose hook failure should abort the transaction |
|
813 | pretxnclose hook failure should abort the transaction | |
814 |
|
814 | |||
815 | $ hg init txnfailure |
|
815 | $ hg init txnfailure | |
816 | $ cd txnfailure |
|
816 | $ cd txnfailure | |
817 | $ touch a && hg commit -Aqm a |
|
817 | $ touch a && hg commit -Aqm a | |
818 | $ cat >> .hg/hgrc <<EOF |
|
818 | $ cat >> .hg/hgrc <<EOF | |
819 | > [hooks] |
|
819 | > [hooks] | |
820 | > pretxnclose.error = exit 1 |
|
820 | > pretxnclose.error = exit 1 | |
821 | > EOF |
|
821 | > EOF | |
822 | $ hg strip -r 0 --config extensions.strip= |
|
822 | $ hg strip -r 0 --config extensions.strip= | |
823 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
|
823 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved | |
824 | saved backup bundle to * (glob) |
|
824 | saved backup bundle to * (glob) | |
825 | transaction abort! |
|
825 | transaction abort! | |
826 | rollback completed |
|
826 | rollback completed | |
827 | strip failed, backup bundle stored in * (glob) |
|
827 | strip failed, backup bundle stored in * (glob) | |
828 | abort: pretxnclose.error hook exited with status 1 |
|
828 | abort: pretxnclose.error hook exited with status 1 | |
829 | [255] |
|
829 | [255] | |
830 | $ hg recover |
|
830 | $ hg recover | |
831 | no interrupted transaction available |
|
831 | no interrupted transaction available | |
832 | [1] |
|
832 | [1] | |
833 | $ cd .. |
|
833 | $ cd .. | |
834 |
|
834 | |||
835 | check whether HG_PENDING makes pending changes only in related |
|
835 | check whether HG_PENDING makes pending changes only in related | |
836 | repositories visible to an external hook. |
|
836 | repositories visible to an external hook. | |
837 |
|
837 | |||
838 | (emulate a transaction running concurrently by copied |
|
838 | (emulate a transaction running concurrently by copied | |
839 | .hg/store/00changelog.i.a in subsequent test) |
|
839 | .hg/store/00changelog.i.a in subsequent test) | |
840 |
|
840 | |||
841 | $ cat > $TESTTMP/savepending.sh <<EOF |
|
841 | $ cat > $TESTTMP/savepending.sh <<EOF | |
842 | > cp .hg/store/00changelog.i.a .hg/store/00changelog.i.a.saved |
|
842 | > cp .hg/store/00changelog.i.a .hg/store/00changelog.i.a.saved | |
843 | > exit 1 # to avoid adding new revision for subsequent tests |
|
843 | > exit 1 # to avoid adding new revision for subsequent tests | |
844 | > EOF |
|
844 | > EOF | |
845 | $ cd a |
|
845 | $ cd a | |
846 | $ hg tip -q |
|
846 | $ hg tip -q | |
847 | 4:539e4b31b6dc |
|
847 | 4:539e4b31b6dc | |
848 | $ hg --config hooks.pretxnclose="sh $TESTTMP/savepending.sh" commit -m "invisible" |
|
848 | $ hg --config hooks.pretxnclose="sh $TESTTMP/savepending.sh" commit -m "invisible" | |
849 | transaction abort! |
|
849 | transaction abort! | |
850 | rollback completed |
|
850 | rollback completed | |
851 | abort: pretxnclose hook exited with status 1 |
|
851 | abort: pretxnclose hook exited with status 1 | |
852 | [255] |
|
852 | [255] | |
853 | $ cp .hg/store/00changelog.i.a.saved .hg/store/00changelog.i.a |
|
853 | $ cp .hg/store/00changelog.i.a.saved .hg/store/00changelog.i.a | |
854 |
|
854 | |||
855 | (check (in)visibility of new changeset while transaction running in |
|
855 | (check (in)visibility of new changeset while transaction running in | |
856 | repo) |
|
856 | repo) | |
857 |
|
857 | |||
858 | $ cat > $TESTTMP/checkpending.sh <<EOF |
|
858 | $ cat > $TESTTMP/checkpending.sh <<EOF | |
859 | > echo '@a' |
|
859 | > echo '@a' | |
860 | > hg -R $TESTTMP/a tip -q |
|
860 | > hg -R $TESTTMP/a tip -q | |
861 | > echo '@a/nested' |
|
861 | > echo '@a/nested' | |
862 | > hg -R $TESTTMP/a/nested tip -q |
|
862 | > hg -R $TESTTMP/a/nested tip -q | |
863 | > exit 1 # to avoid adding new revision for subsequent tests |
|
863 | > exit 1 # to avoid adding new revision for subsequent tests | |
864 | > EOF |
|
864 | > EOF | |
865 | $ hg init nested |
|
865 | $ hg init nested | |
866 | $ cd nested |
|
866 | $ cd nested | |
867 | $ echo a > a |
|
867 | $ echo a > a | |
868 | $ hg add a |
|
868 | $ hg add a | |
869 | $ hg --config hooks.pretxnclose="sh $TESTTMP/checkpending.sh" commit -m '#0' |
|
869 | $ hg --config hooks.pretxnclose="sh $TESTTMP/checkpending.sh" commit -m '#0' | |
870 | @a |
|
870 | @a | |
871 | 4:539e4b31b6dc |
|
871 | 4:539e4b31b6dc | |
872 | @a/nested |
|
872 | @a/nested | |
873 | 0:bf5e395ced2c |
|
873 | 0:bf5e395ced2c | |
874 | transaction abort! |
|
874 | transaction abort! | |
875 | rollback completed |
|
875 | rollback completed | |
876 | abort: pretxnclose hook exited with status 1 |
|
876 | abort: pretxnclose hook exited with status 1 | |
877 | [255] |
|
877 | [255] | |
878 |
|
878 | |||
879 | Hook from untrusted hgrc are reported as failure |
|
879 | Hook from untrusted hgrc are reported as failure | |
880 | ================================================ |
|
880 | ================================================ | |
881 |
|
881 | |||
882 | $ cat << EOF > $TESTTMP/untrusted.py |
|
882 | $ cat << EOF > $TESTTMP/untrusted.py | |
883 | > from mercurial import scmutil, util |
|
883 | > from mercurial import scmutil, util | |
884 | > def uisetup(ui): |
|
884 | > def uisetup(ui): | |
885 | > class untrustedui(ui.__class__): |
|
885 | > class untrustedui(ui.__class__): | |
886 | > def _trusted(self, fp, f): |
|
886 | > def _trusted(self, fp, f): | |
887 | > if util.normpath(fp.name).endswith('untrusted/.hg/hgrc'): |
|
887 | > if util.normpath(fp.name).endswith('untrusted/.hg/hgrc'): | |
888 | > return False |
|
888 | > return False | |
889 | > return super(untrustedui, self)._trusted(fp, f) |
|
889 | > return super(untrustedui, self)._trusted(fp, f) | |
890 | > ui.__class__ = untrustedui |
|
890 | > ui.__class__ = untrustedui | |
891 | > EOF |
|
891 | > EOF | |
892 | $ cat << EOF >> $HGRCPATH |
|
892 | $ cat << EOF >> $HGRCPATH | |
893 | > [extensions] |
|
893 | > [extensions] | |
894 | > untrusted=$TESTTMP/untrusted.py |
|
894 | > untrusted=$TESTTMP/untrusted.py | |
895 | > EOF |
|
895 | > EOF | |
896 | $ hg init untrusted |
|
896 | $ hg init untrusted | |
897 | $ cd untrusted |
|
897 | $ cd untrusted | |
898 |
|
898 | |||
899 | Non-blocking hook |
|
899 | Non-blocking hook | |
900 | ----------------- |
|
900 | ----------------- | |
901 |
|
901 | |||
902 | $ cat << EOF >> .hg/hgrc |
|
902 | $ cat << EOF >> .hg/hgrc | |
903 | > [hooks] |
|
903 | > [hooks] | |
904 | > txnclose.testing=echo txnclose hook called |
|
904 | > txnclose.testing=echo txnclose hook called | |
905 | > EOF |
|
905 | > EOF | |
906 | $ touch a && hg commit -Aqm a |
|
906 | $ touch a && hg commit -Aqm a | |
907 | warning: untrusted hook txnclose not executed |
|
907 | warning: untrusted hook txnclose not executed | |
908 | $ hg log |
|
908 | $ hg log | |
909 | changeset: 0:3903775176ed |
|
909 | changeset: 0:3903775176ed | |
910 | tag: tip |
|
910 | tag: tip | |
911 | user: test |
|
911 | user: test | |
912 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
912 | date: Thu Jan 01 00:00:00 1970 +0000 | |
913 | summary: a |
|
913 | summary: a | |
914 |
|
914 | |||
915 |
|
915 | |||
916 | Non-blocking hook |
|
916 | Non-blocking hook | |
917 | ----------------- |
|
917 | ----------------- | |
918 |
|
918 | |||
919 | $ cat << EOF >> .hg/hgrc |
|
919 | $ cat << EOF >> .hg/hgrc | |
920 | > [hooks] |
|
920 | > [hooks] | |
921 | > pretxnclose.testing=echo pre-txnclose hook called |
|
921 | > pretxnclose.testing=echo pre-txnclose hook called | |
922 | > EOF |
|
922 | > EOF | |
923 | $ touch b && hg commit -Aqm a |
|
923 | $ touch b && hg commit -Aqm a | |
924 | transaction abort! |
|
924 | transaction abort! | |
925 | rollback completed |
|
925 | rollback completed | |
926 | abort: untrusted hook pretxnclose not executed |
|
926 | abort: untrusted hook pretxnclose not executed | |
927 | (see 'hg help config.trusted') |
|
927 | (see 'hg help config.trusted') | |
928 | [255] |
|
928 | [255] | |
929 | $ hg log |
|
929 | $ hg log | |
930 | changeset: 0:3903775176ed |
|
930 | changeset: 0:3903775176ed | |
931 | tag: tip |
|
931 | tag: tip | |
932 | user: test |
|
932 | user: test | |
933 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
933 | date: Thu Jan 01 00:00:00 1970 +0000 | |
934 | summary: a |
|
934 | summary: a | |
935 |
|
935 |
@@ -1,347 +1,347 b'' | |||||
1 | #require serve |
|
1 | #require serve | |
2 |
|
2 | |||
3 | This test is a duplicate of 'test-http.t', feel free to factor out |
|
3 | This test is a duplicate of 'test-http.t', feel free to factor out | |
4 | parts that are not bundle1/bundle2 specific. |
|
4 | parts that are not bundle1/bundle2 specific. | |
5 |
|
5 | |||
6 | $ cat << EOF >> $HGRCPATH |
|
6 | $ cat << EOF >> $HGRCPATH | |
7 | > [devel] |
|
7 | > [devel] | |
8 | > # This test is dedicated to interaction through old bundle |
|
8 | > # This test is dedicated to interaction through old bundle | |
9 | > legacy.exchange = bundle1 |
|
9 | > legacy.exchange = bundle1 | |
10 | > EOF |
|
10 | > EOF | |
11 |
|
11 | |||
12 | $ hg init test |
|
12 | $ hg init test | |
13 | $ cd test |
|
13 | $ cd test | |
14 | $ echo foo>foo |
|
14 | $ echo foo>foo | |
15 | $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg |
|
15 | $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg | |
16 | $ echo foo>foo.d/foo |
|
16 | $ echo foo>foo.d/foo | |
17 | $ echo bar>foo.d/bAr.hg.d/BaR |
|
17 | $ echo bar>foo.d/bAr.hg.d/BaR | |
18 | $ echo bar>foo.d/baR.d.hg/bAR |
|
18 | $ echo bar>foo.d/baR.d.hg/bAR | |
19 | $ hg commit -A -m 1 |
|
19 | $ hg commit -A -m 1 | |
20 | adding foo |
|
20 | adding foo | |
21 | adding foo.d/bAr.hg.d/BaR |
|
21 | adding foo.d/bAr.hg.d/BaR | |
22 | adding foo.d/baR.d.hg/bAR |
|
22 | adding foo.d/baR.d.hg/bAR | |
23 | adding foo.d/foo |
|
23 | adding foo.d/foo | |
24 | $ hg serve -p $HGPORT -d --pid-file=../hg1.pid -E ../error.log |
|
24 | $ hg serve -p $HGPORT -d --pid-file=../hg1.pid -E ../error.log | |
25 | $ hg serve --config server.uncompressed=False -p $HGPORT1 -d --pid-file=../hg2.pid |
|
25 | $ hg serve --config server.uncompressed=False -p $HGPORT1 -d --pid-file=../hg2.pid | |
26 |
|
26 | |||
27 | Test server address cannot be reused |
|
27 | Test server address cannot be reused | |
28 |
|
28 | |||
29 | #if windows |
|
29 | #if windows | |
30 | $ hg serve -p $HGPORT1 2>&1 |
|
30 | $ hg serve -p $HGPORT1 2>&1 | |
31 | abort: cannot start server at 'localhost:$HGPORT1': * (glob) |
|
31 | abort: cannot start server at 'localhost:$HGPORT1': * (glob) | |
32 | [255] |
|
32 | [255] | |
33 | #else |
|
33 | #else | |
34 | $ hg serve -p $HGPORT1 2>&1 |
|
34 | $ hg serve -p $HGPORT1 2>&1 | |
35 | abort: cannot start server at 'localhost:$HGPORT1': Address already in use |
|
35 | abort: cannot start server at 'localhost:$HGPORT1': Address already in use | |
36 | [255] |
|
36 | [255] | |
37 | #endif |
|
37 | #endif | |
38 | $ cd .. |
|
38 | $ cd .. | |
39 | $ cat hg1.pid hg2.pid >> $DAEMON_PIDS |
|
39 | $ cat hg1.pid hg2.pid >> $DAEMON_PIDS | |
40 |
|
40 | |||
41 | clone via stream |
|
41 | clone via stream | |
42 |
|
42 | |||
43 | $ hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1 |
|
43 | $ hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1 | |
44 | streaming all changes |
|
44 | streaming all changes | |
45 | 6 files to transfer, 606 bytes of data |
|
45 | 6 files to transfer, 606 bytes of data | |
46 | transferred * bytes in * seconds (*/sec) (glob) |
|
46 | transferred * bytes in * seconds (*/sec) (glob) | |
47 | searching for changes |
|
47 | searching for changes | |
48 | no changes found |
|
48 | no changes found | |
49 | updating to branch default |
|
49 | updating to branch default | |
50 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
50 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
51 | $ hg verify -R copy |
|
51 | $ hg verify -R copy | |
52 | checking changesets |
|
52 | checking changesets | |
53 | checking manifests |
|
53 | checking manifests | |
54 | crosschecking files in changesets and manifests |
|
54 | crosschecking files in changesets and manifests | |
55 | checking files |
|
55 | checking files | |
56 | 4 files, 1 changesets, 4 total revisions |
|
56 | 4 files, 1 changesets, 4 total revisions | |
57 |
|
57 | |||
58 | try to clone via stream, should use pull instead |
|
58 | try to clone via stream, should use pull instead | |
59 |
|
59 | |||
60 | $ hg clone --uncompressed http://localhost:$HGPORT1/ copy2 |
|
60 | $ hg clone --uncompressed http://localhost:$HGPORT1/ copy2 | |
61 | requesting all changes |
|
61 | requesting all changes | |
62 | adding changesets |
|
62 | adding changesets | |
63 | adding manifests |
|
63 | adding manifests | |
64 | adding file changes |
|
64 | adding file changes | |
65 | added 1 changesets with 4 changes to 4 files |
|
65 | added 1 changesets with 4 changes to 4 files | |
66 | updating to branch default |
|
66 | updating to branch default | |
67 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
67 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
68 |
|
68 | |||
69 | clone via pull |
|
69 | clone via pull | |
70 |
|
70 | |||
71 | $ hg clone http://localhost:$HGPORT1/ copy-pull |
|
71 | $ hg clone http://localhost:$HGPORT1/ copy-pull | |
72 | requesting all changes |
|
72 | requesting all changes | |
73 | adding changesets |
|
73 | adding changesets | |
74 | adding manifests |
|
74 | adding manifests | |
75 | adding file changes |
|
75 | adding file changes | |
76 | added 1 changesets with 4 changes to 4 files |
|
76 | added 1 changesets with 4 changes to 4 files | |
77 | updating to branch default |
|
77 | updating to branch default | |
78 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
78 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
79 | $ hg verify -R copy-pull |
|
79 | $ hg verify -R copy-pull | |
80 | checking changesets |
|
80 | checking changesets | |
81 | checking manifests |
|
81 | checking manifests | |
82 | crosschecking files in changesets and manifests |
|
82 | crosschecking files in changesets and manifests | |
83 | checking files |
|
83 | checking files | |
84 | 4 files, 1 changesets, 4 total revisions |
|
84 | 4 files, 1 changesets, 4 total revisions | |
85 | $ cd test |
|
85 | $ cd test | |
86 | $ echo bar > bar |
|
86 | $ echo bar > bar | |
87 | $ hg commit -A -d '1 0' -m 2 |
|
87 | $ hg commit -A -d '1 0' -m 2 | |
88 | adding bar |
|
88 | adding bar | |
89 | $ cd .. |
|
89 | $ cd .. | |
90 |
|
90 | |||
91 | clone over http with --update |
|
91 | clone over http with --update | |
92 |
|
92 | |||
93 | $ hg clone http://localhost:$HGPORT1/ updated --update 0 |
|
93 | $ hg clone http://localhost:$HGPORT1/ updated --update 0 | |
94 | requesting all changes |
|
94 | requesting all changes | |
95 | adding changesets |
|
95 | adding changesets | |
96 | adding manifests |
|
96 | adding manifests | |
97 | adding file changes |
|
97 | adding file changes | |
98 | added 2 changesets with 5 changes to 5 files |
|
98 | added 2 changesets with 5 changes to 5 files | |
99 | updating to branch default |
|
99 | updating to branch default | |
100 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
100 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
101 | $ hg log -r . -R updated |
|
101 | $ hg log -r . -R updated | |
102 | changeset: 0:8b6053c928fe |
|
102 | changeset: 0:8b6053c928fe | |
103 | user: test |
|
103 | user: test | |
104 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
104 | date: Thu Jan 01 00:00:00 1970 +0000 | |
105 | summary: 1 |
|
105 | summary: 1 | |
106 |
|
106 | |||
107 | $ rm -rf updated |
|
107 | $ rm -rf updated | |
108 |
|
108 | |||
109 | incoming via HTTP |
|
109 | incoming via HTTP | |
110 |
|
110 | |||
111 | $ hg clone http://localhost:$HGPORT1/ --rev 0 partial |
|
111 | $ hg clone http://localhost:$HGPORT1/ --rev 0 partial | |
112 | adding changesets |
|
112 | adding changesets | |
113 | adding manifests |
|
113 | adding manifests | |
114 | adding file changes |
|
114 | adding file changes | |
115 | added 1 changesets with 4 changes to 4 files |
|
115 | added 1 changesets with 4 changes to 4 files | |
116 | updating to branch default |
|
116 | updating to branch default | |
117 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
117 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
118 | $ cd partial |
|
118 | $ cd partial | |
119 | $ touch LOCAL |
|
119 | $ touch LOCAL | |
120 | $ hg ci -qAm LOCAL |
|
120 | $ hg ci -qAm LOCAL | |
121 | $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n' |
|
121 | $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n' | |
122 | comparing with http://localhost:$HGPORT1/ |
|
122 | comparing with http://localhost:$HGPORT1/ | |
123 | searching for changes |
|
123 | searching for changes | |
124 | 2 |
|
124 | 2 | |
125 | $ cd .. |
|
125 | $ cd .. | |
126 |
|
126 | |||
127 | pull |
|
127 | pull | |
128 |
|
128 | |||
129 | $ cd copy-pull |
|
129 | $ cd copy-pull | |
130 | $ cat >> .hg/hgrc <<EOF |
|
130 | $ cat >> .hg/hgrc <<EOF | |
131 | > [hooks] |
|
131 | > [hooks] | |
132 | > changegroup = sh -c "printenv.py changegroup" |
|
132 | > changegroup = sh -c "printenv.py changegroup" | |
133 | > EOF |
|
133 | > EOF | |
134 | $ hg pull |
|
134 | $ hg pull | |
135 | pulling from http://localhost:$HGPORT1/ |
|
135 | pulling from http://localhost:$HGPORT1/ | |
136 | searching for changes |
|
136 | searching for changes | |
137 | adding changesets |
|
137 | adding changesets | |
138 | adding manifests |
|
138 | adding manifests | |
139 | adding file changes |
|
139 | adding file changes | |
140 | added 1 changesets with 1 changes to 1 files |
|
140 | added 1 changesets with 1 changes to 1 files | |
141 |
changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN: |
|
141 | changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=http://localhost:$HGPORT1/ | |
142 | (run 'hg update' to get a working copy) |
|
142 | (run 'hg update' to get a working copy) | |
143 | $ cd .. |
|
143 | $ cd .. | |
144 |
|
144 | |||
145 | clone from invalid URL |
|
145 | clone from invalid URL | |
146 |
|
146 | |||
147 | $ hg clone http://localhost:$HGPORT/bad |
|
147 | $ hg clone http://localhost:$HGPORT/bad | |
148 | abort: HTTP Error 404: Not Found |
|
148 | abort: HTTP Error 404: Not Found | |
149 | [255] |
|
149 | [255] | |
150 |
|
150 | |||
151 | test http authentication |
|
151 | test http authentication | |
152 | + use the same server to test server side streaming preference |
|
152 | + use the same server to test server side streaming preference | |
153 |
|
153 | |||
154 | $ cd test |
|
154 | $ cd test | |
155 | $ cat << EOT > userpass.py |
|
155 | $ cat << EOT > userpass.py | |
156 | > import base64 |
|
156 | > import base64 | |
157 | > from mercurial.hgweb import common |
|
157 | > from mercurial.hgweb import common | |
158 | > def perform_authentication(hgweb, req, op): |
|
158 | > def perform_authentication(hgweb, req, op): | |
159 | > auth = req.env.get('HTTP_AUTHORIZATION') |
|
159 | > auth = req.env.get('HTTP_AUTHORIZATION') | |
160 | > if not auth: |
|
160 | > if not auth: | |
161 | > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who', |
|
161 | > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who', | |
162 | > [('WWW-Authenticate', 'Basic Realm="mercurial"')]) |
|
162 | > [('WWW-Authenticate', 'Basic Realm="mercurial"')]) | |
163 | > if base64.b64decode(auth.split()[1]).split(':', 1) != ['user', 'pass']: |
|
163 | > if base64.b64decode(auth.split()[1]).split(':', 1) != ['user', 'pass']: | |
164 | > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no') |
|
164 | > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no') | |
165 | > def extsetup(): |
|
165 | > def extsetup(): | |
166 | > common.permhooks.insert(0, perform_authentication) |
|
166 | > common.permhooks.insert(0, perform_authentication) | |
167 | > EOT |
|
167 | > EOT | |
168 | $ hg serve --config extensions.x=userpass.py -p $HGPORT2 -d --pid-file=pid \ |
|
168 | $ hg serve --config extensions.x=userpass.py -p $HGPORT2 -d --pid-file=pid \ | |
169 | > --config server.preferuncompressed=True \ |
|
169 | > --config server.preferuncompressed=True \ | |
170 | > --config web.push_ssl=False --config web.allow_push=* -A ../access.log |
|
170 | > --config web.push_ssl=False --config web.allow_push=* -A ../access.log | |
171 | $ cat pid >> $DAEMON_PIDS |
|
171 | $ cat pid >> $DAEMON_PIDS | |
172 |
|
172 | |||
173 | $ cat << EOF > get_pass.py |
|
173 | $ cat << EOF > get_pass.py | |
174 | > import getpass |
|
174 | > import getpass | |
175 | > def newgetpass(arg): |
|
175 | > def newgetpass(arg): | |
176 | > return "pass" |
|
176 | > return "pass" | |
177 | > getpass.getpass = newgetpass |
|
177 | > getpass.getpass = newgetpass | |
178 | > EOF |
|
178 | > EOF | |
179 |
|
179 | |||
180 | $ hg id http://localhost:$HGPORT2/ |
|
180 | $ hg id http://localhost:$HGPORT2/ | |
181 | abort: http authorization required for http://localhost:$HGPORT2/ |
|
181 | abort: http authorization required for http://localhost:$HGPORT2/ | |
182 | [255] |
|
182 | [255] | |
183 | $ hg id http://localhost:$HGPORT2/ |
|
183 | $ hg id http://localhost:$HGPORT2/ | |
184 | abort: http authorization required for http://localhost:$HGPORT2/ |
|
184 | abort: http authorization required for http://localhost:$HGPORT2/ | |
185 | [255] |
|
185 | [255] | |
186 | $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/ |
|
186 | $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/ | |
187 | http authorization required for http://localhost:$HGPORT2/ |
|
187 | http authorization required for http://localhost:$HGPORT2/ | |
188 | realm: mercurial |
|
188 | realm: mercurial | |
189 | user: user |
|
189 | user: user | |
190 | password: 5fed3813f7f5 |
|
190 | password: 5fed3813f7f5 | |
191 | $ hg id http://user:pass@localhost:$HGPORT2/ |
|
191 | $ hg id http://user:pass@localhost:$HGPORT2/ | |
192 | 5fed3813f7f5 |
|
192 | 5fed3813f7f5 | |
193 | $ echo '[auth]' >> .hg/hgrc |
|
193 | $ echo '[auth]' >> .hg/hgrc | |
194 | $ echo 'l.schemes=http' >> .hg/hgrc |
|
194 | $ echo 'l.schemes=http' >> .hg/hgrc | |
195 | $ echo 'l.prefix=lo' >> .hg/hgrc |
|
195 | $ echo 'l.prefix=lo' >> .hg/hgrc | |
196 | $ echo 'l.username=user' >> .hg/hgrc |
|
196 | $ echo 'l.username=user' >> .hg/hgrc | |
197 | $ echo 'l.password=pass' >> .hg/hgrc |
|
197 | $ echo 'l.password=pass' >> .hg/hgrc | |
198 | $ hg id http://localhost:$HGPORT2/ |
|
198 | $ hg id http://localhost:$HGPORT2/ | |
199 | 5fed3813f7f5 |
|
199 | 5fed3813f7f5 | |
200 | $ hg id http://localhost:$HGPORT2/ |
|
200 | $ hg id http://localhost:$HGPORT2/ | |
201 | 5fed3813f7f5 |
|
201 | 5fed3813f7f5 | |
202 | $ hg id http://user@localhost:$HGPORT2/ |
|
202 | $ hg id http://user@localhost:$HGPORT2/ | |
203 | 5fed3813f7f5 |
|
203 | 5fed3813f7f5 | |
204 | $ hg clone http://user:pass@localhost:$HGPORT2/ dest 2>&1 |
|
204 | $ hg clone http://user:pass@localhost:$HGPORT2/ dest 2>&1 | |
205 | streaming all changes |
|
205 | streaming all changes | |
206 | 7 files to transfer, 916 bytes of data |
|
206 | 7 files to transfer, 916 bytes of data | |
207 | transferred * bytes in * seconds (*/sec) (glob) |
|
207 | transferred * bytes in * seconds (*/sec) (glob) | |
208 | searching for changes |
|
208 | searching for changes | |
209 | no changes found |
|
209 | no changes found | |
210 | updating to branch default |
|
210 | updating to branch default | |
211 | 5 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
211 | 5 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
212 | --pull should override server's preferuncompressed |
|
212 | --pull should override server's preferuncompressed | |
213 | $ hg clone --pull http://user:pass@localhost:$HGPORT2/ dest-pull 2>&1 |
|
213 | $ hg clone --pull http://user:pass@localhost:$HGPORT2/ dest-pull 2>&1 | |
214 | requesting all changes |
|
214 | requesting all changes | |
215 | adding changesets |
|
215 | adding changesets | |
216 | adding manifests |
|
216 | adding manifests | |
217 | adding file changes |
|
217 | adding file changes | |
218 | added 2 changesets with 5 changes to 5 files |
|
218 | added 2 changesets with 5 changes to 5 files | |
219 | updating to branch default |
|
219 | updating to branch default | |
220 | 5 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
220 | 5 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
221 |
|
221 | |||
222 | $ hg id http://user2@localhost:$HGPORT2/ |
|
222 | $ hg id http://user2@localhost:$HGPORT2/ | |
223 | abort: http authorization required for http://localhost:$HGPORT2/ |
|
223 | abort: http authorization required for http://localhost:$HGPORT2/ | |
224 | [255] |
|
224 | [255] | |
225 | $ hg id http://user:pass2@localhost:$HGPORT2/ |
|
225 | $ hg id http://user:pass2@localhost:$HGPORT2/ | |
226 | abort: HTTP Error 403: no |
|
226 | abort: HTTP Error 403: no | |
227 | [255] |
|
227 | [255] | |
228 |
|
228 | |||
229 | $ hg -R dest tag -r tip top |
|
229 | $ hg -R dest tag -r tip top | |
230 | $ hg -R dest push http://user:pass@localhost:$HGPORT2/ |
|
230 | $ hg -R dest push http://user:pass@localhost:$HGPORT2/ | |
231 | pushing to http://user:***@localhost:$HGPORT2/ |
|
231 | pushing to http://user:***@localhost:$HGPORT2/ | |
232 | searching for changes |
|
232 | searching for changes | |
233 | remote: adding changesets |
|
233 | remote: adding changesets | |
234 | remote: adding manifests |
|
234 | remote: adding manifests | |
235 | remote: adding file changes |
|
235 | remote: adding file changes | |
236 | remote: added 1 changesets with 1 changes to 1 files |
|
236 | remote: added 1 changesets with 1 changes to 1 files | |
237 | $ hg rollback -q |
|
237 | $ hg rollback -q | |
238 |
|
238 | |||
239 | $ sed 's/.*] "/"/' < ../access.log |
|
239 | $ sed 's/.*] "/"/' < ../access.log | |
240 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
240 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
241 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
241 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
242 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
242 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
243 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
243 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
244 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
244 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
245 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
245 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
246 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
246 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
247 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
247 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
248 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
248 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
249 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
249 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
250 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
250 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
251 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
251 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
252 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
252 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
253 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
253 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
254 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
254 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
255 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
255 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
256 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
256 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
257 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
257 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
258 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
258 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
259 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
259 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
260 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
260 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
261 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
261 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
262 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
262 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
263 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
263 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
264 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
264 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
265 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
265 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
266 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
266 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
267 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
267 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
268 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
268 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
269 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
269 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
270 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
270 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
271 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
271 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
272 | "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
272 | "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
273 | "GET /?cmd=stream_out HTTP/1.1" 401 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
273 | "GET /?cmd=stream_out HTTP/1.1" 401 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
274 | "GET /?cmd=stream_out HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
274 | "GET /?cmd=stream_out HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
275 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
275 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
276 | "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
276 | "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
277 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
277 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
278 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
278 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
279 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
279 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
280 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
280 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
281 | "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
281 | "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
282 | "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
282 | "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
283 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
283 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
284 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
284 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
285 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
285 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
286 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
286 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
287 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
287 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
288 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
288 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
289 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
289 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
290 | "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
290 | "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
291 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
291 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
292 | "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
292 | "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
293 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
293 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
294 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
294 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
295 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
295 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
296 | "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
296 | "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
297 | "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
297 | "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
298 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
298 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
299 | "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=686173686564+5eb5abfefeea63c80dd7553bcc3783f37e0c5524* (glob) |
|
299 | "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=686173686564+5eb5abfefeea63c80dd7553bcc3783f37e0c5524* (glob) | |
300 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
300 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
301 |
|
301 | |||
302 | $ cd .. |
|
302 | $ cd .. | |
303 |
|
303 | |||
304 | clone of serve with repo in root and unserved subrepo (issue2970) |
|
304 | clone of serve with repo in root and unserved subrepo (issue2970) | |
305 |
|
305 | |||
306 | $ hg --cwd test init sub |
|
306 | $ hg --cwd test init sub | |
307 | $ echo empty > test/sub/empty |
|
307 | $ echo empty > test/sub/empty | |
308 | $ hg --cwd test/sub add empty |
|
308 | $ hg --cwd test/sub add empty | |
309 | $ hg --cwd test/sub commit -qm 'add empty' |
|
309 | $ hg --cwd test/sub commit -qm 'add empty' | |
310 | $ hg --cwd test/sub tag -r 0 something |
|
310 | $ hg --cwd test/sub tag -r 0 something | |
311 | $ echo sub = sub > test/.hgsub |
|
311 | $ echo sub = sub > test/.hgsub | |
312 | $ hg --cwd test add .hgsub |
|
312 | $ hg --cwd test add .hgsub | |
313 | $ hg --cwd test commit -qm 'add subrepo' |
|
313 | $ hg --cwd test commit -qm 'add subrepo' | |
314 | $ hg clone http://localhost:$HGPORT noslash-clone |
|
314 | $ hg clone http://localhost:$HGPORT noslash-clone | |
315 | requesting all changes |
|
315 | requesting all changes | |
316 | adding changesets |
|
316 | adding changesets | |
317 | adding manifests |
|
317 | adding manifests | |
318 | adding file changes |
|
318 | adding file changes | |
319 | added 3 changesets with 7 changes to 7 files |
|
319 | added 3 changesets with 7 changes to 7 files | |
320 | updating to branch default |
|
320 | updating to branch default | |
321 | abort: HTTP Error 404: Not Found |
|
321 | abort: HTTP Error 404: Not Found | |
322 | [255] |
|
322 | [255] | |
323 | $ hg clone http://localhost:$HGPORT/ slash-clone |
|
323 | $ hg clone http://localhost:$HGPORT/ slash-clone | |
324 | requesting all changes |
|
324 | requesting all changes | |
325 | adding changesets |
|
325 | adding changesets | |
326 | adding manifests |
|
326 | adding manifests | |
327 | adding file changes |
|
327 | adding file changes | |
328 | added 3 changesets with 7 changes to 7 files |
|
328 | added 3 changesets with 7 changes to 7 files | |
329 | updating to branch default |
|
329 | updating to branch default | |
330 | abort: HTTP Error 404: Not Found |
|
330 | abort: HTTP Error 404: Not Found | |
331 | [255] |
|
331 | [255] | |
332 |
|
332 | |||
333 | check error log |
|
333 | check error log | |
334 |
|
334 | |||
335 | $ cat error.log |
|
335 | $ cat error.log | |
336 |
|
336 | |||
337 | Check error reporting while pulling/cloning |
|
337 | Check error reporting while pulling/cloning | |
338 |
|
338 | |||
339 | $ $RUNTESTDIR/killdaemons.py |
|
339 | $ $RUNTESTDIR/killdaemons.py | |
340 | $ hg -R test serve -p $HGPORT -d --pid-file=hg3.pid -E error.log --config extensions.crash=${TESTDIR}/crashgetbundler.py |
|
340 | $ hg -R test serve -p $HGPORT -d --pid-file=hg3.pid -E error.log --config extensions.crash=${TESTDIR}/crashgetbundler.py | |
341 | $ cat hg3.pid >> $DAEMON_PIDS |
|
341 | $ cat hg3.pid >> $DAEMON_PIDS | |
342 | $ hg clone http://localhost:$HGPORT/ abort-clone |
|
342 | $ hg clone http://localhost:$HGPORT/ abort-clone | |
343 | requesting all changes |
|
343 | requesting all changes | |
344 | abort: remote error: |
|
344 | abort: remote error: | |
345 | this is an exercise |
|
345 | this is an exercise | |
346 | [255] |
|
346 | [255] | |
347 | $ cat error.log |
|
347 | $ cat error.log |
@@ -1,335 +1,335 b'' | |||||
1 | #require serve |
|
1 | #require serve | |
2 |
|
2 | |||
3 | $ hg init test |
|
3 | $ hg init test | |
4 | $ cd test |
|
4 | $ cd test | |
5 | $ echo foo>foo |
|
5 | $ echo foo>foo | |
6 | $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg |
|
6 | $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg | |
7 | $ echo foo>foo.d/foo |
|
7 | $ echo foo>foo.d/foo | |
8 | $ echo bar>foo.d/bAr.hg.d/BaR |
|
8 | $ echo bar>foo.d/bAr.hg.d/BaR | |
9 | $ echo bar>foo.d/baR.d.hg/bAR |
|
9 | $ echo bar>foo.d/baR.d.hg/bAR | |
10 | $ hg commit -A -m 1 |
|
10 | $ hg commit -A -m 1 | |
11 | adding foo |
|
11 | adding foo | |
12 | adding foo.d/bAr.hg.d/BaR |
|
12 | adding foo.d/bAr.hg.d/BaR | |
13 | adding foo.d/baR.d.hg/bAR |
|
13 | adding foo.d/baR.d.hg/bAR | |
14 | adding foo.d/foo |
|
14 | adding foo.d/foo | |
15 | $ hg serve -p $HGPORT -d --pid-file=../hg1.pid -E ../error.log |
|
15 | $ hg serve -p $HGPORT -d --pid-file=../hg1.pid -E ../error.log | |
16 | $ hg serve --config server.uncompressed=False -p $HGPORT1 -d --pid-file=../hg2.pid |
|
16 | $ hg serve --config server.uncompressed=False -p $HGPORT1 -d --pid-file=../hg2.pid | |
17 |
|
17 | |||
18 | Test server address cannot be reused |
|
18 | Test server address cannot be reused | |
19 |
|
19 | |||
20 | #if windows |
|
20 | #if windows | |
21 | $ hg serve -p $HGPORT1 2>&1 |
|
21 | $ hg serve -p $HGPORT1 2>&1 | |
22 | abort: cannot start server at ':$HGPORT1': * (glob) |
|
22 | abort: cannot start server at ':$HGPORT1': * (glob) | |
23 | [255] |
|
23 | [255] | |
24 | #else |
|
24 | #else | |
25 | $ hg serve -p $HGPORT1 2>&1 |
|
25 | $ hg serve -p $HGPORT1 2>&1 | |
26 | abort: cannot start server at 'localhost:$HGPORT1': Address already in use |
|
26 | abort: cannot start server at 'localhost:$HGPORT1': Address already in use | |
27 | [255] |
|
27 | [255] | |
28 | #endif |
|
28 | #endif | |
29 | $ cd .. |
|
29 | $ cd .. | |
30 | $ cat hg1.pid hg2.pid >> $DAEMON_PIDS |
|
30 | $ cat hg1.pid hg2.pid >> $DAEMON_PIDS | |
31 |
|
31 | |||
32 | clone via stream |
|
32 | clone via stream | |
33 |
|
33 | |||
34 | $ hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1 |
|
34 | $ hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1 | |
35 | streaming all changes |
|
35 | streaming all changes | |
36 | 6 files to transfer, 606 bytes of data |
|
36 | 6 files to transfer, 606 bytes of data | |
37 | transferred * bytes in * seconds (*/sec) (glob) |
|
37 | transferred * bytes in * seconds (*/sec) (glob) | |
38 | searching for changes |
|
38 | searching for changes | |
39 | no changes found |
|
39 | no changes found | |
40 | updating to branch default |
|
40 | updating to branch default | |
41 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
41 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
42 | $ hg verify -R copy |
|
42 | $ hg verify -R copy | |
43 | checking changesets |
|
43 | checking changesets | |
44 | checking manifests |
|
44 | checking manifests | |
45 | crosschecking files in changesets and manifests |
|
45 | crosschecking files in changesets and manifests | |
46 | checking files |
|
46 | checking files | |
47 | 4 files, 1 changesets, 4 total revisions |
|
47 | 4 files, 1 changesets, 4 total revisions | |
48 |
|
48 | |||
49 | try to clone via stream, should use pull instead |
|
49 | try to clone via stream, should use pull instead | |
50 |
|
50 | |||
51 | $ hg clone --uncompressed http://localhost:$HGPORT1/ copy2 |
|
51 | $ hg clone --uncompressed http://localhost:$HGPORT1/ copy2 | |
52 | requesting all changes |
|
52 | requesting all changes | |
53 | adding changesets |
|
53 | adding changesets | |
54 | adding manifests |
|
54 | adding manifests | |
55 | adding file changes |
|
55 | adding file changes | |
56 | added 1 changesets with 4 changes to 4 files |
|
56 | added 1 changesets with 4 changes to 4 files | |
57 | updating to branch default |
|
57 | updating to branch default | |
58 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
58 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
59 |
|
59 | |||
60 | clone via pull |
|
60 | clone via pull | |
61 |
|
61 | |||
62 | $ hg clone http://localhost:$HGPORT1/ copy-pull |
|
62 | $ hg clone http://localhost:$HGPORT1/ copy-pull | |
63 | requesting all changes |
|
63 | requesting all changes | |
64 | adding changesets |
|
64 | adding changesets | |
65 | adding manifests |
|
65 | adding manifests | |
66 | adding file changes |
|
66 | adding file changes | |
67 | added 1 changesets with 4 changes to 4 files |
|
67 | added 1 changesets with 4 changes to 4 files | |
68 | updating to branch default |
|
68 | updating to branch default | |
69 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
69 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
70 | $ hg verify -R copy-pull |
|
70 | $ hg verify -R copy-pull | |
71 | checking changesets |
|
71 | checking changesets | |
72 | checking manifests |
|
72 | checking manifests | |
73 | crosschecking files in changesets and manifests |
|
73 | crosschecking files in changesets and manifests | |
74 | checking files |
|
74 | checking files | |
75 | 4 files, 1 changesets, 4 total revisions |
|
75 | 4 files, 1 changesets, 4 total revisions | |
76 | $ cd test |
|
76 | $ cd test | |
77 | $ echo bar > bar |
|
77 | $ echo bar > bar | |
78 | $ hg commit -A -d '1 0' -m 2 |
|
78 | $ hg commit -A -d '1 0' -m 2 | |
79 | adding bar |
|
79 | adding bar | |
80 | $ cd .. |
|
80 | $ cd .. | |
81 |
|
81 | |||
82 | clone over http with --update |
|
82 | clone over http with --update | |
83 |
|
83 | |||
84 | $ hg clone http://localhost:$HGPORT1/ updated --update 0 |
|
84 | $ hg clone http://localhost:$HGPORT1/ updated --update 0 | |
85 | requesting all changes |
|
85 | requesting all changes | |
86 | adding changesets |
|
86 | adding changesets | |
87 | adding manifests |
|
87 | adding manifests | |
88 | adding file changes |
|
88 | adding file changes | |
89 | added 2 changesets with 5 changes to 5 files |
|
89 | added 2 changesets with 5 changes to 5 files | |
90 | updating to branch default |
|
90 | updating to branch default | |
91 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
91 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
92 | $ hg log -r . -R updated |
|
92 | $ hg log -r . -R updated | |
93 | changeset: 0:8b6053c928fe |
|
93 | changeset: 0:8b6053c928fe | |
94 | user: test |
|
94 | user: test | |
95 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
95 | date: Thu Jan 01 00:00:00 1970 +0000 | |
96 | summary: 1 |
|
96 | summary: 1 | |
97 |
|
97 | |||
98 | $ rm -rf updated |
|
98 | $ rm -rf updated | |
99 |
|
99 | |||
100 | incoming via HTTP |
|
100 | incoming via HTTP | |
101 |
|
101 | |||
102 | $ hg clone http://localhost:$HGPORT1/ --rev 0 partial |
|
102 | $ hg clone http://localhost:$HGPORT1/ --rev 0 partial | |
103 | adding changesets |
|
103 | adding changesets | |
104 | adding manifests |
|
104 | adding manifests | |
105 | adding file changes |
|
105 | adding file changes | |
106 | added 1 changesets with 4 changes to 4 files |
|
106 | added 1 changesets with 4 changes to 4 files | |
107 | updating to branch default |
|
107 | updating to branch default | |
108 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
108 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
109 | $ cd partial |
|
109 | $ cd partial | |
110 | $ touch LOCAL |
|
110 | $ touch LOCAL | |
111 | $ hg ci -qAm LOCAL |
|
111 | $ hg ci -qAm LOCAL | |
112 | $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n' |
|
112 | $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n' | |
113 | comparing with http://localhost:$HGPORT1/ |
|
113 | comparing with http://localhost:$HGPORT1/ | |
114 | searching for changes |
|
114 | searching for changes | |
115 | 2 |
|
115 | 2 | |
116 | $ cd .. |
|
116 | $ cd .. | |
117 |
|
117 | |||
118 | pull |
|
118 | pull | |
119 |
|
119 | |||
120 | $ cd copy-pull |
|
120 | $ cd copy-pull | |
121 | $ cat >> .hg/hgrc <<EOF |
|
121 | $ cat >> .hg/hgrc <<EOF | |
122 | > [hooks] |
|
122 | > [hooks] | |
123 | > changegroup = sh -c "printenv.py changegroup" |
|
123 | > changegroup = sh -c "printenv.py changegroup" | |
124 | > EOF |
|
124 | > EOF | |
125 | $ hg pull |
|
125 | $ hg pull | |
126 | pulling from http://localhost:$HGPORT1/ |
|
126 | pulling from http://localhost:$HGPORT1/ | |
127 | searching for changes |
|
127 | searching for changes | |
128 | adding changesets |
|
128 | adding changesets | |
129 | adding manifests |
|
129 | adding manifests | |
130 | adding file changes |
|
130 | adding file changes | |
131 | added 1 changesets with 1 changes to 1 files |
|
131 | added 1 changesets with 1 changes to 1 files | |
132 |
changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN: |
|
132 | changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=http://localhost:$HGPORT1/ | |
133 | (run 'hg update' to get a working copy) |
|
133 | (run 'hg update' to get a working copy) | |
134 | $ cd .. |
|
134 | $ cd .. | |
135 |
|
135 | |||
136 | clone from invalid URL |
|
136 | clone from invalid URL | |
137 |
|
137 | |||
138 | $ hg clone http://localhost:$HGPORT/bad |
|
138 | $ hg clone http://localhost:$HGPORT/bad | |
139 | abort: HTTP Error 404: Not Found |
|
139 | abort: HTTP Error 404: Not Found | |
140 | [255] |
|
140 | [255] | |
141 |
|
141 | |||
142 | test http authentication |
|
142 | test http authentication | |
143 | + use the same server to test server side streaming preference |
|
143 | + use the same server to test server side streaming preference | |
144 |
|
144 | |||
145 | $ cd test |
|
145 | $ cd test | |
146 | $ cat << EOT > userpass.py |
|
146 | $ cat << EOT > userpass.py | |
147 | > import base64 |
|
147 | > import base64 | |
148 | > from mercurial.hgweb import common |
|
148 | > from mercurial.hgweb import common | |
149 | > def perform_authentication(hgweb, req, op): |
|
149 | > def perform_authentication(hgweb, req, op): | |
150 | > auth = req.env.get('HTTP_AUTHORIZATION') |
|
150 | > auth = req.env.get('HTTP_AUTHORIZATION') | |
151 | > if not auth: |
|
151 | > if not auth: | |
152 | > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who', |
|
152 | > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who', | |
153 | > [('WWW-Authenticate', 'Basic Realm="mercurial"')]) |
|
153 | > [('WWW-Authenticate', 'Basic Realm="mercurial"')]) | |
154 | > if base64.b64decode(auth.split()[1]).split(':', 1) != ['user', 'pass']: |
|
154 | > if base64.b64decode(auth.split()[1]).split(':', 1) != ['user', 'pass']: | |
155 | > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no') |
|
155 | > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no') | |
156 | > def extsetup(): |
|
156 | > def extsetup(): | |
157 | > common.permhooks.insert(0, perform_authentication) |
|
157 | > common.permhooks.insert(0, perform_authentication) | |
158 | > EOT |
|
158 | > EOT | |
159 | $ hg serve --config extensions.x=userpass.py -p $HGPORT2 -d --pid-file=pid \ |
|
159 | $ hg serve --config extensions.x=userpass.py -p $HGPORT2 -d --pid-file=pid \ | |
160 | > --config server.preferuncompressed=True \ |
|
160 | > --config server.preferuncompressed=True \ | |
161 | > --config web.push_ssl=False --config web.allow_push=* -A ../access.log |
|
161 | > --config web.push_ssl=False --config web.allow_push=* -A ../access.log | |
162 | $ cat pid >> $DAEMON_PIDS |
|
162 | $ cat pid >> $DAEMON_PIDS | |
163 |
|
163 | |||
164 | $ cat << EOF > get_pass.py |
|
164 | $ cat << EOF > get_pass.py | |
165 | > import getpass |
|
165 | > import getpass | |
166 | > def newgetpass(arg): |
|
166 | > def newgetpass(arg): | |
167 | > return "pass" |
|
167 | > return "pass" | |
168 | > getpass.getpass = newgetpass |
|
168 | > getpass.getpass = newgetpass | |
169 | > EOF |
|
169 | > EOF | |
170 |
|
170 | |||
171 | $ hg id http://localhost:$HGPORT2/ |
|
171 | $ hg id http://localhost:$HGPORT2/ | |
172 | abort: http authorization required for http://localhost:$HGPORT2/ |
|
172 | abort: http authorization required for http://localhost:$HGPORT2/ | |
173 | [255] |
|
173 | [255] | |
174 | $ hg id http://localhost:$HGPORT2/ |
|
174 | $ hg id http://localhost:$HGPORT2/ | |
175 | abort: http authorization required for http://localhost:$HGPORT2/ |
|
175 | abort: http authorization required for http://localhost:$HGPORT2/ | |
176 | [255] |
|
176 | [255] | |
177 | $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/ |
|
177 | $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/ | |
178 | http authorization required for http://localhost:$HGPORT2/ |
|
178 | http authorization required for http://localhost:$HGPORT2/ | |
179 | realm: mercurial |
|
179 | realm: mercurial | |
180 | user: user |
|
180 | user: user | |
181 | password: 5fed3813f7f5 |
|
181 | password: 5fed3813f7f5 | |
182 | $ hg id http://user:pass@localhost:$HGPORT2/ |
|
182 | $ hg id http://user:pass@localhost:$HGPORT2/ | |
183 | 5fed3813f7f5 |
|
183 | 5fed3813f7f5 | |
184 | $ echo '[auth]' >> .hg/hgrc |
|
184 | $ echo '[auth]' >> .hg/hgrc | |
185 | $ echo 'l.schemes=http' >> .hg/hgrc |
|
185 | $ echo 'l.schemes=http' >> .hg/hgrc | |
186 | $ echo 'l.prefix=lo' >> .hg/hgrc |
|
186 | $ echo 'l.prefix=lo' >> .hg/hgrc | |
187 | $ echo 'l.username=user' >> .hg/hgrc |
|
187 | $ echo 'l.username=user' >> .hg/hgrc | |
188 | $ echo 'l.password=pass' >> .hg/hgrc |
|
188 | $ echo 'l.password=pass' >> .hg/hgrc | |
189 | $ hg id http://localhost:$HGPORT2/ |
|
189 | $ hg id http://localhost:$HGPORT2/ | |
190 | 5fed3813f7f5 |
|
190 | 5fed3813f7f5 | |
191 | $ hg id http://localhost:$HGPORT2/ |
|
191 | $ hg id http://localhost:$HGPORT2/ | |
192 | 5fed3813f7f5 |
|
192 | 5fed3813f7f5 | |
193 | $ hg id http://user@localhost:$HGPORT2/ |
|
193 | $ hg id http://user@localhost:$HGPORT2/ | |
194 | 5fed3813f7f5 |
|
194 | 5fed3813f7f5 | |
195 | $ hg clone http://user:pass@localhost:$HGPORT2/ dest 2>&1 |
|
195 | $ hg clone http://user:pass@localhost:$HGPORT2/ dest 2>&1 | |
196 | streaming all changes |
|
196 | streaming all changes | |
197 | 7 files to transfer, 916 bytes of data |
|
197 | 7 files to transfer, 916 bytes of data | |
198 | transferred * bytes in * seconds (*/sec) (glob) |
|
198 | transferred * bytes in * seconds (*/sec) (glob) | |
199 | searching for changes |
|
199 | searching for changes | |
200 | no changes found |
|
200 | no changes found | |
201 | updating to branch default |
|
201 | updating to branch default | |
202 | 5 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
202 | 5 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
203 | --pull should override server's preferuncompressed |
|
203 | --pull should override server's preferuncompressed | |
204 | $ hg clone --pull http://user:pass@localhost:$HGPORT2/ dest-pull 2>&1 |
|
204 | $ hg clone --pull http://user:pass@localhost:$HGPORT2/ dest-pull 2>&1 | |
205 | requesting all changes |
|
205 | requesting all changes | |
206 | adding changesets |
|
206 | adding changesets | |
207 | adding manifests |
|
207 | adding manifests | |
208 | adding file changes |
|
208 | adding file changes | |
209 | added 2 changesets with 5 changes to 5 files |
|
209 | added 2 changesets with 5 changes to 5 files | |
210 | updating to branch default |
|
210 | updating to branch default | |
211 | 5 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
211 | 5 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
212 |
|
212 | |||
213 | $ hg id http://user2@localhost:$HGPORT2/ |
|
213 | $ hg id http://user2@localhost:$HGPORT2/ | |
214 | abort: http authorization required for http://localhost:$HGPORT2/ |
|
214 | abort: http authorization required for http://localhost:$HGPORT2/ | |
215 | [255] |
|
215 | [255] | |
216 | $ hg id http://user:pass2@localhost:$HGPORT2/ |
|
216 | $ hg id http://user:pass2@localhost:$HGPORT2/ | |
217 | abort: HTTP Error 403: no |
|
217 | abort: HTTP Error 403: no | |
218 | [255] |
|
218 | [255] | |
219 |
|
219 | |||
220 | $ hg -R dest tag -r tip top |
|
220 | $ hg -R dest tag -r tip top | |
221 | $ hg -R dest push http://user:pass@localhost:$HGPORT2/ |
|
221 | $ hg -R dest push http://user:pass@localhost:$HGPORT2/ | |
222 | pushing to http://user:***@localhost:$HGPORT2/ |
|
222 | pushing to http://user:***@localhost:$HGPORT2/ | |
223 | searching for changes |
|
223 | searching for changes | |
224 | remote: adding changesets |
|
224 | remote: adding changesets | |
225 | remote: adding manifests |
|
225 | remote: adding manifests | |
226 | remote: adding file changes |
|
226 | remote: adding file changes | |
227 | remote: added 1 changesets with 1 changes to 1 files |
|
227 | remote: added 1 changesets with 1 changes to 1 files | |
228 | $ hg rollback -q |
|
228 | $ hg rollback -q | |
229 |
|
229 | |||
230 | $ sed 's/.*] "/"/' < ../access.log |
|
230 | $ sed 's/.*] "/"/' < ../access.log | |
231 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
231 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
232 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
232 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
233 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
233 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
234 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
234 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
235 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
235 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
236 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
236 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
237 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
237 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
238 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
238 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
239 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
239 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
240 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
240 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
241 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
241 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
242 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
242 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
243 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
243 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
244 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
244 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
245 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
245 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
246 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
246 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
247 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
247 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
248 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
248 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
249 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
249 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
250 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
250 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
251 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
251 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
252 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
252 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
253 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
253 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
254 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
254 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
255 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
255 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
256 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
256 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
257 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
257 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
258 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
258 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
259 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
259 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
260 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
260 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
261 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
261 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
262 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
262 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
263 | "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
263 | "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
264 | "GET /?cmd=stream_out HTTP/1.1" 401 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
264 | "GET /?cmd=stream_out HTTP/1.1" 401 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
265 | "GET /?cmd=stream_out HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
265 | "GET /?cmd=stream_out HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
266 | "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
266 | "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
267 | "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
267 | "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
268 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
268 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
269 | "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
269 | "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
270 | "GET /?cmd=getbundle HTTP/1.1" 401 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
270 | "GET /?cmd=getbundle HTTP/1.1" 401 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
271 | "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
271 | "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
272 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
272 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
273 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
273 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
274 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
274 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
275 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
275 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
276 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
276 | "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
277 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
277 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
278 | "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
278 | "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
279 | "GET /?cmd=capabilities HTTP/1.1" 200 - |
|
279 | "GET /?cmd=capabilities HTTP/1.1" 200 - | |
280 | "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
280 | "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
281 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
281 | "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
282 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
282 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
283 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
283 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
284 | "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
284 | "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
285 | "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
285 | "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
286 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
286 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
287 | "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=666f726365* (glob) |
|
287 | "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=666f726365* (glob) | |
288 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) |
|
288 | "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob) | |
289 |
|
289 | |||
290 | $ cd .. |
|
290 | $ cd .. | |
291 |
|
291 | |||
292 | clone of serve with repo in root and unserved subrepo (issue2970) |
|
292 | clone of serve with repo in root and unserved subrepo (issue2970) | |
293 |
|
293 | |||
294 | $ hg --cwd test init sub |
|
294 | $ hg --cwd test init sub | |
295 | $ echo empty > test/sub/empty |
|
295 | $ echo empty > test/sub/empty | |
296 | $ hg --cwd test/sub add empty |
|
296 | $ hg --cwd test/sub add empty | |
297 | $ hg --cwd test/sub commit -qm 'add empty' |
|
297 | $ hg --cwd test/sub commit -qm 'add empty' | |
298 | $ hg --cwd test/sub tag -r 0 something |
|
298 | $ hg --cwd test/sub tag -r 0 something | |
299 | $ echo sub = sub > test/.hgsub |
|
299 | $ echo sub = sub > test/.hgsub | |
300 | $ hg --cwd test add .hgsub |
|
300 | $ hg --cwd test add .hgsub | |
301 | $ hg --cwd test commit -qm 'add subrepo' |
|
301 | $ hg --cwd test commit -qm 'add subrepo' | |
302 | $ hg clone http://localhost:$HGPORT noslash-clone |
|
302 | $ hg clone http://localhost:$HGPORT noslash-clone | |
303 | requesting all changes |
|
303 | requesting all changes | |
304 | adding changesets |
|
304 | adding changesets | |
305 | adding manifests |
|
305 | adding manifests | |
306 | adding file changes |
|
306 | adding file changes | |
307 | added 3 changesets with 7 changes to 7 files |
|
307 | added 3 changesets with 7 changes to 7 files | |
308 | updating to branch default |
|
308 | updating to branch default | |
309 | abort: HTTP Error 404: Not Found |
|
309 | abort: HTTP Error 404: Not Found | |
310 | [255] |
|
310 | [255] | |
311 | $ hg clone http://localhost:$HGPORT/ slash-clone |
|
311 | $ hg clone http://localhost:$HGPORT/ slash-clone | |
312 | requesting all changes |
|
312 | requesting all changes | |
313 | adding changesets |
|
313 | adding changesets | |
314 | adding manifests |
|
314 | adding manifests | |
315 | adding file changes |
|
315 | adding file changes | |
316 | added 3 changesets with 7 changes to 7 files |
|
316 | added 3 changesets with 7 changes to 7 files | |
317 | updating to branch default |
|
317 | updating to branch default | |
318 | abort: HTTP Error 404: Not Found |
|
318 | abort: HTTP Error 404: Not Found | |
319 | [255] |
|
319 | [255] | |
320 |
|
320 | |||
321 | check error log |
|
321 | check error log | |
322 |
|
322 | |||
323 | $ cat error.log |
|
323 | $ cat error.log | |
324 |
|
324 | |||
325 | check abort error reporting while pulling/cloning |
|
325 | check abort error reporting while pulling/cloning | |
326 |
|
326 | |||
327 | $ $RUNTESTDIR/killdaemons.py |
|
327 | $ $RUNTESTDIR/killdaemons.py | |
328 | $ hg -R test serve -p $HGPORT -d --pid-file=hg3.pid -E error.log --config extensions.crash=${TESTDIR}/crashgetbundler.py |
|
328 | $ hg -R test serve -p $HGPORT -d --pid-file=hg3.pid -E error.log --config extensions.crash=${TESTDIR}/crashgetbundler.py | |
329 | $ cat hg3.pid >> $DAEMON_PIDS |
|
329 | $ cat hg3.pid >> $DAEMON_PIDS | |
330 | $ hg clone http://localhost:$HGPORT/ abort-clone |
|
330 | $ hg clone http://localhost:$HGPORT/ abort-clone | |
331 | requesting all changes |
|
331 | requesting all changes | |
332 | remote: abort: this is an exercise |
|
332 | remote: abort: this is an exercise | |
333 | abort: pull failed on remote |
|
333 | abort: pull failed on remote | |
334 | [255] |
|
334 | [255] | |
335 | $ cat error.log |
|
335 | $ cat error.log |
@@ -1,644 +1,644 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 | Make server certificates: |
|
5 | Make server certificates: | |
6 |
|
6 | |||
7 | $ CERTSDIR="$TESTDIR/sslcerts" |
|
7 | $ CERTSDIR="$TESTDIR/sslcerts" | |
8 | $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub.pem" >> server.pem |
|
8 | $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub.pem" >> server.pem | |
9 | $ PRIV=`pwd`/server.pem |
|
9 | $ PRIV=`pwd`/server.pem | |
10 | $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub-not-yet.pem" > server-not-yet.pem |
|
10 | $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub-not-yet.pem" > server-not-yet.pem | |
11 | $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub-expired.pem" > server-expired.pem |
|
11 | $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub-expired.pem" > server-expired.pem | |
12 |
|
12 | |||
13 | $ hg init test |
|
13 | $ hg init test | |
14 | $ cd test |
|
14 | $ cd test | |
15 | $ echo foo>foo |
|
15 | $ echo foo>foo | |
16 | $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg |
|
16 | $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg | |
17 | $ echo foo>foo.d/foo |
|
17 | $ echo foo>foo.d/foo | |
18 | $ echo bar>foo.d/bAr.hg.d/BaR |
|
18 | $ echo bar>foo.d/bAr.hg.d/BaR | |
19 | $ echo bar>foo.d/baR.d.hg/bAR |
|
19 | $ echo bar>foo.d/baR.d.hg/bAR | |
20 | $ hg commit -A -m 1 |
|
20 | $ hg commit -A -m 1 | |
21 | adding foo |
|
21 | adding foo | |
22 | adding foo.d/bAr.hg.d/BaR |
|
22 | adding foo.d/bAr.hg.d/BaR | |
23 | adding foo.d/baR.d.hg/bAR |
|
23 | adding foo.d/baR.d.hg/bAR | |
24 | adding foo.d/foo |
|
24 | adding foo.d/foo | |
25 | $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV |
|
25 | $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV | |
26 | $ cat ../hg0.pid >> $DAEMON_PIDS |
|
26 | $ cat ../hg0.pid >> $DAEMON_PIDS | |
27 |
|
27 | |||
28 | cacert not found |
|
28 | cacert not found | |
29 |
|
29 | |||
30 | $ hg in --config web.cacerts=no-such.pem https://localhost:$HGPORT/ |
|
30 | $ hg in --config web.cacerts=no-such.pem https://localhost:$HGPORT/ | |
31 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
31 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
32 | abort: could not find web.cacerts: no-such.pem |
|
32 | abort: could not find web.cacerts: no-such.pem | |
33 | [255] |
|
33 | [255] | |
34 |
|
34 | |||
35 | Test server address cannot be reused |
|
35 | Test server address cannot be reused | |
36 |
|
36 | |||
37 | #if windows |
|
37 | #if windows | |
38 | $ hg serve -p $HGPORT --certificate=$PRIV 2>&1 |
|
38 | $ hg serve -p $HGPORT --certificate=$PRIV 2>&1 | |
39 | abort: cannot start server at 'localhost:$HGPORT': |
|
39 | abort: cannot start server at 'localhost:$HGPORT': | |
40 | [255] |
|
40 | [255] | |
41 | #else |
|
41 | #else | |
42 | $ hg serve -p $HGPORT --certificate=$PRIV 2>&1 |
|
42 | $ hg serve -p $HGPORT --certificate=$PRIV 2>&1 | |
43 | abort: cannot start server at 'localhost:$HGPORT': Address already in use |
|
43 | abort: cannot start server at 'localhost:$HGPORT': Address already in use | |
44 | [255] |
|
44 | [255] | |
45 | #endif |
|
45 | #endif | |
46 | $ cd .. |
|
46 | $ cd .. | |
47 |
|
47 | |||
48 | Our test cert is not signed by a trusted CA. It should fail to verify if |
|
48 | Our test cert is not signed by a trusted CA. It should fail to verify if | |
49 | we are able to load CA certs. |
|
49 | we are able to load CA certs. | |
50 |
|
50 | |||
51 | #if sslcontext defaultcacerts no-defaultcacertsloaded |
|
51 | #if sslcontext defaultcacerts no-defaultcacertsloaded | |
52 | $ hg clone https://localhost:$HGPORT/ copy-pull |
|
52 | $ hg clone https://localhost:$HGPORT/ copy-pull | |
53 | (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) |
|
53 | (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 | abort: error: *certificate verify failed* (glob) |
|
54 | abort: error: *certificate verify failed* (glob) | |
55 | [255] |
|
55 | [255] | |
56 | #endif |
|
56 | #endif | |
57 |
|
57 | |||
58 | #if no-sslcontext defaultcacerts |
|
58 | #if no-sslcontext defaultcacerts | |
59 | $ hg clone https://localhost:$HGPORT/ copy-pull |
|
59 | $ hg clone https://localhost:$HGPORT/ copy-pull | |
60 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
60 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
61 | (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) (?) |
|
61 | (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 | abort: error: *certificate verify failed* (glob) |
|
62 | abort: error: *certificate verify failed* (glob) | |
63 | [255] |
|
63 | [255] | |
64 | #endif |
|
64 | #endif | |
65 |
|
65 | |||
66 | #if no-sslcontext windows |
|
66 | #if no-sslcontext windows | |
67 | $ hg clone https://localhost:$HGPORT/ copy-pull |
|
67 | $ hg clone https://localhost:$HGPORT/ copy-pull | |
68 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info |
|
68 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info | |
69 | (unable to load Windows CA certificates; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) |
|
69 | (unable to load Windows CA certificates; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) | |
70 | abort: error: *certificate verify failed* (glob) |
|
70 | abort: error: *certificate verify failed* (glob) | |
71 | [255] |
|
71 | [255] | |
72 | #endif |
|
72 | #endif | |
73 |
|
73 | |||
74 | #if no-sslcontext osx |
|
74 | #if no-sslcontext osx | |
75 | $ hg clone https://localhost:$HGPORT/ copy-pull |
|
75 | $ hg clone https://localhost:$HGPORT/ copy-pull | |
76 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info |
|
76 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info | |
77 | (unable to load CA certificates; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) |
|
77 | (unable to load CA certificates; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) | |
78 | abort: localhost certificate error: no certificate received |
|
78 | abort: localhost certificate error: no certificate received | |
79 | (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) |
|
79 | (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) | |
80 | [255] |
|
80 | [255] | |
81 | #endif |
|
81 | #endif | |
82 |
|
82 | |||
83 | #if defaultcacertsloaded |
|
83 | #if defaultcacertsloaded | |
84 | $ hg clone https://localhost:$HGPORT/ copy-pull |
|
84 | $ hg clone https://localhost:$HGPORT/ copy-pull | |
85 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
85 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
86 | (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) (?) |
|
86 | (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) (?) | |
87 | abort: error: *certificate verify failed* (glob) |
|
87 | abort: error: *certificate verify failed* (glob) | |
88 | [255] |
|
88 | [255] | |
89 | #endif |
|
89 | #endif | |
90 |
|
90 | |||
91 | #if no-defaultcacerts |
|
91 | #if no-defaultcacerts | |
92 | $ hg clone https://localhost:$HGPORT/ copy-pull |
|
92 | $ hg clone https://localhost:$HGPORT/ copy-pull | |
93 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
93 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
94 | (unable to load * certificates; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?) |
|
94 | (unable to load * certificates; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?) | |
95 | abort: localhost certificate error: no certificate received |
|
95 | abort: localhost certificate error: no certificate received | |
96 | (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) |
|
96 | (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) | |
97 | [255] |
|
97 | [255] | |
98 | #endif |
|
98 | #endif | |
99 |
|
99 | |||
100 | Specifying a per-host certificate file that doesn't exist will abort |
|
100 | Specifying a per-host certificate file that doesn't exist will abort | |
101 |
|
101 | |||
102 | $ hg --config hostsecurity.localhost:verifycertsfile=/does/not/exist clone https://localhost:$HGPORT/ |
|
102 | $ hg --config hostsecurity.localhost:verifycertsfile=/does/not/exist clone https://localhost:$HGPORT/ | |
103 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
103 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
104 | abort: path specified by hostsecurity.localhost:verifycertsfile does not exist: /does/not/exist |
|
104 | abort: path specified by hostsecurity.localhost:verifycertsfile does not exist: /does/not/exist | |
105 | [255] |
|
105 | [255] | |
106 |
|
106 | |||
107 | A malformed per-host certificate file will raise an error |
|
107 | A malformed per-host certificate file will raise an error | |
108 |
|
108 | |||
109 | $ echo baddata > badca.pem |
|
109 | $ echo baddata > badca.pem | |
110 | #if sslcontext |
|
110 | #if sslcontext | |
111 | $ hg --config hostsecurity.localhost:verifycertsfile=badca.pem clone https://localhost:$HGPORT/ |
|
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 (?) |
|
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 loading CA file badca.pem: * (glob) |
|
113 | abort: error loading CA file badca.pem: * (glob) | |
114 | (file is empty or malformed?) |
|
114 | (file is empty or malformed?) | |
115 | [255] |
|
115 | [255] | |
116 | #else |
|
116 | #else | |
117 | $ hg --config hostsecurity.localhost:verifycertsfile=badca.pem clone https://localhost:$HGPORT/ |
|
117 | $ hg --config hostsecurity.localhost:verifycertsfile=badca.pem clone https://localhost:$HGPORT/ | |
118 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
118 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
119 | abort: error: * (glob) |
|
119 | abort: error: * (glob) | |
120 | [255] |
|
120 | [255] | |
121 | #endif |
|
121 | #endif | |
122 |
|
122 | |||
123 | A per-host certificate mismatching the server will fail verification |
|
123 | A per-host certificate mismatching the server will fail verification | |
124 |
|
124 | |||
125 | (modern ssl is able to discern whether the loaded cert is a CA cert) |
|
125 | (modern ssl is able to discern whether the loaded cert is a CA cert) | |
126 | #if sslcontext |
|
126 | #if sslcontext | |
127 | $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/client-cert.pem" clone https://localhost:$HGPORT/ |
|
127 | $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/client-cert.pem" clone https://localhost:$HGPORT/ | |
128 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
128 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
129 | (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) |
|
129 | (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) | |
130 | abort: error: *certificate verify failed* (glob) |
|
130 | abort: error: *certificate verify failed* (glob) | |
131 | [255] |
|
131 | [255] | |
132 | #else |
|
132 | #else | |
133 | $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/client-cert.pem" clone https://localhost:$HGPORT/ |
|
133 | $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/client-cert.pem" clone https://localhost:$HGPORT/ | |
134 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
134 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
135 | abort: error: *certificate verify failed* (glob) |
|
135 | abort: error: *certificate verify failed* (glob) | |
136 | [255] |
|
136 | [255] | |
137 | #endif |
|
137 | #endif | |
138 |
|
138 | |||
139 | A per-host certificate matching the server's cert will be accepted |
|
139 | A per-host certificate matching the server's cert will be accepted | |
140 |
|
140 | |||
141 | $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/pub.pem" clone -U https://localhost:$HGPORT/ perhostgood1 |
|
141 | $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/pub.pem" clone -U https://localhost:$HGPORT/ perhostgood1 | |
142 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
142 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
143 | requesting all changes |
|
143 | requesting all changes | |
144 | adding changesets |
|
144 | adding changesets | |
145 | adding manifests |
|
145 | adding manifests | |
146 | adding file changes |
|
146 | adding file changes | |
147 | added 1 changesets with 4 changes to 4 files |
|
147 | added 1 changesets with 4 changes to 4 files | |
148 |
|
148 | |||
149 | A per-host certificate with multiple certs and one matching will be accepted |
|
149 | A per-host certificate with multiple certs and one matching will be accepted | |
150 |
|
150 | |||
151 | $ cat "$CERTSDIR/client-cert.pem" "$CERTSDIR/pub.pem" > perhost.pem |
|
151 | $ cat "$CERTSDIR/client-cert.pem" "$CERTSDIR/pub.pem" > perhost.pem | |
152 | $ hg --config hostsecurity.localhost:verifycertsfile=perhost.pem clone -U https://localhost:$HGPORT/ perhostgood2 |
|
152 | $ hg --config hostsecurity.localhost:verifycertsfile=perhost.pem clone -U https://localhost:$HGPORT/ perhostgood2 | |
153 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
153 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
154 | requesting all changes |
|
154 | requesting all changes | |
155 | adding changesets |
|
155 | adding changesets | |
156 | adding manifests |
|
156 | adding manifests | |
157 | adding file changes |
|
157 | adding file changes | |
158 | added 1 changesets with 4 changes to 4 files |
|
158 | added 1 changesets with 4 changes to 4 files | |
159 |
|
159 | |||
160 | Defining both per-host certificate and a fingerprint will print a warning |
|
160 | Defining both per-host certificate and a fingerprint will print a warning | |
161 |
|
161 | |||
162 | $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/pub.pem" --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 clone -U https://localhost:$HGPORT/ caandfingerwarning |
|
162 | $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/pub.pem" --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 clone -U https://localhost:$HGPORT/ caandfingerwarning | |
163 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
163 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
164 | (hostsecurity.localhost:verifycertsfile ignored when host fingerprints defined; using host fingerprints for verification) |
|
164 | (hostsecurity.localhost:verifycertsfile ignored when host fingerprints defined; using host fingerprints for verification) | |
165 | requesting all changes |
|
165 | requesting all changes | |
166 | adding changesets |
|
166 | adding changesets | |
167 | adding manifests |
|
167 | adding manifests | |
168 | adding file changes |
|
168 | adding file changes | |
169 | added 1 changesets with 4 changes to 4 files |
|
169 | added 1 changesets with 4 changes to 4 files | |
170 |
|
170 | |||
171 | $ DISABLECACERTS="--config devel.disableloaddefaultcerts=true" |
|
171 | $ DISABLECACERTS="--config devel.disableloaddefaultcerts=true" | |
172 |
|
172 | |||
173 | Inability to verify peer certificate will result in abort |
|
173 | Inability to verify peer certificate will result in abort | |
174 |
|
174 | |||
175 | $ hg clone https://localhost:$HGPORT/ copy-pull $DISABLECACERTS |
|
175 | $ hg clone https://localhost:$HGPORT/ copy-pull $DISABLECACERTS | |
176 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
176 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
177 | abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect |
|
177 | abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect | |
178 | (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) |
|
178 | (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) | |
179 | [255] |
|
179 | [255] | |
180 |
|
180 | |||
181 | $ hg clone --insecure https://localhost:$HGPORT/ copy-pull |
|
181 | $ hg clone --insecure https://localhost:$HGPORT/ copy-pull | |
182 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
182 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
183 | warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering |
|
183 | warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering | |
184 | requesting all changes |
|
184 | requesting all changes | |
185 | adding changesets |
|
185 | adding changesets | |
186 | adding manifests |
|
186 | adding manifests | |
187 | adding file changes |
|
187 | adding file changes | |
188 | added 1 changesets with 4 changes to 4 files |
|
188 | added 1 changesets with 4 changes to 4 files | |
189 | updating to branch default |
|
189 | updating to branch default | |
190 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
190 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
191 | $ hg verify -R copy-pull |
|
191 | $ hg verify -R copy-pull | |
192 | checking changesets |
|
192 | checking changesets | |
193 | checking manifests |
|
193 | checking manifests | |
194 | crosschecking files in changesets and manifests |
|
194 | crosschecking files in changesets and manifests | |
195 | checking files |
|
195 | checking files | |
196 | 4 files, 1 changesets, 4 total revisions |
|
196 | 4 files, 1 changesets, 4 total revisions | |
197 | $ cd test |
|
197 | $ cd test | |
198 | $ echo bar > bar |
|
198 | $ echo bar > bar | |
199 | $ hg commit -A -d '1 0' -m 2 |
|
199 | $ hg commit -A -d '1 0' -m 2 | |
200 | adding bar |
|
200 | adding bar | |
201 | $ cd .. |
|
201 | $ cd .. | |
202 |
|
202 | |||
203 | pull without cacert |
|
203 | pull without cacert | |
204 |
|
204 | |||
205 | $ cd copy-pull |
|
205 | $ cd copy-pull | |
206 | $ cat >> .hg/hgrc <<EOF |
|
206 | $ cat >> .hg/hgrc <<EOF | |
207 | > [hooks] |
|
207 | > [hooks] | |
208 | > changegroup = sh -c "printenv.py changegroup" |
|
208 | > changegroup = sh -c "printenv.py changegroup" | |
209 | > EOF |
|
209 | > EOF | |
210 | $ hg pull $DISABLECACERTS |
|
210 | $ hg pull $DISABLECACERTS | |
211 | pulling from https://localhost:$HGPORT/ |
|
211 | pulling from https://localhost:$HGPORT/ | |
212 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
212 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
213 | abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect |
|
213 | abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect | |
214 | (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 | (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) | |
215 | [255] |
|
215 | [255] | |
216 |
|
216 | |||
217 | $ hg pull --insecure |
|
217 | $ hg pull --insecure | |
218 | pulling from https://localhost:$HGPORT/ |
|
218 | pulling from https://localhost:$HGPORT/ | |
219 | 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 (?) | |
220 | warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering |
|
220 | warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering | |
221 | searching for changes |
|
221 | searching for changes | |
222 | adding changesets |
|
222 | adding changesets | |
223 | adding manifests |
|
223 | adding manifests | |
224 | adding file changes |
|
224 | adding file changes | |
225 | added 1 changesets with 1 changes to 1 files |
|
225 | added 1 changesets with 1 changes to 1 files | |
226 |
changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN: |
|
226 | changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=https://localhost:$HGPORT/ | |
227 | (run 'hg update' to get a working copy) |
|
227 | (run 'hg update' to get a working copy) | |
228 | $ cd .. |
|
228 | $ cd .. | |
229 |
|
229 | |||
230 | cacert configured in local repo |
|
230 | cacert configured in local repo | |
231 |
|
231 | |||
232 | $ cp copy-pull/.hg/hgrc copy-pull/.hg/hgrc.bu |
|
232 | $ cp copy-pull/.hg/hgrc copy-pull/.hg/hgrc.bu | |
233 | $ echo "[web]" >> copy-pull/.hg/hgrc |
|
233 | $ echo "[web]" >> copy-pull/.hg/hgrc | |
234 | $ echo "cacerts=$CERTSDIR/pub.pem" >> copy-pull/.hg/hgrc |
|
234 | $ echo "cacerts=$CERTSDIR/pub.pem" >> copy-pull/.hg/hgrc | |
235 | $ hg -R copy-pull pull |
|
235 | $ hg -R copy-pull pull | |
236 | pulling from https://localhost:$HGPORT/ |
|
236 | pulling from https://localhost:$HGPORT/ | |
237 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
237 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
238 | searching for changes |
|
238 | searching for changes | |
239 | no changes found |
|
239 | no changes found | |
240 | $ mv copy-pull/.hg/hgrc.bu copy-pull/.hg/hgrc |
|
240 | $ mv copy-pull/.hg/hgrc.bu copy-pull/.hg/hgrc | |
241 |
|
241 | |||
242 | cacert configured globally, also testing expansion of environment |
|
242 | cacert configured globally, also testing expansion of environment | |
243 | variables in the filename |
|
243 | variables in the filename | |
244 |
|
244 | |||
245 | $ echo "[web]" >> $HGRCPATH |
|
245 | $ echo "[web]" >> $HGRCPATH | |
246 | $ echo 'cacerts=$P/pub.pem' >> $HGRCPATH |
|
246 | $ echo 'cacerts=$P/pub.pem' >> $HGRCPATH | |
247 | $ P="$CERTSDIR" hg -R copy-pull pull |
|
247 | $ P="$CERTSDIR" hg -R copy-pull pull | |
248 | pulling from https://localhost:$HGPORT/ |
|
248 | pulling from https://localhost:$HGPORT/ | |
249 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
249 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
250 | searching for changes |
|
250 | searching for changes | |
251 | no changes found |
|
251 | no changes found | |
252 | $ P="$CERTSDIR" hg -R copy-pull pull --insecure |
|
252 | $ P="$CERTSDIR" hg -R copy-pull pull --insecure | |
253 | pulling from https://localhost:$HGPORT/ |
|
253 | pulling from https://localhost:$HGPORT/ | |
254 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
254 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
255 | warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering |
|
255 | warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering | |
256 | searching for changes |
|
256 | searching for changes | |
257 | no changes found |
|
257 | no changes found | |
258 |
|
258 | |||
259 | empty cacert file |
|
259 | empty cacert file | |
260 |
|
260 | |||
261 | $ touch emptycafile |
|
261 | $ touch emptycafile | |
262 |
|
262 | |||
263 | #if sslcontext |
|
263 | #if sslcontext | |
264 | $ hg --config web.cacerts=emptycafile -R copy-pull pull |
|
264 | $ hg --config web.cacerts=emptycafile -R copy-pull pull | |
265 | pulling from https://localhost:$HGPORT/ |
|
265 | pulling from https://localhost:$HGPORT/ | |
266 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
266 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
267 | abort: error loading CA file emptycafile: * (glob) |
|
267 | abort: error loading CA file emptycafile: * (glob) | |
268 | (file is empty or malformed?) |
|
268 | (file is empty or malformed?) | |
269 | [255] |
|
269 | [255] | |
270 | #else |
|
270 | #else | |
271 | $ hg --config web.cacerts=emptycafile -R copy-pull pull |
|
271 | $ hg --config web.cacerts=emptycafile -R copy-pull pull | |
272 | pulling from https://localhost:$HGPORT/ |
|
272 | pulling from https://localhost:$HGPORT/ | |
273 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
273 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
274 | abort: error: * (glob) |
|
274 | abort: error: * (glob) | |
275 | [255] |
|
275 | [255] | |
276 | #endif |
|
276 | #endif | |
277 |
|
277 | |||
278 | cacert mismatch |
|
278 | cacert mismatch | |
279 |
|
279 | |||
280 | $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub.pem" \ |
|
280 | $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub.pem" \ | |
281 | > https://$LOCALIP:$HGPORT/ |
|
281 | > https://$LOCALIP:$HGPORT/ | |
282 | pulling from https://*:$HGPORT/ (glob) |
|
282 | pulling from https://*:$HGPORT/ (glob) | |
283 | warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
283 | warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
284 | abort: $LOCALIP certificate error: certificate is for localhost |
|
284 | abort: $LOCALIP certificate error: certificate is for localhost | |
285 | (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) |
|
285 | (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) | |
286 | [255] |
|
286 | [255] | |
287 | $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub.pem" \ |
|
287 | $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub.pem" \ | |
288 | > https://$LOCALIP:$HGPORT/ --insecure |
|
288 | > https://$LOCALIP:$HGPORT/ --insecure | |
289 | pulling from https://*:$HGPORT/ (glob) |
|
289 | pulling from https://*:$HGPORT/ (glob) | |
290 | warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
290 | warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
291 | warning: connection security to $LOCALIP is disabled per current settings; communication is susceptible to eavesdropping and tampering |
|
291 | warning: connection security to $LOCALIP is disabled per current settings; communication is susceptible to eavesdropping and tampering | |
292 | searching for changes |
|
292 | searching for changes | |
293 | no changes found |
|
293 | no changes found | |
294 | $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-other.pem" |
|
294 | $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-other.pem" | |
295 | pulling from https://localhost:$HGPORT/ |
|
295 | pulling from https://localhost:$HGPORT/ | |
296 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
296 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
297 | abort: error: *certificate verify failed* (glob) |
|
297 | abort: error: *certificate verify failed* (glob) | |
298 | [255] |
|
298 | [255] | |
299 | $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-other.pem" \ |
|
299 | $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-other.pem" \ | |
300 | > --insecure |
|
300 | > --insecure | |
301 | pulling from https://localhost:$HGPORT/ |
|
301 | pulling from https://localhost:$HGPORT/ | |
302 | 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 (?) | |
303 | warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering |
|
303 | warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering | |
304 | searching for changes |
|
304 | searching for changes | |
305 | no changes found |
|
305 | no changes found | |
306 |
|
306 | |||
307 | Test server cert which isn't valid yet |
|
307 | Test server cert which isn't valid yet | |
308 |
|
308 | |||
309 | $ hg serve -R test -p $HGPORT1 -d --pid-file=hg1.pid --certificate=server-not-yet.pem |
|
309 | $ hg serve -R test -p $HGPORT1 -d --pid-file=hg1.pid --certificate=server-not-yet.pem | |
310 | $ cat hg1.pid >> $DAEMON_PIDS |
|
310 | $ cat hg1.pid >> $DAEMON_PIDS | |
311 | $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-not-yet.pem" \ |
|
311 | $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-not-yet.pem" \ | |
312 | > https://localhost:$HGPORT1/ |
|
312 | > https://localhost:$HGPORT1/ | |
313 | pulling from https://localhost:$HGPORT1/ |
|
313 | pulling from https://localhost:$HGPORT1/ | |
314 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
314 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
315 | abort: error: *certificate verify failed* (glob) |
|
315 | abort: error: *certificate verify failed* (glob) | |
316 | [255] |
|
316 | [255] | |
317 |
|
317 | |||
318 | Test server cert which no longer is valid |
|
318 | Test server cert which no longer is valid | |
319 |
|
319 | |||
320 | $ hg serve -R test -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem |
|
320 | $ hg serve -R test -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem | |
321 | $ cat hg2.pid >> $DAEMON_PIDS |
|
321 | $ cat hg2.pid >> $DAEMON_PIDS | |
322 | $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-expired.pem" \ |
|
322 | $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-expired.pem" \ | |
323 | > https://localhost:$HGPORT2/ |
|
323 | > https://localhost:$HGPORT2/ | |
324 | pulling from https://localhost:$HGPORT2/ |
|
324 | pulling from https://localhost:$HGPORT2/ | |
325 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
325 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
326 | abort: error: *certificate verify failed* (glob) |
|
326 | abort: error: *certificate verify failed* (glob) | |
327 | [255] |
|
327 | [255] | |
328 |
|
328 | |||
329 | Disabling the TLS 1.0 warning works |
|
329 | Disabling the TLS 1.0 warning works | |
330 | $ hg -R copy-pull id https://localhost:$HGPORT/ \ |
|
330 | $ hg -R copy-pull id https://localhost:$HGPORT/ \ | |
331 | > --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 \ |
|
331 | > --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 \ | |
332 | > --config hostsecurity.disabletls10warning=true |
|
332 | > --config hostsecurity.disabletls10warning=true | |
333 | 5fed3813f7f5 |
|
333 | 5fed3813f7f5 | |
334 |
|
334 | |||
335 | #if no-sslcontext no-py27+ |
|
335 | #if no-sslcontext no-py27+ | |
336 | Setting ciphers doesn't work in Python 2.6 |
|
336 | Setting ciphers doesn't work in Python 2.6 | |
337 | $ P="$CERTSDIR" hg --config hostsecurity.ciphers=HIGH -R copy-pull id https://localhost:$HGPORT/ |
|
337 | $ P="$CERTSDIR" hg --config hostsecurity.ciphers=HIGH -R copy-pull id https://localhost:$HGPORT/ | |
338 | 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 | |
339 | abort: setting ciphers in [hostsecurity] is not supported by this version of Python |
|
339 | abort: setting ciphers in [hostsecurity] is not supported by this version of Python | |
340 | (remove the config option or run Mercurial with a modern Python version (preferred)) |
|
340 | (remove the config option or run Mercurial with a modern Python version (preferred)) | |
341 | [255] |
|
341 | [255] | |
342 | #endif |
|
342 | #endif | |
343 |
|
343 | |||
344 | Setting ciphers works in Python 2.7+ but the error message is different on |
|
344 | Setting ciphers works in Python 2.7+ but the error message is different on | |
345 | legacy ssl. We test legacy once and do more feature checking on modern |
|
345 | legacy ssl. We test legacy once and do more feature checking on modern | |
346 | configs. |
|
346 | configs. | |
347 |
|
347 | |||
348 | #if py27+ no-sslcontext |
|
348 | #if py27+ no-sslcontext | |
349 | $ P="$CERTSDIR" hg --config hostsecurity.ciphers=invalid -R copy-pull id https://localhost:$HGPORT/ |
|
349 | $ P="$CERTSDIR" hg --config hostsecurity.ciphers=invalid -R copy-pull id https://localhost:$HGPORT/ | |
350 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info |
|
350 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info | |
351 | abort: *No cipher can be selected. (glob) |
|
351 | abort: *No cipher can be selected. (glob) | |
352 | [255] |
|
352 | [255] | |
353 |
|
353 | |||
354 | $ P="$CERTSDIR" hg --config hostsecurity.ciphers=HIGH -R copy-pull id https://localhost:$HGPORT/ |
|
354 | $ P="$CERTSDIR" hg --config hostsecurity.ciphers=HIGH -R copy-pull id https://localhost:$HGPORT/ | |
355 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info |
|
355 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info | |
356 | 5fed3813f7f5 |
|
356 | 5fed3813f7f5 | |
357 | #endif |
|
357 | #endif | |
358 |
|
358 | |||
359 | #if sslcontext |
|
359 | #if sslcontext | |
360 | Setting ciphers to an invalid value aborts |
|
360 | Setting ciphers to an invalid value aborts | |
361 | $ P="$CERTSDIR" hg --config hostsecurity.ciphers=invalid -R copy-pull id https://localhost:$HGPORT/ |
|
361 | $ P="$CERTSDIR" hg --config hostsecurity.ciphers=invalid -R copy-pull id https://localhost:$HGPORT/ | |
362 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
362 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
363 | abort: could not set ciphers: No cipher can be selected. |
|
363 | abort: could not set ciphers: No cipher can be selected. | |
364 | (change cipher string (invalid) in config) |
|
364 | (change cipher string (invalid) in config) | |
365 | [255] |
|
365 | [255] | |
366 |
|
366 | |||
367 | $ P="$CERTSDIR" hg --config hostsecurity.localhost:ciphers=invalid -R copy-pull id https://localhost:$HGPORT/ |
|
367 | $ P="$CERTSDIR" hg --config hostsecurity.localhost:ciphers=invalid -R copy-pull id https://localhost:$HGPORT/ | |
368 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
368 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
369 | abort: could not set ciphers: No cipher can be selected. |
|
369 | abort: could not set ciphers: No cipher can be selected. | |
370 | (change cipher string (invalid) in config) |
|
370 | (change cipher string (invalid) in config) | |
371 | [255] |
|
371 | [255] | |
372 |
|
372 | |||
373 | Changing the cipher string works |
|
373 | Changing the cipher string works | |
374 |
|
374 | |||
375 | $ P="$CERTSDIR" hg --config hostsecurity.ciphers=HIGH -R copy-pull id https://localhost:$HGPORT/ |
|
375 | $ P="$CERTSDIR" hg --config hostsecurity.ciphers=HIGH -R copy-pull id https://localhost:$HGPORT/ | |
376 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
376 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
377 | 5fed3813f7f5 |
|
377 | 5fed3813f7f5 | |
378 | #endif |
|
378 | #endif | |
379 |
|
379 | |||
380 | Fingerprints |
|
380 | Fingerprints | |
381 |
|
381 | |||
382 | - works without cacerts (hostfingerprints) |
|
382 | - works without cacerts (hostfingerprints) | |
383 | $ 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 |
|
383 | $ 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 | |
384 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
384 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
385 | (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: 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) |
|
385 | (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: 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) | |
386 | 5fed3813f7f5 |
|
386 | 5fed3813f7f5 | |
387 |
|
387 | |||
388 | - works without cacerts (hostsecurity) |
|
388 | - works without cacerts (hostsecurity) | |
389 | $ hg -R copy-pull id https://localhost:$HGPORT/ --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 |
|
389 | $ hg -R copy-pull id https://localhost:$HGPORT/ --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 | |
390 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
390 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
391 | 5fed3813f7f5 |
|
391 | 5fed3813f7f5 | |
392 |
|
392 | |||
393 | $ 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 |
|
393 | $ 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 | |
394 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
394 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
395 | 5fed3813f7f5 |
|
395 | 5fed3813f7f5 | |
396 |
|
396 | |||
397 | - multiple fingerprints specified and first matches |
|
397 | - multiple fingerprints specified and first matches | |
398 | $ hg --config 'hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03, deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure |
|
398 | $ hg --config 'hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03, deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure | |
399 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
399 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
400 | (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: 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) |
|
400 | (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: 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) | |
401 | 5fed3813f7f5 |
|
401 | 5fed3813f7f5 | |
402 |
|
402 | |||
403 | $ hg --config 'hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03, sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ |
|
403 | $ hg --config 'hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03, sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ | |
404 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
404 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
405 | 5fed3813f7f5 |
|
405 | 5fed3813f7f5 | |
406 |
|
406 | |||
407 | - multiple fingerprints specified and last matches |
|
407 | - multiple fingerprints specified and last matches | |
408 | $ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03' -R copy-pull id https://localhost:$HGPORT/ --insecure |
|
408 | $ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03' -R copy-pull id https://localhost:$HGPORT/ --insecure | |
409 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
409 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
410 | (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: 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) |
|
410 | (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: 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) | |
411 | 5fed3813f7f5 |
|
411 | 5fed3813f7f5 | |
412 |
|
412 | |||
413 | $ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03' -R copy-pull id https://localhost:$HGPORT/ |
|
413 | $ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03' -R copy-pull id https://localhost:$HGPORT/ | |
414 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
414 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
415 | 5fed3813f7f5 |
|
415 | 5fed3813f7f5 | |
416 |
|
416 | |||
417 | - multiple fingerprints specified and none match |
|
417 | - multiple fingerprints specified and none match | |
418 |
|
418 | |||
419 | $ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure |
|
419 | $ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure | |
420 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
420 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
421 | 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 |
|
421 | 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 | |
422 | (check hostfingerprint configuration) |
|
422 | (check hostfingerprint configuration) | |
423 | [255] |
|
423 | [255] | |
424 |
|
424 | |||
425 | $ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ |
|
425 | $ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ | |
426 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
426 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
427 | 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 |
|
427 | 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 | |
428 | (check hostsecurity configuration) |
|
428 | (check hostsecurity configuration) | |
429 | [255] |
|
429 | [255] | |
430 |
|
430 | |||
431 | - fails when cert doesn't match hostname (port is ignored) |
|
431 | - fails when cert doesn't match hostname (port is ignored) | |
432 | $ hg -R copy-pull id https://localhost:$HGPORT1/ --config hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 |
|
432 | $ hg -R copy-pull id https://localhost:$HGPORT1/ --config hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 | |
433 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
433 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
434 | 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 |
|
434 | 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 | |
435 | (check hostfingerprint configuration) |
|
435 | (check hostfingerprint configuration) | |
436 | [255] |
|
436 | [255] | |
437 |
|
437 | |||
438 |
|
438 | |||
439 | - ignores that certificate doesn't match hostname |
|
439 | - ignores that certificate doesn't match hostname | |
440 | $ hg -R copy-pull id https://$LOCALIP:$HGPORT/ --config hostfingerprints.$LOCALIP=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 |
|
440 | $ hg -R copy-pull id https://$LOCALIP:$HGPORT/ --config hostfingerprints.$LOCALIP=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 | |
441 | warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
441 | warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
442 | (SHA-1 fingerprint for $LOCALIP found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: $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) |
|
442 | (SHA-1 fingerprint for $LOCALIP found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: $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) | |
443 | 5fed3813f7f5 |
|
443 | 5fed3813f7f5 | |
444 |
|
444 | |||
445 | Ports used by next test. Kill servers. |
|
445 | Ports used by next test. Kill servers. | |
446 |
|
446 | |||
447 | $ killdaemons.py hg0.pid |
|
447 | $ killdaemons.py hg0.pid | |
448 | $ killdaemons.py hg1.pid |
|
448 | $ killdaemons.py hg1.pid | |
449 | $ killdaemons.py hg2.pid |
|
449 | $ killdaemons.py hg2.pid | |
450 |
|
450 | |||
451 | #if sslcontext tls1.2 |
|
451 | #if sslcontext tls1.2 | |
452 | Start servers running supported TLS versions |
|
452 | Start servers running supported TLS versions | |
453 |
|
453 | |||
454 | $ cd test |
|
454 | $ cd test | |
455 | $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV \ |
|
455 | $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV \ | |
456 | > --config devel.serverexactprotocol=tls1.0 |
|
456 | > --config devel.serverexactprotocol=tls1.0 | |
457 | $ cat ../hg0.pid >> $DAEMON_PIDS |
|
457 | $ cat ../hg0.pid >> $DAEMON_PIDS | |
458 | $ hg serve -p $HGPORT1 -d --pid-file=../hg1.pid --certificate=$PRIV \ |
|
458 | $ hg serve -p $HGPORT1 -d --pid-file=../hg1.pid --certificate=$PRIV \ | |
459 | > --config devel.serverexactprotocol=tls1.1 |
|
459 | > --config devel.serverexactprotocol=tls1.1 | |
460 | $ cat ../hg1.pid >> $DAEMON_PIDS |
|
460 | $ cat ../hg1.pid >> $DAEMON_PIDS | |
461 | $ hg serve -p $HGPORT2 -d --pid-file=../hg2.pid --certificate=$PRIV \ |
|
461 | $ hg serve -p $HGPORT2 -d --pid-file=../hg2.pid --certificate=$PRIV \ | |
462 | > --config devel.serverexactprotocol=tls1.2 |
|
462 | > --config devel.serverexactprotocol=tls1.2 | |
463 | $ cat ../hg2.pid >> $DAEMON_PIDS |
|
463 | $ cat ../hg2.pid >> $DAEMON_PIDS | |
464 | $ cd .. |
|
464 | $ cd .. | |
465 |
|
465 | |||
466 | Clients talking same TLS versions work |
|
466 | Clients talking same TLS versions work | |
467 |
|
467 | |||
468 | $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.0 id https://localhost:$HGPORT/ |
|
468 | $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.0 id https://localhost:$HGPORT/ | |
469 | 5fed3813f7f5 |
|
469 | 5fed3813f7f5 | |
470 | $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.1 id https://localhost:$HGPORT1/ |
|
470 | $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.1 id https://localhost:$HGPORT1/ | |
471 | 5fed3813f7f5 |
|
471 | 5fed3813f7f5 | |
472 | $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT2/ |
|
472 | $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT2/ | |
473 | 5fed3813f7f5 |
|
473 | 5fed3813f7f5 | |
474 |
|
474 | |||
475 | Clients requiring newer TLS version than what server supports fail |
|
475 | Clients requiring newer TLS version than what server supports fail | |
476 |
|
476 | |||
477 | $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ |
|
477 | $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ | |
478 | (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) |
|
478 | (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) | |
479 | (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) |
|
479 | (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) | |
480 | (see https://mercurial-scm.org/wiki/SecureConnections for more info) |
|
480 | (see https://mercurial-scm.org/wiki/SecureConnections for more info) | |
481 | abort: error: *unsupported protocol* (glob) |
|
481 | abort: error: *unsupported protocol* (glob) | |
482 | [255] |
|
482 | [255] | |
483 |
|
483 | |||
484 | $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.1 id https://localhost:$HGPORT/ |
|
484 | $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.1 id https://localhost:$HGPORT/ | |
485 | (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) |
|
485 | (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) | |
486 | (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) |
|
486 | (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) | |
487 | (see https://mercurial-scm.org/wiki/SecureConnections for more info) |
|
487 | (see https://mercurial-scm.org/wiki/SecureConnections for more info) | |
488 | abort: error: *unsupported protocol* (glob) |
|
488 | abort: error: *unsupported protocol* (glob) | |
489 | [255] |
|
489 | [255] | |
490 | $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT/ |
|
490 | $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT/ | |
491 | (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) |
|
491 | (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) | |
492 | (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) |
|
492 | (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) | |
493 | (see https://mercurial-scm.org/wiki/SecureConnections for more info) |
|
493 | (see https://mercurial-scm.org/wiki/SecureConnections for more info) | |
494 | abort: error: *unsupported protocol* (glob) |
|
494 | abort: error: *unsupported protocol* (glob) | |
495 | [255] |
|
495 | [255] | |
496 | $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT1/ |
|
496 | $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT1/ | |
497 | (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) |
|
497 | (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) | |
498 | (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) |
|
498 | (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) | |
499 | (see https://mercurial-scm.org/wiki/SecureConnections for more info) |
|
499 | (see https://mercurial-scm.org/wiki/SecureConnections for more info) | |
500 | abort: error: *unsupported protocol* (glob) |
|
500 | abort: error: *unsupported protocol* (glob) | |
501 | [255] |
|
501 | [255] | |
502 |
|
502 | |||
503 | --insecure will allow TLS 1.0 connections and override configs |
|
503 | --insecure will allow TLS 1.0 connections and override configs | |
504 |
|
504 | |||
505 | $ hg --config hostsecurity.minimumprotocol=tls1.2 id --insecure https://localhost:$HGPORT1/ |
|
505 | $ hg --config hostsecurity.minimumprotocol=tls1.2 id --insecure https://localhost:$HGPORT1/ | |
506 | warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering |
|
506 | warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering | |
507 | 5fed3813f7f5 |
|
507 | 5fed3813f7f5 | |
508 |
|
508 | |||
509 | The per-host config option overrides the default |
|
509 | The per-host config option overrides the default | |
510 |
|
510 | |||
511 | $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \ |
|
511 | $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \ | |
512 | > --config hostsecurity.minimumprotocol=tls1.2 \ |
|
512 | > --config hostsecurity.minimumprotocol=tls1.2 \ | |
513 | > --config hostsecurity.localhost:minimumprotocol=tls1.0 |
|
513 | > --config hostsecurity.localhost:minimumprotocol=tls1.0 | |
514 | 5fed3813f7f5 |
|
514 | 5fed3813f7f5 | |
515 |
|
515 | |||
516 | The per-host config option by itself works |
|
516 | The per-host config option by itself works | |
517 |
|
517 | |||
518 | $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \ |
|
518 | $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \ | |
519 | > --config hostsecurity.localhost:minimumprotocol=tls1.2 |
|
519 | > --config hostsecurity.localhost:minimumprotocol=tls1.2 | |
520 | (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) |
|
520 | (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) | |
521 | (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) |
|
521 | (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) | |
522 | (see https://mercurial-scm.org/wiki/SecureConnections for more info) |
|
522 | (see https://mercurial-scm.org/wiki/SecureConnections for more info) | |
523 | abort: error: *unsupported protocol* (glob) |
|
523 | abort: error: *unsupported protocol* (glob) | |
524 | [255] |
|
524 | [255] | |
525 |
|
525 | |||
526 | .hg/hgrc file [hostsecurity] settings are applied to remote ui instances (issue5305) |
|
526 | .hg/hgrc file [hostsecurity] settings are applied to remote ui instances (issue5305) | |
527 |
|
527 | |||
528 | $ cat >> copy-pull/.hg/hgrc << EOF |
|
528 | $ cat >> copy-pull/.hg/hgrc << EOF | |
529 | > [hostsecurity] |
|
529 | > [hostsecurity] | |
530 | > localhost:minimumprotocol=tls1.2 |
|
530 | > localhost:minimumprotocol=tls1.2 | |
531 | > EOF |
|
531 | > EOF | |
532 | $ P="$CERTSDIR" hg -R copy-pull id https://localhost:$HGPORT/ |
|
532 | $ P="$CERTSDIR" hg -R copy-pull id https://localhost:$HGPORT/ | |
533 | (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) |
|
533 | (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) | |
534 | (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) |
|
534 | (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) | |
535 | (see https://mercurial-scm.org/wiki/SecureConnections for more info) |
|
535 | (see https://mercurial-scm.org/wiki/SecureConnections for more info) | |
536 | abort: error: *unsupported protocol* (glob) |
|
536 | abort: error: *unsupported protocol* (glob) | |
537 | [255] |
|
537 | [255] | |
538 |
|
538 | |||
539 | $ killdaemons.py hg0.pid |
|
539 | $ killdaemons.py hg0.pid | |
540 | $ killdaemons.py hg1.pid |
|
540 | $ killdaemons.py hg1.pid | |
541 | $ killdaemons.py hg2.pid |
|
541 | $ killdaemons.py hg2.pid | |
542 | #endif |
|
542 | #endif | |
543 |
|
543 | |||
544 | Prepare for connecting through proxy |
|
544 | Prepare for connecting through proxy | |
545 |
|
545 | |||
546 | $ hg serve -R test -p $HGPORT -d --pid-file=hg0.pid --certificate=$PRIV |
|
546 | $ hg serve -R test -p $HGPORT -d --pid-file=hg0.pid --certificate=$PRIV | |
547 | $ cat hg0.pid >> $DAEMON_PIDS |
|
547 | $ cat hg0.pid >> $DAEMON_PIDS | |
548 | $ hg serve -R test -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem |
|
548 | $ hg serve -R test -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem | |
549 | $ cat hg2.pid >> $DAEMON_PIDS |
|
549 | $ cat hg2.pid >> $DAEMON_PIDS | |
550 | tinyproxy.py doesn't fully detach, so killing it may result in extra output |
|
550 | tinyproxy.py doesn't fully detach, so killing it may result in extra output | |
551 | from the shell. So don't kill it. |
|
551 | from the shell. So don't kill it. | |
552 | $ tinyproxy.py $HGPORT1 localhost >proxy.log </dev/null 2>&1 & |
|
552 | $ tinyproxy.py $HGPORT1 localhost >proxy.log </dev/null 2>&1 & | |
553 | $ while [ ! -f proxy.pid ]; do sleep 0; done |
|
553 | $ while [ ! -f proxy.pid ]; do sleep 0; done | |
554 | $ cat proxy.pid >> $DAEMON_PIDS |
|
554 | $ cat proxy.pid >> $DAEMON_PIDS | |
555 |
|
555 | |||
556 | $ echo "[http_proxy]" >> copy-pull/.hg/hgrc |
|
556 | $ echo "[http_proxy]" >> copy-pull/.hg/hgrc | |
557 | $ echo "always=True" >> copy-pull/.hg/hgrc |
|
557 | $ echo "always=True" >> copy-pull/.hg/hgrc | |
558 | $ echo "[hostfingerprints]" >> copy-pull/.hg/hgrc |
|
558 | $ echo "[hostfingerprints]" >> copy-pull/.hg/hgrc | |
559 | $ echo "localhost =" >> copy-pull/.hg/hgrc |
|
559 | $ echo "localhost =" >> copy-pull/.hg/hgrc | |
560 |
|
560 | |||
561 | Test unvalidated https through proxy |
|
561 | Test unvalidated https through proxy | |
562 |
|
562 | |||
563 | $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull --insecure |
|
563 | $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull --insecure | |
564 | pulling from https://localhost:$HGPORT/ |
|
564 | pulling from https://localhost:$HGPORT/ | |
565 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
565 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
566 | warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering |
|
566 | warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering | |
567 | searching for changes |
|
567 | searching for changes | |
568 | no changes found |
|
568 | no changes found | |
569 |
|
569 | |||
570 | Test https with cacert and fingerprint through proxy |
|
570 | Test https with cacert and fingerprint through proxy | |
571 |
|
571 | |||
572 | $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \ |
|
572 | $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \ | |
573 | > --config web.cacerts="$CERTSDIR/pub.pem" |
|
573 | > --config web.cacerts="$CERTSDIR/pub.pem" | |
574 | pulling from https://localhost:$HGPORT/ |
|
574 | pulling from https://localhost:$HGPORT/ | |
575 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
575 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
576 | searching for changes |
|
576 | searching for changes | |
577 | no changes found |
|
577 | no changes found | |
578 | $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull https://localhost:$HGPORT/ --config hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 --trace |
|
578 | $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull https://localhost:$HGPORT/ --config hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 --trace | |
579 | pulling from https://*:$HGPORT/ (glob) |
|
579 | pulling from https://*:$HGPORT/ (glob) | |
580 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
580 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
581 | (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: 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) |
|
581 | (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: 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) | |
582 | searching for changes |
|
582 | searching for changes | |
583 | no changes found |
|
583 | no changes found | |
584 |
|
584 | |||
585 | Test https with cert problems through proxy |
|
585 | Test https with cert problems through proxy | |
586 |
|
586 | |||
587 | $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \ |
|
587 | $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \ | |
588 | > --config web.cacerts="$CERTSDIR/pub-other.pem" |
|
588 | > --config web.cacerts="$CERTSDIR/pub-other.pem" | |
589 | pulling from https://localhost:$HGPORT/ |
|
589 | pulling from https://localhost:$HGPORT/ | |
590 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
590 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
591 | abort: error: *certificate verify failed* (glob) |
|
591 | abort: error: *certificate verify failed* (glob) | |
592 | [255] |
|
592 | [255] | |
593 | $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \ |
|
593 | $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \ | |
594 | > --config web.cacerts="$CERTSDIR/pub-expired.pem" https://localhost:$HGPORT2/ |
|
594 | > --config web.cacerts="$CERTSDIR/pub-expired.pem" https://localhost:$HGPORT2/ | |
595 | pulling from https://localhost:$HGPORT2/ |
|
595 | pulling from https://localhost:$HGPORT2/ | |
596 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
596 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
597 | abort: error: *certificate verify failed* (glob) |
|
597 | abort: error: *certificate verify failed* (glob) | |
598 | [255] |
|
598 | [255] | |
599 |
|
599 | |||
600 |
|
600 | |||
601 | $ killdaemons.py hg0.pid |
|
601 | $ killdaemons.py hg0.pid | |
602 |
|
602 | |||
603 | #if sslcontext |
|
603 | #if sslcontext | |
604 |
|
604 | |||
605 | Start hgweb that requires client certificates: |
|
605 | Start hgweb that requires client certificates: | |
606 |
|
606 | |||
607 | $ cd test |
|
607 | $ cd test | |
608 | $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV \ |
|
608 | $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV \ | |
609 | > --config devel.servercafile=$PRIV --config devel.serverrequirecert=true |
|
609 | > --config devel.servercafile=$PRIV --config devel.serverrequirecert=true | |
610 | $ cat ../hg0.pid >> $DAEMON_PIDS |
|
610 | $ cat ../hg0.pid >> $DAEMON_PIDS | |
611 | $ cd .. |
|
611 | $ cd .. | |
612 |
|
612 | |||
613 | without client certificate: |
|
613 | without client certificate: | |
614 |
|
614 | |||
615 | $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ |
|
615 | $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ | |
616 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
616 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
617 | abort: error: *handshake failure* (glob) |
|
617 | abort: error: *handshake failure* (glob) | |
618 | [255] |
|
618 | [255] | |
619 |
|
619 | |||
620 | with client certificate: |
|
620 | with client certificate: | |
621 |
|
621 | |||
622 | $ cat << EOT >> $HGRCPATH |
|
622 | $ cat << EOT >> $HGRCPATH | |
623 | > [auth] |
|
623 | > [auth] | |
624 | > l.prefix = localhost |
|
624 | > l.prefix = localhost | |
625 | > l.cert = $CERTSDIR/client-cert.pem |
|
625 | > l.cert = $CERTSDIR/client-cert.pem | |
626 | > l.key = $CERTSDIR/client-key.pem |
|
626 | > l.key = $CERTSDIR/client-key.pem | |
627 | > EOT |
|
627 | > EOT | |
628 |
|
628 | |||
629 | $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \ |
|
629 | $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \ | |
630 | > --config auth.l.key="$CERTSDIR/client-key-decrypted.pem" |
|
630 | > --config auth.l.key="$CERTSDIR/client-key-decrypted.pem" | |
631 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
631 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
632 | 5fed3813f7f5 |
|
632 | 5fed3813f7f5 | |
633 |
|
633 | |||
634 | $ printf '1234\n' | env P="$CERTSDIR" hg id https://localhost:$HGPORT/ \ |
|
634 | $ printf '1234\n' | env P="$CERTSDIR" hg id https://localhost:$HGPORT/ \ | |
635 | > --config ui.interactive=True --config ui.nontty=True |
|
635 | > --config ui.interactive=True --config ui.nontty=True | |
636 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
636 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
637 | passphrase for */client-key.pem: 5fed3813f7f5 (glob) |
|
637 | passphrase for */client-key.pem: 5fed3813f7f5 (glob) | |
638 |
|
638 | |||
639 | $ env P="$CERTSDIR" hg id https://localhost:$HGPORT/ |
|
639 | $ env P="$CERTSDIR" hg id https://localhost:$HGPORT/ | |
640 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) |
|
640 | warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) | |
641 | abort: error: * (glob) |
|
641 | abort: error: * (glob) | |
642 | [255] |
|
642 | [255] | |
643 |
|
643 | |||
644 | #endif |
|
644 | #endif |
@@ -1,203 +1,203 b'' | |||||
1 | #require killdaemons |
|
1 | #require killdaemons | |
2 |
|
2 | |||
3 | This test checks behavior related to bundle1 that changed or is likely |
|
3 | This test checks behavior related to bundle1 that changed or is likely | |
4 | to change with bundle2. Feel free to factor out any part of the test |
|
4 | to change with bundle2. Feel free to factor out any part of the test | |
5 | which does not need to exist to keep bundle1 working. |
|
5 | which does not need to exist to keep bundle1 working. | |
6 |
|
6 | |||
7 | $ cat << EOF >> $HGRCPATH |
|
7 | $ cat << EOF >> $HGRCPATH | |
8 | > [devel] |
|
8 | > [devel] | |
9 | > # This test is dedicated to interaction through old bundle |
|
9 | > # This test is dedicated to interaction through old bundle | |
10 | > legacy.exchange = bundle1 |
|
10 | > legacy.exchange = bundle1 | |
11 | > EOF |
|
11 | > EOF | |
12 |
|
12 | |||
13 | $ hg init test |
|
13 | $ hg init test | |
14 | $ cd test |
|
14 | $ cd test | |
15 | $ echo a > a |
|
15 | $ echo a > a | |
16 | $ hg ci -Ama |
|
16 | $ hg ci -Ama | |
17 | adding a |
|
17 | adding a | |
18 | $ cd .. |
|
18 | $ cd .. | |
19 | $ hg clone test test2 |
|
19 | $ hg clone test test2 | |
20 | updating to branch default |
|
20 | updating to branch default | |
21 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
21 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
22 | $ cd test2 |
|
22 | $ cd test2 | |
23 | $ echo a >> a |
|
23 | $ echo a >> a | |
24 | $ hg ci -mb |
|
24 | $ hg ci -mb | |
25 | $ req() { |
|
25 | $ req() { | |
26 | > hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log |
|
26 | > hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log | |
27 | > cat hg.pid >> $DAEMON_PIDS |
|
27 | > cat hg.pid >> $DAEMON_PIDS | |
28 | > hg --cwd ../test2 push http://localhost:$HGPORT/ |
|
28 | > hg --cwd ../test2 push http://localhost:$HGPORT/ | |
29 | > exitstatus=$? |
|
29 | > exitstatus=$? | |
30 | > killdaemons.py |
|
30 | > killdaemons.py | |
31 | > echo % serve errors |
|
31 | > echo % serve errors | |
32 | > cat errors.log |
|
32 | > cat errors.log | |
33 | > return $exitstatus |
|
33 | > return $exitstatus | |
34 | > } |
|
34 | > } | |
35 | $ cd ../test |
|
35 | $ cd ../test | |
36 |
|
36 | |||
37 | expect ssl error |
|
37 | expect ssl error | |
38 |
|
38 | |||
39 | $ req |
|
39 | $ req | |
40 | pushing to http://localhost:$HGPORT/ |
|
40 | pushing to http://localhost:$HGPORT/ | |
41 | searching for changes |
|
41 | searching for changes | |
42 | abort: HTTP Error 403: ssl required |
|
42 | abort: HTTP Error 403: ssl required | |
43 | % serve errors |
|
43 | % serve errors | |
44 | [255] |
|
44 | [255] | |
45 |
|
45 | |||
46 | expect authorization error |
|
46 | expect authorization error | |
47 |
|
47 | |||
48 | $ echo '[web]' > .hg/hgrc |
|
48 | $ echo '[web]' > .hg/hgrc | |
49 | $ echo 'push_ssl = false' >> .hg/hgrc |
|
49 | $ echo 'push_ssl = false' >> .hg/hgrc | |
50 | $ req |
|
50 | $ req | |
51 | pushing to http://localhost:$HGPORT/ |
|
51 | pushing to http://localhost:$HGPORT/ | |
52 | searching for changes |
|
52 | searching for changes | |
53 | abort: authorization failed |
|
53 | abort: authorization failed | |
54 | % serve errors |
|
54 | % serve errors | |
55 | [255] |
|
55 | [255] | |
56 |
|
56 | |||
57 | expect authorization error: must have authorized user |
|
57 | expect authorization error: must have authorized user | |
58 |
|
58 | |||
59 | $ echo 'allow_push = unperson' >> .hg/hgrc |
|
59 | $ echo 'allow_push = unperson' >> .hg/hgrc | |
60 | $ req |
|
60 | $ req | |
61 | pushing to http://localhost:$HGPORT/ |
|
61 | pushing to http://localhost:$HGPORT/ | |
62 | searching for changes |
|
62 | searching for changes | |
63 | abort: authorization failed |
|
63 | abort: authorization failed | |
64 | % serve errors |
|
64 | % serve errors | |
65 | [255] |
|
65 | [255] | |
66 |
|
66 | |||
67 | expect success |
|
67 | expect success | |
68 |
|
68 | |||
69 | $ cat >> .hg/hgrc <<EOF |
|
69 | $ cat >> .hg/hgrc <<EOF | |
70 | > allow_push = * |
|
70 | > allow_push = * | |
71 | > [hooks] |
|
71 | > [hooks] | |
72 | > changegroup = sh -c "printenv.py changegroup 0" |
|
72 | > changegroup = sh -c "printenv.py changegroup 0" | |
73 | > pushkey = sh -c "printenv.py pushkey 0" |
|
73 | > pushkey = sh -c "printenv.py pushkey 0" | |
74 | > EOF |
|
74 | > EOF | |
75 | $ req |
|
75 | $ req | |
76 | pushing to http://localhost:$HGPORT/ |
|
76 | pushing to http://localhost:$HGPORT/ | |
77 | searching for changes |
|
77 | searching for changes | |
78 | remote: adding changesets |
|
78 | remote: adding changesets | |
79 | remote: adding manifests |
|
79 | remote: adding manifests | |
80 | remote: adding file changes |
|
80 | remote: adding file changes | |
81 | remote: added 1 changesets with 1 changes to 1 files |
|
81 | remote: added 1 changesets with 1 changes to 1 files | |
82 |
remote: changegroup hook: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN: |
|
82 | remote: changegroup hook: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: | |
83 | % serve errors |
|
83 | % serve errors | |
84 | $ hg rollback |
|
84 | $ hg rollback | |
85 | repository tip rolled back to revision 0 (undo serve) |
|
85 | repository tip rolled back to revision 0 (undo serve) | |
86 |
|
86 | |||
87 | expect success, server lacks the httpheader capability |
|
87 | expect success, server lacks the httpheader capability | |
88 |
|
88 | |||
89 | $ CAP=httpheader |
|
89 | $ CAP=httpheader | |
90 | $ . "$TESTDIR/notcapable" |
|
90 | $ . "$TESTDIR/notcapable" | |
91 | $ req |
|
91 | $ req | |
92 | pushing to http://localhost:$HGPORT/ |
|
92 | pushing to http://localhost:$HGPORT/ | |
93 | searching for changes |
|
93 | searching for changes | |
94 | remote: adding changesets |
|
94 | remote: adding changesets | |
95 | remote: adding manifests |
|
95 | remote: adding manifests | |
96 | remote: adding file changes |
|
96 | remote: adding file changes | |
97 | remote: added 1 changesets with 1 changes to 1 files |
|
97 | remote: added 1 changesets with 1 changes to 1 files | |
98 |
remote: changegroup hook: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN: |
|
98 | remote: changegroup hook: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: | |
99 | % serve errors |
|
99 | % serve errors | |
100 | $ hg rollback |
|
100 | $ hg rollback | |
101 | repository tip rolled back to revision 0 (undo serve) |
|
101 | repository tip rolled back to revision 0 (undo serve) | |
102 |
|
102 | |||
103 | expect success, server lacks the unbundlehash capability |
|
103 | expect success, server lacks the unbundlehash capability | |
104 |
|
104 | |||
105 | $ CAP=unbundlehash |
|
105 | $ CAP=unbundlehash | |
106 | $ . "$TESTDIR/notcapable" |
|
106 | $ . "$TESTDIR/notcapable" | |
107 | $ req |
|
107 | $ req | |
108 | pushing to http://localhost:$HGPORT/ |
|
108 | pushing to http://localhost:$HGPORT/ | |
109 | searching for changes |
|
109 | searching for changes | |
110 | remote: adding changesets |
|
110 | remote: adding changesets | |
111 | remote: adding manifests |
|
111 | remote: adding manifests | |
112 | remote: adding file changes |
|
112 | remote: adding file changes | |
113 | remote: added 1 changesets with 1 changes to 1 files |
|
113 | remote: added 1 changesets with 1 changes to 1 files | |
114 |
remote: changegroup hook: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN: |
|
114 | remote: changegroup hook: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: | |
115 | % serve errors |
|
115 | % serve errors | |
116 | $ hg rollback |
|
116 | $ hg rollback | |
117 | repository tip rolled back to revision 0 (undo serve) |
|
117 | repository tip rolled back to revision 0 (undo serve) | |
118 |
|
118 | |||
119 | expect success, pre-d1b16a746db6 server supports the unbundle capability, but |
|
119 | expect success, pre-d1b16a746db6 server supports the unbundle capability, but | |
120 | has no parameter |
|
120 | has no parameter | |
121 |
|
121 | |||
122 | $ cat <<EOF > notcapable-unbundleparam.py |
|
122 | $ cat <<EOF > notcapable-unbundleparam.py | |
123 | > from mercurial import extensions, httppeer |
|
123 | > from mercurial import extensions, httppeer | |
124 | > def capable(orig, self, name): |
|
124 | > def capable(orig, self, name): | |
125 | > if name == 'unbundle': |
|
125 | > if name == 'unbundle': | |
126 | > return True |
|
126 | > return True | |
127 | > return orig(self, name) |
|
127 | > return orig(self, name) | |
128 | > def uisetup(ui): |
|
128 | > def uisetup(ui): | |
129 | > extensions.wrapfunction(httppeer.httppeer, 'capable', capable) |
|
129 | > extensions.wrapfunction(httppeer.httppeer, 'capable', capable) | |
130 | > EOF |
|
130 | > EOF | |
131 | $ cp $HGRCPATH $HGRCPATH.orig |
|
131 | $ cp $HGRCPATH $HGRCPATH.orig | |
132 | $ cat <<EOF >> $HGRCPATH |
|
132 | $ cat <<EOF >> $HGRCPATH | |
133 | > [extensions] |
|
133 | > [extensions] | |
134 | > notcapable-unbundleparam = `pwd`/notcapable-unbundleparam.py |
|
134 | > notcapable-unbundleparam = `pwd`/notcapable-unbundleparam.py | |
135 | > EOF |
|
135 | > EOF | |
136 | $ req |
|
136 | $ req | |
137 | pushing to http://localhost:$HGPORT/ |
|
137 | pushing to http://localhost:$HGPORT/ | |
138 | searching for changes |
|
138 | searching for changes | |
139 | remote: adding changesets |
|
139 | remote: adding changesets | |
140 | remote: adding manifests |
|
140 | remote: adding manifests | |
141 | remote: adding file changes |
|
141 | remote: adding file changes | |
142 | remote: added 1 changesets with 1 changes to 1 files |
|
142 | remote: added 1 changesets with 1 changes to 1 files | |
143 | remote: changegroup hook: * (glob) |
|
143 | remote: changegroup hook: * (glob) | |
144 | % serve errors |
|
144 | % serve errors | |
145 | $ hg rollback |
|
145 | $ hg rollback | |
146 | repository tip rolled back to revision 0 (undo serve) |
|
146 | repository tip rolled back to revision 0 (undo serve) | |
147 | $ mv $HGRCPATH.orig $HGRCPATH |
|
147 | $ mv $HGRCPATH.orig $HGRCPATH | |
148 |
|
148 | |||
149 | expect push success, phase change failure |
|
149 | expect push success, phase change failure | |
150 |
|
150 | |||
151 | $ cat > .hg/hgrc <<EOF |
|
151 | $ cat > .hg/hgrc <<EOF | |
152 | > [web] |
|
152 | > [web] | |
153 | > push_ssl = false |
|
153 | > push_ssl = false | |
154 | > allow_push = * |
|
154 | > allow_push = * | |
155 | > [hooks] |
|
155 | > [hooks] | |
156 | > prepushkey = sh -c "printenv.py prepushkey 1" |
|
156 | > prepushkey = sh -c "printenv.py prepushkey 1" | |
157 | > EOF |
|
157 | > EOF | |
158 | $ req |
|
158 | $ req | |
159 | pushing to http://localhost:$HGPORT/ |
|
159 | pushing to http://localhost:$HGPORT/ | |
160 | searching for changes |
|
160 | searching for changes | |
161 | remote: adding changesets |
|
161 | remote: adding changesets | |
162 | remote: adding manifests |
|
162 | remote: adding manifests | |
163 | remote: adding file changes |
|
163 | remote: adding file changes | |
164 | remote: added 1 changesets with 1 changes to 1 files |
|
164 | remote: added 1 changesets with 1 changes to 1 files | |
165 | % serve errors |
|
165 | % serve errors | |
166 |
|
166 | |||
167 | expect phase change success |
|
167 | expect phase change success | |
168 |
|
168 | |||
169 | $ cat >> .hg/hgrc <<EOF |
|
169 | $ cat >> .hg/hgrc <<EOF | |
170 | > prepushkey = sh -c "printenv.py prepushkey 0" |
|
170 | > prepushkey = sh -c "printenv.py prepushkey 0" | |
171 | > EOF |
|
171 | > EOF | |
172 | $ req |
|
172 | $ req | |
173 | pushing to http://localhost:$HGPORT/ |
|
173 | pushing to http://localhost:$HGPORT/ | |
174 | searching for changes |
|
174 | searching for changes | |
175 | no changes found |
|
175 | no changes found | |
176 | % serve errors |
|
176 | % serve errors | |
177 | [1] |
|
177 | [1] | |
178 | $ hg rollback |
|
178 | $ hg rollback | |
179 | repository tip rolled back to revision 0 (undo serve) |
|
179 | repository tip rolled back to revision 0 (undo serve) | |
180 |
|
180 | |||
181 | expect authorization error: all users denied |
|
181 | expect authorization error: all users denied | |
182 |
|
182 | |||
183 | $ echo '[web]' > .hg/hgrc |
|
183 | $ echo '[web]' > .hg/hgrc | |
184 | $ echo 'push_ssl = false' >> .hg/hgrc |
|
184 | $ echo 'push_ssl = false' >> .hg/hgrc | |
185 | $ echo 'deny_push = *' >> .hg/hgrc |
|
185 | $ echo 'deny_push = *' >> .hg/hgrc | |
186 | $ req |
|
186 | $ req | |
187 | pushing to http://localhost:$HGPORT/ |
|
187 | pushing to http://localhost:$HGPORT/ | |
188 | searching for changes |
|
188 | searching for changes | |
189 | abort: authorization failed |
|
189 | abort: authorization failed | |
190 | % serve errors |
|
190 | % serve errors | |
191 | [255] |
|
191 | [255] | |
192 |
|
192 | |||
193 | expect authorization error: some users denied, users must be authenticated |
|
193 | expect authorization error: some users denied, users must be authenticated | |
194 |
|
194 | |||
195 | $ echo 'deny_push = unperson' >> .hg/hgrc |
|
195 | $ echo 'deny_push = unperson' >> .hg/hgrc | |
196 | $ req |
|
196 | $ req | |
197 | pushing to http://localhost:$HGPORT/ |
|
197 | pushing to http://localhost:$HGPORT/ | |
198 | searching for changes |
|
198 | searching for changes | |
199 | abort: authorization failed |
|
199 | abort: authorization failed | |
200 | % serve errors |
|
200 | % serve errors | |
201 | [255] |
|
201 | [255] | |
202 |
|
202 | |||
203 | $ cd .. |
|
203 | $ cd .. |
@@ -1,175 +1,175 b'' | |||||
1 | #require killdaemons |
|
1 | #require killdaemons | |
2 |
|
2 | |||
3 | $ hg init test |
|
3 | $ hg init test | |
4 | $ cd test |
|
4 | $ cd test | |
5 | $ echo a > a |
|
5 | $ echo a > a | |
6 | $ hg ci -Ama |
|
6 | $ hg ci -Ama | |
7 | adding a |
|
7 | adding a | |
8 | $ cd .. |
|
8 | $ cd .. | |
9 | $ hg clone test test2 |
|
9 | $ hg clone test test2 | |
10 | updating to branch default |
|
10 | updating to branch default | |
11 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
11 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
12 | $ cd test2 |
|
12 | $ cd test2 | |
13 | $ echo a >> a |
|
13 | $ echo a >> a | |
14 | $ hg ci -mb |
|
14 | $ hg ci -mb | |
15 | $ req() { |
|
15 | $ req() { | |
16 | > hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log |
|
16 | > hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log | |
17 | > cat hg.pid >> $DAEMON_PIDS |
|
17 | > cat hg.pid >> $DAEMON_PIDS | |
18 | > hg --cwd ../test2 push http://localhost:$HGPORT/ |
|
18 | > hg --cwd ../test2 push http://localhost:$HGPORT/ | |
19 | > exitstatus=$? |
|
19 | > exitstatus=$? | |
20 | > killdaemons.py |
|
20 | > killdaemons.py | |
21 | > echo % serve errors |
|
21 | > echo % serve errors | |
22 | > cat errors.log |
|
22 | > cat errors.log | |
23 | > return $exitstatus |
|
23 | > return $exitstatus | |
24 | > } |
|
24 | > } | |
25 | $ cd ../test |
|
25 | $ cd ../test | |
26 |
|
26 | |||
27 | expect ssl error |
|
27 | expect ssl error | |
28 |
|
28 | |||
29 | $ req |
|
29 | $ req | |
30 | pushing to http://localhost:$HGPORT/ |
|
30 | pushing to http://localhost:$HGPORT/ | |
31 | searching for changes |
|
31 | searching for changes | |
32 | abort: HTTP Error 403: ssl required |
|
32 | abort: HTTP Error 403: ssl required | |
33 | % serve errors |
|
33 | % serve errors | |
34 | [255] |
|
34 | [255] | |
35 |
|
35 | |||
36 | expect authorization error |
|
36 | expect authorization error | |
37 |
|
37 | |||
38 | $ echo '[web]' > .hg/hgrc |
|
38 | $ echo '[web]' > .hg/hgrc | |
39 | $ echo 'push_ssl = false' >> .hg/hgrc |
|
39 | $ echo 'push_ssl = false' >> .hg/hgrc | |
40 | $ req |
|
40 | $ req | |
41 | pushing to http://localhost:$HGPORT/ |
|
41 | pushing to http://localhost:$HGPORT/ | |
42 | searching for changes |
|
42 | searching for changes | |
43 | abort: authorization failed |
|
43 | abort: authorization failed | |
44 | % serve errors |
|
44 | % serve errors | |
45 | [255] |
|
45 | [255] | |
46 |
|
46 | |||
47 | expect authorization error: must have authorized user |
|
47 | expect authorization error: must have authorized user | |
48 |
|
48 | |||
49 | $ echo 'allow_push = unperson' >> .hg/hgrc |
|
49 | $ echo 'allow_push = unperson' >> .hg/hgrc | |
50 | $ req |
|
50 | $ req | |
51 | pushing to http://localhost:$HGPORT/ |
|
51 | pushing to http://localhost:$HGPORT/ | |
52 | searching for changes |
|
52 | searching for changes | |
53 | abort: authorization failed |
|
53 | abort: authorization failed | |
54 | % serve errors |
|
54 | % serve errors | |
55 | [255] |
|
55 | [255] | |
56 |
|
56 | |||
57 | expect success |
|
57 | expect success | |
58 |
|
58 | |||
59 | $ cat >> .hg/hgrc <<EOF |
|
59 | $ cat >> .hg/hgrc <<EOF | |
60 | > allow_push = * |
|
60 | > allow_push = * | |
61 | > [hooks] |
|
61 | > [hooks] | |
62 | > changegroup = sh -c "printenv.py changegroup 0" |
|
62 | > changegroup = sh -c "printenv.py changegroup 0" | |
63 | > pushkey = sh -c "printenv.py pushkey 0" |
|
63 | > pushkey = sh -c "printenv.py pushkey 0" | |
64 | > EOF |
|
64 | > EOF | |
65 | $ req |
|
65 | $ req | |
66 | pushing to http://localhost:$HGPORT/ |
|
66 | pushing to http://localhost:$HGPORT/ | |
67 | searching for changes |
|
67 | searching for changes | |
68 | remote: adding changesets |
|
68 | remote: adding changesets | |
69 | remote: adding manifests |
|
69 | remote: adding manifests | |
70 | remote: adding file changes |
|
70 | remote: adding file changes | |
71 | remote: added 1 changesets with 1 changes to 1 files |
|
71 | remote: added 1 changesets with 1 changes to 1 files | |
72 | remote: pushkey hook: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1 |
|
72 | remote: pushkey hook: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1 | |
73 |
remote: changegroup hook: HG_BUNDLE2=1 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN: |
|
73 | remote: changegroup hook: HG_BUNDLE2=1 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: | |
74 | % serve errors |
|
74 | % serve errors | |
75 | $ hg rollback |
|
75 | $ hg rollback | |
76 | repository tip rolled back to revision 0 (undo serve) |
|
76 | repository tip rolled back to revision 0 (undo serve) | |
77 |
|
77 | |||
78 | expect success, server lacks the httpheader capability |
|
78 | expect success, server lacks the httpheader capability | |
79 |
|
79 | |||
80 | $ CAP=httpheader |
|
80 | $ CAP=httpheader | |
81 | $ . "$TESTDIR/notcapable" |
|
81 | $ . "$TESTDIR/notcapable" | |
82 | $ req |
|
82 | $ req | |
83 | pushing to http://localhost:$HGPORT/ |
|
83 | pushing to http://localhost:$HGPORT/ | |
84 | searching for changes |
|
84 | searching for changes | |
85 | remote: adding changesets |
|
85 | remote: adding changesets | |
86 | remote: adding manifests |
|
86 | remote: adding manifests | |
87 | remote: adding file changes |
|
87 | remote: adding file changes | |
88 | remote: added 1 changesets with 1 changes to 1 files |
|
88 | remote: added 1 changesets with 1 changes to 1 files | |
89 | remote: pushkey hook: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1 |
|
89 | remote: pushkey hook: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1 | |
90 |
remote: changegroup hook: HG_BUNDLE2=1 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN: |
|
90 | remote: changegroup hook: HG_BUNDLE2=1 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: | |
91 | % serve errors |
|
91 | % serve errors | |
92 | $ hg rollback |
|
92 | $ hg rollback | |
93 | repository tip rolled back to revision 0 (undo serve) |
|
93 | repository tip rolled back to revision 0 (undo serve) | |
94 |
|
94 | |||
95 | expect success, server lacks the unbundlehash capability |
|
95 | expect success, server lacks the unbundlehash capability | |
96 |
|
96 | |||
97 | $ CAP=unbundlehash |
|
97 | $ CAP=unbundlehash | |
98 | $ . "$TESTDIR/notcapable" |
|
98 | $ . "$TESTDIR/notcapable" | |
99 | $ req |
|
99 | $ req | |
100 | pushing to http://localhost:$HGPORT/ |
|
100 | pushing to http://localhost:$HGPORT/ | |
101 | searching for changes |
|
101 | searching for changes | |
102 | remote: adding changesets |
|
102 | remote: adding changesets | |
103 | remote: adding manifests |
|
103 | remote: adding manifests | |
104 | remote: adding file changes |
|
104 | remote: adding file changes | |
105 | remote: added 1 changesets with 1 changes to 1 files |
|
105 | remote: added 1 changesets with 1 changes to 1 files | |
106 | remote: pushkey hook: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1 |
|
106 | remote: pushkey hook: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1 | |
107 |
remote: changegroup hook: HG_BUNDLE2=1 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN: |
|
107 | remote: changegroup hook: HG_BUNDLE2=1 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: | |
108 | % serve errors |
|
108 | % serve errors | |
109 | $ hg rollback |
|
109 | $ hg rollback | |
110 | repository tip rolled back to revision 0 (undo serve) |
|
110 | repository tip rolled back to revision 0 (undo serve) | |
111 |
|
111 | |||
112 | expect push success, phase change failure |
|
112 | expect push success, phase change failure | |
113 |
|
113 | |||
114 | $ cat > .hg/hgrc <<EOF |
|
114 | $ cat > .hg/hgrc <<EOF | |
115 | > [web] |
|
115 | > [web] | |
116 | > push_ssl = false |
|
116 | > push_ssl = false | |
117 | > allow_push = * |
|
117 | > allow_push = * | |
118 | > [hooks] |
|
118 | > [hooks] | |
119 | > prepushkey = sh -c "printenv.py prepushkey 1" |
|
119 | > prepushkey = sh -c "printenv.py prepushkey 1" | |
120 | > EOF |
|
120 | > EOF | |
121 | $ req |
|
121 | $ req | |
122 | pushing to http://localhost:$HGPORT/ |
|
122 | pushing to http://localhost:$HGPORT/ | |
123 | searching for changes |
|
123 | searching for changes | |
124 | remote: adding changesets |
|
124 | remote: adding changesets | |
125 | remote: adding manifests |
|
125 | remote: adding manifests | |
126 | remote: adding file changes |
|
126 | remote: adding file changes | |
127 | remote: added 1 changesets with 1 changes to 1 files |
|
127 | remote: added 1 changesets with 1 changes to 1 files | |
128 |
remote: prepushkey hook: HG_BUNDLE2=1 HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN: |
|
128 | remote: prepushkey hook: HG_BUNDLE2=1 HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: | |
129 | remote: pushkey-abort: prepushkey hook exited with status 1 |
|
129 | remote: pushkey-abort: prepushkey hook exited with status 1 | |
130 | remote: transaction abort! |
|
130 | remote: transaction abort! | |
131 | remote: rollback completed |
|
131 | remote: rollback completed | |
132 | abort: updating ba677d0156c1 to public failed |
|
132 | abort: updating ba677d0156c1 to public failed | |
133 | % serve errors |
|
133 | % serve errors | |
134 | [255] |
|
134 | [255] | |
135 |
|
135 | |||
136 | expect phase change success |
|
136 | expect phase change success | |
137 |
|
137 | |||
138 | $ cat >> .hg/hgrc <<EOF |
|
138 | $ cat >> .hg/hgrc <<EOF | |
139 | > prepushkey = sh -c "printenv.py prepushkey 0" |
|
139 | > prepushkey = sh -c "printenv.py prepushkey 0" | |
140 | > EOF |
|
140 | > EOF | |
141 | $ req |
|
141 | $ req | |
142 | pushing to http://localhost:$HGPORT/ |
|
142 | pushing to http://localhost:$HGPORT/ | |
143 | searching for changes |
|
143 | searching for changes | |
144 | remote: adding changesets |
|
144 | remote: adding changesets | |
145 | remote: adding manifests |
|
145 | remote: adding manifests | |
146 | remote: adding file changes |
|
146 | remote: adding file changes | |
147 | remote: added 1 changesets with 1 changes to 1 files |
|
147 | remote: added 1 changesets with 1 changes to 1 files | |
148 |
remote: prepushkey hook: HG_BUNDLE2=1 HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN: |
|
148 | remote: prepushkey hook: HG_BUNDLE2=1 HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: | |
149 | % serve errors |
|
149 | % serve errors | |
150 | $ hg rollback |
|
150 | $ hg rollback | |
151 | repository tip rolled back to revision 0 (undo serve) |
|
151 | repository tip rolled back to revision 0 (undo serve) | |
152 |
|
152 | |||
153 | expect authorization error: all users denied |
|
153 | expect authorization error: all users denied | |
154 |
|
154 | |||
155 | $ echo '[web]' > .hg/hgrc |
|
155 | $ echo '[web]' > .hg/hgrc | |
156 | $ echo 'push_ssl = false' >> .hg/hgrc |
|
156 | $ echo 'push_ssl = false' >> .hg/hgrc | |
157 | $ echo 'deny_push = *' >> .hg/hgrc |
|
157 | $ echo 'deny_push = *' >> .hg/hgrc | |
158 | $ req |
|
158 | $ req | |
159 | pushing to http://localhost:$HGPORT/ |
|
159 | pushing to http://localhost:$HGPORT/ | |
160 | searching for changes |
|
160 | searching for changes | |
161 | abort: authorization failed |
|
161 | abort: authorization failed | |
162 | % serve errors |
|
162 | % serve errors | |
163 | [255] |
|
163 | [255] | |
164 |
|
164 | |||
165 | expect authorization error: some users denied, users must be authenticated |
|
165 | expect authorization error: some users denied, users must be authenticated | |
166 |
|
166 | |||
167 | $ echo 'deny_push = unperson' >> .hg/hgrc |
|
167 | $ echo 'deny_push = unperson' >> .hg/hgrc | |
168 | $ req |
|
168 | $ req | |
169 | pushing to http://localhost:$HGPORT/ |
|
169 | pushing to http://localhost:$HGPORT/ | |
170 | searching for changes |
|
170 | searching for changes | |
171 | abort: authorization failed |
|
171 | abort: authorization failed | |
172 | % serve errors |
|
172 | % serve errors | |
173 | [255] |
|
173 | [255] | |
174 |
|
174 | |||
175 | $ cd .. |
|
175 | $ cd .. |
@@ -1,562 +1,562 b'' | |||||
1 | This test is a duplicate of 'test-http.t' feel free to factor out |
|
1 | This test is a duplicate of 'test-http.t' feel free to factor out | |
2 | parts that are not bundle1/bundle2 specific. |
|
2 | parts that are not bundle1/bundle2 specific. | |
3 |
|
3 | |||
4 | $ cat << EOF >> $HGRCPATH |
|
4 | $ cat << EOF >> $HGRCPATH | |
5 | > [devel] |
|
5 | > [devel] | |
6 | > # This test is dedicated to interaction through old bundle |
|
6 | > # This test is dedicated to interaction through old bundle | |
7 | > legacy.exchange = bundle1 |
|
7 | > legacy.exchange = bundle1 | |
8 | > [format] # temporary settings |
|
8 | > [format] # temporary settings | |
9 | > usegeneraldelta=yes |
|
9 | > usegeneraldelta=yes | |
10 | > EOF |
|
10 | > EOF | |
11 |
|
11 | |||
12 |
|
12 | |||
13 | This test tries to exercise the ssh functionality with a dummy script |
|
13 | This test tries to exercise the ssh functionality with a dummy script | |
14 |
|
14 | |||
15 | creating 'remote' repo |
|
15 | creating 'remote' repo | |
16 |
|
16 | |||
17 | $ hg init remote |
|
17 | $ hg init remote | |
18 | $ cd remote |
|
18 | $ cd remote | |
19 | $ echo this > foo |
|
19 | $ echo this > foo | |
20 | $ echo this > fooO |
|
20 | $ echo this > fooO | |
21 | $ hg ci -A -m "init" foo fooO |
|
21 | $ hg ci -A -m "init" foo fooO | |
22 |
|
22 | |||
23 | insert a closed branch (issue4428) |
|
23 | insert a closed branch (issue4428) | |
24 |
|
24 | |||
25 | $ hg up null |
|
25 | $ hg up null | |
26 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
26 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved | |
27 | $ hg branch closed |
|
27 | $ hg branch closed | |
28 | marked working directory as branch closed |
|
28 | marked working directory as branch closed | |
29 | (branches are permanent and global, did you want a bookmark?) |
|
29 | (branches are permanent and global, did you want a bookmark?) | |
30 | $ hg ci -mc0 |
|
30 | $ hg ci -mc0 | |
31 | $ hg ci --close-branch -mc1 |
|
31 | $ hg ci --close-branch -mc1 | |
32 | $ hg up -q default |
|
32 | $ hg up -q default | |
33 |
|
33 | |||
34 | configure for serving |
|
34 | configure for serving | |
35 |
|
35 | |||
36 | $ cat <<EOF > .hg/hgrc |
|
36 | $ cat <<EOF > .hg/hgrc | |
37 | > [server] |
|
37 | > [server] | |
38 | > uncompressed = True |
|
38 | > uncompressed = True | |
39 | > |
|
39 | > | |
40 | > [hooks] |
|
40 | > [hooks] | |
41 | > changegroup = sh -c "printenv.py changegroup-in-remote 0 ../dummylog" |
|
41 | > changegroup = sh -c "printenv.py changegroup-in-remote 0 ../dummylog" | |
42 | > EOF |
|
42 | > EOF | |
43 | $ cd .. |
|
43 | $ cd .. | |
44 |
|
44 | |||
45 | repo not found error |
|
45 | repo not found error | |
46 |
|
46 | |||
47 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local |
|
47 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local | |
48 | remote: abort: repository nonexistent not found! |
|
48 | remote: abort: repository nonexistent not found! | |
49 | abort: no suitable response from remote hg! |
|
49 | abort: no suitable response from remote hg! | |
50 | [255] |
|
50 | [255] | |
51 |
|
51 | |||
52 | non-existent absolute path |
|
52 | non-existent absolute path | |
53 |
|
53 | |||
54 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy//`pwd`/nonexistent local |
|
54 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy//`pwd`/nonexistent local | |
55 | remote: abort: repository /$TESTTMP/nonexistent not found! |
|
55 | remote: abort: repository /$TESTTMP/nonexistent not found! | |
56 | abort: no suitable response from remote hg! |
|
56 | abort: no suitable response from remote hg! | |
57 | [255] |
|
57 | [255] | |
58 |
|
58 | |||
59 | clone remote via stream |
|
59 | clone remote via stream | |
60 |
|
60 | |||
61 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/remote local-stream |
|
61 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/remote local-stream | |
62 | streaming all changes |
|
62 | streaming all changes | |
63 | 4 files to transfer, 602 bytes of data |
|
63 | 4 files to transfer, 602 bytes of data | |
64 | transferred 602 bytes in * seconds (*) (glob) |
|
64 | transferred 602 bytes in * seconds (*) (glob) | |
65 | searching for changes |
|
65 | searching for changes | |
66 | no changes found |
|
66 | no changes found | |
67 | updating to branch default |
|
67 | updating to branch default | |
68 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
68 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
69 | $ cd local-stream |
|
69 | $ cd local-stream | |
70 | $ hg verify |
|
70 | $ hg verify | |
71 | checking changesets |
|
71 | checking changesets | |
72 | checking manifests |
|
72 | checking manifests | |
73 | crosschecking files in changesets and manifests |
|
73 | crosschecking files in changesets and manifests | |
74 | checking files |
|
74 | checking files | |
75 | 2 files, 3 changesets, 2 total revisions |
|
75 | 2 files, 3 changesets, 2 total revisions | |
76 | $ hg branches |
|
76 | $ hg branches | |
77 | default 0:1160648e36ce |
|
77 | default 0:1160648e36ce | |
78 | $ cd .. |
|
78 | $ cd .. | |
79 |
|
79 | |||
80 | clone bookmarks via stream |
|
80 | clone bookmarks via stream | |
81 |
|
81 | |||
82 | $ hg -R local-stream book mybook |
|
82 | $ hg -R local-stream book mybook | |
83 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/local-stream stream2 |
|
83 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/local-stream stream2 | |
84 | streaming all changes |
|
84 | streaming all changes | |
85 | 4 files to transfer, 602 bytes of data |
|
85 | 4 files to transfer, 602 bytes of data | |
86 | transferred 602 bytes in * seconds (*) (glob) |
|
86 | transferred 602 bytes in * seconds (*) (glob) | |
87 | searching for changes |
|
87 | searching for changes | |
88 | no changes found |
|
88 | no changes found | |
89 | updating to branch default |
|
89 | updating to branch default | |
90 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
90 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
91 | $ cd stream2 |
|
91 | $ cd stream2 | |
92 | $ hg book |
|
92 | $ hg book | |
93 | mybook 0:1160648e36ce |
|
93 | mybook 0:1160648e36ce | |
94 | $ cd .. |
|
94 | $ cd .. | |
95 | $ rm -rf local-stream stream2 |
|
95 | $ rm -rf local-stream stream2 | |
96 |
|
96 | |||
97 | clone remote via pull |
|
97 | clone remote via pull | |
98 |
|
98 | |||
99 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local |
|
99 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local | |
100 | requesting all changes |
|
100 | requesting all changes | |
101 | adding changesets |
|
101 | adding changesets | |
102 | adding manifests |
|
102 | adding manifests | |
103 | adding file changes |
|
103 | adding file changes | |
104 | added 3 changesets with 2 changes to 2 files |
|
104 | added 3 changesets with 2 changes to 2 files | |
105 | updating to branch default |
|
105 | updating to branch default | |
106 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
106 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
107 |
|
107 | |||
108 | verify |
|
108 | verify | |
109 |
|
109 | |||
110 | $ cd local |
|
110 | $ cd local | |
111 | $ hg verify |
|
111 | $ hg verify | |
112 | checking changesets |
|
112 | checking changesets | |
113 | checking manifests |
|
113 | checking manifests | |
114 | crosschecking files in changesets and manifests |
|
114 | crosschecking files in changesets and manifests | |
115 | checking files |
|
115 | checking files | |
116 | 2 files, 3 changesets, 2 total revisions |
|
116 | 2 files, 3 changesets, 2 total revisions | |
117 | $ cat >> .hg/hgrc <<EOF |
|
117 | $ cat >> .hg/hgrc <<EOF | |
118 | > [hooks] |
|
118 | > [hooks] | |
119 | > changegroup = sh -c "printenv.py changegroup-in-local 0 ../dummylog" |
|
119 | > changegroup = sh -c "printenv.py changegroup-in-local 0 ../dummylog" | |
120 | > EOF |
|
120 | > EOF | |
121 |
|
121 | |||
122 | empty default pull |
|
122 | empty default pull | |
123 |
|
123 | |||
124 | $ hg paths |
|
124 | $ hg paths | |
125 | default = ssh://user@dummy/remote |
|
125 | default = ssh://user@dummy/remote | |
126 | $ hg pull -e "python \"$TESTDIR/dummyssh\"" |
|
126 | $ hg pull -e "python \"$TESTDIR/dummyssh\"" | |
127 | pulling from ssh://user@dummy/remote |
|
127 | pulling from ssh://user@dummy/remote | |
128 | searching for changes |
|
128 | searching for changes | |
129 | no changes found |
|
129 | no changes found | |
130 |
|
130 | |||
131 | pull from wrong ssh URL |
|
131 | pull from wrong ssh URL | |
132 |
|
132 | |||
133 | $ hg pull -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/doesnotexist |
|
133 | $ hg pull -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/doesnotexist | |
134 | pulling from ssh://user@dummy/doesnotexist |
|
134 | pulling from ssh://user@dummy/doesnotexist | |
135 | remote: abort: repository doesnotexist not found! |
|
135 | remote: abort: repository doesnotexist not found! | |
136 | abort: no suitable response from remote hg! |
|
136 | abort: no suitable response from remote hg! | |
137 | [255] |
|
137 | [255] | |
138 |
|
138 | |||
139 | local change |
|
139 | local change | |
140 |
|
140 | |||
141 | $ echo bleah > foo |
|
141 | $ echo bleah > foo | |
142 | $ hg ci -m "add" |
|
142 | $ hg ci -m "add" | |
143 |
|
143 | |||
144 | updating rc |
|
144 | updating rc | |
145 |
|
145 | |||
146 | $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc |
|
146 | $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc | |
147 | $ echo "[ui]" >> .hg/hgrc |
|
147 | $ echo "[ui]" >> .hg/hgrc | |
148 | $ echo "ssh = python \"$TESTDIR/dummyssh\"" >> .hg/hgrc |
|
148 | $ echo "ssh = python \"$TESTDIR/dummyssh\"" >> .hg/hgrc | |
149 |
|
149 | |||
150 | find outgoing |
|
150 | find outgoing | |
151 |
|
151 | |||
152 | $ hg out ssh://user@dummy/remote |
|
152 | $ hg out ssh://user@dummy/remote | |
153 | comparing with ssh://user@dummy/remote |
|
153 | comparing with ssh://user@dummy/remote | |
154 | searching for changes |
|
154 | searching for changes | |
155 | changeset: 3:a28a9d1a809c |
|
155 | changeset: 3:a28a9d1a809c | |
156 | tag: tip |
|
156 | tag: tip | |
157 | parent: 0:1160648e36ce |
|
157 | parent: 0:1160648e36ce | |
158 | user: test |
|
158 | user: test | |
159 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
159 | date: Thu Jan 01 00:00:00 1970 +0000 | |
160 | summary: add |
|
160 | summary: add | |
161 |
|
161 | |||
162 |
|
162 | |||
163 | find incoming on the remote side |
|
163 | find incoming on the remote side | |
164 |
|
164 | |||
165 | $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/local |
|
165 | $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/local | |
166 | comparing with ssh://user@dummy/local |
|
166 | comparing with ssh://user@dummy/local | |
167 | searching for changes |
|
167 | searching for changes | |
168 | changeset: 3:a28a9d1a809c |
|
168 | changeset: 3:a28a9d1a809c | |
169 | tag: tip |
|
169 | tag: tip | |
170 | parent: 0:1160648e36ce |
|
170 | parent: 0:1160648e36ce | |
171 | user: test |
|
171 | user: test | |
172 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
172 | date: Thu Jan 01 00:00:00 1970 +0000 | |
173 | summary: add |
|
173 | summary: add | |
174 |
|
174 | |||
175 |
|
175 | |||
176 | find incoming on the remote side (using absolute path) |
|
176 | find incoming on the remote side (using absolute path) | |
177 |
|
177 | |||
178 | $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/`pwd`" |
|
178 | $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/`pwd`" | |
179 | comparing with ssh://user@dummy/$TESTTMP/local |
|
179 | comparing with ssh://user@dummy/$TESTTMP/local | |
180 | searching for changes |
|
180 | searching for changes | |
181 | changeset: 3:a28a9d1a809c |
|
181 | changeset: 3:a28a9d1a809c | |
182 | tag: tip |
|
182 | tag: tip | |
183 | parent: 0:1160648e36ce |
|
183 | parent: 0:1160648e36ce | |
184 | user: test |
|
184 | user: test | |
185 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
185 | date: Thu Jan 01 00:00:00 1970 +0000 | |
186 | summary: add |
|
186 | summary: add | |
187 |
|
187 | |||
188 |
|
188 | |||
189 | push |
|
189 | push | |
190 |
|
190 | |||
191 | $ hg push |
|
191 | $ hg push | |
192 | pushing to ssh://user@dummy/remote |
|
192 | pushing to ssh://user@dummy/remote | |
193 | searching for changes |
|
193 | searching for changes | |
194 | remote: adding changesets |
|
194 | remote: adding changesets | |
195 | remote: adding manifests |
|
195 | remote: adding manifests | |
196 | remote: adding file changes |
|
196 | remote: adding file changes | |
197 | remote: added 1 changesets with 1 changes to 1 files |
|
197 | remote: added 1 changesets with 1 changes to 1 files | |
198 | $ cd ../remote |
|
198 | $ cd ../remote | |
199 |
|
199 | |||
200 | check remote tip |
|
200 | check remote tip | |
201 |
|
201 | |||
202 | $ hg tip |
|
202 | $ hg tip | |
203 | changeset: 3:a28a9d1a809c |
|
203 | changeset: 3:a28a9d1a809c | |
204 | tag: tip |
|
204 | tag: tip | |
205 | parent: 0:1160648e36ce |
|
205 | parent: 0:1160648e36ce | |
206 | user: test |
|
206 | user: test | |
207 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
207 | date: Thu Jan 01 00:00:00 1970 +0000 | |
208 | summary: add |
|
208 | summary: add | |
209 |
|
209 | |||
210 | $ hg verify |
|
210 | $ hg verify | |
211 | checking changesets |
|
211 | checking changesets | |
212 | checking manifests |
|
212 | checking manifests | |
213 | crosschecking files in changesets and manifests |
|
213 | crosschecking files in changesets and manifests | |
214 | checking files |
|
214 | checking files | |
215 | 2 files, 4 changesets, 3 total revisions |
|
215 | 2 files, 4 changesets, 3 total revisions | |
216 | $ hg cat -r tip foo |
|
216 | $ hg cat -r tip foo | |
217 | bleah |
|
217 | bleah | |
218 | $ echo z > z |
|
218 | $ echo z > z | |
219 | $ hg ci -A -m z z |
|
219 | $ hg ci -A -m z z | |
220 | created new head |
|
220 | created new head | |
221 |
|
221 | |||
222 | test pushkeys and bookmarks |
|
222 | test pushkeys and bookmarks | |
223 |
|
223 | |||
224 | $ cd ../local |
|
224 | $ cd ../local | |
225 | $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote namespaces |
|
225 | $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote namespaces | |
226 | bookmarks |
|
226 | bookmarks | |
227 | namespaces |
|
227 | namespaces | |
228 | phases |
|
228 | phases | |
229 | $ hg book foo -r 0 |
|
229 | $ hg book foo -r 0 | |
230 | $ hg out -B |
|
230 | $ hg out -B | |
231 | comparing with ssh://user@dummy/remote |
|
231 | comparing with ssh://user@dummy/remote | |
232 | searching for changed bookmarks |
|
232 | searching for changed bookmarks | |
233 | foo 1160648e36ce |
|
233 | foo 1160648e36ce | |
234 | $ hg push -B foo |
|
234 | $ hg push -B foo | |
235 | pushing to ssh://user@dummy/remote |
|
235 | pushing to ssh://user@dummy/remote | |
236 | searching for changes |
|
236 | searching for changes | |
237 | no changes found |
|
237 | no changes found | |
238 | exporting bookmark foo |
|
238 | exporting bookmark foo | |
239 | [1] |
|
239 | [1] | |
240 | $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote bookmarks |
|
240 | $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote bookmarks | |
241 | foo 1160648e36cec0054048a7edc4110c6f84fde594 |
|
241 | foo 1160648e36cec0054048a7edc4110c6f84fde594 | |
242 | $ hg book -f foo |
|
242 | $ hg book -f foo | |
243 | $ hg push --traceback |
|
243 | $ hg push --traceback | |
244 | pushing to ssh://user@dummy/remote |
|
244 | pushing to ssh://user@dummy/remote | |
245 | searching for changes |
|
245 | searching for changes | |
246 | no changes found |
|
246 | no changes found | |
247 | updating bookmark foo |
|
247 | updating bookmark foo | |
248 | [1] |
|
248 | [1] | |
249 | $ hg book -d foo |
|
249 | $ hg book -d foo | |
250 | $ hg in -B |
|
250 | $ hg in -B | |
251 | comparing with ssh://user@dummy/remote |
|
251 | comparing with ssh://user@dummy/remote | |
252 | searching for changed bookmarks |
|
252 | searching for changed bookmarks | |
253 | foo a28a9d1a809c |
|
253 | foo a28a9d1a809c | |
254 | $ hg book -f -r 0 foo |
|
254 | $ hg book -f -r 0 foo | |
255 | $ hg pull -B foo |
|
255 | $ hg pull -B foo | |
256 | pulling from ssh://user@dummy/remote |
|
256 | pulling from ssh://user@dummy/remote | |
257 | no changes found |
|
257 | no changes found | |
258 | updating bookmark foo |
|
258 | updating bookmark foo | |
259 | $ hg book -d foo |
|
259 | $ hg book -d foo | |
260 | $ hg push -B foo |
|
260 | $ hg push -B foo | |
261 | pushing to ssh://user@dummy/remote |
|
261 | pushing to ssh://user@dummy/remote | |
262 | searching for changes |
|
262 | searching for changes | |
263 | no changes found |
|
263 | no changes found | |
264 | deleting remote bookmark foo |
|
264 | deleting remote bookmark foo | |
265 | [1] |
|
265 | [1] | |
266 |
|
266 | |||
267 | a bad, evil hook that prints to stdout |
|
267 | a bad, evil hook that prints to stdout | |
268 |
|
268 | |||
269 | $ cat <<EOF > $TESTTMP/badhook |
|
269 | $ cat <<EOF > $TESTTMP/badhook | |
270 | > import sys |
|
270 | > import sys | |
271 | > sys.stdout.write("KABOOM\n") |
|
271 | > sys.stdout.write("KABOOM\n") | |
272 | > EOF |
|
272 | > EOF | |
273 |
|
273 | |||
274 | $ echo '[hooks]' >> ../remote/.hg/hgrc |
|
274 | $ echo '[hooks]' >> ../remote/.hg/hgrc | |
275 | $ echo "changegroup.stdout = python $TESTTMP/badhook" >> ../remote/.hg/hgrc |
|
275 | $ echo "changegroup.stdout = python $TESTTMP/badhook" >> ../remote/.hg/hgrc | |
276 | $ echo r > r |
|
276 | $ echo r > r | |
277 | $ hg ci -A -m z r |
|
277 | $ hg ci -A -m z r | |
278 |
|
278 | |||
279 | push should succeed even though it has an unexpected response |
|
279 | push should succeed even though it has an unexpected response | |
280 |
|
280 | |||
281 | $ hg push |
|
281 | $ hg push | |
282 | pushing to ssh://user@dummy/remote |
|
282 | pushing to ssh://user@dummy/remote | |
283 | searching for changes |
|
283 | searching for changes | |
284 | remote has heads on branch 'default' that are not known locally: 6c0482d977a3 |
|
284 | remote has heads on branch 'default' that are not known locally: 6c0482d977a3 | |
285 | remote: adding changesets |
|
285 | remote: adding changesets | |
286 | remote: adding manifests |
|
286 | remote: adding manifests | |
287 | remote: adding file changes |
|
287 | remote: adding file changes | |
288 | remote: added 1 changesets with 1 changes to 1 files |
|
288 | remote: added 1 changesets with 1 changes to 1 files | |
289 | remote: KABOOM |
|
289 | remote: KABOOM | |
290 | $ hg -R ../remote heads |
|
290 | $ hg -R ../remote heads | |
291 | changeset: 5:1383141674ec |
|
291 | changeset: 5:1383141674ec | |
292 | tag: tip |
|
292 | tag: tip | |
293 | parent: 3:a28a9d1a809c |
|
293 | parent: 3:a28a9d1a809c | |
294 | user: test |
|
294 | user: test | |
295 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
295 | date: Thu Jan 01 00:00:00 1970 +0000 | |
296 | summary: z |
|
296 | summary: z | |
297 |
|
297 | |||
298 | changeset: 4:6c0482d977a3 |
|
298 | changeset: 4:6c0482d977a3 | |
299 | parent: 0:1160648e36ce |
|
299 | parent: 0:1160648e36ce | |
300 | user: test |
|
300 | user: test | |
301 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
301 | date: Thu Jan 01 00:00:00 1970 +0000 | |
302 | summary: z |
|
302 | summary: z | |
303 |
|
303 | |||
304 |
|
304 | |||
305 | clone bookmarks |
|
305 | clone bookmarks | |
306 |
|
306 | |||
307 | $ hg -R ../remote bookmark test |
|
307 | $ hg -R ../remote bookmark test | |
308 | $ hg -R ../remote bookmarks |
|
308 | $ hg -R ../remote bookmarks | |
309 | * test 4:6c0482d977a3 |
|
309 | * test 4:6c0482d977a3 | |
310 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local-bookmarks |
|
310 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local-bookmarks | |
311 | requesting all changes |
|
311 | requesting all changes | |
312 | adding changesets |
|
312 | adding changesets | |
313 | adding manifests |
|
313 | adding manifests | |
314 | adding file changes |
|
314 | adding file changes | |
315 | added 6 changesets with 5 changes to 4 files (+1 heads) |
|
315 | added 6 changesets with 5 changes to 4 files (+1 heads) | |
316 | updating to branch default |
|
316 | updating to branch default | |
317 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
317 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
318 | $ hg -R local-bookmarks bookmarks |
|
318 | $ hg -R local-bookmarks bookmarks | |
319 | test 4:6c0482d977a3 |
|
319 | test 4:6c0482d977a3 | |
320 |
|
320 | |||
321 | passwords in ssh urls are not supported |
|
321 | passwords in ssh urls are not supported | |
322 | (we use a glob here because different Python versions give different |
|
322 | (we use a glob here because different Python versions give different | |
323 | results here) |
|
323 | results here) | |
324 |
|
324 | |||
325 | $ hg push ssh://user:erroneouspwd@dummy/remote |
|
325 | $ hg push ssh://user:erroneouspwd@dummy/remote | |
326 | pushing to ssh://user:*@dummy/remote (glob) |
|
326 | pushing to ssh://user:*@dummy/remote (glob) | |
327 | abort: password in URL not supported! |
|
327 | abort: password in URL not supported! | |
328 | [255] |
|
328 | [255] | |
329 |
|
329 | |||
330 | $ cd .. |
|
330 | $ cd .. | |
331 |
|
331 | |||
332 | hide outer repo |
|
332 | hide outer repo | |
333 | $ hg init |
|
333 | $ hg init | |
334 |
|
334 | |||
335 | Test remote paths with spaces (issue2983): |
|
335 | Test remote paths with spaces (issue2983): | |
336 |
|
336 | |||
337 | $ hg init --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo" |
|
337 | $ hg init --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo" | |
338 | $ touch "$TESTTMP/a repo/test" |
|
338 | $ touch "$TESTTMP/a repo/test" | |
339 | $ hg -R 'a repo' commit -A -m "test" |
|
339 | $ hg -R 'a repo' commit -A -m "test" | |
340 | adding test |
|
340 | adding test | |
341 | $ hg -R 'a repo' tag tag |
|
341 | $ hg -R 'a repo' tag tag | |
342 | $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo" |
|
342 | $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo" | |
343 | 73649e48688a |
|
343 | 73649e48688a | |
344 |
|
344 | |||
345 | $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo#noNoNO" |
|
345 | $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo#noNoNO" | |
346 | abort: unknown revision 'noNoNO'! |
|
346 | abort: unknown revision 'noNoNO'! | |
347 | [255] |
|
347 | [255] | |
348 |
|
348 | |||
349 | Test (non-)escaping of remote paths with spaces when cloning (issue3145): |
|
349 | Test (non-)escaping of remote paths with spaces when cloning (issue3145): | |
350 |
|
350 | |||
351 | $ hg clone --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo" |
|
351 | $ hg clone --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo" | |
352 | destination directory: a repo |
|
352 | destination directory: a repo | |
353 | abort: destination 'a repo' is not empty |
|
353 | abort: destination 'a repo' is not empty | |
354 | [255] |
|
354 | [255] | |
355 |
|
355 | |||
356 | Test hg-ssh using a helper script that will restore PYTHONPATH (which might |
|
356 | Test hg-ssh using a helper script that will restore PYTHONPATH (which might | |
357 | have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right |
|
357 | have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right | |
358 | parameters: |
|
358 | parameters: | |
359 |
|
359 | |||
360 | $ cat > ssh.sh << EOF |
|
360 | $ cat > ssh.sh << EOF | |
361 | > userhost="\$1" |
|
361 | > userhost="\$1" | |
362 | > SSH_ORIGINAL_COMMAND="\$2" |
|
362 | > SSH_ORIGINAL_COMMAND="\$2" | |
363 | > export SSH_ORIGINAL_COMMAND |
|
363 | > export SSH_ORIGINAL_COMMAND | |
364 | > PYTHONPATH="$PYTHONPATH" |
|
364 | > PYTHONPATH="$PYTHONPATH" | |
365 | > export PYTHONPATH |
|
365 | > export PYTHONPATH | |
366 | > python "$TESTDIR/../contrib/hg-ssh" "$TESTTMP/a repo" |
|
366 | > python "$TESTDIR/../contrib/hg-ssh" "$TESTTMP/a repo" | |
367 | > EOF |
|
367 | > EOF | |
368 |
|
368 | |||
369 | $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a repo" |
|
369 | $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a repo" | |
370 | 73649e48688a |
|
370 | 73649e48688a | |
371 |
|
371 | |||
372 | $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo" |
|
372 | $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo" | |
373 | remote: Illegal repository "$TESTTMP/a'repo" (glob) |
|
373 | remote: Illegal repository "$TESTTMP/a'repo" (glob) | |
374 | abort: no suitable response from remote hg! |
|
374 | abort: no suitable response from remote hg! | |
375 | [255] |
|
375 | [255] | |
376 |
|
376 | |||
377 | $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo" |
|
377 | $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo" | |
378 | remote: Illegal command "hacking -R 'a'\''repo' serve --stdio" |
|
378 | remote: Illegal command "hacking -R 'a'\''repo' serve --stdio" | |
379 | abort: no suitable response from remote hg! |
|
379 | abort: no suitable response from remote hg! | |
380 | [255] |
|
380 | [255] | |
381 |
|
381 | |||
382 | $ SSH_ORIGINAL_COMMAND="'hg' serve -R 'a'repo' --stdio" python "$TESTDIR/../contrib/hg-ssh" |
|
382 | $ SSH_ORIGINAL_COMMAND="'hg' serve -R 'a'repo' --stdio" python "$TESTDIR/../contrib/hg-ssh" | |
383 | Illegal command "'hg' serve -R 'a'repo' --stdio": No closing quotation |
|
383 | Illegal command "'hg' serve -R 'a'repo' --stdio": No closing quotation | |
384 | [255] |
|
384 | [255] | |
385 |
|
385 | |||
386 | Test hg-ssh in read-only mode: |
|
386 | Test hg-ssh in read-only mode: | |
387 |
|
387 | |||
388 | $ cat > ssh.sh << EOF |
|
388 | $ cat > ssh.sh << EOF | |
389 | > userhost="\$1" |
|
389 | > userhost="\$1" | |
390 | > SSH_ORIGINAL_COMMAND="\$2" |
|
390 | > SSH_ORIGINAL_COMMAND="\$2" | |
391 | > export SSH_ORIGINAL_COMMAND |
|
391 | > export SSH_ORIGINAL_COMMAND | |
392 | > PYTHONPATH="$PYTHONPATH" |
|
392 | > PYTHONPATH="$PYTHONPATH" | |
393 | > export PYTHONPATH |
|
393 | > export PYTHONPATH | |
394 | > python "$TESTDIR/../contrib/hg-ssh" --read-only "$TESTTMP/remote" |
|
394 | > python "$TESTDIR/../contrib/hg-ssh" --read-only "$TESTTMP/remote" | |
395 | > EOF |
|
395 | > EOF | |
396 |
|
396 | |||
397 | $ hg clone --ssh "sh ssh.sh" "ssh://user@dummy/$TESTTMP/remote" read-only-local |
|
397 | $ hg clone --ssh "sh ssh.sh" "ssh://user@dummy/$TESTTMP/remote" read-only-local | |
398 | requesting all changes |
|
398 | requesting all changes | |
399 | adding changesets |
|
399 | adding changesets | |
400 | adding manifests |
|
400 | adding manifests | |
401 | adding file changes |
|
401 | adding file changes | |
402 | added 6 changesets with 5 changes to 4 files (+1 heads) |
|
402 | added 6 changesets with 5 changes to 4 files (+1 heads) | |
403 | updating to branch default |
|
403 | updating to branch default | |
404 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
404 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
405 |
|
405 | |||
406 | $ cd read-only-local |
|
406 | $ cd read-only-local | |
407 | $ echo "baz" > bar |
|
407 | $ echo "baz" > bar | |
408 | $ hg ci -A -m "unpushable commit" bar |
|
408 | $ hg ci -A -m "unpushable commit" bar | |
409 | $ hg push --ssh "sh ../ssh.sh" |
|
409 | $ hg push --ssh "sh ../ssh.sh" | |
410 | pushing to ssh://user@dummy/*/remote (glob) |
|
410 | pushing to ssh://user@dummy/*/remote (glob) | |
411 | searching for changes |
|
411 | searching for changes | |
412 | remote: Permission denied |
|
412 | remote: Permission denied | |
413 | remote: abort: pretxnopen.hg-ssh hook failed |
|
413 | remote: abort: pretxnopen.hg-ssh hook failed | |
414 | remote: Permission denied |
|
414 | remote: Permission denied | |
415 | remote: pushkey-abort: prepushkey.hg-ssh hook failed |
|
415 | remote: pushkey-abort: prepushkey.hg-ssh hook failed | |
416 | updating 6c0482d977a3 to public failed! |
|
416 | updating 6c0482d977a3 to public failed! | |
417 | [1] |
|
417 | [1] | |
418 |
|
418 | |||
419 | $ cd .. |
|
419 | $ cd .. | |
420 |
|
420 | |||
421 | stderr from remote commands should be printed before stdout from local code (issue4336) |
|
421 | stderr from remote commands should be printed before stdout from local code (issue4336) | |
422 |
|
422 | |||
423 | $ hg clone remote stderr-ordering |
|
423 | $ hg clone remote stderr-ordering | |
424 | updating to branch default |
|
424 | updating to branch default | |
425 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
425 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
426 | $ cd stderr-ordering |
|
426 | $ cd stderr-ordering | |
427 | $ cat >> localwrite.py << EOF |
|
427 | $ cat >> localwrite.py << EOF | |
428 | > from mercurial import exchange, extensions |
|
428 | > from mercurial import exchange, extensions | |
429 | > |
|
429 | > | |
430 | > def wrappedpush(orig, repo, *args, **kwargs): |
|
430 | > def wrappedpush(orig, repo, *args, **kwargs): | |
431 | > res = orig(repo, *args, **kwargs) |
|
431 | > res = orig(repo, *args, **kwargs) | |
432 | > repo.ui.write('local stdout\n') |
|
432 | > repo.ui.write('local stdout\n') | |
433 | > return res |
|
433 | > return res | |
434 | > |
|
434 | > | |
435 | > def extsetup(ui): |
|
435 | > def extsetup(ui): | |
436 | > extensions.wrapfunction(exchange, 'push', wrappedpush) |
|
436 | > extensions.wrapfunction(exchange, 'push', wrappedpush) | |
437 | > EOF |
|
437 | > EOF | |
438 |
|
438 | |||
439 | $ cat >> .hg/hgrc << EOF |
|
439 | $ cat >> .hg/hgrc << EOF | |
440 | > [paths] |
|
440 | > [paths] | |
441 | > default-push = ssh://user@dummy/remote |
|
441 | > default-push = ssh://user@dummy/remote | |
442 | > [ui] |
|
442 | > [ui] | |
443 | > ssh = python "$TESTDIR/dummyssh" |
|
443 | > ssh = python "$TESTDIR/dummyssh" | |
444 | > [extensions] |
|
444 | > [extensions] | |
445 | > localwrite = localwrite.py |
|
445 | > localwrite = localwrite.py | |
446 | > EOF |
|
446 | > EOF | |
447 |
|
447 | |||
448 | $ echo localwrite > foo |
|
448 | $ echo localwrite > foo | |
449 | $ hg commit -m 'testing localwrite' |
|
449 | $ hg commit -m 'testing localwrite' | |
450 | $ hg push |
|
450 | $ hg push | |
451 | pushing to ssh://user@dummy/remote |
|
451 | pushing to ssh://user@dummy/remote | |
452 | searching for changes |
|
452 | searching for changes | |
453 | remote: adding changesets |
|
453 | remote: adding changesets | |
454 | remote: adding manifests |
|
454 | remote: adding manifests | |
455 | remote: adding file changes |
|
455 | remote: adding file changes | |
456 | remote: added 1 changesets with 1 changes to 1 files |
|
456 | remote: added 1 changesets with 1 changes to 1 files | |
457 | remote: KABOOM |
|
457 | remote: KABOOM | |
458 | local stdout |
|
458 | local stdout | |
459 |
|
459 | |||
460 | debug output |
|
460 | debug output | |
461 |
|
461 | |||
462 | $ hg pull --debug ssh://user@dummy/remote |
|
462 | $ hg pull --debug ssh://user@dummy/remote | |
463 | pulling from ssh://user@dummy/remote |
|
463 | pulling from ssh://user@dummy/remote | |
464 | running python ".*/dummyssh" user@dummy ('|")hg -R remote serve --stdio('|") (re) |
|
464 | running python ".*/dummyssh" user@dummy ('|")hg -R remote serve --stdio('|") (re) | |
465 | sending hello command |
|
465 | sending hello command | |
466 | sending between command |
|
466 | sending between command | |
467 | remote: 355 |
|
467 | remote: 355 | |
468 | remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN |
|
468 | remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN | |
469 | remote: 1 |
|
469 | remote: 1 | |
470 | preparing listkeys for "bookmarks" |
|
470 | preparing listkeys for "bookmarks" | |
471 | sending listkeys command |
|
471 | sending listkeys command | |
472 | received listkey for "bookmarks": 45 bytes |
|
472 | received listkey for "bookmarks": 45 bytes | |
473 | query 1; heads |
|
473 | query 1; heads | |
474 | sending batch command |
|
474 | sending batch command | |
475 | searching for changes |
|
475 | searching for changes | |
476 | all remote heads known locally |
|
476 | all remote heads known locally | |
477 | no changes found |
|
477 | no changes found | |
478 | preparing listkeys for "phases" |
|
478 | preparing listkeys for "phases" | |
479 | sending listkeys command |
|
479 | sending listkeys command | |
480 | received listkey for "phases": 15 bytes |
|
480 | received listkey for "phases": 15 bytes | |
481 | checking for updated bookmarks |
|
481 | checking for updated bookmarks | |
482 |
|
482 | |||
483 | $ cd .. |
|
483 | $ cd .. | |
484 |
|
484 | |||
485 | $ cat dummylog |
|
485 | $ cat dummylog | |
486 | Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio |
|
486 | Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio | |
487 | Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio |
|
487 | Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio | |
488 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
488 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
489 | Got arguments 1:user@dummy 2:hg -R local-stream serve --stdio |
|
489 | Got arguments 1:user@dummy 2:hg -R local-stream serve --stdio | |
490 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
490 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
491 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
491 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
492 | Got arguments 1:user@dummy 2:hg -R doesnotexist serve --stdio |
|
492 | Got arguments 1:user@dummy 2:hg -R doesnotexist serve --stdio | |
493 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
493 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
494 | Got arguments 1:user@dummy 2:hg -R local serve --stdio |
|
494 | Got arguments 1:user@dummy 2:hg -R local serve --stdio | |
495 | Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio |
|
495 | Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio | |
496 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
496 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
497 |
changegroup-in-remote hook: HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_NODE_LAST=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_TXNID=TXN: |
|
497 | changegroup-in-remote hook: HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_NODE_LAST=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP | |
498 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
498 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
499 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
499 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
500 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
500 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
501 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
501 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
502 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
502 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
503 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
503 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
504 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
504 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
505 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
505 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
506 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
506 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
507 |
changegroup-in-remote hook: HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_NODE_LAST=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_TXNID=TXN: |
|
507 | changegroup-in-remote hook: HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_NODE_LAST=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP | |
508 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
508 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
509 | Got arguments 1:user@dummy 2:hg init 'a repo' |
|
509 | Got arguments 1:user@dummy 2:hg init 'a repo' | |
510 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio |
|
510 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio | |
511 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio |
|
511 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio | |
512 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio |
|
512 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio | |
513 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio |
|
513 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio | |
514 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
514 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
515 |
changegroup-in-remote hook: HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_NODE_LAST=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_TXNID=TXN: |
|
515 | changegroup-in-remote hook: HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_NODE_LAST=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP | |
516 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
516 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
517 |
|
517 | |||
518 | remote hook failure is attributed to remote |
|
518 | remote hook failure is attributed to remote | |
519 |
|
519 | |||
520 | $ cat > $TESTTMP/failhook << EOF |
|
520 | $ cat > $TESTTMP/failhook << EOF | |
521 | > def hook(ui, repo, **kwargs): |
|
521 | > def hook(ui, repo, **kwargs): | |
522 | > ui.write('hook failure!\n') |
|
522 | > ui.write('hook failure!\n') | |
523 | > ui.flush() |
|
523 | > ui.flush() | |
524 | > return 1 |
|
524 | > return 1 | |
525 | > EOF |
|
525 | > EOF | |
526 |
|
526 | |||
527 | $ echo "pretxnchangegroup.fail = python:$TESTTMP/failhook:hook" >> remote/.hg/hgrc |
|
527 | $ echo "pretxnchangegroup.fail = python:$TESTTMP/failhook:hook" >> remote/.hg/hgrc | |
528 |
|
528 | |||
529 | $ hg -q --config ui.ssh="python $TESTDIR/dummyssh" clone ssh://user@dummy/remote hookout |
|
529 | $ hg -q --config ui.ssh="python $TESTDIR/dummyssh" clone ssh://user@dummy/remote hookout | |
530 | $ cd hookout |
|
530 | $ cd hookout | |
531 | $ touch hookfailure |
|
531 | $ touch hookfailure | |
532 | $ hg -q commit -A -m 'remote hook failure' |
|
532 | $ hg -q commit -A -m 'remote hook failure' | |
533 | $ hg --config ui.ssh="python $TESTDIR/dummyssh" push |
|
533 | $ hg --config ui.ssh="python $TESTDIR/dummyssh" push | |
534 | pushing to ssh://user@dummy/remote |
|
534 | pushing to ssh://user@dummy/remote | |
535 | searching for changes |
|
535 | searching for changes | |
536 | remote: adding changesets |
|
536 | remote: adding changesets | |
537 | remote: adding manifests |
|
537 | remote: adding manifests | |
538 | remote: adding file changes |
|
538 | remote: adding file changes | |
539 | remote: added 1 changesets with 1 changes to 1 files |
|
539 | remote: added 1 changesets with 1 changes to 1 files | |
540 | remote: hook failure! |
|
540 | remote: hook failure! | |
541 | remote: transaction abort! |
|
541 | remote: transaction abort! | |
542 | remote: rollback completed |
|
542 | remote: rollback completed | |
543 | remote: abort: pretxnchangegroup.fail hook failed |
|
543 | remote: abort: pretxnchangegroup.fail hook failed | |
544 | [1] |
|
544 | [1] | |
545 |
|
545 | |||
546 | abort during pull is properly reported as such |
|
546 | abort during pull is properly reported as such | |
547 |
|
547 | |||
548 | $ echo morefoo >> ../remote/foo |
|
548 | $ echo morefoo >> ../remote/foo | |
549 | $ hg -R ../remote commit --message "more foo to be pulled" |
|
549 | $ hg -R ../remote commit --message "more foo to be pulled" | |
550 | $ cat >> ../remote/.hg/hgrc << EOF |
|
550 | $ cat >> ../remote/.hg/hgrc << EOF | |
551 | > [extensions] |
|
551 | > [extensions] | |
552 | > crash = ${TESTDIR}/crashgetbundler.py |
|
552 | > crash = ${TESTDIR}/crashgetbundler.py | |
553 | > EOF |
|
553 | > EOF | |
554 | $ hg --config ui.ssh="python $TESTDIR/dummyssh" pull |
|
554 | $ hg --config ui.ssh="python $TESTDIR/dummyssh" pull | |
555 | pulling from ssh://user@dummy/remote |
|
555 | pulling from ssh://user@dummy/remote | |
556 | searching for changes |
|
556 | searching for changes | |
557 | adding changesets |
|
557 | adding changesets | |
558 | remote: abort: this is an exercise |
|
558 | remote: abort: this is an exercise | |
559 | transaction abort! |
|
559 | transaction abort! | |
560 | rollback completed |
|
560 | rollback completed | |
561 | abort: stream ended unexpectedly (got 0 bytes, expected 4) |
|
561 | abort: stream ended unexpectedly (got 0 bytes, expected 4) | |
562 | [255] |
|
562 | [255] |
@@ -1,564 +1,564 b'' | |||||
1 |
|
1 | |||
2 | This test tries to exercise the ssh functionality with a dummy script |
|
2 | This test tries to exercise the ssh functionality with a dummy script | |
3 |
|
3 | |||
4 | $ cat <<EOF >> $HGRCPATH |
|
4 | $ cat <<EOF >> $HGRCPATH | |
5 | > [format] |
|
5 | > [format] | |
6 | > usegeneraldelta=yes |
|
6 | > usegeneraldelta=yes | |
7 | > EOF |
|
7 | > EOF | |
8 |
|
8 | |||
9 | creating 'remote' repo |
|
9 | creating 'remote' repo | |
10 |
|
10 | |||
11 | $ hg init remote |
|
11 | $ hg init remote | |
12 | $ cd remote |
|
12 | $ cd remote | |
13 | $ echo this > foo |
|
13 | $ echo this > foo | |
14 | $ echo this > fooO |
|
14 | $ echo this > fooO | |
15 | $ hg ci -A -m "init" foo fooO |
|
15 | $ hg ci -A -m "init" foo fooO | |
16 |
|
16 | |||
17 | insert a closed branch (issue4428) |
|
17 | insert a closed branch (issue4428) | |
18 |
|
18 | |||
19 | $ hg up null |
|
19 | $ hg up null | |
20 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved |
|
20 | 0 files updated, 0 files merged, 2 files removed, 0 files unresolved | |
21 | $ hg branch closed |
|
21 | $ hg branch closed | |
22 | marked working directory as branch closed |
|
22 | marked working directory as branch closed | |
23 | (branches are permanent and global, did you want a bookmark?) |
|
23 | (branches are permanent and global, did you want a bookmark?) | |
24 | $ hg ci -mc0 |
|
24 | $ hg ci -mc0 | |
25 | $ hg ci --close-branch -mc1 |
|
25 | $ hg ci --close-branch -mc1 | |
26 | $ hg up -q default |
|
26 | $ hg up -q default | |
27 |
|
27 | |||
28 | configure for serving |
|
28 | configure for serving | |
29 |
|
29 | |||
30 | $ cat <<EOF > .hg/hgrc |
|
30 | $ cat <<EOF > .hg/hgrc | |
31 | > [server] |
|
31 | > [server] | |
32 | > uncompressed = True |
|
32 | > uncompressed = True | |
33 | > |
|
33 | > | |
34 | > [hooks] |
|
34 | > [hooks] | |
35 | > changegroup = sh -c "printenv.py changegroup-in-remote 0 ../dummylog" |
|
35 | > changegroup = sh -c "printenv.py changegroup-in-remote 0 ../dummylog" | |
36 | > EOF |
|
36 | > EOF | |
37 | $ cd .. |
|
37 | $ cd .. | |
38 |
|
38 | |||
39 | repo not found error |
|
39 | repo not found error | |
40 |
|
40 | |||
41 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local |
|
41 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local | |
42 | remote: abort: repository nonexistent not found! |
|
42 | remote: abort: repository nonexistent not found! | |
43 | abort: no suitable response from remote hg! |
|
43 | abort: no suitable response from remote hg! | |
44 | [255] |
|
44 | [255] | |
45 |
|
45 | |||
46 | non-existent absolute path |
|
46 | non-existent absolute path | |
47 |
|
47 | |||
48 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/`pwd`/nonexistent local |
|
48 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/`pwd`/nonexistent local | |
49 | remote: abort: repository $TESTTMP/nonexistent not found! |
|
49 | remote: abort: repository $TESTTMP/nonexistent not found! | |
50 | abort: no suitable response from remote hg! |
|
50 | abort: no suitable response from remote hg! | |
51 | [255] |
|
51 | [255] | |
52 |
|
52 | |||
53 | clone remote via stream |
|
53 | clone remote via stream | |
54 |
|
54 | |||
55 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/remote local-stream |
|
55 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/remote local-stream | |
56 | streaming all changes |
|
56 | streaming all changes | |
57 | 4 files to transfer, 602 bytes of data |
|
57 | 4 files to transfer, 602 bytes of data | |
58 | transferred 602 bytes in * seconds (*) (glob) |
|
58 | transferred 602 bytes in * seconds (*) (glob) | |
59 | searching for changes |
|
59 | searching for changes | |
60 | no changes found |
|
60 | no changes found | |
61 | updating to branch default |
|
61 | updating to branch default | |
62 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
62 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
63 | $ cd local-stream |
|
63 | $ cd local-stream | |
64 | $ hg verify |
|
64 | $ hg verify | |
65 | checking changesets |
|
65 | checking changesets | |
66 | checking manifests |
|
66 | checking manifests | |
67 | crosschecking files in changesets and manifests |
|
67 | crosschecking files in changesets and manifests | |
68 | checking files |
|
68 | checking files | |
69 | 2 files, 3 changesets, 2 total revisions |
|
69 | 2 files, 3 changesets, 2 total revisions | |
70 | $ hg branches |
|
70 | $ hg branches | |
71 | default 0:1160648e36ce |
|
71 | default 0:1160648e36ce | |
72 | $ cd .. |
|
72 | $ cd .. | |
73 |
|
73 | |||
74 | clone bookmarks via stream |
|
74 | clone bookmarks via stream | |
75 |
|
75 | |||
76 | $ hg -R local-stream book mybook |
|
76 | $ hg -R local-stream book mybook | |
77 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/local-stream stream2 |
|
77 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/local-stream stream2 | |
78 | streaming all changes |
|
78 | streaming all changes | |
79 | 4 files to transfer, 602 bytes of data |
|
79 | 4 files to transfer, 602 bytes of data | |
80 | transferred 602 bytes in * seconds (*) (glob) |
|
80 | transferred 602 bytes in * seconds (*) (glob) | |
81 | searching for changes |
|
81 | searching for changes | |
82 | no changes found |
|
82 | no changes found | |
83 | updating to branch default |
|
83 | updating to branch default | |
84 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
84 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
85 | $ cd stream2 |
|
85 | $ cd stream2 | |
86 | $ hg book |
|
86 | $ hg book | |
87 | mybook 0:1160648e36ce |
|
87 | mybook 0:1160648e36ce | |
88 | $ cd .. |
|
88 | $ cd .. | |
89 | $ rm -rf local-stream stream2 |
|
89 | $ rm -rf local-stream stream2 | |
90 |
|
90 | |||
91 | clone remote via pull |
|
91 | clone remote via pull | |
92 |
|
92 | |||
93 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local |
|
93 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local | |
94 | requesting all changes |
|
94 | requesting all changes | |
95 | adding changesets |
|
95 | adding changesets | |
96 | adding manifests |
|
96 | adding manifests | |
97 | adding file changes |
|
97 | adding file changes | |
98 | added 3 changesets with 2 changes to 2 files |
|
98 | added 3 changesets with 2 changes to 2 files | |
99 | updating to branch default |
|
99 | updating to branch default | |
100 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
100 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
101 |
|
101 | |||
102 | verify |
|
102 | verify | |
103 |
|
103 | |||
104 | $ cd local |
|
104 | $ cd local | |
105 | $ hg verify |
|
105 | $ hg verify | |
106 | checking changesets |
|
106 | checking changesets | |
107 | checking manifests |
|
107 | checking manifests | |
108 | crosschecking files in changesets and manifests |
|
108 | crosschecking files in changesets and manifests | |
109 | checking files |
|
109 | checking files | |
110 | 2 files, 3 changesets, 2 total revisions |
|
110 | 2 files, 3 changesets, 2 total revisions | |
111 | $ cat >> .hg/hgrc <<EOF |
|
111 | $ cat >> .hg/hgrc <<EOF | |
112 | > [hooks] |
|
112 | > [hooks] | |
113 | > changegroup = sh -c "printenv.py changegroup-in-local 0 ../dummylog" |
|
113 | > changegroup = sh -c "printenv.py changegroup-in-local 0 ../dummylog" | |
114 | > EOF |
|
114 | > EOF | |
115 |
|
115 | |||
116 | empty default pull |
|
116 | empty default pull | |
117 |
|
117 | |||
118 | $ hg paths |
|
118 | $ hg paths | |
119 | default = ssh://user@dummy/remote |
|
119 | default = ssh://user@dummy/remote | |
120 | $ hg pull -e "python \"$TESTDIR/dummyssh\"" |
|
120 | $ hg pull -e "python \"$TESTDIR/dummyssh\"" | |
121 | pulling from ssh://user@dummy/remote |
|
121 | pulling from ssh://user@dummy/remote | |
122 | searching for changes |
|
122 | searching for changes | |
123 | no changes found |
|
123 | no changes found | |
124 |
|
124 | |||
125 | pull from wrong ssh URL |
|
125 | pull from wrong ssh URL | |
126 |
|
126 | |||
127 | $ hg pull -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/doesnotexist |
|
127 | $ hg pull -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/doesnotexist | |
128 | pulling from ssh://user@dummy/doesnotexist |
|
128 | pulling from ssh://user@dummy/doesnotexist | |
129 | remote: abort: repository doesnotexist not found! |
|
129 | remote: abort: repository doesnotexist not found! | |
130 | abort: no suitable response from remote hg! |
|
130 | abort: no suitable response from remote hg! | |
131 | [255] |
|
131 | [255] | |
132 |
|
132 | |||
133 | local change |
|
133 | local change | |
134 |
|
134 | |||
135 | $ echo bleah > foo |
|
135 | $ echo bleah > foo | |
136 | $ hg ci -m "add" |
|
136 | $ hg ci -m "add" | |
137 |
|
137 | |||
138 | updating rc |
|
138 | updating rc | |
139 |
|
139 | |||
140 | $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc |
|
140 | $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc | |
141 | $ echo "[ui]" >> .hg/hgrc |
|
141 | $ echo "[ui]" >> .hg/hgrc | |
142 | $ echo "ssh = python \"$TESTDIR/dummyssh\"" >> .hg/hgrc |
|
142 | $ echo "ssh = python \"$TESTDIR/dummyssh\"" >> .hg/hgrc | |
143 |
|
143 | |||
144 | find outgoing |
|
144 | find outgoing | |
145 |
|
145 | |||
146 | $ hg out ssh://user@dummy/remote |
|
146 | $ hg out ssh://user@dummy/remote | |
147 | comparing with ssh://user@dummy/remote |
|
147 | comparing with ssh://user@dummy/remote | |
148 | searching for changes |
|
148 | searching for changes | |
149 | changeset: 3:a28a9d1a809c |
|
149 | changeset: 3:a28a9d1a809c | |
150 | tag: tip |
|
150 | tag: tip | |
151 | parent: 0:1160648e36ce |
|
151 | parent: 0:1160648e36ce | |
152 | user: test |
|
152 | user: test | |
153 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
153 | date: Thu Jan 01 00:00:00 1970 +0000 | |
154 | summary: add |
|
154 | summary: add | |
155 |
|
155 | |||
156 |
|
156 | |||
157 | find incoming on the remote side |
|
157 | find incoming on the remote side | |
158 |
|
158 | |||
159 | $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/local |
|
159 | $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/local | |
160 | comparing with ssh://user@dummy/local |
|
160 | comparing with ssh://user@dummy/local | |
161 | searching for changes |
|
161 | searching for changes | |
162 | changeset: 3:a28a9d1a809c |
|
162 | changeset: 3:a28a9d1a809c | |
163 | tag: tip |
|
163 | tag: tip | |
164 | parent: 0:1160648e36ce |
|
164 | parent: 0:1160648e36ce | |
165 | user: test |
|
165 | user: test | |
166 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
166 | date: Thu Jan 01 00:00:00 1970 +0000 | |
167 | summary: add |
|
167 | summary: add | |
168 |
|
168 | |||
169 |
|
169 | |||
170 | find incoming on the remote side (using absolute path) |
|
170 | find incoming on the remote side (using absolute path) | |
171 |
|
171 | |||
172 | $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/`pwd`" |
|
172 | $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/`pwd`" | |
173 | comparing with ssh://user@dummy/$TESTTMP/local |
|
173 | comparing with ssh://user@dummy/$TESTTMP/local | |
174 | searching for changes |
|
174 | searching for changes | |
175 | changeset: 3:a28a9d1a809c |
|
175 | changeset: 3:a28a9d1a809c | |
176 | tag: tip |
|
176 | tag: tip | |
177 | parent: 0:1160648e36ce |
|
177 | parent: 0:1160648e36ce | |
178 | user: test |
|
178 | user: test | |
179 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
179 | date: Thu Jan 01 00:00:00 1970 +0000 | |
180 | summary: add |
|
180 | summary: add | |
181 |
|
181 | |||
182 |
|
182 | |||
183 | push |
|
183 | push | |
184 |
|
184 | |||
185 | $ hg push |
|
185 | $ hg push | |
186 | pushing to ssh://user@dummy/remote |
|
186 | pushing to ssh://user@dummy/remote | |
187 | searching for changes |
|
187 | searching for changes | |
188 | remote: adding changesets |
|
188 | remote: adding changesets | |
189 | remote: adding manifests |
|
189 | remote: adding manifests | |
190 | remote: adding file changes |
|
190 | remote: adding file changes | |
191 | remote: added 1 changesets with 1 changes to 1 files |
|
191 | remote: added 1 changesets with 1 changes to 1 files | |
192 | $ cd ../remote |
|
192 | $ cd ../remote | |
193 |
|
193 | |||
194 | check remote tip |
|
194 | check remote tip | |
195 |
|
195 | |||
196 | $ hg tip |
|
196 | $ hg tip | |
197 | changeset: 3:a28a9d1a809c |
|
197 | changeset: 3:a28a9d1a809c | |
198 | tag: tip |
|
198 | tag: tip | |
199 | parent: 0:1160648e36ce |
|
199 | parent: 0:1160648e36ce | |
200 | user: test |
|
200 | user: test | |
201 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
201 | date: Thu Jan 01 00:00:00 1970 +0000 | |
202 | summary: add |
|
202 | summary: add | |
203 |
|
203 | |||
204 | $ hg verify |
|
204 | $ hg verify | |
205 | checking changesets |
|
205 | checking changesets | |
206 | checking manifests |
|
206 | checking manifests | |
207 | crosschecking files in changesets and manifests |
|
207 | crosschecking files in changesets and manifests | |
208 | checking files |
|
208 | checking files | |
209 | 2 files, 4 changesets, 3 total revisions |
|
209 | 2 files, 4 changesets, 3 total revisions | |
210 | $ hg cat -r tip foo |
|
210 | $ hg cat -r tip foo | |
211 | bleah |
|
211 | bleah | |
212 | $ echo z > z |
|
212 | $ echo z > z | |
213 | $ hg ci -A -m z z |
|
213 | $ hg ci -A -m z z | |
214 | created new head |
|
214 | created new head | |
215 |
|
215 | |||
216 | test pushkeys and bookmarks |
|
216 | test pushkeys and bookmarks | |
217 |
|
217 | |||
218 | $ cd ../local |
|
218 | $ cd ../local | |
219 | $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote namespaces |
|
219 | $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote namespaces | |
220 | bookmarks |
|
220 | bookmarks | |
221 | namespaces |
|
221 | namespaces | |
222 | phases |
|
222 | phases | |
223 | $ hg book foo -r 0 |
|
223 | $ hg book foo -r 0 | |
224 | $ hg out -B |
|
224 | $ hg out -B | |
225 | comparing with ssh://user@dummy/remote |
|
225 | comparing with ssh://user@dummy/remote | |
226 | searching for changed bookmarks |
|
226 | searching for changed bookmarks | |
227 | foo 1160648e36ce |
|
227 | foo 1160648e36ce | |
228 | $ hg push -B foo |
|
228 | $ hg push -B foo | |
229 | pushing to ssh://user@dummy/remote |
|
229 | pushing to ssh://user@dummy/remote | |
230 | searching for changes |
|
230 | searching for changes | |
231 | no changes found |
|
231 | no changes found | |
232 | exporting bookmark foo |
|
232 | exporting bookmark foo | |
233 | [1] |
|
233 | [1] | |
234 | $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote bookmarks |
|
234 | $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote bookmarks | |
235 | foo 1160648e36cec0054048a7edc4110c6f84fde594 |
|
235 | foo 1160648e36cec0054048a7edc4110c6f84fde594 | |
236 | $ hg book -f foo |
|
236 | $ hg book -f foo | |
237 | $ hg push --traceback |
|
237 | $ hg push --traceback | |
238 | pushing to ssh://user@dummy/remote |
|
238 | pushing to ssh://user@dummy/remote | |
239 | searching for changes |
|
239 | searching for changes | |
240 | no changes found |
|
240 | no changes found | |
241 | updating bookmark foo |
|
241 | updating bookmark foo | |
242 | [1] |
|
242 | [1] | |
243 | $ hg book -d foo |
|
243 | $ hg book -d foo | |
244 | $ hg in -B |
|
244 | $ hg in -B | |
245 | comparing with ssh://user@dummy/remote |
|
245 | comparing with ssh://user@dummy/remote | |
246 | searching for changed bookmarks |
|
246 | searching for changed bookmarks | |
247 | foo a28a9d1a809c |
|
247 | foo a28a9d1a809c | |
248 | $ hg book -f -r 0 foo |
|
248 | $ hg book -f -r 0 foo | |
249 | $ hg pull -B foo |
|
249 | $ hg pull -B foo | |
250 | pulling from ssh://user@dummy/remote |
|
250 | pulling from ssh://user@dummy/remote | |
251 | no changes found |
|
251 | no changes found | |
252 | updating bookmark foo |
|
252 | updating bookmark foo | |
253 | $ hg book -d foo |
|
253 | $ hg book -d foo | |
254 | $ hg push -B foo |
|
254 | $ hg push -B foo | |
255 | pushing to ssh://user@dummy/remote |
|
255 | pushing to ssh://user@dummy/remote | |
256 | searching for changes |
|
256 | searching for changes | |
257 | no changes found |
|
257 | no changes found | |
258 | deleting remote bookmark foo |
|
258 | deleting remote bookmark foo | |
259 | [1] |
|
259 | [1] | |
260 |
|
260 | |||
261 | a bad, evil hook that prints to stdout |
|
261 | a bad, evil hook that prints to stdout | |
262 |
|
262 | |||
263 | $ cat <<EOF > $TESTTMP/badhook |
|
263 | $ cat <<EOF > $TESTTMP/badhook | |
264 | > import sys |
|
264 | > import sys | |
265 | > sys.stdout.write("KABOOM\n") |
|
265 | > sys.stdout.write("KABOOM\n") | |
266 | > EOF |
|
266 | > EOF | |
267 |
|
267 | |||
268 | $ cat <<EOF > $TESTTMP/badpyhook.py |
|
268 | $ cat <<EOF > $TESTTMP/badpyhook.py | |
269 | > import sys |
|
269 | > import sys | |
270 | > def hook(ui, repo, hooktype, **kwargs): |
|
270 | > def hook(ui, repo, hooktype, **kwargs): | |
271 | > sys.stdout.write("KABOOM IN PROCESS\n") |
|
271 | > sys.stdout.write("KABOOM IN PROCESS\n") | |
272 | > EOF |
|
272 | > EOF | |
273 |
|
273 | |||
274 | $ cat <<EOF >> ../remote/.hg/hgrc |
|
274 | $ cat <<EOF >> ../remote/.hg/hgrc | |
275 | > [hooks] |
|
275 | > [hooks] | |
276 | > changegroup.stdout = python $TESTTMP/badhook |
|
276 | > changegroup.stdout = python $TESTTMP/badhook | |
277 | > changegroup.pystdout = python:$TESTTMP/badpyhook.py:hook |
|
277 | > changegroup.pystdout = python:$TESTTMP/badpyhook.py:hook | |
278 | > EOF |
|
278 | > EOF | |
279 | $ echo r > r |
|
279 | $ echo r > r | |
280 | $ hg ci -A -m z r |
|
280 | $ hg ci -A -m z r | |
281 |
|
281 | |||
282 | push should succeed even though it has an unexpected response |
|
282 | push should succeed even though it has an unexpected response | |
283 |
|
283 | |||
284 | $ hg push |
|
284 | $ hg push | |
285 | pushing to ssh://user@dummy/remote |
|
285 | pushing to ssh://user@dummy/remote | |
286 | searching for changes |
|
286 | searching for changes | |
287 | remote has heads on branch 'default' that are not known locally: 6c0482d977a3 |
|
287 | remote has heads on branch 'default' that are not known locally: 6c0482d977a3 | |
288 | remote: adding changesets |
|
288 | remote: adding changesets | |
289 | remote: adding manifests |
|
289 | remote: adding manifests | |
290 | remote: adding file changes |
|
290 | remote: adding file changes | |
291 | remote: added 1 changesets with 1 changes to 1 files |
|
291 | remote: added 1 changesets with 1 changes to 1 files | |
292 | remote: KABOOM |
|
292 | remote: KABOOM | |
293 | remote: KABOOM IN PROCESS |
|
293 | remote: KABOOM IN PROCESS | |
294 | $ hg -R ../remote heads |
|
294 | $ hg -R ../remote heads | |
295 | changeset: 5:1383141674ec |
|
295 | changeset: 5:1383141674ec | |
296 | tag: tip |
|
296 | tag: tip | |
297 | parent: 3:a28a9d1a809c |
|
297 | parent: 3:a28a9d1a809c | |
298 | user: test |
|
298 | user: test | |
299 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
299 | date: Thu Jan 01 00:00:00 1970 +0000 | |
300 | summary: z |
|
300 | summary: z | |
301 |
|
301 | |||
302 | changeset: 4:6c0482d977a3 |
|
302 | changeset: 4:6c0482d977a3 | |
303 | parent: 0:1160648e36ce |
|
303 | parent: 0:1160648e36ce | |
304 | user: test |
|
304 | user: test | |
305 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
305 | date: Thu Jan 01 00:00:00 1970 +0000 | |
306 | summary: z |
|
306 | summary: z | |
307 |
|
307 | |||
308 |
|
308 | |||
309 | clone bookmarks |
|
309 | clone bookmarks | |
310 |
|
310 | |||
311 | $ hg -R ../remote bookmark test |
|
311 | $ hg -R ../remote bookmark test | |
312 | $ hg -R ../remote bookmarks |
|
312 | $ hg -R ../remote bookmarks | |
313 | * test 4:6c0482d977a3 |
|
313 | * test 4:6c0482d977a3 | |
314 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local-bookmarks |
|
314 | $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local-bookmarks | |
315 | requesting all changes |
|
315 | requesting all changes | |
316 | adding changesets |
|
316 | adding changesets | |
317 | adding manifests |
|
317 | adding manifests | |
318 | adding file changes |
|
318 | adding file changes | |
319 | added 6 changesets with 5 changes to 4 files (+1 heads) |
|
319 | added 6 changesets with 5 changes to 4 files (+1 heads) | |
320 | updating to branch default |
|
320 | updating to branch default | |
321 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
321 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
322 | $ hg -R local-bookmarks bookmarks |
|
322 | $ hg -R local-bookmarks bookmarks | |
323 | test 4:6c0482d977a3 |
|
323 | test 4:6c0482d977a3 | |
324 |
|
324 | |||
325 | passwords in ssh urls are not supported |
|
325 | passwords in ssh urls are not supported | |
326 | (we use a glob here because different Python versions give different |
|
326 | (we use a glob here because different Python versions give different | |
327 | results here) |
|
327 | results here) | |
328 |
|
328 | |||
329 | $ hg push ssh://user:erroneouspwd@dummy/remote |
|
329 | $ hg push ssh://user:erroneouspwd@dummy/remote | |
330 | pushing to ssh://user:*@dummy/remote (glob) |
|
330 | pushing to ssh://user:*@dummy/remote (glob) | |
331 | abort: password in URL not supported! |
|
331 | abort: password in URL not supported! | |
332 | [255] |
|
332 | [255] | |
333 |
|
333 | |||
334 | $ cd .. |
|
334 | $ cd .. | |
335 |
|
335 | |||
336 | hide outer repo |
|
336 | hide outer repo | |
337 | $ hg init |
|
337 | $ hg init | |
338 |
|
338 | |||
339 | Test remote paths with spaces (issue2983): |
|
339 | Test remote paths with spaces (issue2983): | |
340 |
|
340 | |||
341 | $ hg init --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo" |
|
341 | $ hg init --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo" | |
342 | $ touch "$TESTTMP/a repo/test" |
|
342 | $ touch "$TESTTMP/a repo/test" | |
343 | $ hg -R 'a repo' commit -A -m "test" |
|
343 | $ hg -R 'a repo' commit -A -m "test" | |
344 | adding test |
|
344 | adding test | |
345 | $ hg -R 'a repo' tag tag |
|
345 | $ hg -R 'a repo' tag tag | |
346 | $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo" |
|
346 | $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo" | |
347 | 73649e48688a |
|
347 | 73649e48688a | |
348 |
|
348 | |||
349 | $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo#noNoNO" |
|
349 | $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo#noNoNO" | |
350 | abort: unknown revision 'noNoNO'! |
|
350 | abort: unknown revision 'noNoNO'! | |
351 | [255] |
|
351 | [255] | |
352 |
|
352 | |||
353 | Test (non-)escaping of remote paths with spaces when cloning (issue3145): |
|
353 | Test (non-)escaping of remote paths with spaces when cloning (issue3145): | |
354 |
|
354 | |||
355 | $ hg clone --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo" |
|
355 | $ hg clone --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo" | |
356 | destination directory: a repo |
|
356 | destination directory: a repo | |
357 | abort: destination 'a repo' is not empty |
|
357 | abort: destination 'a repo' is not empty | |
358 | [255] |
|
358 | [255] | |
359 |
|
359 | |||
360 | Test hg-ssh using a helper script that will restore PYTHONPATH (which might |
|
360 | Test hg-ssh using a helper script that will restore PYTHONPATH (which might | |
361 | have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right |
|
361 | have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right | |
362 | parameters: |
|
362 | parameters: | |
363 |
|
363 | |||
364 | $ cat > ssh.sh << EOF |
|
364 | $ cat > ssh.sh << EOF | |
365 | > userhost="\$1" |
|
365 | > userhost="\$1" | |
366 | > SSH_ORIGINAL_COMMAND="\$2" |
|
366 | > SSH_ORIGINAL_COMMAND="\$2" | |
367 | > export SSH_ORIGINAL_COMMAND |
|
367 | > export SSH_ORIGINAL_COMMAND | |
368 | > PYTHONPATH="$PYTHONPATH" |
|
368 | > PYTHONPATH="$PYTHONPATH" | |
369 | > export PYTHONPATH |
|
369 | > export PYTHONPATH | |
370 | > python "$TESTDIR/../contrib/hg-ssh" "$TESTTMP/a repo" |
|
370 | > python "$TESTDIR/../contrib/hg-ssh" "$TESTTMP/a repo" | |
371 | > EOF |
|
371 | > EOF | |
372 |
|
372 | |||
373 | $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a repo" |
|
373 | $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a repo" | |
374 | 73649e48688a |
|
374 | 73649e48688a | |
375 |
|
375 | |||
376 | $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo" |
|
376 | $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo" | |
377 | remote: Illegal repository "$TESTTMP/a'repo" (glob) |
|
377 | remote: Illegal repository "$TESTTMP/a'repo" (glob) | |
378 | abort: no suitable response from remote hg! |
|
378 | abort: no suitable response from remote hg! | |
379 | [255] |
|
379 | [255] | |
380 |
|
380 | |||
381 | $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo" |
|
381 | $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo" | |
382 | remote: Illegal command "hacking -R 'a'\''repo' serve --stdio" |
|
382 | remote: Illegal command "hacking -R 'a'\''repo' serve --stdio" | |
383 | abort: no suitable response from remote hg! |
|
383 | abort: no suitable response from remote hg! | |
384 | [255] |
|
384 | [255] | |
385 |
|
385 | |||
386 | $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" python "$TESTDIR/../contrib/hg-ssh" |
|
386 | $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" python "$TESTDIR/../contrib/hg-ssh" | |
387 | Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation |
|
387 | Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation | |
388 | [255] |
|
388 | [255] | |
389 |
|
389 | |||
390 | Test hg-ssh in read-only mode: |
|
390 | Test hg-ssh in read-only mode: | |
391 |
|
391 | |||
392 | $ cat > ssh.sh << EOF |
|
392 | $ cat > ssh.sh << EOF | |
393 | > userhost="\$1" |
|
393 | > userhost="\$1" | |
394 | > SSH_ORIGINAL_COMMAND="\$2" |
|
394 | > SSH_ORIGINAL_COMMAND="\$2" | |
395 | > export SSH_ORIGINAL_COMMAND |
|
395 | > export SSH_ORIGINAL_COMMAND | |
396 | > PYTHONPATH="$PYTHONPATH" |
|
396 | > PYTHONPATH="$PYTHONPATH" | |
397 | > export PYTHONPATH |
|
397 | > export PYTHONPATH | |
398 | > python "$TESTDIR/../contrib/hg-ssh" --read-only "$TESTTMP/remote" |
|
398 | > python "$TESTDIR/../contrib/hg-ssh" --read-only "$TESTTMP/remote" | |
399 | > EOF |
|
399 | > EOF | |
400 |
|
400 | |||
401 | $ hg clone --ssh "sh ssh.sh" "ssh://user@dummy/$TESTTMP/remote" read-only-local |
|
401 | $ hg clone --ssh "sh ssh.sh" "ssh://user@dummy/$TESTTMP/remote" read-only-local | |
402 | requesting all changes |
|
402 | requesting all changes | |
403 | adding changesets |
|
403 | adding changesets | |
404 | adding manifests |
|
404 | adding manifests | |
405 | adding file changes |
|
405 | adding file changes | |
406 | added 6 changesets with 5 changes to 4 files (+1 heads) |
|
406 | added 6 changesets with 5 changes to 4 files (+1 heads) | |
407 | updating to branch default |
|
407 | updating to branch default | |
408 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
408 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
409 |
|
409 | |||
410 | $ cd read-only-local |
|
410 | $ cd read-only-local | |
411 | $ echo "baz" > bar |
|
411 | $ echo "baz" > bar | |
412 | $ hg ci -A -m "unpushable commit" bar |
|
412 | $ hg ci -A -m "unpushable commit" bar | |
413 | $ hg push --ssh "sh ../ssh.sh" |
|
413 | $ hg push --ssh "sh ../ssh.sh" | |
414 | pushing to ssh://user@dummy/*/remote (glob) |
|
414 | pushing to ssh://user@dummy/*/remote (glob) | |
415 | searching for changes |
|
415 | searching for changes | |
416 | remote: Permission denied |
|
416 | remote: Permission denied | |
417 | remote: pretxnopen.hg-ssh hook failed |
|
417 | remote: pretxnopen.hg-ssh hook failed | |
418 | abort: push failed on remote |
|
418 | abort: push failed on remote | |
419 | [255] |
|
419 | [255] | |
420 |
|
420 | |||
421 | $ cd .. |
|
421 | $ cd .. | |
422 |
|
422 | |||
423 | stderr from remote commands should be printed before stdout from local code (issue4336) |
|
423 | stderr from remote commands should be printed before stdout from local code (issue4336) | |
424 |
|
424 | |||
425 | $ hg clone remote stderr-ordering |
|
425 | $ hg clone remote stderr-ordering | |
426 | updating to branch default |
|
426 | updating to branch default | |
427 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
427 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
428 | $ cd stderr-ordering |
|
428 | $ cd stderr-ordering | |
429 | $ cat >> localwrite.py << EOF |
|
429 | $ cat >> localwrite.py << EOF | |
430 | > from mercurial import exchange, extensions |
|
430 | > from mercurial import exchange, extensions | |
431 | > |
|
431 | > | |
432 | > def wrappedpush(orig, repo, *args, **kwargs): |
|
432 | > def wrappedpush(orig, repo, *args, **kwargs): | |
433 | > res = orig(repo, *args, **kwargs) |
|
433 | > res = orig(repo, *args, **kwargs) | |
434 | > repo.ui.write('local stdout\n') |
|
434 | > repo.ui.write('local stdout\n') | |
435 | > return res |
|
435 | > return res | |
436 | > |
|
436 | > | |
437 | > def extsetup(ui): |
|
437 | > def extsetup(ui): | |
438 | > extensions.wrapfunction(exchange, 'push', wrappedpush) |
|
438 | > extensions.wrapfunction(exchange, 'push', wrappedpush) | |
439 | > EOF |
|
439 | > EOF | |
440 |
|
440 | |||
441 | $ cat >> .hg/hgrc << EOF |
|
441 | $ cat >> .hg/hgrc << EOF | |
442 | > [paths] |
|
442 | > [paths] | |
443 | > default-push = ssh://user@dummy/remote |
|
443 | > default-push = ssh://user@dummy/remote | |
444 | > [ui] |
|
444 | > [ui] | |
445 | > ssh = python "$TESTDIR/dummyssh" |
|
445 | > ssh = python "$TESTDIR/dummyssh" | |
446 | > [extensions] |
|
446 | > [extensions] | |
447 | > localwrite = localwrite.py |
|
447 | > localwrite = localwrite.py | |
448 | > EOF |
|
448 | > EOF | |
449 |
|
449 | |||
450 | $ echo localwrite > foo |
|
450 | $ echo localwrite > foo | |
451 | $ hg commit -m 'testing localwrite' |
|
451 | $ hg commit -m 'testing localwrite' | |
452 | $ hg push |
|
452 | $ hg push | |
453 | pushing to ssh://user@dummy/remote |
|
453 | pushing to ssh://user@dummy/remote | |
454 | searching for changes |
|
454 | searching for changes | |
455 | remote: adding changesets |
|
455 | remote: adding changesets | |
456 | remote: adding manifests |
|
456 | remote: adding manifests | |
457 | remote: adding file changes |
|
457 | remote: adding file changes | |
458 | remote: added 1 changesets with 1 changes to 1 files |
|
458 | remote: added 1 changesets with 1 changes to 1 files | |
459 | remote: KABOOM |
|
459 | remote: KABOOM | |
460 | remote: KABOOM IN PROCESS |
|
460 | remote: KABOOM IN PROCESS | |
461 | local stdout |
|
461 | local stdout | |
462 |
|
462 | |||
463 | debug output |
|
463 | debug output | |
464 |
|
464 | |||
465 | $ hg pull --debug ssh://user@dummy/remote |
|
465 | $ hg pull --debug ssh://user@dummy/remote | |
466 | pulling from ssh://user@dummy/remote |
|
466 | pulling from ssh://user@dummy/remote | |
467 | running python ".*/dummyssh" user@dummy ('|")hg -R remote serve --stdio('|") (re) |
|
467 | running python ".*/dummyssh" user@dummy ('|")hg -R remote serve --stdio('|") (re) | |
468 | sending hello command |
|
468 | sending hello command | |
469 | sending between command |
|
469 | sending between command | |
470 | remote: 355 |
|
470 | remote: 355 | |
471 | remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN |
|
471 | remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN | |
472 | remote: 1 |
|
472 | remote: 1 | |
473 | query 1; heads |
|
473 | query 1; heads | |
474 | sending batch command |
|
474 | sending batch command | |
475 | searching for changes |
|
475 | searching for changes | |
476 | all remote heads known locally |
|
476 | all remote heads known locally | |
477 | no changes found |
|
477 | no changes found | |
478 | sending getbundle command |
|
478 | sending getbundle command | |
479 | bundle2-input-bundle: with-transaction |
|
479 | bundle2-input-bundle: with-transaction | |
480 | bundle2-input-part: "listkeys" (params: 1 mandatory) supported |
|
480 | bundle2-input-part: "listkeys" (params: 1 mandatory) supported | |
481 | bundle2-input-part: total payload size 15 |
|
481 | bundle2-input-part: total payload size 15 | |
482 | bundle2-input-part: "listkeys" (params: 1 mandatory) supported |
|
482 | bundle2-input-part: "listkeys" (params: 1 mandatory) supported | |
483 | bundle2-input-part: total payload size 45 |
|
483 | bundle2-input-part: total payload size 45 | |
484 | bundle2-input-bundle: 1 parts total |
|
484 | bundle2-input-bundle: 1 parts total | |
485 | checking for updated bookmarks |
|
485 | checking for updated bookmarks | |
486 |
|
486 | |||
487 | $ cd .. |
|
487 | $ cd .. | |
488 |
|
488 | |||
489 | $ cat dummylog |
|
489 | $ cat dummylog | |
490 | Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio |
|
490 | Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio | |
491 | Got arguments 1:user@dummy 2:hg -R $TESTTMP/nonexistent serve --stdio |
|
491 | Got arguments 1:user@dummy 2:hg -R $TESTTMP/nonexistent serve --stdio | |
492 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
492 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
493 | Got arguments 1:user@dummy 2:hg -R local-stream serve --stdio |
|
493 | Got arguments 1:user@dummy 2:hg -R local-stream serve --stdio | |
494 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
494 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
495 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
495 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
496 | Got arguments 1:user@dummy 2:hg -R doesnotexist serve --stdio |
|
496 | Got arguments 1:user@dummy 2:hg -R doesnotexist serve --stdio | |
497 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
497 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
498 | Got arguments 1:user@dummy 2:hg -R local serve --stdio |
|
498 | Got arguments 1:user@dummy 2:hg -R local serve --stdio | |
499 | Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio |
|
499 | Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio | |
500 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
500 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
501 |
changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_NODE_LAST=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_TXNID=TXN: |
|
501 | changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_NODE_LAST=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP | |
502 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
502 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
503 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
503 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
504 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
504 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
505 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
505 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
506 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
506 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
507 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
507 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
508 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
508 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
509 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
509 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
510 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
510 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
511 |
changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_NODE_LAST=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_TXNID=TXN: |
|
511 | changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_NODE_LAST=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP | |
512 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
512 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
513 | Got arguments 1:user@dummy 2:hg init 'a repo' |
|
513 | Got arguments 1:user@dummy 2:hg init 'a repo' | |
514 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio |
|
514 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio | |
515 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio |
|
515 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio | |
516 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio |
|
516 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio | |
517 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio |
|
517 | Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio | |
518 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
518 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
519 |
changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_NODE_LAST=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_TXNID=TXN: |
|
519 | changegroup-in-remote hook: HG_BUNDLE2=1 HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_NODE_LAST=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP | |
520 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio |
|
520 | Got arguments 1:user@dummy 2:hg -R remote serve --stdio | |
521 |
|
521 | |||
522 | remote hook failure is attributed to remote |
|
522 | remote hook failure is attributed to remote | |
523 |
|
523 | |||
524 | $ cat > $TESTTMP/failhook << EOF |
|
524 | $ cat > $TESTTMP/failhook << EOF | |
525 | > def hook(ui, repo, **kwargs): |
|
525 | > def hook(ui, repo, **kwargs): | |
526 | > ui.write('hook failure!\n') |
|
526 | > ui.write('hook failure!\n') | |
527 | > ui.flush() |
|
527 | > ui.flush() | |
528 | > return 1 |
|
528 | > return 1 | |
529 | > EOF |
|
529 | > EOF | |
530 |
|
530 | |||
531 | $ echo "pretxnchangegroup.fail = python:$TESTTMP/failhook:hook" >> remote/.hg/hgrc |
|
531 | $ echo "pretxnchangegroup.fail = python:$TESTTMP/failhook:hook" >> remote/.hg/hgrc | |
532 |
|
532 | |||
533 | $ hg -q --config ui.ssh="python $TESTDIR/dummyssh" clone ssh://user@dummy/remote hookout |
|
533 | $ hg -q --config ui.ssh="python $TESTDIR/dummyssh" clone ssh://user@dummy/remote hookout | |
534 | $ cd hookout |
|
534 | $ cd hookout | |
535 | $ touch hookfailure |
|
535 | $ touch hookfailure | |
536 | $ hg -q commit -A -m 'remote hook failure' |
|
536 | $ hg -q commit -A -m 'remote hook failure' | |
537 | $ hg --config ui.ssh="python $TESTDIR/dummyssh" push |
|
537 | $ hg --config ui.ssh="python $TESTDIR/dummyssh" push | |
538 | pushing to ssh://user@dummy/remote |
|
538 | pushing to ssh://user@dummy/remote | |
539 | searching for changes |
|
539 | searching for changes | |
540 | remote: adding changesets |
|
540 | remote: adding changesets | |
541 | remote: adding manifests |
|
541 | remote: adding manifests | |
542 | remote: adding file changes |
|
542 | remote: adding file changes | |
543 | remote: added 1 changesets with 1 changes to 1 files |
|
543 | remote: added 1 changesets with 1 changes to 1 files | |
544 | remote: hook failure! |
|
544 | remote: hook failure! | |
545 | remote: transaction abort! |
|
545 | remote: transaction abort! | |
546 | remote: rollback completed |
|
546 | remote: rollback completed | |
547 | remote: pretxnchangegroup.fail hook failed |
|
547 | remote: pretxnchangegroup.fail hook failed | |
548 | abort: push failed on remote |
|
548 | abort: push failed on remote | |
549 | [255] |
|
549 | [255] | |
550 |
|
550 | |||
551 | abort during pull is properly reported as such |
|
551 | abort during pull is properly reported as such | |
552 |
|
552 | |||
553 | $ echo morefoo >> ../remote/foo |
|
553 | $ echo morefoo >> ../remote/foo | |
554 | $ hg -R ../remote commit --message "more foo to be pulled" |
|
554 | $ hg -R ../remote commit --message "more foo to be pulled" | |
555 | $ cat >> ../remote/.hg/hgrc << EOF |
|
555 | $ cat >> ../remote/.hg/hgrc << EOF | |
556 | > [extensions] |
|
556 | > [extensions] | |
557 | > crash = ${TESTDIR}/crashgetbundler.py |
|
557 | > crash = ${TESTDIR}/crashgetbundler.py | |
558 | > EOF |
|
558 | > EOF | |
559 | $ hg --config ui.ssh="python $TESTDIR/dummyssh" pull |
|
559 | $ hg --config ui.ssh="python $TESTDIR/dummyssh" pull | |
560 | pulling from ssh://user@dummy/remote |
|
560 | pulling from ssh://user@dummy/remote | |
561 | searching for changes |
|
561 | searching for changes | |
562 | remote: abort: this is an exercise |
|
562 | remote: abort: this is an exercise | |
563 | abort: pull failed on remote |
|
563 | abort: pull failed on remote | |
564 | [255] |
|
564 | [255] |
@@ -1,159 +1,159 b'' | |||||
1 | #require killdaemons |
|
1 | #require killdaemons | |
2 |
|
2 | |||
3 | $ hg clone http://localhost:$HGPORT/ copy |
|
3 | $ hg clone http://localhost:$HGPORT/ copy | |
4 | abort: * (glob) |
|
4 | abort: * (glob) | |
5 | [255] |
|
5 | [255] | |
6 | $ test -d copy |
|
6 | $ test -d copy | |
7 | [1] |
|
7 | [1] | |
8 |
|
8 | |||
9 | This server doesn't do range requests so it's basically only good for |
|
9 | This server doesn't do range requests so it's basically only good for | |
10 | one pull |
|
10 | one pull | |
11 |
|
11 | |||
12 | $ python "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid |
|
12 | $ python "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid | |
13 | $ cat dumb.pid >> $DAEMON_PIDS |
|
13 | $ cat dumb.pid >> $DAEMON_PIDS | |
14 | $ hg init remote |
|
14 | $ hg init remote | |
15 | $ cd remote |
|
15 | $ cd remote | |
16 | $ echo foo > bar |
|
16 | $ echo foo > bar | |
17 | $ echo c2 > '.dotfile with spaces' |
|
17 | $ echo c2 > '.dotfile with spaces' | |
18 | $ hg add |
|
18 | $ hg add | |
19 | adding .dotfile with spaces |
|
19 | adding .dotfile with spaces | |
20 | adding bar |
|
20 | adding bar | |
21 | $ hg commit -m"test" |
|
21 | $ hg commit -m"test" | |
22 | $ hg tip |
|
22 | $ hg tip | |
23 | changeset: 0:02770d679fb8 |
|
23 | changeset: 0:02770d679fb8 | |
24 | tag: tip |
|
24 | tag: tip | |
25 | user: test |
|
25 | user: test | |
26 | date: Thu Jan 01 00:00:00 1970 +0000 |
|
26 | date: Thu Jan 01 00:00:00 1970 +0000 | |
27 | summary: test |
|
27 | summary: test | |
28 |
|
28 | |||
29 | $ cd .. |
|
29 | $ cd .. | |
30 | $ hg clone static-http://localhost:$HGPORT/remote local |
|
30 | $ hg clone static-http://localhost:$HGPORT/remote local | |
31 | requesting all changes |
|
31 | requesting all changes | |
32 | adding changesets |
|
32 | adding changesets | |
33 | adding manifests |
|
33 | adding manifests | |
34 | adding file changes |
|
34 | adding file changes | |
35 | added 1 changesets with 2 changes to 2 files |
|
35 | added 1 changesets with 2 changes to 2 files | |
36 | updating to branch default |
|
36 | updating to branch default | |
37 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
37 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
38 | $ cd local |
|
38 | $ cd local | |
39 | $ hg verify |
|
39 | $ hg verify | |
40 | checking changesets |
|
40 | checking changesets | |
41 | checking manifests |
|
41 | checking manifests | |
42 | crosschecking files in changesets and manifests |
|
42 | crosschecking files in changesets and manifests | |
43 | checking files |
|
43 | checking files | |
44 | 2 files, 1 changesets, 2 total revisions |
|
44 | 2 files, 1 changesets, 2 total revisions | |
45 | $ cat bar |
|
45 | $ cat bar | |
46 | foo |
|
46 | foo | |
47 | $ cd ../remote |
|
47 | $ cd ../remote | |
48 | $ echo baz > quux |
|
48 | $ echo baz > quux | |
49 | $ hg commit -A -mtest2 |
|
49 | $ hg commit -A -mtest2 | |
50 | adding quux |
|
50 | adding quux | |
51 |
|
51 | |||
52 | check for HTTP opener failures when cachefile does not exist |
|
52 | check for HTTP opener failures when cachefile does not exist | |
53 |
|
53 | |||
54 | $ rm .hg/cache/* |
|
54 | $ rm .hg/cache/* | |
55 | $ cd ../local |
|
55 | $ cd ../local | |
56 | $ cat >> .hg/hgrc <<EOF |
|
56 | $ cat >> .hg/hgrc <<EOF | |
57 | > [hooks] |
|
57 | > [hooks] | |
58 | > changegroup = sh -c "printenv.py changegroup" |
|
58 | > changegroup = sh -c "printenv.py changegroup" | |
59 | > EOF |
|
59 | > EOF | |
60 | $ hg pull |
|
60 | $ hg pull | |
61 | pulling from static-http://localhost:$HGPORT/remote |
|
61 | pulling from static-http://localhost:$HGPORT/remote | |
62 | searching for changes |
|
62 | searching for changes | |
63 | adding changesets |
|
63 | adding changesets | |
64 | adding manifests |
|
64 | adding manifests | |
65 | adding file changes |
|
65 | adding file changes | |
66 | added 1 changesets with 1 changes to 1 files |
|
66 | added 1 changesets with 1 changes to 1 files | |
67 |
changegroup hook: HG_NODE=4ac2e3648604439c580c69b09ec9d93a88d93432 HG_NODE_LAST=4ac2e3648604439c580c69b09ec9d93a88d93432 HG_SOURCE=pull HG_TXNID=TXN: |
|
67 | changegroup hook: HG_NODE=4ac2e3648604439c580c69b09ec9d93a88d93432 HG_NODE_LAST=4ac2e3648604439c580c69b09ec9d93a88d93432 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=http://localhost:$HGPORT/remote | |
68 | (run 'hg update' to get a working copy) |
|
68 | (run 'hg update' to get a working copy) | |
69 |
|
69 | |||
70 | trying to push |
|
70 | trying to push | |
71 |
|
71 | |||
72 | $ hg update |
|
72 | $ hg update | |
73 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
73 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
74 | $ echo more foo >> bar |
|
74 | $ echo more foo >> bar | |
75 | $ hg commit -m"test" |
|
75 | $ hg commit -m"test" | |
76 | $ hg push |
|
76 | $ hg push | |
77 | pushing to static-http://localhost:$HGPORT/remote |
|
77 | pushing to static-http://localhost:$HGPORT/remote | |
78 | abort: destination does not support push |
|
78 | abort: destination does not support push | |
79 | [255] |
|
79 | [255] | |
80 |
|
80 | |||
81 | trying clone -r |
|
81 | trying clone -r | |
82 |
|
82 | |||
83 | $ cd .. |
|
83 | $ cd .. | |
84 | $ hg clone -r doesnotexist static-http://localhost:$HGPORT/remote local0 |
|
84 | $ hg clone -r doesnotexist static-http://localhost:$HGPORT/remote local0 | |
85 | abort: unknown revision 'doesnotexist'! |
|
85 | abort: unknown revision 'doesnotexist'! | |
86 | [255] |
|
86 | [255] | |
87 | $ hg clone -r 0 static-http://localhost:$HGPORT/remote local0 |
|
87 | $ hg clone -r 0 static-http://localhost:$HGPORT/remote local0 | |
88 | adding changesets |
|
88 | adding changesets | |
89 | adding manifests |
|
89 | adding manifests | |
90 | adding file changes |
|
90 | adding file changes | |
91 | added 1 changesets with 2 changes to 2 files |
|
91 | added 1 changesets with 2 changes to 2 files | |
92 | updating to branch default |
|
92 | updating to branch default | |
93 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
93 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
94 |
|
94 | |||
95 | test with "/" URI (issue747) and subrepo |
|
95 | test with "/" URI (issue747) and subrepo | |
96 |
|
96 | |||
97 | $ hg init |
|
97 | $ hg init | |
98 | $ hg init sub |
|
98 | $ hg init sub | |
99 | $ touch sub/test |
|
99 | $ touch sub/test | |
100 | $ hg -R sub commit -A -m "test" |
|
100 | $ hg -R sub commit -A -m "test" | |
101 | adding test |
|
101 | adding test | |
102 | $ hg -R sub tag not-empty |
|
102 | $ hg -R sub tag not-empty | |
103 | $ echo sub=sub > .hgsub |
|
103 | $ echo sub=sub > .hgsub | |
104 | $ echo a > a |
|
104 | $ echo a > a | |
105 | $ hg add a .hgsub |
|
105 | $ hg add a .hgsub | |
106 | $ hg -q ci -ma |
|
106 | $ hg -q ci -ma | |
107 | $ hg clone static-http://localhost:$HGPORT/ local2 |
|
107 | $ hg clone static-http://localhost:$HGPORT/ local2 | |
108 | requesting all changes |
|
108 | requesting all changes | |
109 | adding changesets |
|
109 | adding changesets | |
110 | adding manifests |
|
110 | adding manifests | |
111 | adding file changes |
|
111 | adding file changes | |
112 | added 1 changesets with 3 changes to 3 files |
|
112 | added 1 changesets with 3 changes to 3 files | |
113 | updating to branch default |
|
113 | updating to branch default | |
114 | cloning subrepo sub from static-http://localhost:$HGPORT/sub |
|
114 | cloning subrepo sub from static-http://localhost:$HGPORT/sub | |
115 | requesting all changes |
|
115 | requesting all changes | |
116 | adding changesets |
|
116 | adding changesets | |
117 | adding manifests |
|
117 | adding manifests | |
118 | adding file changes |
|
118 | adding file changes | |
119 | added 2 changesets with 2 changes to 2 files |
|
119 | added 2 changesets with 2 changes to 2 files | |
120 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
120 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
121 | $ cd local2 |
|
121 | $ cd local2 | |
122 | $ hg verify |
|
122 | $ hg verify | |
123 | checking changesets |
|
123 | checking changesets | |
124 | checking manifests |
|
124 | checking manifests | |
125 | crosschecking files in changesets and manifests |
|
125 | crosschecking files in changesets and manifests | |
126 | checking files |
|
126 | checking files | |
127 | 3 files, 1 changesets, 3 total revisions |
|
127 | 3 files, 1 changesets, 3 total revisions | |
128 | checking subrepo links |
|
128 | checking subrepo links | |
129 | $ cat a |
|
129 | $ cat a | |
130 | a |
|
130 | a | |
131 | $ hg paths |
|
131 | $ hg paths | |
132 | default = static-http://localhost:$HGPORT/ |
|
132 | default = static-http://localhost:$HGPORT/ | |
133 |
|
133 | |||
134 | test with empty repo (issue965) |
|
134 | test with empty repo (issue965) | |
135 |
|
135 | |||
136 | $ cd .. |
|
136 | $ cd .. | |
137 | $ hg init remotempty |
|
137 | $ hg init remotempty | |
138 | $ hg clone static-http://localhost:$HGPORT/remotempty local3 |
|
138 | $ hg clone static-http://localhost:$HGPORT/remotempty local3 | |
139 | no changes found |
|
139 | no changes found | |
140 | updating to branch default |
|
140 | updating to branch default | |
141 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
141 | 0 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
142 | $ cd local3 |
|
142 | $ cd local3 | |
143 | $ hg verify |
|
143 | $ hg verify | |
144 | checking changesets |
|
144 | checking changesets | |
145 | checking manifests |
|
145 | checking manifests | |
146 | crosschecking files in changesets and manifests |
|
146 | crosschecking files in changesets and manifests | |
147 | checking files |
|
147 | checking files | |
148 | 0 files, 0 changesets, 0 total revisions |
|
148 | 0 files, 0 changesets, 0 total revisions | |
149 | $ hg paths |
|
149 | $ hg paths | |
150 | default = static-http://localhost:$HGPORT/remotempty |
|
150 | default = static-http://localhost:$HGPORT/remotempty | |
151 |
|
151 | |||
152 | test with non-repo |
|
152 | test with non-repo | |
153 |
|
153 | |||
154 | $ cd .. |
|
154 | $ cd .. | |
155 | $ mkdir notarepo |
|
155 | $ mkdir notarepo | |
156 | $ hg clone static-http://localhost:$HGPORT/notarepo local3 |
|
156 | $ hg clone static-http://localhost:$HGPORT/notarepo local3 | |
157 | abort: 'http://localhost:$HGPORT/notarepo' does not appear to be an hg repository! |
|
157 | abort: 'http://localhost:$HGPORT/notarepo' does not appear to be an hg repository! | |
158 | [255] |
|
158 | [255] | |
159 | $ killdaemons.py |
|
159 | $ killdaemons.py |
General Comments 0
You need to be logged in to leave comments.
Login now