##// END OF EJS Templates
change tests to use simplemerge by default
Alexis S. L. Carvalho -
r4365:46280c00 default
parent child Browse files
Show More
@@ -1,432 +1,433 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
7 # This software may be used and distributed according to the terms
8 # of the GNU General Public License, incorporated herein by reference.
8 # of the GNU General Public License, incorporated herein by reference.
9
9
10 import difflib
10 import difflib
11 import errno
11 import errno
12 import optparse
12 import optparse
13 import os
13 import os
14 import popen2
14 import popen2
15 import re
15 import re
16 import shutil
16 import shutil
17 import signal
17 import signal
18 import sys
18 import sys
19 import tempfile
19 import tempfile
20 import time
20 import time
21
21
22 required_tools = ["python", "diff", "grep", "unzip", "gunzip", "bunzip2", "sed", "merge"]
22 required_tools = ["python", "diff", "grep", "unzip", "gunzip", "bunzip2", "sed"]
23
23
24 parser = optparse.OptionParser("%prog [options] [tests]")
24 parser = optparse.OptionParser("%prog [options] [tests]")
25 parser.add_option("-v", "--verbose", action="store_true",
25 parser.add_option("-v", "--verbose", action="store_true",
26 help="output verbose messages")
26 help="output verbose messages")
27 parser.add_option("-t", "--timeout", type="int",
27 parser.add_option("-t", "--timeout", type="int",
28 help="kill errant tests after TIMEOUT seconds")
28 help="kill errant tests after TIMEOUT seconds")
29 parser.add_option("-c", "--cover", action="store_true",
29 parser.add_option("-c", "--cover", action="store_true",
30 help="print a test coverage report")
30 help="print a test coverage report")
31 parser.add_option("-s", "--cover_stdlib", action="store_true",
31 parser.add_option("-s", "--cover_stdlib", action="store_true",
32 help="print a test coverage report inc. standard libraries")
32 help="print a test coverage report inc. standard libraries")
33 parser.add_option("-C", "--annotate", action="store_true",
33 parser.add_option("-C", "--annotate", action="store_true",
34 help="output files annotated with coverage")
34 help="output files annotated with coverage")
35 parser.add_option("-r", "--retest", action="store_true",
35 parser.add_option("-r", "--retest", action="store_true",
36 help="retest failed tests")
36 help="retest failed tests")
37 parser.add_option("-f", "--first", action="store_true",
37 parser.add_option("-f", "--first", action="store_true",
38 help="exit on the first test failure")
38 help="exit on the first test failure")
39 parser.add_option("-R", "--restart", action="store_true",
39 parser.add_option("-R", "--restart", action="store_true",
40 help="restart at last error")
40 help="restart at last error")
41 parser.add_option("-i", "--interactive", action="store_true",
41 parser.add_option("-i", "--interactive", action="store_true",
42 help="prompt to accept changed output")
42 help="prompt to accept changed output")
43
43
44 parser.set_defaults(timeout=180)
44 parser.set_defaults(timeout=180)
45 (options, args) = parser.parse_args()
45 (options, args) = parser.parse_args()
46 verbose = options.verbose
46 verbose = options.verbose
47 coverage = options.cover or options.cover_stdlib or options.annotate
47 coverage = options.cover or options.cover_stdlib or options.annotate
48 python = sys.executable
48 python = sys.executable
49
49
50 def vlog(*msg):
50 def vlog(*msg):
51 if verbose:
51 if verbose:
52 for m in msg:
52 for m in msg:
53 print m,
53 print m,
54 print
54 print
55
55
56 def splitnewlines(text):
56 def splitnewlines(text):
57 '''like str.splitlines, but only split on newlines.
57 '''like str.splitlines, but only split on newlines.
58 keep line endings.'''
58 keep line endings.'''
59 i = 0
59 i = 0
60 lines = []
60 lines = []
61 while True:
61 while True:
62 n = text.find('\n', i)
62 n = text.find('\n', i)
63 if n == -1:
63 if n == -1:
64 last = text[i:]
64 last = text[i:]
65 if last:
65 if last:
66 lines.append(last)
66 lines.append(last)
67 return lines
67 return lines
68 lines.append(text[i:n+1])
68 lines.append(text[i:n+1])
69 i = n + 1
69 i = n + 1
70
70
71 def show_diff(expected, output):
71 def show_diff(expected, output):
72 for line in difflib.unified_diff(expected, output,
72 for line in difflib.unified_diff(expected, output,
73 "Expected output", "Test output"):
73 "Expected output", "Test output"):
74 sys.stdout.write(line)
74 sys.stdout.write(line)
75
75
76 def find_program(program):
76 def find_program(program):
77 """Search PATH for a executable program"""
77 """Search PATH for a executable program"""
78 for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
78 for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
79 name = os.path.join(p, program)
79 name = os.path.join(p, program)
80 if os.access(name, os.X_OK):
80 if os.access(name, os.X_OK):
81 return name
81 return name
82 return None
82 return None
83
83
84 def check_required_tools():
84 def check_required_tools():
85 # Before we go any further, check for pre-requisite tools
85 # Before we go any further, check for pre-requisite tools
86 # stuff from coreutils (cat, rm, etc) are not tested
86 # stuff from coreutils (cat, rm, etc) are not tested
87 for p in required_tools:
87 for p in required_tools:
88 if os.name == 'nt':
88 if os.name == 'nt':
89 p += '.exe'
89 p += '.exe'
90 found = find_program(p)
90 found = find_program(p)
91 if found:
91 if found:
92 vlog("# Found prerequisite", p, "at", found)
92 vlog("# Found prerequisite", p, "at", found)
93 else:
93 else:
94 print "WARNING: Did not find prerequisite tool: "+p
94 print "WARNING: Did not find prerequisite tool: "+p
95
95
96 def cleanup_exit():
96 def cleanup_exit():
97 if verbose:
97 if verbose:
98 print "# Cleaning up HGTMP", HGTMP
98 print "# Cleaning up HGTMP", HGTMP
99 shutil.rmtree(HGTMP, True)
99 shutil.rmtree(HGTMP, True)
100
100
101 def use_correct_python():
101 def use_correct_python():
102 # some tests run python interpreter. they must use same
102 # some tests run python interpreter. they must use same
103 # interpreter we use or bad things will happen.
103 # interpreter we use or bad things will happen.
104 exedir, exename = os.path.split(sys.executable)
104 exedir, exename = os.path.split(sys.executable)
105 if exename == 'python':
105 if exename == 'python':
106 path = find_program('python')
106 path = find_program('python')
107 if os.path.dirname(path) == exedir:
107 if os.path.dirname(path) == exedir:
108 return
108 return
109 vlog('# Making python executable in test path use correct Python')
109 vlog('# Making python executable in test path use correct Python')
110 my_python = os.path.join(BINDIR, 'python')
110 my_python = os.path.join(BINDIR, 'python')
111 try:
111 try:
112 os.symlink(sys.executable, my_python)
112 os.symlink(sys.executable, my_python)
113 except AttributeError:
113 except AttributeError:
114 # windows fallback
114 # windows fallback
115 shutil.copyfile(sys.executable, my_python)
115 shutil.copyfile(sys.executable, my_python)
116 shutil.copymode(sys.executable, my_python)
116 shutil.copymode(sys.executable, my_python)
117
117
118 def install_hg():
118 def install_hg():
119 global python
119 global python
120 vlog("# Performing temporary installation of HG")
120 vlog("# Performing temporary installation of HG")
121 installerrs = os.path.join("tests", "install.err")
121 installerrs = os.path.join("tests", "install.err")
122
122
123 os.chdir("..") # Get back to hg root
123 os.chdir("..") # Get back to hg root
124 cmd = ('%s setup.py clean --all'
124 cmd = ('%s setup.py clean --all'
125 ' install --force --home="%s" --install-lib="%s" >%s 2>&1'
125 ' install --force --home="%s" --install-lib="%s" >%s 2>&1'
126 % (sys.executable, INST, PYTHONDIR, installerrs))
126 % (sys.executable, INST, PYTHONDIR, installerrs))
127 vlog("# Running", cmd)
127 vlog("# Running", cmd)
128 if os.system(cmd) == 0:
128 if os.system(cmd) == 0:
129 if not verbose:
129 if not verbose:
130 os.remove(installerrs)
130 os.remove(installerrs)
131 else:
131 else:
132 f = open(installerrs)
132 f = open(installerrs)
133 for line in f:
133 for line in f:
134 print line,
134 print line,
135 f.close()
135 f.close()
136 sys.exit(1)
136 sys.exit(1)
137 os.chdir(TESTDIR)
137 os.chdir(TESTDIR)
138
138
139 os.environ["PATH"] = "%s%s%s" % (BINDIR, os.pathsep, os.environ["PATH"])
139 os.environ["PATH"] = "%s%s%s" % (BINDIR, os.pathsep, os.environ["PATH"])
140 os.environ["PYTHONPATH"] = PYTHONDIR
140 os.environ["PYTHONPATH"] = PYTHONDIR
141
141
142 use_correct_python()
142 use_correct_python()
143
143
144 if coverage:
144 if coverage:
145 vlog("# Installing coverage wrapper")
145 vlog("# Installing coverage wrapper")
146 os.environ['COVERAGE_FILE'] = COVERAGE_FILE
146 os.environ['COVERAGE_FILE'] = COVERAGE_FILE
147 if os.path.exists(COVERAGE_FILE):
147 if os.path.exists(COVERAGE_FILE):
148 os.unlink(COVERAGE_FILE)
148 os.unlink(COVERAGE_FILE)
149 # Create a wrapper script to invoke hg via coverage.py
149 # Create a wrapper script to invoke hg via coverage.py
150 os.rename(os.path.join(BINDIR, "hg"), os.path.join(BINDIR, "_hg.py"))
150 os.rename(os.path.join(BINDIR, "hg"), os.path.join(BINDIR, "_hg.py"))
151 f = open(os.path.join(BINDIR, 'hg'), 'w')
151 f = open(os.path.join(BINDIR, 'hg'), 'w')
152 f.write('#!' + sys.executable + '\n')
152 f.write('#!' + sys.executable + '\n')
153 f.write('import sys, os; os.execv(sys.executable, [sys.executable, '+ \
153 f.write('import sys, os; os.execv(sys.executable, [sys.executable, '+ \
154 '"%s", "-x", "%s"] + sys.argv[1:])\n' % (
154 '"%s", "-x", "%s"] + sys.argv[1:])\n' % (
155 os.path.join(TESTDIR, 'coverage.py'),
155 os.path.join(TESTDIR, 'coverage.py'),
156 os.path.join(BINDIR, '_hg.py')))
156 os.path.join(BINDIR, '_hg.py')))
157 f.close()
157 f.close()
158 os.chmod(os.path.join(BINDIR, 'hg'), 0700)
158 os.chmod(os.path.join(BINDIR, 'hg'), 0700)
159 python = '"%s" "%s" -x' % (sys.executable,
159 python = '"%s" "%s" -x' % (sys.executable,
160 os.path.join(TESTDIR,'coverage.py'))
160 os.path.join(TESTDIR,'coverage.py'))
161
161
162 def output_coverage():
162 def output_coverage():
163 vlog("# Producing coverage report")
163 vlog("# Producing coverage report")
164 omit = [BINDIR, TESTDIR, PYTHONDIR]
164 omit = [BINDIR, TESTDIR, PYTHONDIR]
165 if not options.cover_stdlib:
165 if not options.cover_stdlib:
166 # Exclude as system paths (ignoring empty strings seen on win)
166 # Exclude as system paths (ignoring empty strings seen on win)
167 omit += [x for x in sys.path if x != '']
167 omit += [x for x in sys.path if x != '']
168 omit = ','.join(omit)
168 omit = ','.join(omit)
169 os.chdir(PYTHONDIR)
169 os.chdir(PYTHONDIR)
170 cmd = '"%s" "%s" -i -r "--omit=%s"' % (
170 cmd = '"%s" "%s" -i -r "--omit=%s"' % (
171 sys.executable, os.path.join(TESTDIR, 'coverage.py'), omit)
171 sys.executable, os.path.join(TESTDIR, 'coverage.py'), omit)
172 vlog("# Running: "+cmd)
172 vlog("# Running: "+cmd)
173 os.system(cmd)
173 os.system(cmd)
174 if options.annotate:
174 if options.annotate:
175 adir = os.path.join(TESTDIR, 'annotated')
175 adir = os.path.join(TESTDIR, 'annotated')
176 if not os.path.isdir(adir):
176 if not os.path.isdir(adir):
177 os.mkdir(adir)
177 os.mkdir(adir)
178 cmd = '"%s" "%s" -i -a "--directory=%s" "--omit=%s"' % (
178 cmd = '"%s" "%s" -i -a "--directory=%s" "--omit=%s"' % (
179 sys.executable, os.path.join(TESTDIR, 'coverage.py'),
179 sys.executable, os.path.join(TESTDIR, 'coverage.py'),
180 adir, omit)
180 adir, omit)
181 vlog("# Running: "+cmd)
181 vlog("# Running: "+cmd)
182 os.system(cmd)
182 os.system(cmd)
183
183
184 class Timeout(Exception):
184 class Timeout(Exception):
185 pass
185 pass
186
186
187 def alarmed(signum, frame):
187 def alarmed(signum, frame):
188 raise Timeout
188 raise Timeout
189
189
190 def run(cmd):
190 def run(cmd):
191 """Run command in a sub-process, capturing the output (stdout and stderr).
191 """Run command in a sub-process, capturing the output (stdout and stderr).
192 Return the exist code, and output."""
192 Return the exist code, and output."""
193 # TODO: Use subprocess.Popen if we're running on Python 2.4
193 # TODO: Use subprocess.Popen if we're running on Python 2.4
194 if os.name == 'nt':
194 if os.name == 'nt':
195 tochild, fromchild = os.popen4(cmd)
195 tochild, fromchild = os.popen4(cmd)
196 tochild.close()
196 tochild.close()
197 output = fromchild.read()
197 output = fromchild.read()
198 ret = fromchild.close()
198 ret = fromchild.close()
199 if ret == None:
199 if ret == None:
200 ret = 0
200 ret = 0
201 else:
201 else:
202 proc = popen2.Popen4(cmd)
202 proc = popen2.Popen4(cmd)
203 try:
203 try:
204 output = ''
204 output = ''
205 proc.tochild.close()
205 proc.tochild.close()
206 output = proc.fromchild.read()
206 output = proc.fromchild.read()
207 ret = proc.wait()
207 ret = proc.wait()
208 except Timeout:
208 except Timeout:
209 vlog('# Process %d timed out - killing it' % proc.pid)
209 vlog('# Process %d timed out - killing it' % proc.pid)
210 os.kill(proc.pid, signal.SIGTERM)
210 os.kill(proc.pid, signal.SIGTERM)
211 ret = proc.wait()
211 ret = proc.wait()
212 if ret == 0:
212 if ret == 0:
213 ret = signal.SIGTERM << 8
213 ret = signal.SIGTERM << 8
214 return ret, splitnewlines(output)
214 return ret, splitnewlines(output)
215
215
216 def run_one(test):
216 def run_one(test):
217 '''tristate output:
217 '''tristate output:
218 None -> skipped
218 None -> skipped
219 True -> passed
219 True -> passed
220 False -> failed'''
220 False -> failed'''
221
221
222 vlog("# Test", test)
222 vlog("# Test", test)
223 if not verbose:
223 if not verbose:
224 sys.stdout.write('.')
224 sys.stdout.write('.')
225 sys.stdout.flush()
225 sys.stdout.flush()
226
226
227 # create a fresh hgrc
227 # create a fresh hgrc
228 hgrc = file(HGRCPATH, 'w+')
228 hgrc = file(HGRCPATH, 'w+')
229 hgrc.close()
229 hgrc.close()
230
230
231 err = os.path.join(TESTDIR, test+".err")
231 err = os.path.join(TESTDIR, test+".err")
232 ref = os.path.join(TESTDIR, test+".out")
232 ref = os.path.join(TESTDIR, test+".out")
233 testpath = os.path.join(TESTDIR, test)
233 testpath = os.path.join(TESTDIR, test)
234
234
235 if os.path.exists(err):
235 if os.path.exists(err):
236 os.remove(err) # Remove any previous output files
236 os.remove(err) # Remove any previous output files
237
237
238 # Make a tmp subdirectory to work in
238 # Make a tmp subdirectory to work in
239 tmpd = os.path.join(HGTMP, test)
239 tmpd = os.path.join(HGTMP, test)
240 os.mkdir(tmpd)
240 os.mkdir(tmpd)
241 os.chdir(tmpd)
241 os.chdir(tmpd)
242
242
243 try:
243 try:
244 tf = open(testpath)
244 tf = open(testpath)
245 firstline = tf.readline().rstrip()
245 firstline = tf.readline().rstrip()
246 tf.close()
246 tf.close()
247 except:
247 except:
248 firstline = ''
248 firstline = ''
249 lctest = test.lower()
249 lctest = test.lower()
250
250
251 if lctest.endswith('.py') or firstline == '#!/usr/bin/env python':
251 if lctest.endswith('.py') or firstline == '#!/usr/bin/env python':
252 cmd = '%s "%s"' % (python, testpath)
252 cmd = '%s "%s"' % (python, testpath)
253 elif lctest.endswith('.bat'):
253 elif lctest.endswith('.bat'):
254 # do not run batch scripts on non-windows
254 # do not run batch scripts on non-windows
255 if os.name != 'nt':
255 if os.name != 'nt':
256 print '\nSkipping %s: batch script' % test
256 print '\nSkipping %s: batch script' % test
257 return None
257 return None
258 # To reliably get the error code from batch files on WinXP,
258 # To reliably get the error code from batch files on WinXP,
259 # the "cmd /c call" prefix is needed. Grrr
259 # the "cmd /c call" prefix is needed. Grrr
260 cmd = 'cmd /c call "%s"' % testpath
260 cmd = 'cmd /c call "%s"' % testpath
261 else:
261 else:
262 # do not run shell scripts on windows
262 # do not run shell scripts on windows
263 if os.name == 'nt':
263 if os.name == 'nt':
264 print '\nSkipping %s: shell script' % test
264 print '\nSkipping %s: shell script' % test
265 return None
265 return None
266 # do not try to run non-executable programs
266 # do not try to run non-executable programs
267 if not os.access(testpath, os.X_OK):
267 if not os.access(testpath, os.X_OK):
268 print '\nSkipping %s: not executable' % test
268 print '\nSkipping %s: not executable' % test
269 return None
269 return None
270 cmd = '"%s"' % testpath
270 cmd = '"%s"' % testpath
271
271
272 if options.timeout > 0:
272 if options.timeout > 0:
273 signal.alarm(options.timeout)
273 signal.alarm(options.timeout)
274
274
275 vlog("# Running", cmd)
275 vlog("# Running", cmd)
276 ret, out = run(cmd)
276 ret, out = run(cmd)
277 vlog("# Ret was:", ret)
277 vlog("# Ret was:", ret)
278
278
279 if options.timeout > 0:
279 if options.timeout > 0:
280 signal.alarm(0)
280 signal.alarm(0)
281
281
282 diffret = 0
282 diffret = 0
283 # If reference output file exists, check test output against it
283 # If reference output file exists, check test output against it
284 if os.path.exists(ref):
284 if os.path.exists(ref):
285 f = open(ref, "r")
285 f = open(ref, "r")
286 ref_out = splitnewlines(f.read())
286 ref_out = splitnewlines(f.read())
287 f.close()
287 f.close()
288 else:
288 else:
289 ref_out = []
289 ref_out = []
290 if out != ref_out:
290 if out != ref_out:
291 diffret = 1
291 diffret = 1
292 print "\nERROR: %s output changed" % (test)
292 print "\nERROR: %s output changed" % (test)
293 show_diff(ref_out, out)
293 show_diff(ref_out, out)
294 if ret:
294 if ret:
295 print "\nERROR: %s failed with error code %d" % (test, ret)
295 print "\nERROR: %s failed with error code %d" % (test, ret)
296 elif diffret:
296 elif diffret:
297 ret = diffret
297 ret = diffret
298
298
299 if ret != 0: # Save errors to a file for diagnosis
299 if ret != 0: # Save errors to a file for diagnosis
300 f = open(err, "wb")
300 f = open(err, "wb")
301 for line in out:
301 for line in out:
302 f.write(line)
302 f.write(line)
303 f.close()
303 f.close()
304
304
305 # Kill off any leftover daemon processes
305 # Kill off any leftover daemon processes
306 try:
306 try:
307 fp = file(DAEMON_PIDS)
307 fp = file(DAEMON_PIDS)
308 for line in fp:
308 for line in fp:
309 try:
309 try:
310 pid = int(line)
310 pid = int(line)
311 except ValueError:
311 except ValueError:
312 continue
312 continue
313 try:
313 try:
314 os.kill(pid, 0)
314 os.kill(pid, 0)
315 vlog('# Killing daemon process %d' % pid)
315 vlog('# Killing daemon process %d' % pid)
316 os.kill(pid, signal.SIGTERM)
316 os.kill(pid, signal.SIGTERM)
317 time.sleep(0.25)
317 time.sleep(0.25)
318 os.kill(pid, 0)
318 os.kill(pid, 0)
319 vlog('# Daemon process %d is stuck - really killing it' % pid)
319 vlog('# Daemon process %d is stuck - really killing it' % pid)
320 os.kill(pid, signal.SIGKILL)
320 os.kill(pid, signal.SIGKILL)
321 except OSError, err:
321 except OSError, err:
322 if err.errno != errno.ESRCH:
322 if err.errno != errno.ESRCH:
323 raise
323 raise
324 fp.close()
324 fp.close()
325 os.unlink(DAEMON_PIDS)
325 os.unlink(DAEMON_PIDS)
326 except IOError:
326 except IOError:
327 pass
327 pass
328
328
329 os.chdir(TESTDIR)
329 os.chdir(TESTDIR)
330 shutil.rmtree(tmpd, True)
330 shutil.rmtree(tmpd, True)
331 return ret == 0
331 return ret == 0
332
332
333
333
334 os.umask(022)
334 os.umask(022)
335
335
336 check_required_tools()
336 check_required_tools()
337
337
338 # Reset some environment variables to well-known values so that
338 # Reset some environment variables to well-known values so that
339 # the tests produce repeatable output.
339 # the tests produce repeatable output.
340 os.environ['LANG'] = os.environ['LC_ALL'] = 'C'
340 os.environ['LANG'] = os.environ['LC_ALL'] = 'C'
341 os.environ['TZ'] = 'GMT'
341 os.environ['TZ'] = 'GMT'
342
342
343 os.environ["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
344 os.environ["HGMERGE"] = sys.executable + ' -c "import sys; sys.exit(0)"'
345 os.environ["HGUSER"] = "test"
346 os.environ["HGENCODING"] = "ascii"
347 os.environ["HGENCODINGMODE"] = "strict"
348
349 TESTDIR = os.environ["TESTDIR"] = os.getcwd()
343 TESTDIR = os.environ["TESTDIR"] = os.getcwd()
350 HGTMP = os.environ["HGTMP"] = tempfile.mkdtemp("", "hgtests.")
344 HGTMP = os.environ["HGTMP"] = tempfile.mkdtemp("", "hgtests.")
351 DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids')
345 DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids')
352 HGRCPATH = os.environ["HGRCPATH"] = os.path.join(HGTMP, '.hgrc')
346 HGRCPATH = os.environ["HGRCPATH"] = os.path.join(HGTMP, '.hgrc')
353
347
348 os.environ["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
349 os.environ["HGMERGE"] = 'python "%s"' % os.path.join(TESTDIR, os.path.pardir,
350 'contrib', 'simplemerge')
351 os.environ["HGUSER"] = "test"
352 os.environ["HGENCODING"] = "ascii"
353 os.environ["HGENCODINGMODE"] = "strict"
354
354 vlog("# Using TESTDIR", TESTDIR)
355 vlog("# Using TESTDIR", TESTDIR)
355 vlog("# Using HGTMP", HGTMP)
356 vlog("# Using HGTMP", HGTMP)
356
357
357 INST = os.path.join(HGTMP, "install")
358 INST = os.path.join(HGTMP, "install")
358 BINDIR = os.path.join(INST, "bin")
359 BINDIR = os.path.join(INST, "bin")
359 PYTHONDIR = os.path.join(INST, "lib", "python")
360 PYTHONDIR = os.path.join(INST, "lib", "python")
360 COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
361 COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
361
362
362 try:
363 try:
363 try:
364 try:
364 install_hg()
365 install_hg()
365
366
366 if options.timeout > 0:
367 if options.timeout > 0:
367 try:
368 try:
368 signal.signal(signal.SIGALRM, alarmed)
369 signal.signal(signal.SIGALRM, alarmed)
369 vlog('# Running tests with %d-second timeout' %
370 vlog('# Running tests with %d-second timeout' %
370 options.timeout)
371 options.timeout)
371 except AttributeError:
372 except AttributeError:
372 print 'WARNING: cannot run tests with timeouts'
373 print 'WARNING: cannot run tests with timeouts'
373 options.timeout = 0
374 options.timeout = 0
374
375
375 tested = 0
376 tested = 0
376 failed = 0
377 failed = 0
377 skipped = 0
378 skipped = 0
378
379
379 if len(args) == 0:
380 if len(args) == 0:
380 args = os.listdir(".")
381 args = os.listdir(".")
381 args.sort()
382 args.sort()
382
383
383
384
384 tests = []
385 tests = []
385 for test in args:
386 for test in args:
386 if (test.startswith("test-") and '~' not in test and
387 if (test.startswith("test-") and '~' not in test and
387 ('.' not in test or test.endswith('.py') or
388 ('.' not in test or test.endswith('.py') or
388 test.endswith('.bat'))):
389 test.endswith('.bat'))):
389 tests.append(test)
390 tests.append(test)
390
391
391 if options.restart:
392 if options.restart:
392 orig = list(tests)
393 orig = list(tests)
393 while tests:
394 while tests:
394 if os.path.exists(tests[0] + ".err"):
395 if os.path.exists(tests[0] + ".err"):
395 break
396 break
396 tests.pop(0)
397 tests.pop(0)
397 if not tests:
398 if not tests:
398 print "running all tests"
399 print "running all tests"
399 tests = orig
400 tests = orig
400
401
401 for test in tests:
402 for test in tests:
402 if options.retest and not os.path.exists(test + ".err"):
403 if options.retest and not os.path.exists(test + ".err"):
403 skipped += 1
404 skipped += 1
404 continue
405 continue
405 ret = run_one(test)
406 ret = run_one(test)
406 if ret is None:
407 if ret is None:
407 skipped += 1
408 skipped += 1
408 elif not ret:
409 elif not ret:
409 if options.interactive:
410 if options.interactive:
410 print "Accept this change? [n] ",
411 print "Accept this change? [n] ",
411 answer = sys.stdin.readline().strip()
412 answer = sys.stdin.readline().strip()
412 if answer.lower() in "y yes".split():
413 if answer.lower() in "y yes".split():
413 os.rename(test + ".err", test + ".out")
414 os.rename(test + ".err", test + ".out")
414 tested += 1
415 tested += 1
415 continue
416 continue
416 failed += 1
417 failed += 1
417 if options.first:
418 if options.first:
418 break
419 break
419 tested += 1
420 tested += 1
420
421
421 print "\n# Ran %d tests, %d skipped, %d failed." % (tested, skipped,
422 print "\n# Ran %d tests, %d skipped, %d failed." % (tested, skipped,
422 failed)
423 failed)
423 if coverage:
424 if coverage:
424 output_coverage()
425 output_coverage()
425 except KeyboardInterrupt:
426 except KeyboardInterrupt:
426 failed = True
427 failed = True
427 print "\ninterrupted!"
428 print "\ninterrupted!"
428 finally:
429 finally:
429 cleanup_exit()
430 cleanup_exit()
430
431
431 if failed:
432 if failed:
432 sys.exit(1)
433 sys.exit(1)
@@ -1,76 +1,78 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 HGMERGE=true; export HGMERGE
4
3 echo % init
5 echo % init
4 hg init
6 hg init
5
7
6 echo % commit
8 echo % commit
7 echo 'a' > a
9 echo 'a' > a
8 hg ci -A -m test -u nobody -d '1 0'
10 hg ci -A -m test -u nobody -d '1 0'
9
11
10 echo % annotate -c
12 echo % annotate -c
11 hg annotate -c a
13 hg annotate -c a
12
14
13 echo % annotate -d
15 echo % annotate -d
14 hg annotate -d a
16 hg annotate -d a
15
17
16 echo % annotate -n
18 echo % annotate -n
17 hg annotate -n a
19 hg annotate -n a
18
20
19 echo % annotate -u
21 echo % annotate -u
20 hg annotate -u a
22 hg annotate -u a
21
23
22 echo % annotate -cdnu
24 echo % annotate -cdnu
23 hg annotate -cdnu a
25 hg annotate -cdnu a
24
26
25 cat <<EOF >>a
27 cat <<EOF >>a
26 a
28 a
27 a
29 a
28 EOF
30 EOF
29 hg ci -ma1 -d '1 0'
31 hg ci -ma1 -d '1 0'
30 hg cp a b
32 hg cp a b
31 hg ci -mb -d '1 0'
33 hg ci -mb -d '1 0'
32 cat <<EOF >> b
34 cat <<EOF >> b
33 b
35 b
34 b
36 b
35 b
37 b
36 EOF
38 EOF
37 hg ci -mb2 -d '2 0'
39 hg ci -mb2 -d '2 0'
38
40
39 echo % annotate b
41 echo % annotate b
40 hg annotate b
42 hg annotate b
41 echo % annotate -nf b
43 echo % annotate -nf b
42 hg annotate -nf b
44 hg annotate -nf b
43
45
44 hg up -C 2
46 hg up -C 2
45 cat <<EOF >> b
47 cat <<EOF >> b
46 b
48 b
47 c
49 c
48 b
50 b
49 EOF
51 EOF
50 hg ci -mb2.1 -d '2 0'
52 hg ci -mb2.1 -d '2 0'
51 hg merge
53 hg merge
52 hg ci -mmergeb -d '3 0'
54 hg ci -mmergeb -d '3 0'
53 echo % annotate after merge
55 echo % annotate after merge
54 hg annotate -nf b
56 hg annotate -nf b
55
57
56 hg up -C 1
58 hg up -C 1
57 hg cp a b
59 hg cp a b
58 cat <<EOF > b
60 cat <<EOF > b
59 a
61 a
60 z
62 z
61 a
63 a
62 EOF
64 EOF
63 hg ci -mc -d '3 0'
65 hg ci -mc -d '3 0'
64 hg merge
66 hg merge
65 cat <<EOF >> b
67 cat <<EOF >> b
66 b
68 b
67 c
69 c
68 b
70 b
69 EOF
71 EOF
70 echo d >> b
72 echo d >> b
71 hg ci -mmerge2 -d '4 0'
73 hg ci -mmerge2 -d '4 0'
72 echo % annotate after rename merge
74 echo % annotate after rename merge
73 hg annotate -nf b
75 hg annotate -nf b
74
76
75 echo % linkrev vs rev
77 echo % linkrev vs rev
76 hg annotate -r tip a
78 hg annotate -r tip a
@@ -1,99 +1,101 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 HGMERGE=true; export HGMERGE
4
3 echo '# basic operation'
5 echo '# basic operation'
4 hg init basic
6 hg init basic
5 cd basic
7 cd basic
6 echo a > a
8 echo a > a
7 hg commit -d '0 0' -A -m a
9 hg commit -d '0 0' -A -m a
8 echo b >> a
10 echo b >> a
9 hg commit -d '1 0' -m b
11 hg commit -d '1 0' -m b
10
12
11 hg backout -d '2 0' tip
13 hg backout -d '2 0' tip
12 cat a
14 cat a
13
15
14 echo '# file that was removed is recreated'
16 echo '# file that was removed is recreated'
15 cd ..
17 cd ..
16 hg init remove
18 hg init remove
17 cd remove
19 cd remove
18
20
19 echo content > a
21 echo content > a
20 hg commit -d '0 0' -A -m a
22 hg commit -d '0 0' -A -m a
21
23
22 hg rm a
24 hg rm a
23 hg commit -d '1 0' -m b
25 hg commit -d '1 0' -m b
24
26
25 hg backout -d '2 0' --merge tip
27 hg backout -d '2 0' --merge tip
26 cat a
28 cat a
27
29
28 echo '# backout of backout is as if nothing happened'
30 echo '# backout of backout is as if nothing happened'
29
31
30 hg backout -d '3 0' --merge tip
32 hg backout -d '3 0' --merge tip
31 cat a 2>/dev/null || echo cat: a: No such file or directory
33 cat a 2>/dev/null || echo cat: a: No such file or directory
32
34
33 echo '# backout with merge'
35 echo '# backout with merge'
34 cd ..
36 cd ..
35 hg init merge
37 hg init merge
36 cd merge
38 cd merge
37
39
38 echo line 1 > a
40 echo line 1 > a
39 hg commit -d '0 0' -A -m a
41 hg commit -d '0 0' -A -m a
40
42
41 echo line 2 >> a
43 echo line 2 >> a
42 hg commit -d '1 0' -m b
44 hg commit -d '1 0' -m b
43
45
44 echo line 3 >> a
46 echo line 3 >> a
45 hg commit -d '2 0' -m c
47 hg commit -d '2 0' -m c
46
48
47 hg backout --merge -d '3 0' 1
49 hg backout --merge -d '3 0' 1
48 hg commit -d '4 0' -m d
50 hg commit -d '4 0' -m d
49 cat a
51 cat a
50
52
51 echo '# backout should not back out subsequent changesets'
53 echo '# backout should not back out subsequent changesets'
52 hg init onecs
54 hg init onecs
53 cd onecs
55 cd onecs
54 echo 1 > a
56 echo 1 > a
55 hg commit -d '0 0' -A -m a
57 hg commit -d '0 0' -A -m a
56 echo 2 >> a
58 echo 2 >> a
57 hg commit -d '1 0' -m b
59 hg commit -d '1 0' -m b
58 echo 1 > b
60 echo 1 > b
59 hg commit -d '2 0' -A -m c
61 hg commit -d '2 0' -A -m c
60 hg backout -d '3 0' 1
62 hg backout -d '3 0' 1
61 hg locate b
63 hg locate b
62
64
63 cd ..
65 cd ..
64 hg init m
66 hg init m
65 cd m
67 cd m
66 echo a > a
68 echo a > a
67 hg commit -d '0 0' -A -m a
69 hg commit -d '0 0' -A -m a
68 echo b > b
70 echo b > b
69 hg commit -d '1 0' -A -m b
71 hg commit -d '1 0' -A -m b
70 echo c > c
72 echo c > c
71 hg commit -d '2 0' -A -m b
73 hg commit -d '2 0' -A -m b
72 hg update 1
74 hg update 1
73 echo d > d
75 echo d > d
74 hg commit -d '3 0' -A -m c
76 hg commit -d '3 0' -A -m c
75 hg merge 2
77 hg merge 2
76 hg commit -d '4 0' -A -m d
78 hg commit -d '4 0' -A -m d
77
79
78 echo '# backout of merge should fail'
80 echo '# backout of merge should fail'
79
81
80 hg backout 4
82 hg backout 4
81
83
82 echo '# backout of merge with bad parent should fail'
84 echo '# backout of merge with bad parent should fail'
83
85
84 hg backout --parent 0 4
86 hg backout --parent 0 4
85
87
86 echo '# backout of non-merge with parent should fail'
88 echo '# backout of non-merge with parent should fail'
87
89
88 hg backout --parent 0 3
90 hg backout --parent 0 3
89
91
90 echo '# backout with valid parent should be ok'
92 echo '# backout with valid parent should be ok'
91
93
92 hg backout -d '5 0' --parent 2 4
94 hg backout -d '5 0' --parent 2 4
93
95
94 hg rollback
96 hg rollback
95 hg update -C
97 hg update -C
96
98
97 hg backout -d '6 0' --parent 3 4
99 hg backout -d '6 0' --parent 3 4
98
100
99 exit 0
101 exit 0
@@ -1,16 +1,15 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 hg init
3 hg init
4 echo "nothing" > a
4 echo "nothing" > a
5 hg add a
5 hg add a
6 hg commit -m ancestor -d "1000000 0"
6 hg commit -m ancestor -d "1000000 0"
7 echo "something" > a
7 echo "something" > a
8 hg commit -m branch1 -d "1000000 0"
8 hg commit -m branch1 -d "1000000 0"
9 hg co 0
9 hg co 0
10 echo "something else" > a
10 echo "something else" > a
11 hg commit -m branch2 -d "1000000 0"
11 hg commit -m branch2 -d "1000000 0"
12 HGMERGE=merge; export HGMERGE
13 hg merge 1
12 hg merge 1
14 hg id
13 hg id
15 egrep -v ">>>|<<<" a
14 egrep -v ">>>|<<<" a
16 hg status
15 hg status
@@ -1,13 +1,13 b''
1 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2 merge: warning: conflicts during merge
2 warning: conflicts during merge.
3 merging a
3 merging a
4 merging a failed!
4 merging a failed!
5 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
5 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
6 There are unresolved merges, you can redo the full merge using:
6 There are unresolved merges, you can redo the full merge using:
7 hg update -C 2
7 hg update -C 2
8 hg merge 1
8 hg merge 1
9 e7fe8eb3e180+0d24b7662d3e+ tip
9 e7fe8eb3e180+0d24b7662d3e+ tip
10 something else
10 something else
11 =======
11 =======
12 something
12 something
13 M a
13 M a
@@ -1,72 +1,72 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 hg init a
3 hg init a
4 cd a
4 cd a
5 echo a > a
5 echo a > a
6 hg ci -A -d'1 0' -m a
6 hg ci -A -d'1 0' -m a
7
7
8 cd ..
8 cd ..
9
9
10 hg init b
10 hg init b
11 cd b
11 cd b
12 echo b > b
12 echo b > b
13 hg ci -A -d'1 0' -m b
13 hg ci -A -d'1 0' -m b
14
14
15 cd ..
15 cd ..
16
16
17 hg clone a c
17 hg clone a c
18 cd c
18 cd c
19 hg pull -f ../b
19 hg pull -f ../b
20 HGMERGE=merge hg merge
20 hg merge
21
21
22 cd ..
22 cd ..
23
23
24 echo %% -R/--repository
24 echo %% -R/--repository
25 hg -R a tip
25 hg -R a tip
26 hg --repository b tip
26 hg --repository b tip
27
27
28 echo %% abbrev of long option
28 echo %% abbrev of long option
29 hg --repo c tip
29 hg --repo c tip
30
30
31 echo %% --cwd
31 echo %% --cwd
32 hg --cwd a parents
32 hg --cwd a parents
33
33
34 echo %% -y/--noninteractive - just be sure it is parsed
34 echo %% -y/--noninteractive - just be sure it is parsed
35 hg --cwd a tip -q --noninteractive
35 hg --cwd a tip -q --noninteractive
36 hg --cwd a tip -q -y
36 hg --cwd a tip -q -y
37
37
38 echo %% -q/--quiet
38 echo %% -q/--quiet
39 hg -R a -q tip
39 hg -R a -q tip
40 hg -R b -q tip
40 hg -R b -q tip
41 hg -R c --quiet parents
41 hg -R c --quiet parents
42
42
43 echo %% -v/--verbose
43 echo %% -v/--verbose
44 hg --cwd c head -v
44 hg --cwd c head -v
45 hg --cwd b tip --verbose
45 hg --cwd b tip --verbose
46
46
47 echo %% --config
47 echo %% --config
48 hg --cwd c --config paths.quuxfoo=bar paths | grep quuxfoo > /dev/null && echo quuxfoo
48 hg --cwd c --config paths.quuxfoo=bar paths | grep quuxfoo > /dev/null && echo quuxfoo
49 hg --cwd c --config '' tip -q
49 hg --cwd c --config '' tip -q
50 hg --cwd c --config a.b tip -q
50 hg --cwd c --config a.b tip -q
51 hg --cwd c --config a tip -q
51 hg --cwd c --config a tip -q
52 hg --cwd c --config a.= tip -q
52 hg --cwd c --config a.= tip -q
53 hg --cwd c --config .b= tip -q
53 hg --cwd c --config .b= tip -q
54
54
55 echo %% --debug
55 echo %% --debug
56 hg --cwd c log --debug
56 hg --cwd c log --debug
57
57
58 echo %% --traceback
58 echo %% --traceback
59 hg --cwd c --config x --traceback tip 2>&1 | grep -i 'traceback'
59 hg --cwd c --config x --traceback tip 2>&1 | grep -i 'traceback'
60
60
61 echo %% --time
61 echo %% --time
62 hg --cwd a --time tip 2>&1 | grep '^Time:' | sed 's/[0-9][0-9]*/x/g'
62 hg --cwd a --time tip 2>&1 | grep '^Time:' | sed 's/[0-9][0-9]*/x/g'
63
63
64 echo %% --version
64 echo %% --version
65 hg --version -q | sed 's/version [^)]*/version xxx/'
65 hg --version -q | sed 's/version [^)]*/version xxx/'
66
66
67 echo %% -h/--help
67 echo %% -h/--help
68 hg -h
68 hg -h
69 hg --help
69 hg --help
70
70
71 echo %% not tested: --debugger
71 echo %% not tested: --debugger
72
72
@@ -1,3 +1,3 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 HGMERGE=merge hg debuginstall
3 hg debuginstall
@@ -1,77 +1,74 b''
1 #!/bin/sh
1 #!/bin/sh
2 # check that renames are correctly saved by a commit after a merge
2 # check that renames are correctly saved by a commit after a merge
3
3
4 HGMERGE=merge
5 export HGMERGE
6
7 # test with the merge on 3 having the rename on the local parent
4 # test with the merge on 3 having the rename on the local parent
8 hg init a
5 hg init a
9 cd a
6 cd a
10
7
11 echo line1 > foo
8 echo line1 > foo
12 hg add foo
9 hg add foo
13 hg ci -m '0: add foo' -d '0 0'
10 hg ci -m '0: add foo' -d '0 0'
14
11
15 echo line2 >> foo
12 echo line2 >> foo
16 hg ci -m '1: change foo' -d '0 0'
13 hg ci -m '1: change foo' -d '0 0'
17
14
18 hg up -C 0
15 hg up -C 0
19 hg mv foo bar
16 hg mv foo bar
20 rm bar
17 rm bar
21 echo line0 > bar
18 echo line0 > bar
22 echo line1 >> bar
19 echo line1 >> bar
23 hg ci -m '2: mv foo bar; change bar' -d '0 0'
20 hg ci -m '2: mv foo bar; change bar' -d '0 0'
24
21
25 hg merge 1
22 hg merge 1
26 echo '% contents of bar should be line0 line1 line2'
23 echo '% contents of bar should be line0 line1 line2'
27 cat bar
24 cat bar
28 hg ci -m '3: merge with local rename' -d '0 0'
25 hg ci -m '3: merge with local rename' -d '0 0'
29 hg debugindex .hg/store/data/bar.i
26 hg debugindex .hg/store/data/bar.i
30 hg debugrename bar
27 hg debugrename bar
31 hg debugindex .hg/store/data/foo.i
28 hg debugindex .hg/store/data/foo.i
32
29
33 # revert the content change from rev 2
30 # revert the content change from rev 2
34 hg up -C 2
31 hg up -C 2
35 rm bar
32 rm bar
36 echo line1 > bar
33 echo line1 > bar
37 hg ci -m '4: revert content change from rev 2' -d '0 0'
34 hg ci -m '4: revert content change from rev 2' -d '0 0'
38
35
39 hg log --template '#rev#:#node|short# #parents#\n'
36 hg log --template '#rev#:#node|short# #parents#\n'
40 echo '% this should use bar@rev2 as the ancestor'
37 echo '% this should use bar@rev2 as the ancestor'
41 hg --debug merge 3
38 hg --debug merge 3
42 echo '% contents of bar should be line1 line2'
39 echo '% contents of bar should be line1 line2'
43 cat bar
40 cat bar
44 hg ci -m '5: merge' -d '0 0'
41 hg ci -m '5: merge' -d '0 0'
45 hg debugindex .hg/store/data/bar.i
42 hg debugindex .hg/store/data/bar.i
46
43
47
44
48 # same thing, but with the merge on 3 having the rename on the remote parent
45 # same thing, but with the merge on 3 having the rename on the remote parent
49 echo
46 echo
50 echo
47 echo
51 cd ..
48 cd ..
52 hg clone -U -r 1 -r 2 a b
49 hg clone -U -r 1 -r 2 a b
53 cd b
50 cd b
54
51
55 hg up -C 1
52 hg up -C 1
56 hg merge 2
53 hg merge 2
57 echo '% contents of bar should be line0 line1 line2'
54 echo '% contents of bar should be line0 line1 line2'
58 cat bar
55 cat bar
59 hg ci -m '3: merge with remote rename' -d '0 0'
56 hg ci -m '3: merge with remote rename' -d '0 0'
60 hg debugindex .hg/store/data/bar.i
57 hg debugindex .hg/store/data/bar.i
61 hg debugrename bar
58 hg debugrename bar
62 hg debugindex .hg/store/data/foo.i
59 hg debugindex .hg/store/data/foo.i
63
60
64 # revert the content change from rev 2
61 # revert the content change from rev 2
65 hg up -C 2
62 hg up -C 2
66 rm bar
63 rm bar
67 echo line1 > bar
64 echo line1 > bar
68 hg ci -m '4: revert content change from rev 2' -d '0 0'
65 hg ci -m '4: revert content change from rev 2' -d '0 0'
69
66
70 hg log --template '#rev#:#node|short# #parents#\n'
67 hg log --template '#rev#:#node|short# #parents#\n'
71 echo '% this should use bar@rev2 as the ancestor'
68 echo '% this should use bar@rev2 as the ancestor'
72 hg --debug merge 3
69 hg --debug merge 3
73 echo '% contents of bar should be line1 line2'
70 echo '% contents of bar should be line1 line2'
74 cat bar
71 cat bar
75 hg ci -m '5: merge' -d '0 0'
72 hg ci -m '5: merge' -d '0 0'
76 hg debugindex .hg/store/data/bar.i
73 hg debugindex .hg/store/data/bar.i
77
74
@@ -1,50 +1,50 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 hg init
3 hg init
4
4
5 echo "# revision 0"
5 echo "# revision 0"
6 echo "unchanged" > unchanged
6 echo "unchanged" > unchanged
7 echo "remove me" > remove
7 echo "remove me" > remove
8 echo "copy me" > copy
8 echo "copy me" > copy
9 echo "move me" > move
9 echo "move me" > move
10 for i in 1 2 3 4 5 6 7 8 9; do
10 for i in 1 2 3 4 5 6 7 8 9; do
11 echo "merge ok $i" >> zzz1_merge_ok
11 echo "merge ok $i" >> zzz1_merge_ok
12 done
12 done
13 echo "merge bad" > zzz2_merge_bad
13 echo "merge bad" > zzz2_merge_bad
14 hg ci -Am "revision 0" -d "1000000 0"
14 hg ci -Am "revision 0" -d "1000000 0"
15
15
16 echo "# revision 1"
16 echo "# revision 1"
17 hg rm remove
17 hg rm remove
18 hg mv move moved
18 hg mv move moved
19 hg cp copy copied
19 hg cp copy copied
20 echo "added" > added
20 echo "added" > added
21 hg add added
21 hg add added
22 echo "new first line" > zzz1_merge_ok
22 echo "new first line" > zzz1_merge_ok
23 hg cat zzz1_merge_ok >> zzz1_merge_ok
23 hg cat zzz1_merge_ok >> zzz1_merge_ok
24 echo "new last line" >> zzz2_merge_bad
24 echo "new last line" >> zzz2_merge_bad
25 hg ci -m "revision 1" -d "1000000 0"
25 hg ci -m "revision 1" -d "1000000 0"
26
26
27 echo "# local changes to revision 0"
27 echo "# local changes to revision 0"
28 hg co 0
28 hg co 0
29 echo "new last line" >> zzz1_merge_ok
29 echo "new last line" >> zzz1_merge_ok
30 echo "another last line" >> zzz2_merge_bad
30 echo "another last line" >> zzz2_merge_bad
31 hg diff --nodates | grep "^[+-][^<>]"
31 hg diff --nodates | grep "^[+-][^<>]"
32 hg st
32 hg st
33
33
34 echo "# local merge with bad merge tool"
34 echo "# local merge with bad merge tool"
35 HGMERGE=false hg co
35 HGMERGE=false hg co
36 hg co 0
36 hg co 0
37 hg diff --nodates | grep "^[+-][^<>]"
37 hg diff --nodates | grep "^[+-][^<>]"
38 hg st
38 hg st
39
39
40 echo "# local merge with conflicts"
40 echo "# local merge with conflicts"
41 HGMERGE=merge hg co
41 hg co
42 hg co 0
42 hg co 0
43 hg diff --nodates | grep "^[+-][^<>]"
43 hg diff --nodates | grep "^[+-][^<>]"
44 hg st
44 hg st
45
45
46 echo "# local merge without conflicts"
46 echo "# local merge without conflicts"
47 hg revert zzz2_merge_bad
47 hg revert zzz2_merge_bad
48 HGMERGE=merge hg co
48 hg co
49 hg diff --nodates | grep "^[+-][^<>]"
49 hg diff --nodates | grep "^[+-][^<>]"
50 hg st
50 hg st
@@ -1,67 +1,67 b''
1 # revision 0
1 # revision 0
2 adding copy
2 adding copy
3 adding move
3 adding move
4 adding remove
4 adding remove
5 adding unchanged
5 adding unchanged
6 adding zzz1_merge_ok
6 adding zzz1_merge_ok
7 adding zzz2_merge_bad
7 adding zzz2_merge_bad
8 # revision 1
8 # revision 1
9 # local changes to revision 0
9 # local changes to revision 0
10 4 files updated, 0 files merged, 3 files removed, 0 files unresolved
10 4 files updated, 0 files merged, 3 files removed, 0 files unresolved
11 --- a/zzz1_merge_ok
11 --- a/zzz1_merge_ok
12 +++ b/zzz1_merge_ok
12 +++ b/zzz1_merge_ok
13 +new last line
13 +new last line
14 --- a/zzz2_merge_bad
14 --- a/zzz2_merge_bad
15 +++ b/zzz2_merge_bad
15 +++ b/zzz2_merge_bad
16 +another last line
16 +another last line
17 M zzz1_merge_ok
17 M zzz1_merge_ok
18 M zzz2_merge_bad
18 M zzz2_merge_bad
19 # local merge with bad merge tool
19 # local merge with bad merge tool
20 merging zzz1_merge_ok
20 merging zzz1_merge_ok
21 merging zzz1_merge_ok failed!
21 merging zzz1_merge_ok failed!
22 merging zzz2_merge_bad
22 merging zzz2_merge_bad
23 merging zzz2_merge_bad failed!
23 merging zzz2_merge_bad failed!
24 3 files updated, 0 files merged, 1 files removed, 2 files unresolved
24 3 files updated, 0 files merged, 1 files removed, 2 files unresolved
25 There are unresolved merges with locally modified files.
25 There are unresolved merges with locally modified files.
26 You can redo the full merge using:
26 You can redo the full merge using:
27 hg update 0
27 hg update 0
28 hg update 1
28 hg update 1
29 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
29 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
30 --- a/zzz1_merge_ok
30 --- a/zzz1_merge_ok
31 +++ b/zzz1_merge_ok
31 +++ b/zzz1_merge_ok
32 +new last line
32 +new last line
33 --- a/zzz2_merge_bad
33 --- a/zzz2_merge_bad
34 +++ b/zzz2_merge_bad
34 +++ b/zzz2_merge_bad
35 +another last line
35 +another last line
36 M zzz1_merge_ok
36 M zzz1_merge_ok
37 M zzz2_merge_bad
37 M zzz2_merge_bad
38 # local merge with conflicts
38 # local merge with conflicts
39 merge: warning: conflicts during merge
39 warning: conflicts during merge.
40 merging zzz1_merge_ok
40 merging zzz1_merge_ok
41 merging zzz2_merge_bad
41 merging zzz2_merge_bad
42 merging zzz2_merge_bad failed!
42 merging zzz2_merge_bad failed!
43 3 files updated, 1 files merged, 1 files removed, 1 files unresolved
43 3 files updated, 1 files merged, 1 files removed, 1 files unresolved
44 There are unresolved merges with locally modified files.
44 There are unresolved merges with locally modified files.
45 You can finish the partial merge using:
45 You can finish the partial merge using:
46 hg update 0
46 hg update 0
47 hg update 1
47 hg update 1
48 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
48 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
49 --- a/zzz1_merge_ok
49 --- a/zzz1_merge_ok
50 +++ b/zzz1_merge_ok
50 +++ b/zzz1_merge_ok
51 +new first line
51 +new first line
52 +new last line
52 +new last line
53 --- a/zzz2_merge_bad
53 --- a/zzz2_merge_bad
54 +++ b/zzz2_merge_bad
54 +++ b/zzz2_merge_bad
55 +another last line
55 +another last line
56 +=======
56 +=======
57 +new last line
57 +new last line
58 M zzz1_merge_ok
58 M zzz1_merge_ok
59 M zzz2_merge_bad
59 M zzz2_merge_bad
60 # local merge without conflicts
60 # local merge without conflicts
61 merging zzz1_merge_ok
61 merging zzz1_merge_ok
62 4 files updated, 1 files merged, 1 files removed, 0 files unresolved
62 4 files updated, 1 files merged, 1 files removed, 0 files unresolved
63 --- a/zzz1_merge_ok
63 --- a/zzz1_merge_ok
64 +++ b/zzz1_merge_ok
64 +++ b/zzz1_merge_ok
65 +new last line
65 +new last line
66 M zzz1_merge_ok
66 M zzz1_merge_ok
67 ? zzz2_merge_bad.orig
67 ? zzz2_merge_bad.orig
@@ -1,44 +1,44 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 mkdir t
3 mkdir t
4 cd t
4 cd t
5 hg init
5 hg init
6 echo "added file1" > file1
6 echo "added file1" > file1
7 echo "added file2" > file2
7 echo "added file2" > file2
8 hg add file1 file2
8 hg add file1 file2
9 hg commit -m "added file1 and file2" -d "1000000 0" -u user
9 hg commit -m "added file1 and file2" -d "1000000 0" -u user
10 echo "changed file1" >> file1
10 echo "changed file1" >> file1
11 hg commit -m "changed file1" -d "1000000 0" -u user
11 hg commit -m "changed file1" -d "1000000 0" -u user
12 hg -q log
12 hg -q log
13 hg id
13 hg id
14 hg update -C 0
14 hg update -C 0
15 hg id
15 hg id
16 echo "changed file1" >> file1
16 echo "changed file1" >> file1
17 hg id
17 hg id
18 hg revert --all
18 hg revert --all
19 hg diff
19 hg diff
20 hg status
20 hg status
21 hg id
21 hg id
22 hg update
22 hg update
23 hg diff
23 hg diff
24 hg status
24 hg status
25 hg id
25 hg id
26 hg update -C 0
26 hg update -C 0
27 echo "changed file1" >> file1
27 echo "changed file1" >> file1
28 HGMERGE=merge hg update
28 hg update
29 hg diff
29 hg diff
30 hg status
30 hg status
31 hg id
31 hg id
32 hg revert --all
32 hg revert --all
33 hg diff
33 hg diff
34 hg status
34 hg status
35 hg id
35 hg id
36 hg revert -r tip --all
36 hg revert -r tip --all
37 hg diff
37 hg diff
38 hg status
38 hg status
39 hg id
39 hg id
40 hg update -C
40 hg update -C
41 hg diff
41 hg diff
42 hg status
42 hg status
43 hg id
43 hg id
44
44
@@ -1,45 +1,45 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 mkdir t
3 mkdir t
4 cd t
4 cd t
5 hg init
5 hg init
6 echo "added file1" > file1
6 echo "added file1" > file1
7 echo "another line of text" >> file1
7 echo "another line of text" >> file1
8 echo "added file2" > file2
8 echo "added file2" > file2
9 hg add file1 file2
9 hg add file1 file2
10 hg commit -m "added file1 and file2" -d "1000000 0" -u user
10 hg commit -m "added file1 and file2" -d "1000000 0" -u user
11 echo "changed file1" >> file1
11 echo "changed file1" >> file1
12 hg commit -m "changed file1" -d "1000000 0" -u user
12 hg commit -m "changed file1" -d "1000000 0" -u user
13 hg -q log
13 hg -q log
14 hg id
14 hg id
15 hg update -C 0
15 hg update -C 0
16 hg id
16 hg id
17 echo "changed file1" >> file1
17 echo "changed file1" >> file1
18 hg id
18 hg id
19 hg revert --no-backup --all
19 hg revert --no-backup --all
20 hg diff
20 hg diff
21 hg status
21 hg status
22 hg id
22 hg id
23 hg update
23 hg update
24 hg diff
24 hg diff
25 hg status
25 hg status
26 hg id
26 hg id
27 hg update -C 0
27 hg update -C 0
28 echo "changed file1 different" >> file1
28 echo "changed file1 different" >> file1
29 HGMERGE=merge hg update
29 hg update
30 hg diff --nodates | sed -e "s/\(<<<<<<<\) .*/\1/" -e "s/\(>>>>>>>\) .*/\1/"
30 hg diff --nodates | sed -e "s/\(<<<<<<<\) .*/\1/" -e "s/\(>>>>>>>\) .*/\1/"
31 hg status
31 hg status
32 hg id
32 hg id
33 hg revert --no-backup --all
33 hg revert --no-backup --all
34 hg diff
34 hg diff
35 hg status
35 hg status
36 hg id
36 hg id
37 hg revert -r tip --no-backup --all
37 hg revert -r tip --no-backup --all
38 hg diff
38 hg diff
39 hg status
39 hg status
40 hg id
40 hg id
41 hg update -C
41 hg update -C
42 hg diff
42 hg diff
43 hg status
43 hg status
44 hg id
44 hg id
45
45
@@ -1,37 +1,37 b''
1 1:f248da0d4c3e
1 1:f248da0d4c3e
2 0:9eca13a34789
2 0:9eca13a34789
3 f248da0d4c3e tip
3 f248da0d4c3e tip
4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
5 9eca13a34789
5 9eca13a34789
6 9eca13a34789+
6 9eca13a34789+
7 reverting file1
7 reverting file1
8 9eca13a34789
8 9eca13a34789
9 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
9 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
10 f248da0d4c3e tip
10 f248da0d4c3e tip
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 merge: warning: conflicts during merge
12 warning: conflicts during merge.
13 merging file1
13 merging file1
14 merging file1 failed!
14 merging file1 failed!
15 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
15 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
16 There are unresolved merges with locally modified files.
16 There are unresolved merges with locally modified files.
17 You can redo the full merge using:
17 You can redo the full merge using:
18 hg update 0
18 hg update 0
19 hg update 1
19 hg update 1
20 diff -r f248da0d4c3e file1
20 diff -r f248da0d4c3e file1
21 --- a/file1
21 --- a/file1
22 +++ b/file1
22 +++ b/file1
23 @@ -1,3 +1,7 @@ added file1
23 @@ -1,3 +1,7 @@ added file1
24 added file1
24 added file1
25 another line of text
25 another line of text
26 +<<<<<<<
26 +<<<<<<<
27 +changed file1 different
27 +changed file1 different
28 +=======
28 +=======
29 changed file1
29 changed file1
30 +>>>>>>>
30 +>>>>>>>
31 M file1
31 M file1
32 f248da0d4c3e+ tip
32 f248da0d4c3e+ tip
33 reverting file1
33 reverting file1
34 f248da0d4c3e tip
34 f248da0d4c3e tip
35 f248da0d4c3e tip
35 f248da0d4c3e tip
36 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
36 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
37 f248da0d4c3e tip
37 f248da0d4c3e tip
@@ -1,66 +1,66 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 # initial
3 # initial
4 hg init test-a
4 hg init test-a
5 cd test-a
5 cd test-a
6 cat >test.txt <<"EOF"
6 cat >test.txt <<"EOF"
7 1
7 1
8 2
8 2
9 3
9 3
10 EOF
10 EOF
11 hg add test.txt
11 hg add test.txt
12 hg commit -m "Initial" -d "1000000 0"
12 hg commit -m "Initial" -d "1000000 0"
13
13
14 # clone
14 # clone
15 cd ..
15 cd ..
16 hg clone test-a test-b
16 hg clone test-a test-b
17
17
18 # change test-a
18 # change test-a
19 cd test-a
19 cd test-a
20 cat >test.txt <<"EOF"
20 cat >test.txt <<"EOF"
21 one
21 one
22 two
22 two
23 three
23 three
24 EOF
24 EOF
25 hg commit -m "Numbers as words" -d "1000000 0"
25 hg commit -m "Numbers as words" -d "1000000 0"
26
26
27 # change test-b
27 # change test-b
28 cd ../test-b
28 cd ../test-b
29 cat >test.txt <<"EOF"
29 cat >test.txt <<"EOF"
30 1
30 1
31 2.5
31 2.5
32 3
32 3
33 EOF
33 EOF
34 hg commit -m "2 -> 2.5" -d "1000000 0"
34 hg commit -m "2 -> 2.5" -d "1000000 0"
35
35
36 # now pull and merge from test-a
36 # now pull and merge from test-a
37 hg pull ../test-a
37 hg pull ../test-a
38 HGMERGE=merge hg merge
38 hg merge
39 # resolve conflict
39 # resolve conflict
40 cat >test.txt <<"EOF"
40 cat >test.txt <<"EOF"
41 one
41 one
42 two-point-five
42 two-point-five
43 three
43 three
44 EOF
44 EOF
45 rm -f *.orig
45 rm -f *.orig
46 hg commit -m "Merge 1" -d "1000000 0"
46 hg commit -m "Merge 1" -d "1000000 0"
47
47
48 # change test-a again
48 # change test-a again
49 cd ../test-a
49 cd ../test-a
50 cat >test.txt <<"EOF"
50 cat >test.txt <<"EOF"
51 one
51 one
52 two-point-one
52 two-point-one
53 three
53 three
54 EOF
54 EOF
55 hg commit -m "two -> two-point-one" -d "1000000 0"
55 hg commit -m "two -> two-point-one" -d "1000000 0"
56
56
57 # pull and merge from test-a again
57 # pull and merge from test-a again
58 cd ../test-b
58 cd ../test-b
59 hg pull ../test-a
59 hg pull ../test-a
60 HGMERGE=merge hg merge --debug
60 hg merge --debug
61
61
62 cat test.txt | sed "s% .*%%"
62 cat test.txt | sed "s% .*%%"
63
63
64 hg debugindex .hg/store/data/test.txt.i
64 hg debugindex .hg/store/data/test.txt.i
65
65
66 hg log
66 hg log
@@ -1,77 +1,77 b''
1 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2 pulling from ../test-a
2 pulling from ../test-a
3 searching for changes
3 searching for changes
4 adding changesets
4 adding changesets
5 adding manifests
5 adding manifests
6 adding file changes
6 adding file changes
7 added 1 changesets with 1 changes to 1 files (+1 heads)
7 added 1 changesets with 1 changes to 1 files (+1 heads)
8 (run 'hg heads' to see heads, 'hg merge' to merge)
8 (run 'hg heads' to see heads, 'hg merge' to merge)
9 merge: warning: conflicts during merge
9 warning: conflicts during merge.
10 merging test.txt
10 merging test.txt
11 merging test.txt failed!
11 merging test.txt failed!
12 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
12 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
13 There are unresolved merges, you can redo the full merge using:
13 There are unresolved merges, you can redo the full merge using:
14 hg update -C 1
14 hg update -C 1
15 hg merge 2
15 hg merge 2
16 pulling from ../test-a
16 pulling from ../test-a
17 searching for changes
17 searching for changes
18 adding changesets
18 adding changesets
19 adding manifests
19 adding manifests
20 adding file changes
20 adding file changes
21 added 1 changesets with 1 changes to 1 files (+1 heads)
21 added 1 changesets with 1 changes to 1 files (+1 heads)
22 (run 'hg heads' to see heads, 'hg merge' to merge)
22 (run 'hg heads' to see heads, 'hg merge' to merge)
23 merge: warning: conflicts during merge
23 warning: conflicts during merge.
24 resolving manifests
24 resolving manifests
25 overwrite None partial False
25 overwrite None partial False
26 ancestor faaea63e63a9 local 451c744aabcc+ remote a070d41e8360
26 ancestor faaea63e63a9 local 451c744aabcc+ remote a070d41e8360
27 test.txt: versions differ -> m
27 test.txt: versions differ -> m
28 merging test.txt
28 merging test.txt
29 my test.txt@451c744aabcc+ other test.txt@a070d41e8360 ancestor test.txt@faaea63e63a9
29 my test.txt@451c744aabcc+ other test.txt@a070d41e8360 ancestor test.txt@faaea63e63a9
30 merging test.txt failed!
30 merging test.txt failed!
31 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
31 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
32 There are unresolved merges, you can redo the full merge using:
32 There are unresolved merges, you can redo the full merge using:
33 hg update -C 3
33 hg update -C 3
34 hg merge 4
34 hg merge 4
35 one
35 one
36 <<<<<<<
36 <<<<<<<
37 two-point-five
37 two-point-five
38 =======
38 =======
39 two-point-one
39 two-point-one
40 >>>>>>>
40 >>>>>>>
41 three
41 three
42 rev offset length base linkrev nodeid p1 p2
42 rev offset length base linkrev nodeid p1 p2
43 0 0 7 0 0 01365c4cca56 000000000000 000000000000
43 0 0 7 0 0 01365c4cca56 000000000000 000000000000
44 1 7 9 1 1 7b013192566a 01365c4cca56 000000000000
44 1 7 9 1 1 7b013192566a 01365c4cca56 000000000000
45 2 16 15 2 2 8fe46a3eb557 01365c4cca56 000000000000
45 2 16 15 2 2 8fe46a3eb557 01365c4cca56 000000000000
46 3 31 27 2 3 fc3148072371 7b013192566a 8fe46a3eb557
46 3 31 27 2 3 fc3148072371 7b013192566a 8fe46a3eb557
47 4 58 25 4 4 d40249267ae3 8fe46a3eb557 000000000000
47 4 58 25 4 4 d40249267ae3 8fe46a3eb557 000000000000
48 changeset: 4:a070d41e8360
48 changeset: 4:a070d41e8360
49 tag: tip
49 tag: tip
50 parent: 2:faaea63e63a9
50 parent: 2:faaea63e63a9
51 user: test
51 user: test
52 date: Mon Jan 12 13:46:40 1970 +0000
52 date: Mon Jan 12 13:46:40 1970 +0000
53 summary: two -> two-point-one
53 summary: two -> two-point-one
54
54
55 changeset: 3:451c744aabcc
55 changeset: 3:451c744aabcc
56 parent: 1:e409be6afcc0
56 parent: 1:e409be6afcc0
57 parent: 2:faaea63e63a9
57 parent: 2:faaea63e63a9
58 user: test
58 user: test
59 date: Mon Jan 12 13:46:40 1970 +0000
59 date: Mon Jan 12 13:46:40 1970 +0000
60 summary: Merge 1
60 summary: Merge 1
61
61
62 changeset: 2:faaea63e63a9
62 changeset: 2:faaea63e63a9
63 parent: 0:095c92b91f1a
63 parent: 0:095c92b91f1a
64 user: test
64 user: test
65 date: Mon Jan 12 13:46:40 1970 +0000
65 date: Mon Jan 12 13:46:40 1970 +0000
66 summary: Numbers as words
66 summary: Numbers as words
67
67
68 changeset: 1:e409be6afcc0
68 changeset: 1:e409be6afcc0
69 user: test
69 user: test
70 date: Mon Jan 12 13:46:40 1970 +0000
70 date: Mon Jan 12 13:46:40 1970 +0000
71 summary: 2 -> 2.5
71 summary: 2 -> 2.5
72
72
73 changeset: 0:095c92b91f1a
73 changeset: 0:095c92b91f1a
74 user: test
74 user: test
75 date: Mon Jan 12 13:46:40 1970 +0000
75 date: Mon Jan 12 13:46:40 1970 +0000
76 summary: Initial
76 summary: Initial
77
77
@@ -1,66 +1,68 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 HGMERGE=true; export HGMERGE
4
3 set -e
5 set -e
4 mkdir r1
6 mkdir r1
5 cd r1
7 cd r1
6 hg init
8 hg init
7 echo a > a
9 echo a > a
8 hg addremove
10 hg addremove
9 hg commit -m "1" -d "1000000 0"
11 hg commit -m "1" -d "1000000 0"
10
12
11 hg clone . ../r2
13 hg clone . ../r2
12 cd ../r2
14 cd ../r2
13 hg up
15 hg up
14 echo abc > a
16 echo abc > a
15 hg diff --nodates
17 hg diff --nodates
16
18
17 cd ../r1
19 cd ../r1
18 echo b > b
20 echo b > b
19 echo a2 > a
21 echo a2 > a
20 hg addremove
22 hg addremove
21 hg commit -m "2" -d "1000000 0"
23 hg commit -m "2" -d "1000000 0"
22
24
23 cd ../r2
25 cd ../r2
24 hg -q pull ../r1
26 hg -q pull ../r1
25 hg status
27 hg status
26 hg parents
28 hg parents
27 hg --debug up
29 hg --debug up
28 hg parents
30 hg parents
29 hg --debug up 0
31 hg --debug up 0
30 hg parents
32 hg parents
31 hg --debug merge || echo failed
33 hg --debug merge || echo failed
32 hg parents
34 hg parents
33 hg --debug up
35 hg --debug up
34 hg parents
36 hg parents
35 hg -v history
37 hg -v history
36 hg diff --nodates
38 hg diff --nodates
37
39
38 # create a second head
40 # create a second head
39 cd ../r1
41 cd ../r1
40 hg up 0
42 hg up 0
41 echo b2 > b
43 echo b2 > b
42 echo a3 > a
44 echo a3 > a
43 hg addremove
45 hg addremove
44 hg commit -m "3" -d "1000000 0"
46 hg commit -m "3" -d "1000000 0"
45
47
46 cd ../r2
48 cd ../r2
47 hg -q pull ../r1
49 hg -q pull ../r1
48 hg status
50 hg status
49 hg parents
51 hg parents
50 hg --debug up || echo failed
52 hg --debug up || echo failed
51 hg --debug merge || echo failed
53 hg --debug merge || echo failed
52 hg --debug merge -f
54 hg --debug merge -f
53 hg parents
55 hg parents
54 hg diff --nodates
56 hg diff --nodates
55
57
56 # test a local add
58 # test a local add
57 cd ..
59 cd ..
58 hg init a
60 hg init a
59 hg init b
61 hg init b
60 echo a > a/a
62 echo a > a/a
61 echo a > b/a
63 echo a > b/a
62 hg --cwd a commit -A -m a
64 hg --cwd a commit -A -m a
63 cd b
65 cd b
64 hg add a
66 hg add a
65 hg pull -u ../a
67 hg pull -u ../a
66 hg st
68 hg st
General Comments 0
You need to be logged in to leave comments. Login now