##// END OF EJS Templates
tests: run "cwd was removed" test only if cwd can actually be removed...
Yuya Nishihara -
r30230:46a0203d stable
parent child Browse files
Show More
@@ -1,592 +1,607 b''
1 from __future__ import absolute_import
1 from __future__ import absolute_import
2
2
3 import errno
3 import errno
4 import os
4 import os
5 import re
5 import re
6 import socket
6 import socket
7 import stat
7 import stat
8 import subprocess
8 import subprocess
9 import sys
9 import sys
10 import tempfile
10 import tempfile
11
11
12 tempprefix = 'hg-hghave-'
12 tempprefix = 'hg-hghave-'
13
13
14 checks = {
14 checks = {
15 "true": (lambda: True, "yak shaving"),
15 "true": (lambda: True, "yak shaving"),
16 "false": (lambda: False, "nail clipper"),
16 "false": (lambda: False, "nail clipper"),
17 }
17 }
18
18
19 def check(name, desc):
19 def check(name, desc):
20 """Registers a check function for a feature."""
20 """Registers a check function for a feature."""
21 def decorator(func):
21 def decorator(func):
22 checks[name] = (func, desc)
22 checks[name] = (func, desc)
23 return func
23 return func
24 return decorator
24 return decorator
25
25
26 def checkvers(name, desc, vers):
26 def checkvers(name, desc, vers):
27 """Registers a check function for each of a series of versions.
27 """Registers a check function for each of a series of versions.
28
28
29 vers can be a list or an iterator"""
29 vers can be a list or an iterator"""
30 def decorator(func):
30 def decorator(func):
31 def funcv(v):
31 def funcv(v):
32 def f():
32 def f():
33 return func(v)
33 return func(v)
34 return f
34 return f
35 for v in vers:
35 for v in vers:
36 v = str(v)
36 v = str(v)
37 f = funcv(v)
37 f = funcv(v)
38 checks['%s%s' % (name, v.replace('.', ''))] = (f, desc % v)
38 checks['%s%s' % (name, v.replace('.', ''))] = (f, desc % v)
39 return func
39 return func
40 return decorator
40 return decorator
41
41
42 def checkfeatures(features):
42 def checkfeatures(features):
43 result = {
43 result = {
44 'error': [],
44 'error': [],
45 'missing': [],
45 'missing': [],
46 'skipped': [],
46 'skipped': [],
47 }
47 }
48
48
49 for feature in features:
49 for feature in features:
50 negate = feature.startswith('no-')
50 negate = feature.startswith('no-')
51 if negate:
51 if negate:
52 feature = feature[3:]
52 feature = feature[3:]
53
53
54 if feature not in checks:
54 if feature not in checks:
55 result['missing'].append(feature)
55 result['missing'].append(feature)
56 continue
56 continue
57
57
58 check, desc = checks[feature]
58 check, desc = checks[feature]
59 try:
59 try:
60 available = check()
60 available = check()
61 except Exception:
61 except Exception:
62 result['error'].append('hghave check failed: %s' % feature)
62 result['error'].append('hghave check failed: %s' % feature)
63 continue
63 continue
64
64
65 if not negate and not available:
65 if not negate and not available:
66 result['skipped'].append('missing feature: %s' % desc)
66 result['skipped'].append('missing feature: %s' % desc)
67 elif negate and available:
67 elif negate and available:
68 result['skipped'].append('system supports %s' % desc)
68 result['skipped'].append('system supports %s' % desc)
69
69
70 return result
70 return result
71
71
72 def require(features):
72 def require(features):
73 """Require that features are available, exiting if not."""
73 """Require that features are available, exiting if not."""
74 result = checkfeatures(features)
74 result = checkfeatures(features)
75
75
76 for missing in result['missing']:
76 for missing in result['missing']:
77 sys.stderr.write('skipped: unknown feature: %s\n' % missing)
77 sys.stderr.write('skipped: unknown feature: %s\n' % missing)
78 for msg in result['skipped']:
78 for msg in result['skipped']:
79 sys.stderr.write('skipped: %s\n' % msg)
79 sys.stderr.write('skipped: %s\n' % msg)
80 for msg in result['error']:
80 for msg in result['error']:
81 sys.stderr.write('%s\n' % msg)
81 sys.stderr.write('%s\n' % msg)
82
82
83 if result['missing']:
83 if result['missing']:
84 sys.exit(2)
84 sys.exit(2)
85
85
86 if result['skipped'] or result['error']:
86 if result['skipped'] or result['error']:
87 sys.exit(1)
87 sys.exit(1)
88
88
89 def matchoutput(cmd, regexp, ignorestatus=False):
89 def matchoutput(cmd, regexp, ignorestatus=False):
90 """Return the match object if cmd executes successfully and its output
90 """Return the match object if cmd executes successfully and its output
91 is matched by the supplied regular expression.
91 is matched by the supplied regular expression.
92 """
92 """
93 r = re.compile(regexp)
93 r = re.compile(regexp)
94 try:
94 try:
95 p = subprocess.Popen(
95 p = subprocess.Popen(
96 cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
96 cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
97 except OSError as e:
97 except OSError as e:
98 if e.errno != errno.ENOENT:
98 if e.errno != errno.ENOENT:
99 raise
99 raise
100 ret = -1
100 ret = -1
101 ret = p.wait()
101 ret = p.wait()
102 s = p.stdout.read()
102 s = p.stdout.read()
103 return (ignorestatus or not ret) and r.search(s)
103 return (ignorestatus or not ret) and r.search(s)
104
104
105 @check("baz", "GNU Arch baz client")
105 @check("baz", "GNU Arch baz client")
106 def has_baz():
106 def has_baz():
107 return matchoutput('baz --version 2>&1', br'baz Bazaar version')
107 return matchoutput('baz --version 2>&1', br'baz Bazaar version')
108
108
109 @check("bzr", "Canonical's Bazaar client")
109 @check("bzr", "Canonical's Bazaar client")
110 def has_bzr():
110 def has_bzr():
111 try:
111 try:
112 import bzrlib
112 import bzrlib
113 import bzrlib.bzrdir
113 import bzrlib.bzrdir
114 import bzrlib.errors
114 import bzrlib.errors
115 import bzrlib.revision
115 import bzrlib.revision
116 import bzrlib.revisionspec
116 import bzrlib.revisionspec
117 bzrlib.revisionspec.RevisionSpec
117 bzrlib.revisionspec.RevisionSpec
118 return bzrlib.__doc__ is not None
118 return bzrlib.__doc__ is not None
119 except (AttributeError, ImportError):
119 except (AttributeError, ImportError):
120 return False
120 return False
121
121
122 @checkvers("bzr", "Canonical's Bazaar client >= %s", (1.14,))
122 @checkvers("bzr", "Canonical's Bazaar client >= %s", (1.14,))
123 def has_bzr_range(v):
123 def has_bzr_range(v):
124 major, minor = v.split('.')[0:2]
124 major, minor = v.split('.')[0:2]
125 try:
125 try:
126 import bzrlib
126 import bzrlib
127 return (bzrlib.__doc__ is not None
127 return (bzrlib.__doc__ is not None
128 and bzrlib.version_info[:2] >= (int(major), int(minor)))
128 and bzrlib.version_info[:2] >= (int(major), int(minor)))
129 except ImportError:
129 except ImportError:
130 return False
130 return False
131
131
132 @check("chg", "running with chg")
132 @check("chg", "running with chg")
133 def has_chg():
133 def has_chg():
134 return 'CHGHG' in os.environ
134 return 'CHGHG' in os.environ
135
135
136 @check("cvs", "cvs client/server")
136 @check("cvs", "cvs client/server")
137 def has_cvs():
137 def has_cvs():
138 re = br'Concurrent Versions System.*?server'
138 re = br'Concurrent Versions System.*?server'
139 return matchoutput('cvs --version 2>&1', re) and not has_msys()
139 return matchoutput('cvs --version 2>&1', re) and not has_msys()
140
140
141 @check("cvs112", "cvs client/server 1.12.* (not cvsnt)")
141 @check("cvs112", "cvs client/server 1.12.* (not cvsnt)")
142 def has_cvs112():
142 def has_cvs112():
143 re = br'Concurrent Versions System \(CVS\) 1.12.*?server'
143 re = br'Concurrent Versions System \(CVS\) 1.12.*?server'
144 return matchoutput('cvs --version 2>&1', re) and not has_msys()
144 return matchoutput('cvs --version 2>&1', re) and not has_msys()
145
145
146 @check("cvsnt", "cvsnt client/server")
146 @check("cvsnt", "cvsnt client/server")
147 def has_cvsnt():
147 def has_cvsnt():
148 re = br'Concurrent Versions System \(CVSNT\) (\d+).(\d+).*\(client/server\)'
148 re = br'Concurrent Versions System \(CVSNT\) (\d+).(\d+).*\(client/server\)'
149 return matchoutput('cvsnt --version 2>&1', re)
149 return matchoutput('cvsnt --version 2>&1', re)
150
150
151 @check("darcs", "darcs client")
151 @check("darcs", "darcs client")
152 def has_darcs():
152 def has_darcs():
153 return matchoutput('darcs --version', br'2\.[2-9]', True)
153 return matchoutput('darcs --version', br'2\.[2-9]', True)
154
154
155 @check("mtn", "monotone client (>= 1.0)")
155 @check("mtn", "monotone client (>= 1.0)")
156 def has_mtn():
156 def has_mtn():
157 return matchoutput('mtn --version', br'monotone', True) and not matchoutput(
157 return matchoutput('mtn --version', br'monotone', True) and not matchoutput(
158 'mtn --version', br'monotone 0\.', True)
158 'mtn --version', br'monotone 0\.', True)
159
159
160 @check("eol-in-paths", "end-of-lines in paths")
160 @check("eol-in-paths", "end-of-lines in paths")
161 def has_eol_in_paths():
161 def has_eol_in_paths():
162 try:
162 try:
163 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
163 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
164 os.close(fd)
164 os.close(fd)
165 os.remove(path)
165 os.remove(path)
166 return True
166 return True
167 except (IOError, OSError):
167 except (IOError, OSError):
168 return False
168 return False
169
169
170 @check("execbit", "executable bit")
170 @check("execbit", "executable bit")
171 def has_executablebit():
171 def has_executablebit():
172 try:
172 try:
173 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
173 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
174 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
174 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
175 try:
175 try:
176 os.close(fh)
176 os.close(fh)
177 m = os.stat(fn).st_mode & 0o777
177 m = os.stat(fn).st_mode & 0o777
178 new_file_has_exec = m & EXECFLAGS
178 new_file_has_exec = m & EXECFLAGS
179 os.chmod(fn, m ^ EXECFLAGS)
179 os.chmod(fn, m ^ EXECFLAGS)
180 exec_flags_cannot_flip = ((os.stat(fn).st_mode & 0o777) == m)
180 exec_flags_cannot_flip = ((os.stat(fn).st_mode & 0o777) == m)
181 finally:
181 finally:
182 os.unlink(fn)
182 os.unlink(fn)
183 except (IOError, OSError):
183 except (IOError, OSError):
184 # we don't care, the user probably won't be able to commit anyway
184 # we don't care, the user probably won't be able to commit anyway
185 return False
185 return False
186 return not (new_file_has_exec or exec_flags_cannot_flip)
186 return not (new_file_has_exec or exec_flags_cannot_flip)
187
187
188 @check("icasefs", "case insensitive file system")
188 @check("icasefs", "case insensitive file system")
189 def has_icasefs():
189 def has_icasefs():
190 # Stolen from mercurial.util
190 # Stolen from mercurial.util
191 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
191 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
192 os.close(fd)
192 os.close(fd)
193 try:
193 try:
194 s1 = os.stat(path)
194 s1 = os.stat(path)
195 d, b = os.path.split(path)
195 d, b = os.path.split(path)
196 p2 = os.path.join(d, b.upper())
196 p2 = os.path.join(d, b.upper())
197 if path == p2:
197 if path == p2:
198 p2 = os.path.join(d, b.lower())
198 p2 = os.path.join(d, b.lower())
199 try:
199 try:
200 s2 = os.stat(p2)
200 s2 = os.stat(p2)
201 return s2 == s1
201 return s2 == s1
202 except OSError:
202 except OSError:
203 return False
203 return False
204 finally:
204 finally:
205 os.remove(path)
205 os.remove(path)
206
206
207 @check("fifo", "named pipes")
207 @check("fifo", "named pipes")
208 def has_fifo():
208 def has_fifo():
209 if getattr(os, "mkfifo", None) is None:
209 if getattr(os, "mkfifo", None) is None:
210 return False
210 return False
211 name = tempfile.mktemp(dir='.', prefix=tempprefix)
211 name = tempfile.mktemp(dir='.', prefix=tempprefix)
212 try:
212 try:
213 os.mkfifo(name)
213 os.mkfifo(name)
214 os.unlink(name)
214 os.unlink(name)
215 return True
215 return True
216 except OSError:
216 except OSError:
217 return False
217 return False
218
218
219 @check("killdaemons", 'killdaemons.py support')
219 @check("killdaemons", 'killdaemons.py support')
220 def has_killdaemons():
220 def has_killdaemons():
221 return True
221 return True
222
222
223 @check("cacheable", "cacheable filesystem")
223 @check("cacheable", "cacheable filesystem")
224 def has_cacheable_fs():
224 def has_cacheable_fs():
225 from mercurial import util
225 from mercurial import util
226
226
227 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
227 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
228 os.close(fd)
228 os.close(fd)
229 try:
229 try:
230 return util.cachestat(path).cacheable()
230 return util.cachestat(path).cacheable()
231 finally:
231 finally:
232 os.remove(path)
232 os.remove(path)
233
233
234 @check("lsprof", "python lsprof module")
234 @check("lsprof", "python lsprof module")
235 def has_lsprof():
235 def has_lsprof():
236 try:
236 try:
237 import _lsprof
237 import _lsprof
238 _lsprof.Profiler # silence unused import warning
238 _lsprof.Profiler # silence unused import warning
239 return True
239 return True
240 except ImportError:
240 except ImportError:
241 return False
241 return False
242
242
243 def gethgversion():
243 def gethgversion():
244 m = matchoutput('hg --version --quiet 2>&1', br'(\d+)\.(\d+)')
244 m = matchoutput('hg --version --quiet 2>&1', br'(\d+)\.(\d+)')
245 if not m:
245 if not m:
246 return (0, 0)
246 return (0, 0)
247 return (int(m.group(1)), int(m.group(2)))
247 return (int(m.group(1)), int(m.group(2)))
248
248
249 @checkvers("hg", "Mercurial >= %s",
249 @checkvers("hg", "Mercurial >= %s",
250 list([(1.0 * x) / 10 for x in range(9, 40)]))
250 list([(1.0 * x) / 10 for x in range(9, 40)]))
251 def has_hg_range(v):
251 def has_hg_range(v):
252 major, minor = v.split('.')[0:2]
252 major, minor = v.split('.')[0:2]
253 return gethgversion() >= (int(major), int(minor))
253 return gethgversion() >= (int(major), int(minor))
254
254
255 @check("hg08", "Mercurial >= 0.8")
255 @check("hg08", "Mercurial >= 0.8")
256 def has_hg08():
256 def has_hg08():
257 if checks["hg09"][0]():
257 if checks["hg09"][0]():
258 return True
258 return True
259 return matchoutput('hg help annotate 2>&1', '--date')
259 return matchoutput('hg help annotate 2>&1', '--date')
260
260
261 @check("hg07", "Mercurial >= 0.7")
261 @check("hg07", "Mercurial >= 0.7")
262 def has_hg07():
262 def has_hg07():
263 if checks["hg08"][0]():
263 if checks["hg08"][0]():
264 return True
264 return True
265 return matchoutput('hg --version --quiet 2>&1', 'Mercurial Distributed SCM')
265 return matchoutput('hg --version --quiet 2>&1', 'Mercurial Distributed SCM')
266
266
267 @check("hg06", "Mercurial >= 0.6")
267 @check("hg06", "Mercurial >= 0.6")
268 def has_hg06():
268 def has_hg06():
269 if checks["hg07"][0]():
269 if checks["hg07"][0]():
270 return True
270 return True
271 return matchoutput('hg --version --quiet 2>&1', 'Mercurial version')
271 return matchoutput('hg --version --quiet 2>&1', 'Mercurial version')
272
272
273 @check("gettext", "GNU Gettext (msgfmt)")
273 @check("gettext", "GNU Gettext (msgfmt)")
274 def has_gettext():
274 def has_gettext():
275 return matchoutput('msgfmt --version', br'GNU gettext-tools')
275 return matchoutput('msgfmt --version', br'GNU gettext-tools')
276
276
277 @check("git", "git command line client")
277 @check("git", "git command line client")
278 def has_git():
278 def has_git():
279 return matchoutput('git --version 2>&1', br'^git version')
279 return matchoutput('git --version 2>&1', br'^git version')
280
280
281 @check("docutils", "Docutils text processing library")
281 @check("docutils", "Docutils text processing library")
282 def has_docutils():
282 def has_docutils():
283 try:
283 try:
284 import docutils.core
284 import docutils.core
285 docutils.core.publish_cmdline # silence unused import
285 docutils.core.publish_cmdline # silence unused import
286 return True
286 return True
287 except ImportError:
287 except ImportError:
288 return False
288 return False
289
289
290 def getsvnversion():
290 def getsvnversion():
291 m = matchoutput('svn --version --quiet 2>&1', br'^(\d+)\.(\d+)')
291 m = matchoutput('svn --version --quiet 2>&1', br'^(\d+)\.(\d+)')
292 if not m:
292 if not m:
293 return (0, 0)
293 return (0, 0)
294 return (int(m.group(1)), int(m.group(2)))
294 return (int(m.group(1)), int(m.group(2)))
295
295
296 @checkvers("svn", "subversion client and admin tools >= %s", (1.3, 1.5))
296 @checkvers("svn", "subversion client and admin tools >= %s", (1.3, 1.5))
297 def has_svn_range(v):
297 def has_svn_range(v):
298 major, minor = v.split('.')[0:2]
298 major, minor = v.split('.')[0:2]
299 return getsvnversion() >= (int(major), int(minor))
299 return getsvnversion() >= (int(major), int(minor))
300
300
301 @check("svn", "subversion client and admin tools")
301 @check("svn", "subversion client and admin tools")
302 def has_svn():
302 def has_svn():
303 return matchoutput('svn --version 2>&1', br'^svn, version') and \
303 return matchoutput('svn --version 2>&1', br'^svn, version') and \
304 matchoutput('svnadmin --version 2>&1', br'^svnadmin, version')
304 matchoutput('svnadmin --version 2>&1', br'^svnadmin, version')
305
305
306 @check("svn-bindings", "subversion python bindings")
306 @check("svn-bindings", "subversion python bindings")
307 def has_svn_bindings():
307 def has_svn_bindings():
308 try:
308 try:
309 import svn.core
309 import svn.core
310 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
310 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
311 if version < (1, 4):
311 if version < (1, 4):
312 return False
312 return False
313 return True
313 return True
314 except ImportError:
314 except ImportError:
315 return False
315 return False
316
316
317 @check("p4", "Perforce server and client")
317 @check("p4", "Perforce server and client")
318 def has_p4():
318 def has_p4():
319 return (matchoutput('p4 -V', br'Rev\. P4/') and
319 return (matchoutput('p4 -V', br'Rev\. P4/') and
320 matchoutput('p4d -V', br'Rev\. P4D/'))
320 matchoutput('p4d -V', br'Rev\. P4D/'))
321
321
322 @check("symlink", "symbolic links")
322 @check("symlink", "symbolic links")
323 def has_symlink():
323 def has_symlink():
324 if getattr(os, "symlink", None) is None:
324 if getattr(os, "symlink", None) is None:
325 return False
325 return False
326 name = tempfile.mktemp(dir='.', prefix=tempprefix)
326 name = tempfile.mktemp(dir='.', prefix=tempprefix)
327 try:
327 try:
328 os.symlink(".", name)
328 os.symlink(".", name)
329 os.unlink(name)
329 os.unlink(name)
330 return True
330 return True
331 except (OSError, AttributeError):
331 except (OSError, AttributeError):
332 return False
332 return False
333
333
334 @check("hardlink", "hardlinks")
334 @check("hardlink", "hardlinks")
335 def has_hardlink():
335 def has_hardlink():
336 from mercurial import util
336 from mercurial import util
337 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
337 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
338 os.close(fh)
338 os.close(fh)
339 name = tempfile.mktemp(dir='.', prefix=tempprefix)
339 name = tempfile.mktemp(dir='.', prefix=tempprefix)
340 try:
340 try:
341 util.oslink(fn, name)
341 util.oslink(fn, name)
342 os.unlink(name)
342 os.unlink(name)
343 return True
343 return True
344 except OSError:
344 except OSError:
345 return False
345 return False
346 finally:
346 finally:
347 os.unlink(fn)
347 os.unlink(fn)
348
348
349 @check("rmcwd", "can remove current working directory")
350 def has_rmcwd():
351 ocwd = os.getcwd()
352 temp = tempfile.mkdtemp(dir='.', prefix=tempprefix)
353 try:
354 os.chdir(temp)
355 # On Linux, 'rmdir .' isn't allowed, but the other names are okay.
356 # On Solaris and Windows, the cwd can't be removed by any names.
357 os.rmdir(os.getcwd())
358 return True
359 except OSError:
360 return False
361 finally:
362 os.chdir(ocwd)
363
349 @check("tla", "GNU Arch tla client")
364 @check("tla", "GNU Arch tla client")
350 def has_tla():
365 def has_tla():
351 return matchoutput('tla --version 2>&1', br'The GNU Arch Revision')
366 return matchoutput('tla --version 2>&1', br'The GNU Arch Revision')
352
367
353 @check("gpg", "gpg client")
368 @check("gpg", "gpg client")
354 def has_gpg():
369 def has_gpg():
355 return matchoutput('gpg --version 2>&1', br'GnuPG')
370 return matchoutput('gpg --version 2>&1', br'GnuPG')
356
371
357 @check("gpg2", "gpg client v2")
372 @check("gpg2", "gpg client v2")
358 def has_gpg2():
373 def has_gpg2():
359 return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.')
374 return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.')
360
375
361 @check("gpg21", "gpg client v2.1+")
376 @check("gpg21", "gpg client v2.1+")
362 def has_gpg21():
377 def has_gpg21():
363 return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.(?!0)')
378 return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.(?!0)')
364
379
365 @check("unix-permissions", "unix-style permissions")
380 @check("unix-permissions", "unix-style permissions")
366 def has_unix_permissions():
381 def has_unix_permissions():
367 d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
382 d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
368 try:
383 try:
369 fname = os.path.join(d, 'foo')
384 fname = os.path.join(d, 'foo')
370 for umask in (0o77, 0o07, 0o22):
385 for umask in (0o77, 0o07, 0o22):
371 os.umask(umask)
386 os.umask(umask)
372 f = open(fname, 'w')
387 f = open(fname, 'w')
373 f.close()
388 f.close()
374 mode = os.stat(fname).st_mode
389 mode = os.stat(fname).st_mode
375 os.unlink(fname)
390 os.unlink(fname)
376 if mode & 0o777 != ~umask & 0o666:
391 if mode & 0o777 != ~umask & 0o666:
377 return False
392 return False
378 return True
393 return True
379 finally:
394 finally:
380 os.rmdir(d)
395 os.rmdir(d)
381
396
382 @check("unix-socket", "AF_UNIX socket family")
397 @check("unix-socket", "AF_UNIX socket family")
383 def has_unix_socket():
398 def has_unix_socket():
384 return getattr(socket, 'AF_UNIX', None) is not None
399 return getattr(socket, 'AF_UNIX', None) is not None
385
400
386 @check("root", "root permissions")
401 @check("root", "root permissions")
387 def has_root():
402 def has_root():
388 return getattr(os, 'geteuid', None) and os.geteuid() == 0
403 return getattr(os, 'geteuid', None) and os.geteuid() == 0
389
404
390 @check("pyflakes", "Pyflakes python linter")
405 @check("pyflakes", "Pyflakes python linter")
391 def has_pyflakes():
406 def has_pyflakes():
392 return matchoutput("sh -c \"echo 'import re' 2>&1 | pyflakes\"",
407 return matchoutput("sh -c \"echo 'import re' 2>&1 | pyflakes\"",
393 br"<stdin>:1: 're' imported but unused",
408 br"<stdin>:1: 're' imported but unused",
394 True)
409 True)
395
410
396 @check("pygments", "Pygments source highlighting library")
411 @check("pygments", "Pygments source highlighting library")
397 def has_pygments():
412 def has_pygments():
398 try:
413 try:
399 import pygments
414 import pygments
400 pygments.highlight # silence unused import warning
415 pygments.highlight # silence unused import warning
401 return True
416 return True
402 except ImportError:
417 except ImportError:
403 return False
418 return False
404
419
405 @check("outer-repo", "outer repo")
420 @check("outer-repo", "outer repo")
406 def has_outer_repo():
421 def has_outer_repo():
407 # failing for other reasons than 'no repo' imply that there is a repo
422 # failing for other reasons than 'no repo' imply that there is a repo
408 return not matchoutput('hg root 2>&1',
423 return not matchoutput('hg root 2>&1',
409 br'abort: no repository found', True)
424 br'abort: no repository found', True)
410
425
411 @check("ssl", "ssl module available")
426 @check("ssl", "ssl module available")
412 def has_ssl():
427 def has_ssl():
413 try:
428 try:
414 import ssl
429 import ssl
415 ssl.CERT_NONE
430 ssl.CERT_NONE
416 return True
431 return True
417 except ImportError:
432 except ImportError:
418 return False
433 return False
419
434
420 @check("sslcontext", "python >= 2.7.9 ssl")
435 @check("sslcontext", "python >= 2.7.9 ssl")
421 def has_sslcontext():
436 def has_sslcontext():
422 try:
437 try:
423 import ssl
438 import ssl
424 ssl.SSLContext
439 ssl.SSLContext
425 return True
440 return True
426 except (ImportError, AttributeError):
441 except (ImportError, AttributeError):
427 return False
442 return False
428
443
429 @check("defaultcacerts", "can verify SSL certs by system's CA certs store")
444 @check("defaultcacerts", "can verify SSL certs by system's CA certs store")
430 def has_defaultcacerts():
445 def has_defaultcacerts():
431 from mercurial import sslutil, ui as uimod
446 from mercurial import sslutil, ui as uimod
432 ui = uimod.ui()
447 ui = uimod.ui()
433 return sslutil._defaultcacerts(ui) or sslutil._canloaddefaultcerts
448 return sslutil._defaultcacerts(ui) or sslutil._canloaddefaultcerts
434
449
435 @check("defaultcacertsloaded", "detected presence of loaded system CA certs")
450 @check("defaultcacertsloaded", "detected presence of loaded system CA certs")
436 def has_defaultcacertsloaded():
451 def has_defaultcacertsloaded():
437 import ssl
452 import ssl
438 from mercurial import sslutil, ui as uimod
453 from mercurial import sslutil, ui as uimod
439
454
440 if not has_defaultcacerts():
455 if not has_defaultcacerts():
441 return False
456 return False
442 if not has_sslcontext():
457 if not has_sslcontext():
443 return False
458 return False
444
459
445 ui = uimod.ui()
460 ui = uimod.ui()
446 cafile = sslutil._defaultcacerts(ui)
461 cafile = sslutil._defaultcacerts(ui)
447 ctx = ssl.create_default_context()
462 ctx = ssl.create_default_context()
448 if cafile:
463 if cafile:
449 ctx.load_verify_locations(cafile=cafile)
464 ctx.load_verify_locations(cafile=cafile)
450 else:
465 else:
451 ctx.load_default_certs()
466 ctx.load_default_certs()
452
467
453 return len(ctx.get_ca_certs()) > 0
468 return len(ctx.get_ca_certs()) > 0
454
469
455 @check("tls1.2", "TLS 1.2 protocol support")
470 @check("tls1.2", "TLS 1.2 protocol support")
456 def has_tls1_2():
471 def has_tls1_2():
457 from mercurial import sslutil
472 from mercurial import sslutil
458 return 'tls1.2' in sslutil.supportedprotocols
473 return 'tls1.2' in sslutil.supportedprotocols
459
474
460 @check("windows", "Windows")
475 @check("windows", "Windows")
461 def has_windows():
476 def has_windows():
462 return os.name == 'nt'
477 return os.name == 'nt'
463
478
464 @check("system-sh", "system() uses sh")
479 @check("system-sh", "system() uses sh")
465 def has_system_sh():
480 def has_system_sh():
466 return os.name != 'nt'
481 return os.name != 'nt'
467
482
468 @check("serve", "platform and python can manage 'hg serve -d'")
483 @check("serve", "platform and python can manage 'hg serve -d'")
469 def has_serve():
484 def has_serve():
470 return os.name != 'nt' # gross approximation
485 return os.name != 'nt' # gross approximation
471
486
472 @check("test-repo", "running tests from repository")
487 @check("test-repo", "running tests from repository")
473 def has_test_repo():
488 def has_test_repo():
474 t = os.environ["TESTDIR"]
489 t = os.environ["TESTDIR"]
475 return os.path.isdir(os.path.join(t, "..", ".hg"))
490 return os.path.isdir(os.path.join(t, "..", ".hg"))
476
491
477 @check("tic", "terminfo compiler and curses module")
492 @check("tic", "terminfo compiler and curses module")
478 def has_tic():
493 def has_tic():
479 try:
494 try:
480 import curses
495 import curses
481 curses.COLOR_BLUE
496 curses.COLOR_BLUE
482 return matchoutput('test -x "`which tic`"', br'')
497 return matchoutput('test -x "`which tic`"', br'')
483 except ImportError:
498 except ImportError:
484 return False
499 return False
485
500
486 @check("msys", "Windows with MSYS")
501 @check("msys", "Windows with MSYS")
487 def has_msys():
502 def has_msys():
488 return os.getenv('MSYSTEM')
503 return os.getenv('MSYSTEM')
489
504
490 @check("aix", "AIX")
505 @check("aix", "AIX")
491 def has_aix():
506 def has_aix():
492 return sys.platform.startswith("aix")
507 return sys.platform.startswith("aix")
493
508
494 @check("osx", "OS X")
509 @check("osx", "OS X")
495 def has_osx():
510 def has_osx():
496 return sys.platform == 'darwin'
511 return sys.platform == 'darwin'
497
512
498 @check("osxpackaging", "OS X packaging tools")
513 @check("osxpackaging", "OS X packaging tools")
499 def has_osxpackaging():
514 def has_osxpackaging():
500 try:
515 try:
501 return (matchoutput('pkgbuild', br'Usage: pkgbuild ', ignorestatus=1)
516 return (matchoutput('pkgbuild', br'Usage: pkgbuild ', ignorestatus=1)
502 and matchoutput(
517 and matchoutput(
503 'productbuild', br'Usage: productbuild ',
518 'productbuild', br'Usage: productbuild ',
504 ignorestatus=1)
519 ignorestatus=1)
505 and matchoutput('lsbom', br'Usage: lsbom', ignorestatus=1)
520 and matchoutput('lsbom', br'Usage: lsbom', ignorestatus=1)
506 and matchoutput(
521 and matchoutput(
507 'xar --help', br'Usage: xar', ignorestatus=1))
522 'xar --help', br'Usage: xar', ignorestatus=1))
508 except ImportError:
523 except ImportError:
509 return False
524 return False
510
525
511 @check("docker", "docker support")
526 @check("docker", "docker support")
512 def has_docker():
527 def has_docker():
513 pat = br'A self-sufficient runtime for'
528 pat = br'A self-sufficient runtime for'
514 if matchoutput('docker --help', pat):
529 if matchoutput('docker --help', pat):
515 if 'linux' not in sys.platform:
530 if 'linux' not in sys.platform:
516 # TODO: in theory we should be able to test docker-based
531 # TODO: in theory we should be able to test docker-based
517 # package creation on non-linux using boot2docker, but in
532 # package creation on non-linux using boot2docker, but in
518 # practice that requires extra coordination to make sure
533 # practice that requires extra coordination to make sure
519 # $TESTTEMP is going to be visible at the same path to the
534 # $TESTTEMP is going to be visible at the same path to the
520 # boot2docker VM. If we figure out how to verify that, we
535 # boot2docker VM. If we figure out how to verify that, we
521 # can use the following instead of just saying False:
536 # can use the following instead of just saying False:
522 # return 'DOCKER_HOST' in os.environ
537 # return 'DOCKER_HOST' in os.environ
523 return False
538 return False
524
539
525 return True
540 return True
526 return False
541 return False
527
542
528 @check("debhelper", "debian packaging tools")
543 @check("debhelper", "debian packaging tools")
529 def has_debhelper():
544 def has_debhelper():
530 dpkg = matchoutput('dpkg --version',
545 dpkg = matchoutput('dpkg --version',
531 br"Debian `dpkg' package management program")
546 br"Debian `dpkg' package management program")
532 dh = matchoutput('dh --help',
547 dh = matchoutput('dh --help',
533 br'dh is a part of debhelper.', ignorestatus=True)
548 br'dh is a part of debhelper.', ignorestatus=True)
534 dh_py2 = matchoutput('dh_python2 --help',
549 dh_py2 = matchoutput('dh_python2 --help',
535 br'other supported Python versions')
550 br'other supported Python versions')
536 return dpkg and dh and dh_py2
551 return dpkg and dh and dh_py2
537
552
538 @check("demandimport", "demandimport enabled")
553 @check("demandimport", "demandimport enabled")
539 def has_demandimport():
554 def has_demandimport():
540 return os.environ.get('HGDEMANDIMPORT') != 'disable'
555 return os.environ.get('HGDEMANDIMPORT') != 'disable'
541
556
542 @check("absimport", "absolute_import in __future__")
557 @check("absimport", "absolute_import in __future__")
543 def has_absimport():
558 def has_absimport():
544 import __future__
559 import __future__
545 from mercurial import util
560 from mercurial import util
546 return util.safehasattr(__future__, "absolute_import")
561 return util.safehasattr(__future__, "absolute_import")
547
562
548 @check("py27+", "running with Python 2.7+")
563 @check("py27+", "running with Python 2.7+")
549 def has_python27ornewer():
564 def has_python27ornewer():
550 return sys.version_info[0:2] >= (2, 7)
565 return sys.version_info[0:2] >= (2, 7)
551
566
552 @check("py3k", "running with Python 3.x")
567 @check("py3k", "running with Python 3.x")
553 def has_py3k():
568 def has_py3k():
554 return 3 == sys.version_info[0]
569 return 3 == sys.version_info[0]
555
570
556 @check("py3exe", "a Python 3.x interpreter is available")
571 @check("py3exe", "a Python 3.x interpreter is available")
557 def has_python3exe():
572 def has_python3exe():
558 return 'PYTHON3' in os.environ
573 return 'PYTHON3' in os.environ
559
574
560 @check("py3pygments", "Pygments available on Python 3.x")
575 @check("py3pygments", "Pygments available on Python 3.x")
561 def has_py3pygments():
576 def has_py3pygments():
562 if has_py3k():
577 if has_py3k():
563 return has_pygments()
578 return has_pygments()
564 elif has_python3exe():
579 elif has_python3exe():
565 # just check exit status (ignoring output)
580 # just check exit status (ignoring output)
566 py3 = os.environ['PYTHON3']
581 py3 = os.environ['PYTHON3']
567 return matchoutput('%s -c "import pygments"' % py3, br'')
582 return matchoutput('%s -c "import pygments"' % py3, br'')
568 return False
583 return False
569
584
570 @check("pure", "running with pure Python code")
585 @check("pure", "running with pure Python code")
571 def has_pure():
586 def has_pure():
572 return any([
587 return any([
573 os.environ.get("HGMODULEPOLICY") == "py",
588 os.environ.get("HGMODULEPOLICY") == "py",
574 os.environ.get("HGTEST_RUN_TESTS_PURE") == "--pure",
589 os.environ.get("HGTEST_RUN_TESTS_PURE") == "--pure",
575 ])
590 ])
576
591
577 @check("slow", "allow slow tests")
592 @check("slow", "allow slow tests")
578 def has_slow():
593 def has_slow():
579 return os.environ.get('HGTEST_SLOW') == 'slow'
594 return os.environ.get('HGTEST_SLOW') == 'slow'
580
595
581 @check("hypothesis", "Hypothesis automated test generation")
596 @check("hypothesis", "Hypothesis automated test generation")
582 def has_hypothesis():
597 def has_hypothesis():
583 try:
598 try:
584 import hypothesis
599 import hypothesis
585 hypothesis.given
600 hypothesis.given
586 return True
601 return True
587 except ImportError:
602 except ImportError:
588 return False
603 return False
589
604
590 @check("unziplinks", "unzip(1) understands and extracts symlinks")
605 @check("unziplinks", "unzip(1) understands and extracts symlinks")
591 def unzip_understands_symlinks():
606 def unzip_understands_symlinks():
592 return matchoutput('unzip --help', br'Info-ZIP')
607 return matchoutput('unzip --help', br'Info-ZIP')
@@ -1,899 +1,906 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extensions]
2 > [extensions]
3 > rebase=
3 > rebase=
4 >
4 >
5 > [phases]
5 > [phases]
6 > publish=False
6 > publish=False
7 >
7 >
8 > [alias]
8 > [alias]
9 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
9 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
10 > EOF
10 > EOF
11
11
12
12
13 $ hg init a
13 $ hg init a
14 $ cd a
14 $ cd a
15 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
15 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
16 adding changesets
16 adding changesets
17 adding manifests
17 adding manifests
18 adding file changes
18 adding file changes
19 added 8 changesets with 7 changes to 7 files (+2 heads)
19 added 8 changesets with 7 changes to 7 files (+2 heads)
20 (run 'hg heads' to see heads, 'hg merge' to merge)
20 (run 'hg heads' to see heads, 'hg merge' to merge)
21 $ hg up tip
21 $ hg up tip
22 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
23 $ cd ..
23 $ cd ..
24
24
25
25
26 Rebasing
26 Rebasing
27 D onto H - simple rebase:
27 D onto H - simple rebase:
28 (this also tests that editor is invoked if '--edit' is specified, and that we
28 (this also tests that editor is invoked if '--edit' is specified, and that we
29 can abort or warn for colliding untracked files)
29 can abort or warn for colliding untracked files)
30
30
31 $ hg clone -q -u . a a1
31 $ hg clone -q -u . a a1
32 $ cd a1
32 $ cd a1
33
33
34 $ hg tglog
34 $ hg tglog
35 @ 7: 'H'
35 @ 7: 'H'
36 |
36 |
37 | o 6: 'G'
37 | o 6: 'G'
38 |/|
38 |/|
39 o | 5: 'F'
39 o | 5: 'F'
40 | |
40 | |
41 | o 4: 'E'
41 | o 4: 'E'
42 |/
42 |/
43 | o 3: 'D'
43 | o 3: 'D'
44 | |
44 | |
45 | o 2: 'C'
45 | o 2: 'C'
46 | |
46 | |
47 | o 1: 'B'
47 | o 1: 'B'
48 |/
48 |/
49 o 0: 'A'
49 o 0: 'A'
50
50
51
51
52 $ hg status --rev "3^1" --rev 3
52 $ hg status --rev "3^1" --rev 3
53 A D
53 A D
54 $ echo collide > D
54 $ echo collide > D
55 $ HGEDITOR=cat hg rebase -s 3 -d 7 --edit --config merge.checkunknown=warn
55 $ HGEDITOR=cat hg rebase -s 3 -d 7 --edit --config merge.checkunknown=warn
56 rebasing 3:32af7686d403 "D"
56 rebasing 3:32af7686d403 "D"
57 D: replacing untracked file
57 D: replacing untracked file
58 D
58 D
59
59
60
60
61 HG: Enter commit message. Lines beginning with 'HG:' are removed.
61 HG: Enter commit message. Lines beginning with 'HG:' are removed.
62 HG: Leave message empty to abort commit.
62 HG: Leave message empty to abort commit.
63 HG: --
63 HG: --
64 HG: user: Nicolas Dumazet <nicdumz.commits@gmail.com>
64 HG: user: Nicolas Dumazet <nicdumz.commits@gmail.com>
65 HG: branch 'default'
65 HG: branch 'default'
66 HG: added D
66 HG: added D
67 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/32af7686d403-6f7dface-backup.hg (glob)
67 saved backup bundle to $TESTTMP/a1/.hg/strip-backup/32af7686d403-6f7dface-backup.hg (glob)
68 $ cat D.orig
68 $ cat D.orig
69 collide
69 collide
70 $ rm D.orig
70 $ rm D.orig
71
71
72 $ hg tglog
72 $ hg tglog
73 o 7: 'D'
73 o 7: 'D'
74 |
74 |
75 @ 6: 'H'
75 @ 6: 'H'
76 |
76 |
77 | o 5: 'G'
77 | o 5: 'G'
78 |/|
78 |/|
79 o | 4: 'F'
79 o | 4: 'F'
80 | |
80 | |
81 | o 3: 'E'
81 | o 3: 'E'
82 |/
82 |/
83 | o 2: 'C'
83 | o 2: 'C'
84 | |
84 | |
85 | o 1: 'B'
85 | o 1: 'B'
86 |/
86 |/
87 o 0: 'A'
87 o 0: 'A'
88
88
89 $ cd ..
89 $ cd ..
90
90
91
91
92 D onto F - intermediate point:
92 D onto F - intermediate point:
93 (this also tests that editor is not invoked if '--edit' is not specified, and
93 (this also tests that editor is not invoked if '--edit' is not specified, and
94 that we can ignore for colliding untracked files)
94 that we can ignore for colliding untracked files)
95
95
96 $ hg clone -q -u . a a2
96 $ hg clone -q -u . a a2
97 $ cd a2
97 $ cd a2
98 $ echo collide > D
98 $ echo collide > D
99
99
100 $ HGEDITOR=cat hg rebase -s 3 -d 5 --config merge.checkunknown=ignore
100 $ HGEDITOR=cat hg rebase -s 3 -d 5 --config merge.checkunknown=ignore
101 rebasing 3:32af7686d403 "D"
101 rebasing 3:32af7686d403 "D"
102 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/32af7686d403-6f7dface-backup.hg (glob)
102 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/32af7686d403-6f7dface-backup.hg (glob)
103 $ cat D.orig
103 $ cat D.orig
104 collide
104 collide
105 $ rm D.orig
105 $ rm D.orig
106
106
107 $ hg tglog
107 $ hg tglog
108 o 7: 'D'
108 o 7: 'D'
109 |
109 |
110 | @ 6: 'H'
110 | @ 6: 'H'
111 |/
111 |/
112 | o 5: 'G'
112 | o 5: 'G'
113 |/|
113 |/|
114 o | 4: 'F'
114 o | 4: 'F'
115 | |
115 | |
116 | o 3: 'E'
116 | o 3: 'E'
117 |/
117 |/
118 | o 2: 'C'
118 | o 2: 'C'
119 | |
119 | |
120 | o 1: 'B'
120 | o 1: 'B'
121 |/
121 |/
122 o 0: 'A'
122 o 0: 'A'
123
123
124 $ cd ..
124 $ cd ..
125
125
126
126
127 E onto H - skip of G:
127 E onto H - skip of G:
128 (this also tests that we can overwrite untracked files and don't create backups
128 (this also tests that we can overwrite untracked files and don't create backups
129 if they have the same contents)
129 if they have the same contents)
130
130
131 $ hg clone -q -u . a a3
131 $ hg clone -q -u . a a3
132 $ cd a3
132 $ cd a3
133 $ hg cat -r 4 E | tee E
133 $ hg cat -r 4 E | tee E
134 E
134 E
135
135
136 $ hg rebase -s 4 -d 7
136 $ hg rebase -s 4 -d 7
137 rebasing 4:9520eea781bc "E"
137 rebasing 4:9520eea781bc "E"
138 rebasing 6:eea13746799a "G"
138 rebasing 6:eea13746799a "G"
139 note: rebase of 6:eea13746799a created no changes to commit
139 note: rebase of 6:eea13746799a created no changes to commit
140 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/9520eea781bc-fcd8edd4-backup.hg (glob)
140 saved backup bundle to $TESTTMP/a3/.hg/strip-backup/9520eea781bc-fcd8edd4-backup.hg (glob)
141 $ f E.orig
141 $ f E.orig
142 E.orig: file not found
142 E.orig: file not found
143
143
144 $ hg tglog
144 $ hg tglog
145 o 6: 'E'
145 o 6: 'E'
146 |
146 |
147 @ 5: 'H'
147 @ 5: 'H'
148 |
148 |
149 o 4: 'F'
149 o 4: 'F'
150 |
150 |
151 | o 3: 'D'
151 | o 3: 'D'
152 | |
152 | |
153 | o 2: 'C'
153 | o 2: 'C'
154 | |
154 | |
155 | o 1: 'B'
155 | o 1: 'B'
156 |/
156 |/
157 o 0: 'A'
157 o 0: 'A'
158
158
159 $ cd ..
159 $ cd ..
160
160
161
161
162 F onto E - rebase of a branching point (skip G):
162 F onto E - rebase of a branching point (skip G):
163
163
164 $ hg clone -q -u . a a4
164 $ hg clone -q -u . a a4
165 $ cd a4
165 $ cd a4
166
166
167 $ hg rebase -s 5 -d 4
167 $ hg rebase -s 5 -d 4
168 rebasing 5:24b6387c8c8c "F"
168 rebasing 5:24b6387c8c8c "F"
169 rebasing 6:eea13746799a "G"
169 rebasing 6:eea13746799a "G"
170 note: rebase of 6:eea13746799a created no changes to commit
170 note: rebase of 6:eea13746799a created no changes to commit
171 rebasing 7:02de42196ebe "H" (tip)
171 rebasing 7:02de42196ebe "H" (tip)
172 saved backup bundle to $TESTTMP/a4/.hg/strip-backup/24b6387c8c8c-c3fe765d-backup.hg (glob)
172 saved backup bundle to $TESTTMP/a4/.hg/strip-backup/24b6387c8c8c-c3fe765d-backup.hg (glob)
173
173
174 $ hg tglog
174 $ hg tglog
175 @ 6: 'H'
175 @ 6: 'H'
176 |
176 |
177 o 5: 'F'
177 o 5: 'F'
178 |
178 |
179 o 4: 'E'
179 o 4: 'E'
180 |
180 |
181 | o 3: 'D'
181 | o 3: 'D'
182 | |
182 | |
183 | o 2: 'C'
183 | o 2: 'C'
184 | |
184 | |
185 | o 1: 'B'
185 | o 1: 'B'
186 |/
186 |/
187 o 0: 'A'
187 o 0: 'A'
188
188
189 $ cd ..
189 $ cd ..
190
190
191
191
192 G onto H - merged revision having a parent in ancestors of target:
192 G onto H - merged revision having a parent in ancestors of target:
193
193
194 $ hg clone -q -u . a a5
194 $ hg clone -q -u . a a5
195 $ cd a5
195 $ cd a5
196
196
197 $ hg rebase -s 6 -d 7
197 $ hg rebase -s 6 -d 7
198 rebasing 6:eea13746799a "G"
198 rebasing 6:eea13746799a "G"
199 saved backup bundle to $TESTTMP/a5/.hg/strip-backup/eea13746799a-883828ed-backup.hg (glob)
199 saved backup bundle to $TESTTMP/a5/.hg/strip-backup/eea13746799a-883828ed-backup.hg (glob)
200
200
201 $ hg tglog
201 $ hg tglog
202 o 7: 'G'
202 o 7: 'G'
203 |\
203 |\
204 | @ 6: 'H'
204 | @ 6: 'H'
205 | |
205 | |
206 | o 5: 'F'
206 | o 5: 'F'
207 | |
207 | |
208 o | 4: 'E'
208 o | 4: 'E'
209 |/
209 |/
210 | o 3: 'D'
210 | o 3: 'D'
211 | |
211 | |
212 | o 2: 'C'
212 | o 2: 'C'
213 | |
213 | |
214 | o 1: 'B'
214 | o 1: 'B'
215 |/
215 |/
216 o 0: 'A'
216 o 0: 'A'
217
217
218 $ cd ..
218 $ cd ..
219
219
220
220
221 F onto B - G maintains E as parent:
221 F onto B - G maintains E as parent:
222
222
223 $ hg clone -q -u . a a6
223 $ hg clone -q -u . a a6
224 $ cd a6
224 $ cd a6
225
225
226 $ hg rebase -s 5 -d 1
226 $ hg rebase -s 5 -d 1
227 rebasing 5:24b6387c8c8c "F"
227 rebasing 5:24b6387c8c8c "F"
228 rebasing 6:eea13746799a "G"
228 rebasing 6:eea13746799a "G"
229 rebasing 7:02de42196ebe "H" (tip)
229 rebasing 7:02de42196ebe "H" (tip)
230 saved backup bundle to $TESTTMP/a6/.hg/strip-backup/24b6387c8c8c-c3fe765d-backup.hg (glob)
230 saved backup bundle to $TESTTMP/a6/.hg/strip-backup/24b6387c8c8c-c3fe765d-backup.hg (glob)
231
231
232 $ hg tglog
232 $ hg tglog
233 @ 7: 'H'
233 @ 7: 'H'
234 |
234 |
235 | o 6: 'G'
235 | o 6: 'G'
236 |/|
236 |/|
237 o | 5: 'F'
237 o | 5: 'F'
238 | |
238 | |
239 | o 4: 'E'
239 | o 4: 'E'
240 | |
240 | |
241 | | o 3: 'D'
241 | | o 3: 'D'
242 | | |
242 | | |
243 +---o 2: 'C'
243 +---o 2: 'C'
244 | |
244 | |
245 o | 1: 'B'
245 o | 1: 'B'
246 |/
246 |/
247 o 0: 'A'
247 o 0: 'A'
248
248
249 $ cd ..
249 $ cd ..
250
250
251
251
252 These will fail (using --source):
252 These will fail (using --source):
253
253
254 G onto F - rebase onto an ancestor:
254 G onto F - rebase onto an ancestor:
255
255
256 $ hg clone -q -u . a a7
256 $ hg clone -q -u . a a7
257 $ cd a7
257 $ cd a7
258
258
259 $ hg rebase -s 6 -d 5
259 $ hg rebase -s 6 -d 5
260 nothing to rebase
260 nothing to rebase
261 [1]
261 [1]
262
262
263 F onto G - rebase onto a descendant:
263 F onto G - rebase onto a descendant:
264
264
265 $ hg rebase -s 5 -d 6
265 $ hg rebase -s 5 -d 6
266 abort: source is ancestor of destination
266 abort: source is ancestor of destination
267 [255]
267 [255]
268
268
269 G onto B - merge revision with both parents not in ancestors of target:
269 G onto B - merge revision with both parents not in ancestors of target:
270
270
271 $ hg rebase -s 6 -d 1
271 $ hg rebase -s 6 -d 1
272 rebasing 6:eea13746799a "G"
272 rebasing 6:eea13746799a "G"
273 abort: cannot use revision 6 as base, result would have 3 parents
273 abort: cannot use revision 6 as base, result would have 3 parents
274 [255]
274 [255]
275
275
276
276
277 These will abort gracefully (using --base):
277 These will abort gracefully (using --base):
278
278
279 G onto G - rebase onto same changeset:
279 G onto G - rebase onto same changeset:
280
280
281 $ hg rebase -b 6 -d 6
281 $ hg rebase -b 6 -d 6
282 nothing to rebase - eea13746799a is both "base" and destination
282 nothing to rebase - eea13746799a is both "base" and destination
283 [1]
283 [1]
284
284
285 G onto F - rebase onto an ancestor:
285 G onto F - rebase onto an ancestor:
286
286
287 $ hg rebase -b 6 -d 5
287 $ hg rebase -b 6 -d 5
288 nothing to rebase
288 nothing to rebase
289 [1]
289 [1]
290
290
291 F onto G - rebase onto a descendant:
291 F onto G - rebase onto a descendant:
292
292
293 $ hg rebase -b 5 -d 6
293 $ hg rebase -b 5 -d 6
294 nothing to rebase - "base" 24b6387c8c8c is already an ancestor of destination eea13746799a
294 nothing to rebase - "base" 24b6387c8c8c is already an ancestor of destination eea13746799a
295 [1]
295 [1]
296
296
297 C onto A - rebase onto an ancestor:
297 C onto A - rebase onto an ancestor:
298
298
299 $ hg rebase -d 0 -s 2
299 $ hg rebase -d 0 -s 2
300 rebasing 2:5fddd98957c8 "C"
300 rebasing 2:5fddd98957c8 "C"
301 rebasing 3:32af7686d403 "D"
301 rebasing 3:32af7686d403 "D"
302 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/5fddd98957c8-f9244fa1-backup.hg (glob)
302 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/5fddd98957c8-f9244fa1-backup.hg (glob)
303 $ hg tglog
303 $ hg tglog
304 o 7: 'D'
304 o 7: 'D'
305 |
305 |
306 o 6: 'C'
306 o 6: 'C'
307 |
307 |
308 | @ 5: 'H'
308 | @ 5: 'H'
309 | |
309 | |
310 | | o 4: 'G'
310 | | o 4: 'G'
311 | |/|
311 | |/|
312 | o | 3: 'F'
312 | o | 3: 'F'
313 |/ /
313 |/ /
314 | o 2: 'E'
314 | o 2: 'E'
315 |/
315 |/
316 | o 1: 'B'
316 | o 1: 'B'
317 |/
317 |/
318 o 0: 'A'
318 o 0: 'A'
319
319
320
320
321 Check rebasing public changeset
321 Check rebasing public changeset
322
322
323 $ hg pull --config phases.publish=True -q -r 6 . # update phase of 6
323 $ hg pull --config phases.publish=True -q -r 6 . # update phase of 6
324 $ hg rebase -d 0 -b 6
324 $ hg rebase -d 0 -b 6
325 nothing to rebase
325 nothing to rebase
326 [1]
326 [1]
327 $ hg rebase -d 5 -b 6
327 $ hg rebase -d 5 -b 6
328 abort: can't rebase public changeset e1c4361dd923
328 abort: can't rebase public changeset e1c4361dd923
329 (see 'hg help phases' for details)
329 (see 'hg help phases' for details)
330 [255]
330 [255]
331
331
332 $ hg rebase -d 5 -b 6 --keep
332 $ hg rebase -d 5 -b 6 --keep
333 rebasing 6:e1c4361dd923 "C"
333 rebasing 6:e1c4361dd923 "C"
334 rebasing 7:c9659aac0000 "D" (tip)
334 rebasing 7:c9659aac0000 "D" (tip)
335
335
336 Check rebasing mutable changeset
336 Check rebasing mutable changeset
337 Source phase greater or equal to destination phase: new changeset get the phase of source:
337 Source phase greater or equal to destination phase: new changeset get the phase of source:
338 $ hg id -n
338 $ hg id -n
339 5
339 5
340 $ hg rebase -s9 -d0
340 $ hg rebase -s9 -d0
341 rebasing 9:2b23e52411f4 "D" (tip)
341 rebasing 9:2b23e52411f4 "D" (tip)
342 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2b23e52411f4-f942decf-backup.hg (glob)
342 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2b23e52411f4-f942decf-backup.hg (glob)
343 $ hg id -n # check we updated back to parent
343 $ hg id -n # check we updated back to parent
344 5
344 5
345 $ hg log --template "{phase}\n" -r 9
345 $ hg log --template "{phase}\n" -r 9
346 draft
346 draft
347 $ hg rebase -s9 -d1
347 $ hg rebase -s9 -d1
348 rebasing 9:2cb10d0cfc6c "D" (tip)
348 rebasing 9:2cb10d0cfc6c "D" (tip)
349 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2cb10d0cfc6c-ddb0f256-backup.hg (glob)
349 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2cb10d0cfc6c-ddb0f256-backup.hg (glob)
350 $ hg log --template "{phase}\n" -r 9
350 $ hg log --template "{phase}\n" -r 9
351 draft
351 draft
352 $ hg phase --force --secret 9
352 $ hg phase --force --secret 9
353 $ hg rebase -s9 -d0
353 $ hg rebase -s9 -d0
354 rebasing 9:c5b12b67163a "D" (tip)
354 rebasing 9:c5b12b67163a "D" (tip)
355 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/c5b12b67163a-4e372053-backup.hg (glob)
355 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/c5b12b67163a-4e372053-backup.hg (glob)
356 $ hg log --template "{phase}\n" -r 9
356 $ hg log --template "{phase}\n" -r 9
357 secret
357 secret
358 $ hg rebase -s9 -d1
358 $ hg rebase -s9 -d1
359 rebasing 9:2a0524f868ac "D" (tip)
359 rebasing 9:2a0524f868ac "D" (tip)
360 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2a0524f868ac-cefd8574-backup.hg (glob)
360 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/2a0524f868ac-cefd8574-backup.hg (glob)
361 $ hg log --template "{phase}\n" -r 9
361 $ hg log --template "{phase}\n" -r 9
362 secret
362 secret
363 Source phase lower than destination phase: new changeset get the phase of destination:
363 Source phase lower than destination phase: new changeset get the phase of destination:
364 $ hg rebase -s8 -d9
364 $ hg rebase -s8 -d9
365 rebasing 8:6d4f22462821 "C"
365 rebasing 8:6d4f22462821 "C"
366 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/6d4f22462821-3441f70b-backup.hg (glob)
366 saved backup bundle to $TESTTMP/a7/.hg/strip-backup/6d4f22462821-3441f70b-backup.hg (glob)
367 $ hg log --template "{phase}\n" -r 'rev(9)'
367 $ hg log --template "{phase}\n" -r 'rev(9)'
368 secret
368 secret
369
369
370 $ cd ..
370 $ cd ..
371
371
372 Test for revset
372 Test for revset
373
373
374 We need a bit different graph
374 We need a bit different graph
375 All destination are B
375 All destination are B
376
376
377 $ hg init ah
377 $ hg init ah
378 $ cd ah
378 $ cd ah
379 $ hg unbundle "$TESTDIR/bundles/rebase-revset.hg"
379 $ hg unbundle "$TESTDIR/bundles/rebase-revset.hg"
380 adding changesets
380 adding changesets
381 adding manifests
381 adding manifests
382 adding file changes
382 adding file changes
383 added 9 changesets with 9 changes to 9 files (+2 heads)
383 added 9 changesets with 9 changes to 9 files (+2 heads)
384 (run 'hg heads' to see heads, 'hg merge' to merge)
384 (run 'hg heads' to see heads, 'hg merge' to merge)
385 $ hg tglog
385 $ hg tglog
386 o 8: 'I'
386 o 8: 'I'
387 |
387 |
388 o 7: 'H'
388 o 7: 'H'
389 |
389 |
390 o 6: 'G'
390 o 6: 'G'
391 |
391 |
392 | o 5: 'F'
392 | o 5: 'F'
393 | |
393 | |
394 | o 4: 'E'
394 | o 4: 'E'
395 |/
395 |/
396 o 3: 'D'
396 o 3: 'D'
397 |
397 |
398 o 2: 'C'
398 o 2: 'C'
399 |
399 |
400 | o 1: 'B'
400 | o 1: 'B'
401 |/
401 |/
402 o 0: 'A'
402 o 0: 'A'
403
403
404 $ cd ..
404 $ cd ..
405
405
406
406
407 Simple case with keep:
407 Simple case with keep:
408
408
409 Source on have two descendant heads but ask for one
409 Source on have two descendant heads but ask for one
410
410
411 $ hg clone -q -u . ah ah1
411 $ hg clone -q -u . ah ah1
412 $ cd ah1
412 $ cd ah1
413 $ hg rebase -r '2::8' -d 1
413 $ hg rebase -r '2::8' -d 1
414 abort: can't remove original changesets with unrebased descendants
414 abort: can't remove original changesets with unrebased descendants
415 (use --keep to keep original changesets)
415 (use --keep to keep original changesets)
416 [255]
416 [255]
417 $ hg rebase -r '2::8' -d 1 -k
417 $ hg rebase -r '2::8' -d 1 -k
418 rebasing 2:c9e50f6cdc55 "C"
418 rebasing 2:c9e50f6cdc55 "C"
419 rebasing 3:ffd453c31098 "D"
419 rebasing 3:ffd453c31098 "D"
420 rebasing 6:3d8a618087a7 "G"
420 rebasing 6:3d8a618087a7 "G"
421 rebasing 7:72434a4e60b0 "H"
421 rebasing 7:72434a4e60b0 "H"
422 rebasing 8:479ddb54a924 "I" (tip)
422 rebasing 8:479ddb54a924 "I" (tip)
423 $ hg tglog
423 $ hg tglog
424 o 13: 'I'
424 o 13: 'I'
425 |
425 |
426 o 12: 'H'
426 o 12: 'H'
427 |
427 |
428 o 11: 'G'
428 o 11: 'G'
429 |
429 |
430 o 10: 'D'
430 o 10: 'D'
431 |
431 |
432 o 9: 'C'
432 o 9: 'C'
433 |
433 |
434 | o 8: 'I'
434 | o 8: 'I'
435 | |
435 | |
436 | o 7: 'H'
436 | o 7: 'H'
437 | |
437 | |
438 | o 6: 'G'
438 | o 6: 'G'
439 | |
439 | |
440 | | o 5: 'F'
440 | | o 5: 'F'
441 | | |
441 | | |
442 | | o 4: 'E'
442 | | o 4: 'E'
443 | |/
443 | |/
444 | o 3: 'D'
444 | o 3: 'D'
445 | |
445 | |
446 | o 2: 'C'
446 | o 2: 'C'
447 | |
447 | |
448 o | 1: 'B'
448 o | 1: 'B'
449 |/
449 |/
450 o 0: 'A'
450 o 0: 'A'
451
451
452
452
453 $ cd ..
453 $ cd ..
454
454
455 Base on have one descendant heads we ask for but common ancestor have two
455 Base on have one descendant heads we ask for but common ancestor have two
456
456
457 $ hg clone -q -u . ah ah2
457 $ hg clone -q -u . ah ah2
458 $ cd ah2
458 $ cd ah2
459 $ hg rebase -r '3::8' -d 1
459 $ hg rebase -r '3::8' -d 1
460 abort: can't remove original changesets with unrebased descendants
460 abort: can't remove original changesets with unrebased descendants
461 (use --keep to keep original changesets)
461 (use --keep to keep original changesets)
462 [255]
462 [255]
463 $ hg rebase -r '3::8' -d 1 --keep
463 $ hg rebase -r '3::8' -d 1 --keep
464 rebasing 3:ffd453c31098 "D"
464 rebasing 3:ffd453c31098 "D"
465 rebasing 6:3d8a618087a7 "G"
465 rebasing 6:3d8a618087a7 "G"
466 rebasing 7:72434a4e60b0 "H"
466 rebasing 7:72434a4e60b0 "H"
467 rebasing 8:479ddb54a924 "I" (tip)
467 rebasing 8:479ddb54a924 "I" (tip)
468 $ hg tglog
468 $ hg tglog
469 o 12: 'I'
469 o 12: 'I'
470 |
470 |
471 o 11: 'H'
471 o 11: 'H'
472 |
472 |
473 o 10: 'G'
473 o 10: 'G'
474 |
474 |
475 o 9: 'D'
475 o 9: 'D'
476 |
476 |
477 | o 8: 'I'
477 | o 8: 'I'
478 | |
478 | |
479 | o 7: 'H'
479 | o 7: 'H'
480 | |
480 | |
481 | o 6: 'G'
481 | o 6: 'G'
482 | |
482 | |
483 | | o 5: 'F'
483 | | o 5: 'F'
484 | | |
484 | | |
485 | | o 4: 'E'
485 | | o 4: 'E'
486 | |/
486 | |/
487 | o 3: 'D'
487 | o 3: 'D'
488 | |
488 | |
489 | o 2: 'C'
489 | o 2: 'C'
490 | |
490 | |
491 o | 1: 'B'
491 o | 1: 'B'
492 |/
492 |/
493 o 0: 'A'
493 o 0: 'A'
494
494
495
495
496 $ cd ..
496 $ cd ..
497
497
498 rebase subset
498 rebase subset
499
499
500 $ hg clone -q -u . ah ah3
500 $ hg clone -q -u . ah ah3
501 $ cd ah3
501 $ cd ah3
502 $ hg rebase -r '3::7' -d 1
502 $ hg rebase -r '3::7' -d 1
503 abort: can't remove original changesets with unrebased descendants
503 abort: can't remove original changesets with unrebased descendants
504 (use --keep to keep original changesets)
504 (use --keep to keep original changesets)
505 [255]
505 [255]
506 $ hg rebase -r '3::7' -d 1 --keep
506 $ hg rebase -r '3::7' -d 1 --keep
507 rebasing 3:ffd453c31098 "D"
507 rebasing 3:ffd453c31098 "D"
508 rebasing 6:3d8a618087a7 "G"
508 rebasing 6:3d8a618087a7 "G"
509 rebasing 7:72434a4e60b0 "H"
509 rebasing 7:72434a4e60b0 "H"
510 $ hg tglog
510 $ hg tglog
511 o 11: 'H'
511 o 11: 'H'
512 |
512 |
513 o 10: 'G'
513 o 10: 'G'
514 |
514 |
515 o 9: 'D'
515 o 9: 'D'
516 |
516 |
517 | o 8: 'I'
517 | o 8: 'I'
518 | |
518 | |
519 | o 7: 'H'
519 | o 7: 'H'
520 | |
520 | |
521 | o 6: 'G'
521 | o 6: 'G'
522 | |
522 | |
523 | | o 5: 'F'
523 | | o 5: 'F'
524 | | |
524 | | |
525 | | o 4: 'E'
525 | | o 4: 'E'
526 | |/
526 | |/
527 | o 3: 'D'
527 | o 3: 'D'
528 | |
528 | |
529 | o 2: 'C'
529 | o 2: 'C'
530 | |
530 | |
531 o | 1: 'B'
531 o | 1: 'B'
532 |/
532 |/
533 o 0: 'A'
533 o 0: 'A'
534
534
535
535
536 $ cd ..
536 $ cd ..
537
537
538 rebase subset with multiple head
538 rebase subset with multiple head
539
539
540 $ hg clone -q -u . ah ah4
540 $ hg clone -q -u . ah ah4
541 $ cd ah4
541 $ cd ah4
542 $ hg rebase -r '3::(7+5)' -d 1
542 $ hg rebase -r '3::(7+5)' -d 1
543 abort: can't remove original changesets with unrebased descendants
543 abort: can't remove original changesets with unrebased descendants
544 (use --keep to keep original changesets)
544 (use --keep to keep original changesets)
545 [255]
545 [255]
546 $ hg rebase -r '3::(7+5)' -d 1 --keep
546 $ hg rebase -r '3::(7+5)' -d 1 --keep
547 rebasing 3:ffd453c31098 "D"
547 rebasing 3:ffd453c31098 "D"
548 rebasing 4:c01897464e7f "E"
548 rebasing 4:c01897464e7f "E"
549 rebasing 5:41bfcc75ed73 "F"
549 rebasing 5:41bfcc75ed73 "F"
550 rebasing 6:3d8a618087a7 "G"
550 rebasing 6:3d8a618087a7 "G"
551 rebasing 7:72434a4e60b0 "H"
551 rebasing 7:72434a4e60b0 "H"
552 $ hg tglog
552 $ hg tglog
553 o 13: 'H'
553 o 13: 'H'
554 |
554 |
555 o 12: 'G'
555 o 12: 'G'
556 |
556 |
557 | o 11: 'F'
557 | o 11: 'F'
558 | |
558 | |
559 | o 10: 'E'
559 | o 10: 'E'
560 |/
560 |/
561 o 9: 'D'
561 o 9: 'D'
562 |
562 |
563 | o 8: 'I'
563 | o 8: 'I'
564 | |
564 | |
565 | o 7: 'H'
565 | o 7: 'H'
566 | |
566 | |
567 | o 6: 'G'
567 | o 6: 'G'
568 | |
568 | |
569 | | o 5: 'F'
569 | | o 5: 'F'
570 | | |
570 | | |
571 | | o 4: 'E'
571 | | o 4: 'E'
572 | |/
572 | |/
573 | o 3: 'D'
573 | o 3: 'D'
574 | |
574 | |
575 | o 2: 'C'
575 | o 2: 'C'
576 | |
576 | |
577 o | 1: 'B'
577 o | 1: 'B'
578 |/
578 |/
579 o 0: 'A'
579 o 0: 'A'
580
580
581
581
582 $ cd ..
582 $ cd ..
583
583
584 More advanced tests
584 More advanced tests
585
585
586 rebase on ancestor with revset
586 rebase on ancestor with revset
587
587
588 $ hg clone -q -u . ah ah5
588 $ hg clone -q -u . ah ah5
589 $ cd ah5
589 $ cd ah5
590 $ hg rebase -r '6::' -d 2
590 $ hg rebase -r '6::' -d 2
591 rebasing 6:3d8a618087a7 "G"
591 rebasing 6:3d8a618087a7 "G"
592 rebasing 7:72434a4e60b0 "H"
592 rebasing 7:72434a4e60b0 "H"
593 rebasing 8:479ddb54a924 "I" (tip)
593 rebasing 8:479ddb54a924 "I" (tip)
594 saved backup bundle to $TESTTMP/ah5/.hg/strip-backup/3d8a618087a7-b4f73f31-backup.hg (glob)
594 saved backup bundle to $TESTTMP/ah5/.hg/strip-backup/3d8a618087a7-b4f73f31-backup.hg (glob)
595 $ hg tglog
595 $ hg tglog
596 o 8: 'I'
596 o 8: 'I'
597 |
597 |
598 o 7: 'H'
598 o 7: 'H'
599 |
599 |
600 o 6: 'G'
600 o 6: 'G'
601 |
601 |
602 | o 5: 'F'
602 | o 5: 'F'
603 | |
603 | |
604 | o 4: 'E'
604 | o 4: 'E'
605 | |
605 | |
606 | o 3: 'D'
606 | o 3: 'D'
607 |/
607 |/
608 o 2: 'C'
608 o 2: 'C'
609 |
609 |
610 | o 1: 'B'
610 | o 1: 'B'
611 |/
611 |/
612 o 0: 'A'
612 o 0: 'A'
613
613
614 $ cd ..
614 $ cd ..
615
615
616
616
617 rebase with multiple root.
617 rebase with multiple root.
618 We rebase E and G on B
618 We rebase E and G on B
619 We would expect heads are I, F if it was supported
619 We would expect heads are I, F if it was supported
620
620
621 $ hg clone -q -u . ah ah6
621 $ hg clone -q -u . ah ah6
622 $ cd ah6
622 $ cd ah6
623 $ hg rebase -r '(4+6)::' -d 1
623 $ hg rebase -r '(4+6)::' -d 1
624 rebasing 4:c01897464e7f "E"
624 rebasing 4:c01897464e7f "E"
625 rebasing 5:41bfcc75ed73 "F"
625 rebasing 5:41bfcc75ed73 "F"
626 rebasing 6:3d8a618087a7 "G"
626 rebasing 6:3d8a618087a7 "G"
627 rebasing 7:72434a4e60b0 "H"
627 rebasing 7:72434a4e60b0 "H"
628 rebasing 8:479ddb54a924 "I" (tip)
628 rebasing 8:479ddb54a924 "I" (tip)
629 saved backup bundle to $TESTTMP/ah6/.hg/strip-backup/3d8a618087a7-aae93a24-backup.hg (glob)
629 saved backup bundle to $TESTTMP/ah6/.hg/strip-backup/3d8a618087a7-aae93a24-backup.hg (glob)
630 $ hg tglog
630 $ hg tglog
631 o 8: 'I'
631 o 8: 'I'
632 |
632 |
633 o 7: 'H'
633 o 7: 'H'
634 |
634 |
635 o 6: 'G'
635 o 6: 'G'
636 |
636 |
637 | o 5: 'F'
637 | o 5: 'F'
638 | |
638 | |
639 | o 4: 'E'
639 | o 4: 'E'
640 |/
640 |/
641 | o 3: 'D'
641 | o 3: 'D'
642 | |
642 | |
643 | o 2: 'C'
643 | o 2: 'C'
644 | |
644 | |
645 o | 1: 'B'
645 o | 1: 'B'
646 |/
646 |/
647 o 0: 'A'
647 o 0: 'A'
648
648
649 $ cd ..
649 $ cd ..
650
650
651 More complex rebase with multiple roots
651 More complex rebase with multiple roots
652 each root have a different common ancestor with the destination and this is a detach
652 each root have a different common ancestor with the destination and this is a detach
653
653
654 (setup)
654 (setup)
655
655
656 $ hg clone -q -u . a a8
656 $ hg clone -q -u . a a8
657 $ cd a8
657 $ cd a8
658 $ echo I > I
658 $ echo I > I
659 $ hg add I
659 $ hg add I
660 $ hg commit -m I
660 $ hg commit -m I
661 $ hg up 4
661 $ hg up 4
662 1 files updated, 0 files merged, 3 files removed, 0 files unresolved
662 1 files updated, 0 files merged, 3 files removed, 0 files unresolved
663 $ echo I > J
663 $ echo I > J
664 $ hg add J
664 $ hg add J
665 $ hg commit -m J
665 $ hg commit -m J
666 created new head
666 created new head
667 $ echo I > K
667 $ echo I > K
668 $ hg add K
668 $ hg add K
669 $ hg commit -m K
669 $ hg commit -m K
670 $ hg tglog
670 $ hg tglog
671 @ 10: 'K'
671 @ 10: 'K'
672 |
672 |
673 o 9: 'J'
673 o 9: 'J'
674 |
674 |
675 | o 8: 'I'
675 | o 8: 'I'
676 | |
676 | |
677 | o 7: 'H'
677 | o 7: 'H'
678 | |
678 | |
679 +---o 6: 'G'
679 +---o 6: 'G'
680 | |/
680 | |/
681 | o 5: 'F'
681 | o 5: 'F'
682 | |
682 | |
683 o | 4: 'E'
683 o | 4: 'E'
684 |/
684 |/
685 | o 3: 'D'
685 | o 3: 'D'
686 | |
686 | |
687 | o 2: 'C'
687 | o 2: 'C'
688 | |
688 | |
689 | o 1: 'B'
689 | o 1: 'B'
690 |/
690 |/
691 o 0: 'A'
691 o 0: 'A'
692
692
693 (actual test)
693 (actual test)
694
694
695 $ hg rebase --dest 'desc(G)' --rev 'desc(K) + desc(I)'
695 $ hg rebase --dest 'desc(G)' --rev 'desc(K) + desc(I)'
696 rebasing 8:e7ec4e813ba6 "I"
696 rebasing 8:e7ec4e813ba6 "I"
697 rebasing 10:23a4ace37988 "K" (tip)
697 rebasing 10:23a4ace37988 "K" (tip)
698 saved backup bundle to $TESTTMP/a8/.hg/strip-backup/23a4ace37988-b06984b3-backup.hg (glob)
698 saved backup bundle to $TESTTMP/a8/.hg/strip-backup/23a4ace37988-b06984b3-backup.hg (glob)
699 $ hg log --rev 'children(desc(G))'
699 $ hg log --rev 'children(desc(G))'
700 changeset: 9:adb617877056
700 changeset: 9:adb617877056
701 parent: 6:eea13746799a
701 parent: 6:eea13746799a
702 user: test
702 user: test
703 date: Thu Jan 01 00:00:00 1970 +0000
703 date: Thu Jan 01 00:00:00 1970 +0000
704 summary: I
704 summary: I
705
705
706 changeset: 10:882431a34a0e
706 changeset: 10:882431a34a0e
707 tag: tip
707 tag: tip
708 parent: 6:eea13746799a
708 parent: 6:eea13746799a
709 user: test
709 user: test
710 date: Thu Jan 01 00:00:00 1970 +0000
710 date: Thu Jan 01 00:00:00 1970 +0000
711 summary: K
711 summary: K
712
712
713 $ hg tglog
713 $ hg tglog
714 @ 10: 'K'
714 @ 10: 'K'
715 |
715 |
716 | o 9: 'I'
716 | o 9: 'I'
717 |/
717 |/
718 | o 8: 'J'
718 | o 8: 'J'
719 | |
719 | |
720 | | o 7: 'H'
720 | | o 7: 'H'
721 | | |
721 | | |
722 o---+ 6: 'G'
722 o---+ 6: 'G'
723 |/ /
723 |/ /
724 | o 5: 'F'
724 | o 5: 'F'
725 | |
725 | |
726 o | 4: 'E'
726 o | 4: 'E'
727 |/
727 |/
728 | o 3: 'D'
728 | o 3: 'D'
729 | |
729 | |
730 | o 2: 'C'
730 | o 2: 'C'
731 | |
731 | |
732 | o 1: 'B'
732 | o 1: 'B'
733 |/
733 |/
734 o 0: 'A'
734 o 0: 'A'
735
735
736
736
737 Test that rebase is not confused by $CWD disappearing during rebase (issue4121)
737 Test that rebase is not confused by $CWD disappearing during rebase (issue4121)
738
738
739 $ cd ..
739 $ cd ..
740 $ hg init cwd-vanish
740 $ hg init cwd-vanish
741 $ cd cwd-vanish
741 $ cd cwd-vanish
742 $ touch initial-file
742 $ touch initial-file
743 $ hg add initial-file
743 $ hg add initial-file
744 $ hg commit -m 'initial commit'
744 $ hg commit -m 'initial commit'
745 $ touch dest-file
745 $ touch dest-file
746 $ hg add dest-file
746 $ hg add dest-file
747 $ hg commit -m 'dest commit'
747 $ hg commit -m 'dest commit'
748 $ hg up 0
748 $ hg up 0
749 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
749 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
750 $ touch other-file
750 $ touch other-file
751 $ hg add other-file
751 $ hg add other-file
752 $ hg commit -m 'first source commit'
752 $ hg commit -m 'first source commit'
753 created new head
753 created new head
754 $ mkdir subdir
754 $ mkdir subdir
755 $ cd subdir
755 $ cd subdir
756 $ touch subfile
756 $ touch subfile
757 $ hg add subfile
757 $ hg add subfile
758 $ hg commit -m 'second source with subdir'
758 $ hg commit -m 'second source with subdir'
759 #if rmcwd
759 $ hg rebase -b . -d 1 --traceback
760 $ hg rebase -b . -d 1 --traceback
760 rebasing 2:779a07b1b7a0 "first source commit"
761 rebasing 2:779a07b1b7a0 "first source commit"
761 current directory was removed
762 current directory was removed
762 (consider changing to repo root: $TESTTMP/cwd-vanish)
763 (consider changing to repo root: $TESTTMP/cwd-vanish)
763 rebasing 3:a7d6f3a00bf3 "second source with subdir" (tip)
764 rebasing 3:a7d6f3a00bf3 "second source with subdir" (tip)
764 saved backup bundle to $TESTTMP/cwd-vanish/.hg/strip-backup/779a07b1b7a0-853e0073-backup.hg (glob)
765 saved backup bundle to $TESTTMP/cwd-vanish/.hg/strip-backup/779a07b1b7a0-853e0073-backup.hg (glob)
766 #else
767 $ hg rebase -b . -d 1 --traceback
768 rebasing 2:779a07b1b7a0 "first source commit"
769 rebasing 3:a7d6f3a00bf3 "second source with subdir" (tip)
770 saved backup bundle to $TESTTMP/cwd-vanish/.hg/strip-backup/779a07b1b7a0-853e0073-backup.hg (glob)
771 #endif
765
772
766 Test that rebase is done in topo order (issue5370)
773 Test that rebase is done in topo order (issue5370)
767
774
768 $ cd ..
775 $ cd ..
769 $ hg init order
776 $ hg init order
770 $ cd order
777 $ cd order
771 $ touch a && hg add a && hg ci -m A
778 $ touch a && hg add a && hg ci -m A
772 $ touch b && hg add b && hg ci -m B
779 $ touch b && hg add b && hg ci -m B
773 $ touch c && hg add c && hg ci -m C
780 $ touch c && hg add c && hg ci -m C
774 $ hg up 1
781 $ hg up 1
775 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
782 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
776 $ touch d && hg add d && hg ci -m D
783 $ touch d && hg add d && hg ci -m D
777 created new head
784 created new head
778 $ hg up 2
785 $ hg up 2
779 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
786 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
780 $ touch e && hg add e && hg ci -m E
787 $ touch e && hg add e && hg ci -m E
781 $ hg up 3
788 $ hg up 3
782 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
789 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
783 $ touch f && hg add f && hg ci -m F
790 $ touch f && hg add f && hg ci -m F
784 $ hg up 0
791 $ hg up 0
785 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
792 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
786 $ touch g && hg add g && hg ci -m G
793 $ touch g && hg add g && hg ci -m G
787 created new head
794 created new head
788
795
789 $ hg tglog
796 $ hg tglog
790 @ 6: 'G'
797 @ 6: 'G'
791 |
798 |
792 | o 5: 'F'
799 | o 5: 'F'
793 | |
800 | |
794 | | o 4: 'E'
801 | | o 4: 'E'
795 | | |
802 | | |
796 | o | 3: 'D'
803 | o | 3: 'D'
797 | | |
804 | | |
798 | | o 2: 'C'
805 | | o 2: 'C'
799 | |/
806 | |/
800 | o 1: 'B'
807 | o 1: 'B'
801 |/
808 |/
802 o 0: 'A'
809 o 0: 'A'
803
810
804
811
805 $ hg rebase -s 1 -d 6
812 $ hg rebase -s 1 -d 6
806 rebasing 1:76035bbd54bd "B"
813 rebasing 1:76035bbd54bd "B"
807 rebasing 2:d84f5cfaaf14 "C"
814 rebasing 2:d84f5cfaaf14 "C"
808 rebasing 4:82ae8dc7a9b7 "E"
815 rebasing 4:82ae8dc7a9b7 "E"
809 rebasing 3:ab709c9f7171 "D"
816 rebasing 3:ab709c9f7171 "D"
810 rebasing 5:412b391de760 "F"
817 rebasing 5:412b391de760 "F"
811 saved backup bundle to $TESTTMP/cwd-vanish/order/.hg/strip-backup/76035bbd54bd-e341bc99-backup.hg (glob)
818 saved backup bundle to $TESTTMP/cwd-vanish/order/.hg/strip-backup/76035bbd54bd-e341bc99-backup.hg (glob)
812
819
813 $ hg tglog
820 $ hg tglog
814 o 6: 'F'
821 o 6: 'F'
815 |
822 |
816 o 5: 'D'
823 o 5: 'D'
817 |
824 |
818 | o 4: 'E'
825 | o 4: 'E'
819 | |
826 | |
820 | o 3: 'C'
827 | o 3: 'C'
821 |/
828 |/
822 o 2: 'B'
829 o 2: 'B'
823 |
830 |
824 @ 1: 'G'
831 @ 1: 'G'
825 |
832 |
826 o 0: 'A'
833 o 0: 'A'
827
834
828
835
829 Test experimental revset
836 Test experimental revset
830 ========================
837 ========================
831
838
832 $ cd ..
839 $ cd ..
833
840
834 Make the repo a bit more interresting
841 Make the repo a bit more interresting
835
842
836 $ hg up 1
843 $ hg up 1
837 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
844 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
838 $ echo aaa > aaa
845 $ echo aaa > aaa
839 $ hg add aaa
846 $ hg add aaa
840 $ hg commit -m aaa
847 $ hg commit -m aaa
841 created new head
848 created new head
842 $ hg log -G
849 $ hg log -G
843 @ changeset: 4:5f7bc9025ed2
850 @ changeset: 4:5f7bc9025ed2
844 | tag: tip
851 | tag: tip
845 | parent: 1:58d79cc1cf43
852 | parent: 1:58d79cc1cf43
846 | user: test
853 | user: test
847 | date: Thu Jan 01 00:00:00 1970 +0000
854 | date: Thu Jan 01 00:00:00 1970 +0000
848 | summary: aaa
855 | summary: aaa
849 |
856 |
850 | o changeset: 3:1910d5ff34ea
857 | o changeset: 3:1910d5ff34ea
851 | | user: test
858 | | user: test
852 | | date: Thu Jan 01 00:00:00 1970 +0000
859 | | date: Thu Jan 01 00:00:00 1970 +0000
853 | | summary: second source with subdir
860 | | summary: second source with subdir
854 | |
861 | |
855 | o changeset: 2:82901330b6ef
862 | o changeset: 2:82901330b6ef
856 |/ user: test
863 |/ user: test
857 | date: Thu Jan 01 00:00:00 1970 +0000
864 | date: Thu Jan 01 00:00:00 1970 +0000
858 | summary: first source commit
865 | summary: first source commit
859 |
866 |
860 o changeset: 1:58d79cc1cf43
867 o changeset: 1:58d79cc1cf43
861 | user: test
868 | user: test
862 | date: Thu Jan 01 00:00:00 1970 +0000
869 | date: Thu Jan 01 00:00:00 1970 +0000
863 | summary: dest commit
870 | summary: dest commit
864 |
871 |
865 o changeset: 0:e94b687f7da3
872 o changeset: 0:e94b687f7da3
866 user: test
873 user: test
867 date: Thu Jan 01 00:00:00 1970 +0000
874 date: Thu Jan 01 00:00:00 1970 +0000
868 summary: initial commit
875 summary: initial commit
869
876
870
877
871 Testing from lower head
878 Testing from lower head
872
879
873 $ hg up 3
880 $ hg up 3
874 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
881 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
875 $ hg log -r '_destrebase()'
882 $ hg log -r '_destrebase()'
876 changeset: 4:5f7bc9025ed2
883 changeset: 4:5f7bc9025ed2
877 tag: tip
884 tag: tip
878 parent: 1:58d79cc1cf43
885 parent: 1:58d79cc1cf43
879 user: test
886 user: test
880 date: Thu Jan 01 00:00:00 1970 +0000
887 date: Thu Jan 01 00:00:00 1970 +0000
881 summary: aaa
888 summary: aaa
882
889
883
890
884 Testing from upper head
891 Testing from upper head
885
892
886 $ hg log -r '_destrebase(4)'
893 $ hg log -r '_destrebase(4)'
887 changeset: 3:1910d5ff34ea
894 changeset: 3:1910d5ff34ea
888 user: test
895 user: test
889 date: Thu Jan 01 00:00:00 1970 +0000
896 date: Thu Jan 01 00:00:00 1970 +0000
890 summary: second source with subdir
897 summary: second source with subdir
891
898
892 $ hg up 4
899 $ hg up 4
893 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
900 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
894 $ hg log -r '_destrebase()'
901 $ hg log -r '_destrebase()'
895 changeset: 3:1910d5ff34ea
902 changeset: 3:1910d5ff34ea
896 user: test
903 user: test
897 date: Thu Jan 01 00:00:00 1970 +0000
904 date: Thu Jan 01 00:00:00 1970 +0000
898 summary: second source with subdir
905 summary: second source with subdir
899
906
@@ -1,86 +1,90 b''
1 Test update logic when there are renames or weird same-name cases between dirs
1 Test update logic when there are renames or weird same-name cases between dirs
2 and files
2 and files
3
3
4 Update with local changes across a file rename
4 Update with local changes across a file rename
5
5
6 $ hg init r1 && cd r1
6 $ hg init r1 && cd r1
7
7
8 $ echo a > a
8 $ echo a > a
9 $ hg add a
9 $ hg add a
10 $ hg ci -m a
10 $ hg ci -m a
11
11
12 $ hg mv a b
12 $ hg mv a b
13 $ hg ci -m rename
13 $ hg ci -m rename
14
14
15 $ echo b > b
15 $ echo b > b
16 $ hg ci -m change
16 $ hg ci -m change
17
17
18 $ hg up -q 0
18 $ hg up -q 0
19
19
20 $ echo c > a
20 $ echo c > a
21
21
22 $ hg up
22 $ hg up
23 merging a and b to b
23 merging a and b to b
24 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
24 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
25 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
25 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
26 use 'hg resolve' to retry unresolved file merges
26 use 'hg resolve' to retry unresolved file merges
27 [1]
27 [1]
28
28
29 Test update when local untracked directory exists with the same name as a
29 Test update when local untracked directory exists with the same name as a
30 tracked file in a commit we are updating to
30 tracked file in a commit we are updating to
31 $ hg init r2 && cd r2
31 $ hg init r2 && cd r2
32 $ echo root > root && hg ci -Am root # rev 0
32 $ echo root > root && hg ci -Am root # rev 0
33 adding root
33 adding root
34 $ echo text > name && hg ci -Am "name is a file" # rev 1
34 $ echo text > name && hg ci -Am "name is a file" # rev 1
35 adding name
35 adding name
36 $ hg up 0
36 $ hg up 0
37 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
37 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
38 $ mkdir name
38 $ mkdir name
39 $ hg up 1
39 $ hg up 1
40 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
40 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
41
41
42 Test update when local untracked directory exists with some files in it and has
42 Test update when local untracked directory exists with some files in it and has
43 the same name a tracked file in a commit we are updating to. In future this
43 the same name a tracked file in a commit we are updating to. In future this
44 should be updated to give an friendlier error message, but now we should just
44 should be updated to give an friendlier error message, but now we should just
45 make sure that this does not erase untracked data
45 make sure that this does not erase untracked data
46 $ hg up 0
46 $ hg up 0
47 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
47 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
48 $ mkdir name
48 $ mkdir name
49 $ echo text > name/file
49 $ echo text > name/file
50 $ hg st
50 $ hg st
51 ? name/file
51 ? name/file
52 $ hg up 1
52 $ hg up 1
53 abort: *: '$TESTTMP/r1/r2/name' (glob)
53 abort: *: '$TESTTMP/r1/r2/name' (glob)
54 [255]
54 [255]
55 $ cd ..
55 $ cd ..
56
56
57 #if symlink
57 #if symlink
58
58
59 Test update when two commits have symlinks that point to different folders
59 Test update when two commits have symlinks that point to different folders
60 $ hg init r3 && cd r3
60 $ hg init r3 && cd r3
61 $ echo root > root && hg ci -Am root
61 $ echo root > root && hg ci -Am root
62 adding root
62 adding root
63 $ mkdir folder1 && mkdir folder2
63 $ mkdir folder1 && mkdir folder2
64 $ ln -s folder1 folder
64 $ ln -s folder1 folder
65 $ hg ci -Am "symlink to folder1"
65 $ hg ci -Am "symlink to folder1"
66 adding folder
66 adding folder
67 $ rm folder
67 $ rm folder
68 $ ln -s folder2 folder
68 $ ln -s folder2 folder
69 $ hg ci -Am "symlink to folder2"
69 $ hg ci -Am "symlink to folder2"
70 $ hg up 1
70 $ hg up 1
71 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
71 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
72 $ cd ..
72 $ cd ..
73
73
74 #endif
74 #endif
75
75
76 #if rmcwd
77
76 Test that warning is printed if cwd is deleted during update
78 Test that warning is printed if cwd is deleted during update
77 $ hg init r4 && cd r4
79 $ hg init r4 && cd r4
78 $ mkdir dir
80 $ mkdir dir
79 $ cd dir
81 $ cd dir
80 $ echo a > a
82 $ echo a > a
81 $ echo b > b
83 $ echo b > b
82 $ hg add a b
84 $ hg add a b
83 $ hg ci -m "file and dir"
85 $ hg ci -m "file and dir"
84 $ hg up -q null
86 $ hg up -q null
85 current directory was removed
87 current directory was removed
86 (consider changing to repo root: $TESTTMP/r1/r4)
88 (consider changing to repo root: $TESTTMP/r1/r4)
89
90 #endif
General Comments 0
You need to be logged in to leave comments. Login now