##// END OF EJS Templates
util: implement a deterministic __repr__ on sortdict...
Gregory Szorc -
r29592:37cccad5 default
parent child Browse files
Show More
@@ -1,2859 +1,2863 b''
1 # util.py - Mercurial utility functions and platform specific implementations
1 # util.py - Mercurial utility functions and platform specific implementations
2 #
2 #
3 # Copyright 2005 K. Thananchayan <thananck@yahoo.com>
3 # Copyright 2005 K. Thananchayan <thananck@yahoo.com>
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
6 #
6 #
7 # This software may be used and distributed according to the terms of the
7 # This software may be used and distributed according to the terms of the
8 # GNU General Public License version 2 or any later version.
8 # GNU General Public License version 2 or any later version.
9
9
10 """Mercurial utility functions and platform specific implementations.
10 """Mercurial utility functions and platform specific implementations.
11
11
12 This contains helper routines that are independent of the SCM core and
12 This contains helper routines that are independent of the SCM core and
13 hide platform-specific details from the core.
13 hide platform-specific details from the core.
14 """
14 """
15
15
16 from __future__ import absolute_import
16 from __future__ import absolute_import
17
17
18 import bz2
18 import bz2
19 import calendar
19 import calendar
20 import collections
20 import collections
21 import datetime
21 import datetime
22 import errno
22 import errno
23 import gc
23 import gc
24 import hashlib
24 import hashlib
25 import imp
25 import imp
26 import os
26 import os
27 import re as remod
27 import re as remod
28 import shutil
28 import shutil
29 import signal
29 import signal
30 import socket
30 import socket
31 import subprocess
31 import subprocess
32 import sys
32 import sys
33 import tempfile
33 import tempfile
34 import textwrap
34 import textwrap
35 import time
35 import time
36 import traceback
36 import traceback
37 import zlib
37 import zlib
38
38
39 from . import (
39 from . import (
40 encoding,
40 encoding,
41 error,
41 error,
42 i18n,
42 i18n,
43 osutil,
43 osutil,
44 parsers,
44 parsers,
45 pycompat,
45 pycompat,
46 )
46 )
47
47
48 for attr in (
48 for attr in (
49 'empty',
49 'empty',
50 'httplib',
50 'httplib',
51 'httpserver',
51 'httpserver',
52 'pickle',
52 'pickle',
53 'queue',
53 'queue',
54 'urlerr',
54 'urlerr',
55 'urlparse',
55 'urlparse',
56 # we do import urlreq, but we do it outside the loop
56 # we do import urlreq, but we do it outside the loop
57 #'urlreq',
57 #'urlreq',
58 'stringio',
58 'stringio',
59 'socketserver',
59 'socketserver',
60 'xmlrpclib',
60 'xmlrpclib',
61 ):
61 ):
62 globals()[attr] = getattr(pycompat, attr)
62 globals()[attr] = getattr(pycompat, attr)
63
63
64 # This line is to make pyflakes happy:
64 # This line is to make pyflakes happy:
65 urlreq = pycompat.urlreq
65 urlreq = pycompat.urlreq
66
66
67 if os.name == 'nt':
67 if os.name == 'nt':
68 from . import windows as platform
68 from . import windows as platform
69 else:
69 else:
70 from . import posix as platform
70 from . import posix as platform
71
71
72 _ = i18n._
72 _ = i18n._
73
73
74 bindunixsocket = platform.bindunixsocket
74 bindunixsocket = platform.bindunixsocket
75 cachestat = platform.cachestat
75 cachestat = platform.cachestat
76 checkexec = platform.checkexec
76 checkexec = platform.checkexec
77 checklink = platform.checklink
77 checklink = platform.checklink
78 copymode = platform.copymode
78 copymode = platform.copymode
79 executablepath = platform.executablepath
79 executablepath = platform.executablepath
80 expandglobs = platform.expandglobs
80 expandglobs = platform.expandglobs
81 explainexit = platform.explainexit
81 explainexit = platform.explainexit
82 findexe = platform.findexe
82 findexe = platform.findexe
83 gethgcmd = platform.gethgcmd
83 gethgcmd = platform.gethgcmd
84 getuser = platform.getuser
84 getuser = platform.getuser
85 getpid = os.getpid
85 getpid = os.getpid
86 groupmembers = platform.groupmembers
86 groupmembers = platform.groupmembers
87 groupname = platform.groupname
87 groupname = platform.groupname
88 hidewindow = platform.hidewindow
88 hidewindow = platform.hidewindow
89 isexec = platform.isexec
89 isexec = platform.isexec
90 isowner = platform.isowner
90 isowner = platform.isowner
91 localpath = platform.localpath
91 localpath = platform.localpath
92 lookupreg = platform.lookupreg
92 lookupreg = platform.lookupreg
93 makedir = platform.makedir
93 makedir = platform.makedir
94 nlinks = platform.nlinks
94 nlinks = platform.nlinks
95 normpath = platform.normpath
95 normpath = platform.normpath
96 normcase = platform.normcase
96 normcase = platform.normcase
97 normcasespec = platform.normcasespec
97 normcasespec = platform.normcasespec
98 normcasefallback = platform.normcasefallback
98 normcasefallback = platform.normcasefallback
99 openhardlinks = platform.openhardlinks
99 openhardlinks = platform.openhardlinks
100 oslink = platform.oslink
100 oslink = platform.oslink
101 parsepatchoutput = platform.parsepatchoutput
101 parsepatchoutput = platform.parsepatchoutput
102 pconvert = platform.pconvert
102 pconvert = platform.pconvert
103 poll = platform.poll
103 poll = platform.poll
104 popen = platform.popen
104 popen = platform.popen
105 posixfile = platform.posixfile
105 posixfile = platform.posixfile
106 quotecommand = platform.quotecommand
106 quotecommand = platform.quotecommand
107 readpipe = platform.readpipe
107 readpipe = platform.readpipe
108 rename = platform.rename
108 rename = platform.rename
109 removedirs = platform.removedirs
109 removedirs = platform.removedirs
110 samedevice = platform.samedevice
110 samedevice = platform.samedevice
111 samefile = platform.samefile
111 samefile = platform.samefile
112 samestat = platform.samestat
112 samestat = platform.samestat
113 setbinary = platform.setbinary
113 setbinary = platform.setbinary
114 setflags = platform.setflags
114 setflags = platform.setflags
115 setsignalhandler = platform.setsignalhandler
115 setsignalhandler = platform.setsignalhandler
116 shellquote = platform.shellquote
116 shellquote = platform.shellquote
117 spawndetached = platform.spawndetached
117 spawndetached = platform.spawndetached
118 split = platform.split
118 split = platform.split
119 sshargs = platform.sshargs
119 sshargs = platform.sshargs
120 statfiles = getattr(osutil, 'statfiles', platform.statfiles)
120 statfiles = getattr(osutil, 'statfiles', platform.statfiles)
121 statisexec = platform.statisexec
121 statisexec = platform.statisexec
122 statislink = platform.statislink
122 statislink = platform.statislink
123 termwidth = platform.termwidth
123 termwidth = platform.termwidth
124 testpid = platform.testpid
124 testpid = platform.testpid
125 umask = platform.umask
125 umask = platform.umask
126 unlink = platform.unlink
126 unlink = platform.unlink
127 unlinkpath = platform.unlinkpath
127 unlinkpath = platform.unlinkpath
128 username = platform.username
128 username = platform.username
129
129
130 # Python compatibility
130 # Python compatibility
131
131
132 _notset = object()
132 _notset = object()
133
133
134 # disable Python's problematic floating point timestamps (issue4836)
134 # disable Python's problematic floating point timestamps (issue4836)
135 # (Python hypocritically says you shouldn't change this behavior in
135 # (Python hypocritically says you shouldn't change this behavior in
136 # libraries, and sure enough Mercurial is not a library.)
136 # libraries, and sure enough Mercurial is not a library.)
137 os.stat_float_times(False)
137 os.stat_float_times(False)
138
138
139 def safehasattr(thing, attr):
139 def safehasattr(thing, attr):
140 return getattr(thing, attr, _notset) is not _notset
140 return getattr(thing, attr, _notset) is not _notset
141
141
142 DIGESTS = {
142 DIGESTS = {
143 'md5': hashlib.md5,
143 'md5': hashlib.md5,
144 'sha1': hashlib.sha1,
144 'sha1': hashlib.sha1,
145 'sha512': hashlib.sha512,
145 'sha512': hashlib.sha512,
146 }
146 }
147 # List of digest types from strongest to weakest
147 # List of digest types from strongest to weakest
148 DIGESTS_BY_STRENGTH = ['sha512', 'sha1', 'md5']
148 DIGESTS_BY_STRENGTH = ['sha512', 'sha1', 'md5']
149
149
150 for k in DIGESTS_BY_STRENGTH:
150 for k in DIGESTS_BY_STRENGTH:
151 assert k in DIGESTS
151 assert k in DIGESTS
152
152
153 class digester(object):
153 class digester(object):
154 """helper to compute digests.
154 """helper to compute digests.
155
155
156 This helper can be used to compute one or more digests given their name.
156 This helper can be used to compute one or more digests given their name.
157
157
158 >>> d = digester(['md5', 'sha1'])
158 >>> d = digester(['md5', 'sha1'])
159 >>> d.update('foo')
159 >>> d.update('foo')
160 >>> [k for k in sorted(d)]
160 >>> [k for k in sorted(d)]
161 ['md5', 'sha1']
161 ['md5', 'sha1']
162 >>> d['md5']
162 >>> d['md5']
163 'acbd18db4cc2f85cedef654fccc4a4d8'
163 'acbd18db4cc2f85cedef654fccc4a4d8'
164 >>> d['sha1']
164 >>> d['sha1']
165 '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
165 '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
166 >>> digester.preferred(['md5', 'sha1'])
166 >>> digester.preferred(['md5', 'sha1'])
167 'sha1'
167 'sha1'
168 """
168 """
169
169
170 def __init__(self, digests, s=''):
170 def __init__(self, digests, s=''):
171 self._hashes = {}
171 self._hashes = {}
172 for k in digests:
172 for k in digests:
173 if k not in DIGESTS:
173 if k not in DIGESTS:
174 raise Abort(_('unknown digest type: %s') % k)
174 raise Abort(_('unknown digest type: %s') % k)
175 self._hashes[k] = DIGESTS[k]()
175 self._hashes[k] = DIGESTS[k]()
176 if s:
176 if s:
177 self.update(s)
177 self.update(s)
178
178
179 def update(self, data):
179 def update(self, data):
180 for h in self._hashes.values():
180 for h in self._hashes.values():
181 h.update(data)
181 h.update(data)
182
182
183 def __getitem__(self, key):
183 def __getitem__(self, key):
184 if key not in DIGESTS:
184 if key not in DIGESTS:
185 raise Abort(_('unknown digest type: %s') % k)
185 raise Abort(_('unknown digest type: %s') % k)
186 return self._hashes[key].hexdigest()
186 return self._hashes[key].hexdigest()
187
187
188 def __iter__(self):
188 def __iter__(self):
189 return iter(self._hashes)
189 return iter(self._hashes)
190
190
191 @staticmethod
191 @staticmethod
192 def preferred(supported):
192 def preferred(supported):
193 """returns the strongest digest type in both supported and DIGESTS."""
193 """returns the strongest digest type in both supported and DIGESTS."""
194
194
195 for k in DIGESTS_BY_STRENGTH:
195 for k in DIGESTS_BY_STRENGTH:
196 if k in supported:
196 if k in supported:
197 return k
197 return k
198 return None
198 return None
199
199
200 class digestchecker(object):
200 class digestchecker(object):
201 """file handle wrapper that additionally checks content against a given
201 """file handle wrapper that additionally checks content against a given
202 size and digests.
202 size and digests.
203
203
204 d = digestchecker(fh, size, {'md5': '...'})
204 d = digestchecker(fh, size, {'md5': '...'})
205
205
206 When multiple digests are given, all of them are validated.
206 When multiple digests are given, all of them are validated.
207 """
207 """
208
208
209 def __init__(self, fh, size, digests):
209 def __init__(self, fh, size, digests):
210 self._fh = fh
210 self._fh = fh
211 self._size = size
211 self._size = size
212 self._got = 0
212 self._got = 0
213 self._digests = dict(digests)
213 self._digests = dict(digests)
214 self._digester = digester(self._digests.keys())
214 self._digester = digester(self._digests.keys())
215
215
216 def read(self, length=-1):
216 def read(self, length=-1):
217 content = self._fh.read(length)
217 content = self._fh.read(length)
218 self._digester.update(content)
218 self._digester.update(content)
219 self._got += len(content)
219 self._got += len(content)
220 return content
220 return content
221
221
222 def validate(self):
222 def validate(self):
223 if self._size != self._got:
223 if self._size != self._got:
224 raise Abort(_('size mismatch: expected %d, got %d') %
224 raise Abort(_('size mismatch: expected %d, got %d') %
225 (self._size, self._got))
225 (self._size, self._got))
226 for k, v in self._digests.items():
226 for k, v in self._digests.items():
227 if v != self._digester[k]:
227 if v != self._digester[k]:
228 # i18n: first parameter is a digest name
228 # i18n: first parameter is a digest name
229 raise Abort(_('%s mismatch: expected %s, got %s') %
229 raise Abort(_('%s mismatch: expected %s, got %s') %
230 (k, v, self._digester[k]))
230 (k, v, self._digester[k]))
231
231
232 try:
232 try:
233 buffer = buffer
233 buffer = buffer
234 except NameError:
234 except NameError:
235 if sys.version_info[0] < 3:
235 if sys.version_info[0] < 3:
236 def buffer(sliceable, offset=0):
236 def buffer(sliceable, offset=0):
237 return sliceable[offset:]
237 return sliceable[offset:]
238 else:
238 else:
239 def buffer(sliceable, offset=0):
239 def buffer(sliceable, offset=0):
240 return memoryview(sliceable)[offset:]
240 return memoryview(sliceable)[offset:]
241
241
242 closefds = os.name == 'posix'
242 closefds = os.name == 'posix'
243
243
244 _chunksize = 4096
244 _chunksize = 4096
245
245
246 class bufferedinputpipe(object):
246 class bufferedinputpipe(object):
247 """a manually buffered input pipe
247 """a manually buffered input pipe
248
248
249 Python will not let us use buffered IO and lazy reading with 'polling' at
249 Python will not let us use buffered IO and lazy reading with 'polling' at
250 the same time. We cannot probe the buffer state and select will not detect
250 the same time. We cannot probe the buffer state and select will not detect
251 that data are ready to read if they are already buffered.
251 that data are ready to read if they are already buffered.
252
252
253 This class let us work around that by implementing its own buffering
253 This class let us work around that by implementing its own buffering
254 (allowing efficient readline) while offering a way to know if the buffer is
254 (allowing efficient readline) while offering a way to know if the buffer is
255 empty from the output (allowing collaboration of the buffer with polling).
255 empty from the output (allowing collaboration of the buffer with polling).
256
256
257 This class lives in the 'util' module because it makes use of the 'os'
257 This class lives in the 'util' module because it makes use of the 'os'
258 module from the python stdlib.
258 module from the python stdlib.
259 """
259 """
260
260
261 def __init__(self, input):
261 def __init__(self, input):
262 self._input = input
262 self._input = input
263 self._buffer = []
263 self._buffer = []
264 self._eof = False
264 self._eof = False
265 self._lenbuf = 0
265 self._lenbuf = 0
266
266
267 @property
267 @property
268 def hasbuffer(self):
268 def hasbuffer(self):
269 """True is any data is currently buffered
269 """True is any data is currently buffered
270
270
271 This will be used externally a pre-step for polling IO. If there is
271 This will be used externally a pre-step for polling IO. If there is
272 already data then no polling should be set in place."""
272 already data then no polling should be set in place."""
273 return bool(self._buffer)
273 return bool(self._buffer)
274
274
275 @property
275 @property
276 def closed(self):
276 def closed(self):
277 return self._input.closed
277 return self._input.closed
278
278
279 def fileno(self):
279 def fileno(self):
280 return self._input.fileno()
280 return self._input.fileno()
281
281
282 def close(self):
282 def close(self):
283 return self._input.close()
283 return self._input.close()
284
284
285 def read(self, size):
285 def read(self, size):
286 while (not self._eof) and (self._lenbuf < size):
286 while (not self._eof) and (self._lenbuf < size):
287 self._fillbuffer()
287 self._fillbuffer()
288 return self._frombuffer(size)
288 return self._frombuffer(size)
289
289
290 def readline(self, *args, **kwargs):
290 def readline(self, *args, **kwargs):
291 if 1 < len(self._buffer):
291 if 1 < len(self._buffer):
292 # this should not happen because both read and readline end with a
292 # this should not happen because both read and readline end with a
293 # _frombuffer call that collapse it.
293 # _frombuffer call that collapse it.
294 self._buffer = [''.join(self._buffer)]
294 self._buffer = [''.join(self._buffer)]
295 self._lenbuf = len(self._buffer[0])
295 self._lenbuf = len(self._buffer[0])
296 lfi = -1
296 lfi = -1
297 if self._buffer:
297 if self._buffer:
298 lfi = self._buffer[-1].find('\n')
298 lfi = self._buffer[-1].find('\n')
299 while (not self._eof) and lfi < 0:
299 while (not self._eof) and lfi < 0:
300 self._fillbuffer()
300 self._fillbuffer()
301 if self._buffer:
301 if self._buffer:
302 lfi = self._buffer[-1].find('\n')
302 lfi = self._buffer[-1].find('\n')
303 size = lfi + 1
303 size = lfi + 1
304 if lfi < 0: # end of file
304 if lfi < 0: # end of file
305 size = self._lenbuf
305 size = self._lenbuf
306 elif 1 < len(self._buffer):
306 elif 1 < len(self._buffer):
307 # we need to take previous chunks into account
307 # we need to take previous chunks into account
308 size += self._lenbuf - len(self._buffer[-1])
308 size += self._lenbuf - len(self._buffer[-1])
309 return self._frombuffer(size)
309 return self._frombuffer(size)
310
310
311 def _frombuffer(self, size):
311 def _frombuffer(self, size):
312 """return at most 'size' data from the buffer
312 """return at most 'size' data from the buffer
313
313
314 The data are removed from the buffer."""
314 The data are removed from the buffer."""
315 if size == 0 or not self._buffer:
315 if size == 0 or not self._buffer:
316 return ''
316 return ''
317 buf = self._buffer[0]
317 buf = self._buffer[0]
318 if 1 < len(self._buffer):
318 if 1 < len(self._buffer):
319 buf = ''.join(self._buffer)
319 buf = ''.join(self._buffer)
320
320
321 data = buf[:size]
321 data = buf[:size]
322 buf = buf[len(data):]
322 buf = buf[len(data):]
323 if buf:
323 if buf:
324 self._buffer = [buf]
324 self._buffer = [buf]
325 self._lenbuf = len(buf)
325 self._lenbuf = len(buf)
326 else:
326 else:
327 self._buffer = []
327 self._buffer = []
328 self._lenbuf = 0
328 self._lenbuf = 0
329 return data
329 return data
330
330
331 def _fillbuffer(self):
331 def _fillbuffer(self):
332 """read data to the buffer"""
332 """read data to the buffer"""
333 data = os.read(self._input.fileno(), _chunksize)
333 data = os.read(self._input.fileno(), _chunksize)
334 if not data:
334 if not data:
335 self._eof = True
335 self._eof = True
336 else:
336 else:
337 self._lenbuf += len(data)
337 self._lenbuf += len(data)
338 self._buffer.append(data)
338 self._buffer.append(data)
339
339
340 def popen2(cmd, env=None, newlines=False):
340 def popen2(cmd, env=None, newlines=False):
341 # Setting bufsize to -1 lets the system decide the buffer size.
341 # Setting bufsize to -1 lets the system decide the buffer size.
342 # The default for bufsize is 0, meaning unbuffered. This leads to
342 # The default for bufsize is 0, meaning unbuffered. This leads to
343 # poor performance on Mac OS X: http://bugs.python.org/issue4194
343 # poor performance on Mac OS X: http://bugs.python.org/issue4194
344 p = subprocess.Popen(cmd, shell=True, bufsize=-1,
344 p = subprocess.Popen(cmd, shell=True, bufsize=-1,
345 close_fds=closefds,
345 close_fds=closefds,
346 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
346 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
347 universal_newlines=newlines,
347 universal_newlines=newlines,
348 env=env)
348 env=env)
349 return p.stdin, p.stdout
349 return p.stdin, p.stdout
350
350
351 def popen3(cmd, env=None, newlines=False):
351 def popen3(cmd, env=None, newlines=False):
352 stdin, stdout, stderr, p = popen4(cmd, env, newlines)
352 stdin, stdout, stderr, p = popen4(cmd, env, newlines)
353 return stdin, stdout, stderr
353 return stdin, stdout, stderr
354
354
355 def popen4(cmd, env=None, newlines=False, bufsize=-1):
355 def popen4(cmd, env=None, newlines=False, bufsize=-1):
356 p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
356 p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
357 close_fds=closefds,
357 close_fds=closefds,
358 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
358 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
359 stderr=subprocess.PIPE,
359 stderr=subprocess.PIPE,
360 universal_newlines=newlines,
360 universal_newlines=newlines,
361 env=env)
361 env=env)
362 return p.stdin, p.stdout, p.stderr, p
362 return p.stdin, p.stdout, p.stderr, p
363
363
364 def version():
364 def version():
365 """Return version information if available."""
365 """Return version information if available."""
366 try:
366 try:
367 from . import __version__
367 from . import __version__
368 return __version__.version
368 return __version__.version
369 except ImportError:
369 except ImportError:
370 return 'unknown'
370 return 'unknown'
371
371
372 def versiontuple(v=None, n=4):
372 def versiontuple(v=None, n=4):
373 """Parses a Mercurial version string into an N-tuple.
373 """Parses a Mercurial version string into an N-tuple.
374
374
375 The version string to be parsed is specified with the ``v`` argument.
375 The version string to be parsed is specified with the ``v`` argument.
376 If it isn't defined, the current Mercurial version string will be parsed.
376 If it isn't defined, the current Mercurial version string will be parsed.
377
377
378 ``n`` can be 2, 3, or 4. Here is how some version strings map to
378 ``n`` can be 2, 3, or 4. Here is how some version strings map to
379 returned values:
379 returned values:
380
380
381 >>> v = '3.6.1+190-df9b73d2d444'
381 >>> v = '3.6.1+190-df9b73d2d444'
382 >>> versiontuple(v, 2)
382 >>> versiontuple(v, 2)
383 (3, 6)
383 (3, 6)
384 >>> versiontuple(v, 3)
384 >>> versiontuple(v, 3)
385 (3, 6, 1)
385 (3, 6, 1)
386 >>> versiontuple(v, 4)
386 >>> versiontuple(v, 4)
387 (3, 6, 1, '190-df9b73d2d444')
387 (3, 6, 1, '190-df9b73d2d444')
388
388
389 >>> versiontuple('3.6.1+190-df9b73d2d444+20151118')
389 >>> versiontuple('3.6.1+190-df9b73d2d444+20151118')
390 (3, 6, 1, '190-df9b73d2d444+20151118')
390 (3, 6, 1, '190-df9b73d2d444+20151118')
391
391
392 >>> v = '3.6'
392 >>> v = '3.6'
393 >>> versiontuple(v, 2)
393 >>> versiontuple(v, 2)
394 (3, 6)
394 (3, 6)
395 >>> versiontuple(v, 3)
395 >>> versiontuple(v, 3)
396 (3, 6, None)
396 (3, 6, None)
397 >>> versiontuple(v, 4)
397 >>> versiontuple(v, 4)
398 (3, 6, None, None)
398 (3, 6, None, None)
399 """
399 """
400 if not v:
400 if not v:
401 v = version()
401 v = version()
402 parts = v.split('+', 1)
402 parts = v.split('+', 1)
403 if len(parts) == 1:
403 if len(parts) == 1:
404 vparts, extra = parts[0], None
404 vparts, extra = parts[0], None
405 else:
405 else:
406 vparts, extra = parts
406 vparts, extra = parts
407
407
408 vints = []
408 vints = []
409 for i in vparts.split('.'):
409 for i in vparts.split('.'):
410 try:
410 try:
411 vints.append(int(i))
411 vints.append(int(i))
412 except ValueError:
412 except ValueError:
413 break
413 break
414 # (3, 6) -> (3, 6, None)
414 # (3, 6) -> (3, 6, None)
415 while len(vints) < 3:
415 while len(vints) < 3:
416 vints.append(None)
416 vints.append(None)
417
417
418 if n == 2:
418 if n == 2:
419 return (vints[0], vints[1])
419 return (vints[0], vints[1])
420 if n == 3:
420 if n == 3:
421 return (vints[0], vints[1], vints[2])
421 return (vints[0], vints[1], vints[2])
422 if n == 4:
422 if n == 4:
423 return (vints[0], vints[1], vints[2], extra)
423 return (vints[0], vints[1], vints[2], extra)
424
424
425 # used by parsedate
425 # used by parsedate
426 defaultdateformats = (
426 defaultdateformats = (
427 '%Y-%m-%d %H:%M:%S',
427 '%Y-%m-%d %H:%M:%S',
428 '%Y-%m-%d %I:%M:%S%p',
428 '%Y-%m-%d %I:%M:%S%p',
429 '%Y-%m-%d %H:%M',
429 '%Y-%m-%d %H:%M',
430 '%Y-%m-%d %I:%M%p',
430 '%Y-%m-%d %I:%M%p',
431 '%Y-%m-%d',
431 '%Y-%m-%d',
432 '%m-%d',
432 '%m-%d',
433 '%m/%d',
433 '%m/%d',
434 '%m/%d/%y',
434 '%m/%d/%y',
435 '%m/%d/%Y',
435 '%m/%d/%Y',
436 '%a %b %d %H:%M:%S %Y',
436 '%a %b %d %H:%M:%S %Y',
437 '%a %b %d %I:%M:%S%p %Y',
437 '%a %b %d %I:%M:%S%p %Y',
438 '%a, %d %b %Y %H:%M:%S', # GNU coreutils "/bin/date --rfc-2822"
438 '%a, %d %b %Y %H:%M:%S', # GNU coreutils "/bin/date --rfc-2822"
439 '%b %d %H:%M:%S %Y',
439 '%b %d %H:%M:%S %Y',
440 '%b %d %I:%M:%S%p %Y',
440 '%b %d %I:%M:%S%p %Y',
441 '%b %d %H:%M:%S',
441 '%b %d %H:%M:%S',
442 '%b %d %I:%M:%S%p',
442 '%b %d %I:%M:%S%p',
443 '%b %d %H:%M',
443 '%b %d %H:%M',
444 '%b %d %I:%M%p',
444 '%b %d %I:%M%p',
445 '%b %d %Y',
445 '%b %d %Y',
446 '%b %d',
446 '%b %d',
447 '%H:%M:%S',
447 '%H:%M:%S',
448 '%I:%M:%S%p',
448 '%I:%M:%S%p',
449 '%H:%M',
449 '%H:%M',
450 '%I:%M%p',
450 '%I:%M%p',
451 )
451 )
452
452
453 extendeddateformats = defaultdateformats + (
453 extendeddateformats = defaultdateformats + (
454 "%Y",
454 "%Y",
455 "%Y-%m",
455 "%Y-%m",
456 "%b",
456 "%b",
457 "%b %Y",
457 "%b %Y",
458 )
458 )
459
459
460 def cachefunc(func):
460 def cachefunc(func):
461 '''cache the result of function calls'''
461 '''cache the result of function calls'''
462 # XXX doesn't handle keywords args
462 # XXX doesn't handle keywords args
463 if func.__code__.co_argcount == 0:
463 if func.__code__.co_argcount == 0:
464 cache = []
464 cache = []
465 def f():
465 def f():
466 if len(cache) == 0:
466 if len(cache) == 0:
467 cache.append(func())
467 cache.append(func())
468 return cache[0]
468 return cache[0]
469 return f
469 return f
470 cache = {}
470 cache = {}
471 if func.__code__.co_argcount == 1:
471 if func.__code__.co_argcount == 1:
472 # we gain a small amount of time because
472 # we gain a small amount of time because
473 # we don't need to pack/unpack the list
473 # we don't need to pack/unpack the list
474 def f(arg):
474 def f(arg):
475 if arg not in cache:
475 if arg not in cache:
476 cache[arg] = func(arg)
476 cache[arg] = func(arg)
477 return cache[arg]
477 return cache[arg]
478 else:
478 else:
479 def f(*args):
479 def f(*args):
480 if args not in cache:
480 if args not in cache:
481 cache[args] = func(*args)
481 cache[args] = func(*args)
482 return cache[args]
482 return cache[args]
483
483
484 return f
484 return f
485
485
486 class sortdict(dict):
486 class sortdict(dict):
487 '''a simple sorted dictionary'''
487 '''a simple sorted dictionary'''
488 def __init__(self, data=None):
488 def __init__(self, data=None):
489 self._list = []
489 self._list = []
490 if data:
490 if data:
491 self.update(data)
491 self.update(data)
492 def copy(self):
492 def copy(self):
493 return sortdict(self)
493 return sortdict(self)
494 def __setitem__(self, key, val):
494 def __setitem__(self, key, val):
495 if key in self:
495 if key in self:
496 self._list.remove(key)
496 self._list.remove(key)
497 self._list.append(key)
497 self._list.append(key)
498 dict.__setitem__(self, key, val)
498 dict.__setitem__(self, key, val)
499 def __iter__(self):
499 def __iter__(self):
500 return self._list.__iter__()
500 return self._list.__iter__()
501 def update(self, src):
501 def update(self, src):
502 if isinstance(src, dict):
502 if isinstance(src, dict):
503 src = src.iteritems()
503 src = src.iteritems()
504 for k, v in src:
504 for k, v in src:
505 self[k] = v
505 self[k] = v
506 def clear(self):
506 def clear(self):
507 dict.clear(self)
507 dict.clear(self)
508 self._list = []
508 self._list = []
509 def items(self):
509 def items(self):
510 return [(k, self[k]) for k in self._list]
510 return [(k, self[k]) for k in self._list]
511 def __delitem__(self, key):
511 def __delitem__(self, key):
512 dict.__delitem__(self, key)
512 dict.__delitem__(self, key)
513 self._list.remove(key)
513 self._list.remove(key)
514 def pop(self, key, *args, **kwargs):
514 def pop(self, key, *args, **kwargs):
515 dict.pop(self, key, *args, **kwargs)
515 dict.pop(self, key, *args, **kwargs)
516 try:
516 try:
517 self._list.remove(key)
517 self._list.remove(key)
518 except ValueError:
518 except ValueError:
519 pass
519 pass
520 def keys(self):
520 def keys(self):
521 return self._list
521 return self._list
522 def iterkeys(self):
522 def iterkeys(self):
523 return self._list.__iter__()
523 return self._list.__iter__()
524 def iteritems(self):
524 def iteritems(self):
525 for k in self._list:
525 for k in self._list:
526 yield k, self[k]
526 yield k, self[k]
527 def insert(self, index, key, val):
527 def insert(self, index, key, val):
528 self._list.insert(index, key)
528 self._list.insert(index, key)
529 dict.__setitem__(self, key, val)
529 dict.__setitem__(self, key, val)
530 def __repr__(self):
531 if not self:
532 return '%s()' % self.__class__.__name__
533 return '%s(%r)' % (self.__class__.__name__, self.items())
530
534
531 class _lrucachenode(object):
535 class _lrucachenode(object):
532 """A node in a doubly linked list.
536 """A node in a doubly linked list.
533
537
534 Holds a reference to nodes on either side as well as a key-value
538 Holds a reference to nodes on either side as well as a key-value
535 pair for the dictionary entry.
539 pair for the dictionary entry.
536 """
540 """
537 __slots__ = ('next', 'prev', 'key', 'value')
541 __slots__ = ('next', 'prev', 'key', 'value')
538
542
539 def __init__(self):
543 def __init__(self):
540 self.next = None
544 self.next = None
541 self.prev = None
545 self.prev = None
542
546
543 self.key = _notset
547 self.key = _notset
544 self.value = None
548 self.value = None
545
549
546 def markempty(self):
550 def markempty(self):
547 """Mark the node as emptied."""
551 """Mark the node as emptied."""
548 self.key = _notset
552 self.key = _notset
549
553
550 class lrucachedict(object):
554 class lrucachedict(object):
551 """Dict that caches most recent accesses and sets.
555 """Dict that caches most recent accesses and sets.
552
556
553 The dict consists of an actual backing dict - indexed by original
557 The dict consists of an actual backing dict - indexed by original
554 key - and a doubly linked circular list defining the order of entries in
558 key - and a doubly linked circular list defining the order of entries in
555 the cache.
559 the cache.
556
560
557 The head node is the newest entry in the cache. If the cache is full,
561 The head node is the newest entry in the cache. If the cache is full,
558 we recycle head.prev and make it the new head. Cache accesses result in
562 we recycle head.prev and make it the new head. Cache accesses result in
559 the node being moved to before the existing head and being marked as the
563 the node being moved to before the existing head and being marked as the
560 new head node.
564 new head node.
561 """
565 """
562 def __init__(self, max):
566 def __init__(self, max):
563 self._cache = {}
567 self._cache = {}
564
568
565 self._head = head = _lrucachenode()
569 self._head = head = _lrucachenode()
566 head.prev = head
570 head.prev = head
567 head.next = head
571 head.next = head
568 self._size = 1
572 self._size = 1
569 self._capacity = max
573 self._capacity = max
570
574
571 def __len__(self):
575 def __len__(self):
572 return len(self._cache)
576 return len(self._cache)
573
577
574 def __contains__(self, k):
578 def __contains__(self, k):
575 return k in self._cache
579 return k in self._cache
576
580
577 def __iter__(self):
581 def __iter__(self):
578 # We don't have to iterate in cache order, but why not.
582 # We don't have to iterate in cache order, but why not.
579 n = self._head
583 n = self._head
580 for i in range(len(self._cache)):
584 for i in range(len(self._cache)):
581 yield n.key
585 yield n.key
582 n = n.next
586 n = n.next
583
587
584 def __getitem__(self, k):
588 def __getitem__(self, k):
585 node = self._cache[k]
589 node = self._cache[k]
586 self._movetohead(node)
590 self._movetohead(node)
587 return node.value
591 return node.value
588
592
589 def __setitem__(self, k, v):
593 def __setitem__(self, k, v):
590 node = self._cache.get(k)
594 node = self._cache.get(k)
591 # Replace existing value and mark as newest.
595 # Replace existing value and mark as newest.
592 if node is not None:
596 if node is not None:
593 node.value = v
597 node.value = v
594 self._movetohead(node)
598 self._movetohead(node)
595 return
599 return
596
600
597 if self._size < self._capacity:
601 if self._size < self._capacity:
598 node = self._addcapacity()
602 node = self._addcapacity()
599 else:
603 else:
600 # Grab the last/oldest item.
604 # Grab the last/oldest item.
601 node = self._head.prev
605 node = self._head.prev
602
606
603 # At capacity. Kill the old entry.
607 # At capacity. Kill the old entry.
604 if node.key is not _notset:
608 if node.key is not _notset:
605 del self._cache[node.key]
609 del self._cache[node.key]
606
610
607 node.key = k
611 node.key = k
608 node.value = v
612 node.value = v
609 self._cache[k] = node
613 self._cache[k] = node
610 # And mark it as newest entry. No need to adjust order since it
614 # And mark it as newest entry. No need to adjust order since it
611 # is already self._head.prev.
615 # is already self._head.prev.
612 self._head = node
616 self._head = node
613
617
614 def __delitem__(self, k):
618 def __delitem__(self, k):
615 node = self._cache.pop(k)
619 node = self._cache.pop(k)
616 node.markempty()
620 node.markempty()
617
621
618 # Temporarily mark as newest item before re-adjusting head to make
622 # Temporarily mark as newest item before re-adjusting head to make
619 # this node the oldest item.
623 # this node the oldest item.
620 self._movetohead(node)
624 self._movetohead(node)
621 self._head = node.next
625 self._head = node.next
622
626
623 # Additional dict methods.
627 # Additional dict methods.
624
628
625 def get(self, k, default=None):
629 def get(self, k, default=None):
626 try:
630 try:
627 return self._cache[k]
631 return self._cache[k]
628 except KeyError:
632 except KeyError:
629 return default
633 return default
630
634
631 def clear(self):
635 def clear(self):
632 n = self._head
636 n = self._head
633 while n.key is not _notset:
637 while n.key is not _notset:
634 n.markempty()
638 n.markempty()
635 n = n.next
639 n = n.next
636
640
637 self._cache.clear()
641 self._cache.clear()
638
642
639 def copy(self):
643 def copy(self):
640 result = lrucachedict(self._capacity)
644 result = lrucachedict(self._capacity)
641 n = self._head.prev
645 n = self._head.prev
642 # Iterate in oldest-to-newest order, so the copy has the right ordering
646 # Iterate in oldest-to-newest order, so the copy has the right ordering
643 for i in range(len(self._cache)):
647 for i in range(len(self._cache)):
644 result[n.key] = n.value
648 result[n.key] = n.value
645 n = n.prev
649 n = n.prev
646 return result
650 return result
647
651
648 def _movetohead(self, node):
652 def _movetohead(self, node):
649 """Mark a node as the newest, making it the new head.
653 """Mark a node as the newest, making it the new head.
650
654
651 When a node is accessed, it becomes the freshest entry in the LRU
655 When a node is accessed, it becomes the freshest entry in the LRU
652 list, which is denoted by self._head.
656 list, which is denoted by self._head.
653
657
654 Visually, let's make ``N`` the new head node (* denotes head):
658 Visually, let's make ``N`` the new head node (* denotes head):
655
659
656 previous/oldest <-> head <-> next/next newest
660 previous/oldest <-> head <-> next/next newest
657
661
658 ----<->--- A* ---<->-----
662 ----<->--- A* ---<->-----
659 | |
663 | |
660 E <-> D <-> N <-> C <-> B
664 E <-> D <-> N <-> C <-> B
661
665
662 To:
666 To:
663
667
664 ----<->--- N* ---<->-----
668 ----<->--- N* ---<->-----
665 | |
669 | |
666 E <-> D <-> C <-> B <-> A
670 E <-> D <-> C <-> B <-> A
667
671
668 This requires the following moves:
672 This requires the following moves:
669
673
670 C.next = D (node.prev.next = node.next)
674 C.next = D (node.prev.next = node.next)
671 D.prev = C (node.next.prev = node.prev)
675 D.prev = C (node.next.prev = node.prev)
672 E.next = N (head.prev.next = node)
676 E.next = N (head.prev.next = node)
673 N.prev = E (node.prev = head.prev)
677 N.prev = E (node.prev = head.prev)
674 N.next = A (node.next = head)
678 N.next = A (node.next = head)
675 A.prev = N (head.prev = node)
679 A.prev = N (head.prev = node)
676 """
680 """
677 head = self._head
681 head = self._head
678 # C.next = D
682 # C.next = D
679 node.prev.next = node.next
683 node.prev.next = node.next
680 # D.prev = C
684 # D.prev = C
681 node.next.prev = node.prev
685 node.next.prev = node.prev
682 # N.prev = E
686 # N.prev = E
683 node.prev = head.prev
687 node.prev = head.prev
684 # N.next = A
688 # N.next = A
685 # It is tempting to do just "head" here, however if node is
689 # It is tempting to do just "head" here, however if node is
686 # adjacent to head, this will do bad things.
690 # adjacent to head, this will do bad things.
687 node.next = head.prev.next
691 node.next = head.prev.next
688 # E.next = N
692 # E.next = N
689 node.next.prev = node
693 node.next.prev = node
690 # A.prev = N
694 # A.prev = N
691 node.prev.next = node
695 node.prev.next = node
692
696
693 self._head = node
697 self._head = node
694
698
695 def _addcapacity(self):
699 def _addcapacity(self):
696 """Add a node to the circular linked list.
700 """Add a node to the circular linked list.
697
701
698 The new node is inserted before the head node.
702 The new node is inserted before the head node.
699 """
703 """
700 head = self._head
704 head = self._head
701 node = _lrucachenode()
705 node = _lrucachenode()
702 head.prev.next = node
706 head.prev.next = node
703 node.prev = head.prev
707 node.prev = head.prev
704 node.next = head
708 node.next = head
705 head.prev = node
709 head.prev = node
706 self._size += 1
710 self._size += 1
707 return node
711 return node
708
712
709 def lrucachefunc(func):
713 def lrucachefunc(func):
710 '''cache most recent results of function calls'''
714 '''cache most recent results of function calls'''
711 cache = {}
715 cache = {}
712 order = collections.deque()
716 order = collections.deque()
713 if func.__code__.co_argcount == 1:
717 if func.__code__.co_argcount == 1:
714 def f(arg):
718 def f(arg):
715 if arg not in cache:
719 if arg not in cache:
716 if len(cache) > 20:
720 if len(cache) > 20:
717 del cache[order.popleft()]
721 del cache[order.popleft()]
718 cache[arg] = func(arg)
722 cache[arg] = func(arg)
719 else:
723 else:
720 order.remove(arg)
724 order.remove(arg)
721 order.append(arg)
725 order.append(arg)
722 return cache[arg]
726 return cache[arg]
723 else:
727 else:
724 def f(*args):
728 def f(*args):
725 if args not in cache:
729 if args not in cache:
726 if len(cache) > 20:
730 if len(cache) > 20:
727 del cache[order.popleft()]
731 del cache[order.popleft()]
728 cache[args] = func(*args)
732 cache[args] = func(*args)
729 else:
733 else:
730 order.remove(args)
734 order.remove(args)
731 order.append(args)
735 order.append(args)
732 return cache[args]
736 return cache[args]
733
737
734 return f
738 return f
735
739
736 class propertycache(object):
740 class propertycache(object):
737 def __init__(self, func):
741 def __init__(self, func):
738 self.func = func
742 self.func = func
739 self.name = func.__name__
743 self.name = func.__name__
740 def __get__(self, obj, type=None):
744 def __get__(self, obj, type=None):
741 result = self.func(obj)
745 result = self.func(obj)
742 self.cachevalue(obj, result)
746 self.cachevalue(obj, result)
743 return result
747 return result
744
748
745 def cachevalue(self, obj, value):
749 def cachevalue(self, obj, value):
746 # __dict__ assignment required to bypass __setattr__ (eg: repoview)
750 # __dict__ assignment required to bypass __setattr__ (eg: repoview)
747 obj.__dict__[self.name] = value
751 obj.__dict__[self.name] = value
748
752
749 def pipefilter(s, cmd):
753 def pipefilter(s, cmd):
750 '''filter string S through command CMD, returning its output'''
754 '''filter string S through command CMD, returning its output'''
751 p = subprocess.Popen(cmd, shell=True, close_fds=closefds,
755 p = subprocess.Popen(cmd, shell=True, close_fds=closefds,
752 stdin=subprocess.PIPE, stdout=subprocess.PIPE)
756 stdin=subprocess.PIPE, stdout=subprocess.PIPE)
753 pout, perr = p.communicate(s)
757 pout, perr = p.communicate(s)
754 return pout
758 return pout
755
759
756 def tempfilter(s, cmd):
760 def tempfilter(s, cmd):
757 '''filter string S through a pair of temporary files with CMD.
761 '''filter string S through a pair of temporary files with CMD.
758 CMD is used as a template to create the real command to be run,
762 CMD is used as a template to create the real command to be run,
759 with the strings INFILE and OUTFILE replaced by the real names of
763 with the strings INFILE and OUTFILE replaced by the real names of
760 the temporary files generated.'''
764 the temporary files generated.'''
761 inname, outname = None, None
765 inname, outname = None, None
762 try:
766 try:
763 infd, inname = tempfile.mkstemp(prefix='hg-filter-in-')
767 infd, inname = tempfile.mkstemp(prefix='hg-filter-in-')
764 fp = os.fdopen(infd, 'wb')
768 fp = os.fdopen(infd, 'wb')
765 fp.write(s)
769 fp.write(s)
766 fp.close()
770 fp.close()
767 outfd, outname = tempfile.mkstemp(prefix='hg-filter-out-')
771 outfd, outname = tempfile.mkstemp(prefix='hg-filter-out-')
768 os.close(outfd)
772 os.close(outfd)
769 cmd = cmd.replace('INFILE', inname)
773 cmd = cmd.replace('INFILE', inname)
770 cmd = cmd.replace('OUTFILE', outname)
774 cmd = cmd.replace('OUTFILE', outname)
771 code = os.system(cmd)
775 code = os.system(cmd)
772 if sys.platform == 'OpenVMS' and code & 1:
776 if sys.platform == 'OpenVMS' and code & 1:
773 code = 0
777 code = 0
774 if code:
778 if code:
775 raise Abort(_("command '%s' failed: %s") %
779 raise Abort(_("command '%s' failed: %s") %
776 (cmd, explainexit(code)))
780 (cmd, explainexit(code)))
777 return readfile(outname)
781 return readfile(outname)
778 finally:
782 finally:
779 try:
783 try:
780 if inname:
784 if inname:
781 os.unlink(inname)
785 os.unlink(inname)
782 except OSError:
786 except OSError:
783 pass
787 pass
784 try:
788 try:
785 if outname:
789 if outname:
786 os.unlink(outname)
790 os.unlink(outname)
787 except OSError:
791 except OSError:
788 pass
792 pass
789
793
790 filtertable = {
794 filtertable = {
791 'tempfile:': tempfilter,
795 'tempfile:': tempfilter,
792 'pipe:': pipefilter,
796 'pipe:': pipefilter,
793 }
797 }
794
798
795 def filter(s, cmd):
799 def filter(s, cmd):
796 "filter a string through a command that transforms its input to its output"
800 "filter a string through a command that transforms its input to its output"
797 for name, fn in filtertable.iteritems():
801 for name, fn in filtertable.iteritems():
798 if cmd.startswith(name):
802 if cmd.startswith(name):
799 return fn(s, cmd[len(name):].lstrip())
803 return fn(s, cmd[len(name):].lstrip())
800 return pipefilter(s, cmd)
804 return pipefilter(s, cmd)
801
805
802 def binary(s):
806 def binary(s):
803 """return true if a string is binary data"""
807 """return true if a string is binary data"""
804 return bool(s and '\0' in s)
808 return bool(s and '\0' in s)
805
809
806 def increasingchunks(source, min=1024, max=65536):
810 def increasingchunks(source, min=1024, max=65536):
807 '''return no less than min bytes per chunk while data remains,
811 '''return no less than min bytes per chunk while data remains,
808 doubling min after each chunk until it reaches max'''
812 doubling min after each chunk until it reaches max'''
809 def log2(x):
813 def log2(x):
810 if not x:
814 if not x:
811 return 0
815 return 0
812 i = 0
816 i = 0
813 while x:
817 while x:
814 x >>= 1
818 x >>= 1
815 i += 1
819 i += 1
816 return i - 1
820 return i - 1
817
821
818 buf = []
822 buf = []
819 blen = 0
823 blen = 0
820 for chunk in source:
824 for chunk in source:
821 buf.append(chunk)
825 buf.append(chunk)
822 blen += len(chunk)
826 blen += len(chunk)
823 if blen >= min:
827 if blen >= min:
824 if min < max:
828 if min < max:
825 min = min << 1
829 min = min << 1
826 nmin = 1 << log2(blen)
830 nmin = 1 << log2(blen)
827 if nmin > min:
831 if nmin > min:
828 min = nmin
832 min = nmin
829 if min > max:
833 if min > max:
830 min = max
834 min = max
831 yield ''.join(buf)
835 yield ''.join(buf)
832 blen = 0
836 blen = 0
833 buf = []
837 buf = []
834 if buf:
838 if buf:
835 yield ''.join(buf)
839 yield ''.join(buf)
836
840
837 Abort = error.Abort
841 Abort = error.Abort
838
842
839 def always(fn):
843 def always(fn):
840 return True
844 return True
841
845
842 def never(fn):
846 def never(fn):
843 return False
847 return False
844
848
845 def nogc(func):
849 def nogc(func):
846 """disable garbage collector
850 """disable garbage collector
847
851
848 Python's garbage collector triggers a GC each time a certain number of
852 Python's garbage collector triggers a GC each time a certain number of
849 container objects (the number being defined by gc.get_threshold()) are
853 container objects (the number being defined by gc.get_threshold()) are
850 allocated even when marked not to be tracked by the collector. Tracking has
854 allocated even when marked not to be tracked by the collector. Tracking has
851 no effect on when GCs are triggered, only on what objects the GC looks
855 no effect on when GCs are triggered, only on what objects the GC looks
852 into. As a workaround, disable GC while building complex (huge)
856 into. As a workaround, disable GC while building complex (huge)
853 containers.
857 containers.
854
858
855 This garbage collector issue have been fixed in 2.7.
859 This garbage collector issue have been fixed in 2.7.
856 """
860 """
857 def wrapper(*args, **kwargs):
861 def wrapper(*args, **kwargs):
858 gcenabled = gc.isenabled()
862 gcenabled = gc.isenabled()
859 gc.disable()
863 gc.disable()
860 try:
864 try:
861 return func(*args, **kwargs)
865 return func(*args, **kwargs)
862 finally:
866 finally:
863 if gcenabled:
867 if gcenabled:
864 gc.enable()
868 gc.enable()
865 return wrapper
869 return wrapper
866
870
867 def pathto(root, n1, n2):
871 def pathto(root, n1, n2):
868 '''return the relative path from one place to another.
872 '''return the relative path from one place to another.
869 root should use os.sep to separate directories
873 root should use os.sep to separate directories
870 n1 should use os.sep to separate directories
874 n1 should use os.sep to separate directories
871 n2 should use "/" to separate directories
875 n2 should use "/" to separate directories
872 returns an os.sep-separated path.
876 returns an os.sep-separated path.
873
877
874 If n1 is a relative path, it's assumed it's
878 If n1 is a relative path, it's assumed it's
875 relative to root.
879 relative to root.
876 n2 should always be relative to root.
880 n2 should always be relative to root.
877 '''
881 '''
878 if not n1:
882 if not n1:
879 return localpath(n2)
883 return localpath(n2)
880 if os.path.isabs(n1):
884 if os.path.isabs(n1):
881 if os.path.splitdrive(root)[0] != os.path.splitdrive(n1)[0]:
885 if os.path.splitdrive(root)[0] != os.path.splitdrive(n1)[0]:
882 return os.path.join(root, localpath(n2))
886 return os.path.join(root, localpath(n2))
883 n2 = '/'.join((pconvert(root), n2))
887 n2 = '/'.join((pconvert(root), n2))
884 a, b = splitpath(n1), n2.split('/')
888 a, b = splitpath(n1), n2.split('/')
885 a.reverse()
889 a.reverse()
886 b.reverse()
890 b.reverse()
887 while a and b and a[-1] == b[-1]:
891 while a and b and a[-1] == b[-1]:
888 a.pop()
892 a.pop()
889 b.pop()
893 b.pop()
890 b.reverse()
894 b.reverse()
891 return os.sep.join((['..'] * len(a)) + b) or '.'
895 return os.sep.join((['..'] * len(a)) + b) or '.'
892
896
893 def mainfrozen():
897 def mainfrozen():
894 """return True if we are a frozen executable.
898 """return True if we are a frozen executable.
895
899
896 The code supports py2exe (most common, Windows only) and tools/freeze
900 The code supports py2exe (most common, Windows only) and tools/freeze
897 (portable, not much used).
901 (portable, not much used).
898 """
902 """
899 return (safehasattr(sys, "frozen") or # new py2exe
903 return (safehasattr(sys, "frozen") or # new py2exe
900 safehasattr(sys, "importers") or # old py2exe
904 safehasattr(sys, "importers") or # old py2exe
901 imp.is_frozen("__main__")) # tools/freeze
905 imp.is_frozen("__main__")) # tools/freeze
902
906
903 # the location of data files matching the source code
907 # the location of data files matching the source code
904 if mainfrozen() and getattr(sys, 'frozen', None) != 'macosx_app':
908 if mainfrozen() and getattr(sys, 'frozen', None) != 'macosx_app':
905 # executable version (py2exe) doesn't support __file__
909 # executable version (py2exe) doesn't support __file__
906 datapath = os.path.dirname(sys.executable)
910 datapath = os.path.dirname(sys.executable)
907 else:
911 else:
908 datapath = os.path.dirname(__file__)
912 datapath = os.path.dirname(__file__)
909
913
910 i18n.setdatapath(datapath)
914 i18n.setdatapath(datapath)
911
915
912 _hgexecutable = None
916 _hgexecutable = None
913
917
914 def hgexecutable():
918 def hgexecutable():
915 """return location of the 'hg' executable.
919 """return location of the 'hg' executable.
916
920
917 Defaults to $HG or 'hg' in the search path.
921 Defaults to $HG or 'hg' in the search path.
918 """
922 """
919 if _hgexecutable is None:
923 if _hgexecutable is None:
920 hg = os.environ.get('HG')
924 hg = os.environ.get('HG')
921 mainmod = sys.modules['__main__']
925 mainmod = sys.modules['__main__']
922 if hg:
926 if hg:
923 _sethgexecutable(hg)
927 _sethgexecutable(hg)
924 elif mainfrozen():
928 elif mainfrozen():
925 if getattr(sys, 'frozen', None) == 'macosx_app':
929 if getattr(sys, 'frozen', None) == 'macosx_app':
926 # Env variable set by py2app
930 # Env variable set by py2app
927 _sethgexecutable(os.environ['EXECUTABLEPATH'])
931 _sethgexecutable(os.environ['EXECUTABLEPATH'])
928 else:
932 else:
929 _sethgexecutable(sys.executable)
933 _sethgexecutable(sys.executable)
930 elif os.path.basename(getattr(mainmod, '__file__', '')) == 'hg':
934 elif os.path.basename(getattr(mainmod, '__file__', '')) == 'hg':
931 _sethgexecutable(mainmod.__file__)
935 _sethgexecutable(mainmod.__file__)
932 else:
936 else:
933 exe = findexe('hg') or os.path.basename(sys.argv[0])
937 exe = findexe('hg') or os.path.basename(sys.argv[0])
934 _sethgexecutable(exe)
938 _sethgexecutable(exe)
935 return _hgexecutable
939 return _hgexecutable
936
940
937 def _sethgexecutable(path):
941 def _sethgexecutable(path):
938 """set location of the 'hg' executable"""
942 """set location of the 'hg' executable"""
939 global _hgexecutable
943 global _hgexecutable
940 _hgexecutable = path
944 _hgexecutable = path
941
945
942 def _isstdout(f):
946 def _isstdout(f):
943 fileno = getattr(f, 'fileno', None)
947 fileno = getattr(f, 'fileno', None)
944 return fileno and fileno() == sys.__stdout__.fileno()
948 return fileno and fileno() == sys.__stdout__.fileno()
945
949
946 def system(cmd, environ=None, cwd=None, onerr=None, errprefix=None, out=None):
950 def system(cmd, environ=None, cwd=None, onerr=None, errprefix=None, out=None):
947 '''enhanced shell command execution.
951 '''enhanced shell command execution.
948 run with environment maybe modified, maybe in different dir.
952 run with environment maybe modified, maybe in different dir.
949
953
950 if command fails and onerr is None, return status, else raise onerr
954 if command fails and onerr is None, return status, else raise onerr
951 object as exception.
955 object as exception.
952
956
953 if out is specified, it is assumed to be a file-like object that has a
957 if out is specified, it is assumed to be a file-like object that has a
954 write() method. stdout and stderr will be redirected to out.'''
958 write() method. stdout and stderr will be redirected to out.'''
955 if environ is None:
959 if environ is None:
956 environ = {}
960 environ = {}
957 try:
961 try:
958 sys.stdout.flush()
962 sys.stdout.flush()
959 except Exception:
963 except Exception:
960 pass
964 pass
961 def py2shell(val):
965 def py2shell(val):
962 'convert python object into string that is useful to shell'
966 'convert python object into string that is useful to shell'
963 if val is None or val is False:
967 if val is None or val is False:
964 return '0'
968 return '0'
965 if val is True:
969 if val is True:
966 return '1'
970 return '1'
967 return str(val)
971 return str(val)
968 origcmd = cmd
972 origcmd = cmd
969 cmd = quotecommand(cmd)
973 cmd = quotecommand(cmd)
970 if sys.platform == 'plan9' and (sys.version_info[0] == 2
974 if sys.platform == 'plan9' and (sys.version_info[0] == 2
971 and sys.version_info[1] < 7):
975 and sys.version_info[1] < 7):
972 # subprocess kludge to work around issues in half-baked Python
976 # subprocess kludge to work around issues in half-baked Python
973 # ports, notably bichued/python:
977 # ports, notably bichued/python:
974 if not cwd is None:
978 if not cwd is None:
975 os.chdir(cwd)
979 os.chdir(cwd)
976 rc = os.system(cmd)
980 rc = os.system(cmd)
977 else:
981 else:
978 env = dict(os.environ)
982 env = dict(os.environ)
979 env.update((k, py2shell(v)) for k, v in environ.iteritems())
983 env.update((k, py2shell(v)) for k, v in environ.iteritems())
980 env['HG'] = hgexecutable()
984 env['HG'] = hgexecutable()
981 if out is None or _isstdout(out):
985 if out is None or _isstdout(out):
982 rc = subprocess.call(cmd, shell=True, close_fds=closefds,
986 rc = subprocess.call(cmd, shell=True, close_fds=closefds,
983 env=env, cwd=cwd)
987 env=env, cwd=cwd)
984 else:
988 else:
985 proc = subprocess.Popen(cmd, shell=True, close_fds=closefds,
989 proc = subprocess.Popen(cmd, shell=True, close_fds=closefds,
986 env=env, cwd=cwd, stdout=subprocess.PIPE,
990 env=env, cwd=cwd, stdout=subprocess.PIPE,
987 stderr=subprocess.STDOUT)
991 stderr=subprocess.STDOUT)
988 while True:
992 while True:
989 line = proc.stdout.readline()
993 line = proc.stdout.readline()
990 if not line:
994 if not line:
991 break
995 break
992 out.write(line)
996 out.write(line)
993 proc.wait()
997 proc.wait()
994 rc = proc.returncode
998 rc = proc.returncode
995 if sys.platform == 'OpenVMS' and rc & 1:
999 if sys.platform == 'OpenVMS' and rc & 1:
996 rc = 0
1000 rc = 0
997 if rc and onerr:
1001 if rc and onerr:
998 errmsg = '%s %s' % (os.path.basename(origcmd.split(None, 1)[0]),
1002 errmsg = '%s %s' % (os.path.basename(origcmd.split(None, 1)[0]),
999 explainexit(rc)[0])
1003 explainexit(rc)[0])
1000 if errprefix:
1004 if errprefix:
1001 errmsg = '%s: %s' % (errprefix, errmsg)
1005 errmsg = '%s: %s' % (errprefix, errmsg)
1002 raise onerr(errmsg)
1006 raise onerr(errmsg)
1003 return rc
1007 return rc
1004
1008
1005 def checksignature(func):
1009 def checksignature(func):
1006 '''wrap a function with code to check for calling errors'''
1010 '''wrap a function with code to check for calling errors'''
1007 def check(*args, **kwargs):
1011 def check(*args, **kwargs):
1008 try:
1012 try:
1009 return func(*args, **kwargs)
1013 return func(*args, **kwargs)
1010 except TypeError:
1014 except TypeError:
1011 if len(traceback.extract_tb(sys.exc_info()[2])) == 1:
1015 if len(traceback.extract_tb(sys.exc_info()[2])) == 1:
1012 raise error.SignatureError
1016 raise error.SignatureError
1013 raise
1017 raise
1014
1018
1015 return check
1019 return check
1016
1020
1017 def copyfile(src, dest, hardlink=False, copystat=False, checkambig=False):
1021 def copyfile(src, dest, hardlink=False, copystat=False, checkambig=False):
1018 '''copy a file, preserving mode and optionally other stat info like
1022 '''copy a file, preserving mode and optionally other stat info like
1019 atime/mtime
1023 atime/mtime
1020
1024
1021 checkambig argument is used with filestat, and is useful only if
1025 checkambig argument is used with filestat, and is useful only if
1022 destination file is guarded by any lock (e.g. repo.lock or
1026 destination file is guarded by any lock (e.g. repo.lock or
1023 repo.wlock).
1027 repo.wlock).
1024
1028
1025 copystat and checkambig should be exclusive.
1029 copystat and checkambig should be exclusive.
1026 '''
1030 '''
1027 assert not (copystat and checkambig)
1031 assert not (copystat and checkambig)
1028 oldstat = None
1032 oldstat = None
1029 if os.path.lexists(dest):
1033 if os.path.lexists(dest):
1030 if checkambig:
1034 if checkambig:
1031 oldstat = checkambig and filestat(dest)
1035 oldstat = checkambig and filestat(dest)
1032 unlink(dest)
1036 unlink(dest)
1033 # hardlinks are problematic on CIFS, quietly ignore this flag
1037 # hardlinks are problematic on CIFS, quietly ignore this flag
1034 # until we find a way to work around it cleanly (issue4546)
1038 # until we find a way to work around it cleanly (issue4546)
1035 if False and hardlink:
1039 if False and hardlink:
1036 try:
1040 try:
1037 oslink(src, dest)
1041 oslink(src, dest)
1038 return
1042 return
1039 except (IOError, OSError):
1043 except (IOError, OSError):
1040 pass # fall back to normal copy
1044 pass # fall back to normal copy
1041 if os.path.islink(src):
1045 if os.path.islink(src):
1042 os.symlink(os.readlink(src), dest)
1046 os.symlink(os.readlink(src), dest)
1043 # copytime is ignored for symlinks, but in general copytime isn't needed
1047 # copytime is ignored for symlinks, but in general copytime isn't needed
1044 # for them anyway
1048 # for them anyway
1045 else:
1049 else:
1046 try:
1050 try:
1047 shutil.copyfile(src, dest)
1051 shutil.copyfile(src, dest)
1048 if copystat:
1052 if copystat:
1049 # copystat also copies mode
1053 # copystat also copies mode
1050 shutil.copystat(src, dest)
1054 shutil.copystat(src, dest)
1051 else:
1055 else:
1052 shutil.copymode(src, dest)
1056 shutil.copymode(src, dest)
1053 if oldstat and oldstat.stat:
1057 if oldstat and oldstat.stat:
1054 newstat = filestat(dest)
1058 newstat = filestat(dest)
1055 if newstat.isambig(oldstat):
1059 if newstat.isambig(oldstat):
1056 # stat of copied file is ambiguous to original one
1060 # stat of copied file is ambiguous to original one
1057 advanced = (oldstat.stat.st_mtime + 1) & 0x7fffffff
1061 advanced = (oldstat.stat.st_mtime + 1) & 0x7fffffff
1058 os.utime(dest, (advanced, advanced))
1062 os.utime(dest, (advanced, advanced))
1059 except shutil.Error as inst:
1063 except shutil.Error as inst:
1060 raise Abort(str(inst))
1064 raise Abort(str(inst))
1061
1065
1062 def copyfiles(src, dst, hardlink=None, progress=lambda t, pos: None):
1066 def copyfiles(src, dst, hardlink=None, progress=lambda t, pos: None):
1063 """Copy a directory tree using hardlinks if possible."""
1067 """Copy a directory tree using hardlinks if possible."""
1064 num = 0
1068 num = 0
1065
1069
1066 if hardlink is None:
1070 if hardlink is None:
1067 hardlink = (os.stat(src).st_dev ==
1071 hardlink = (os.stat(src).st_dev ==
1068 os.stat(os.path.dirname(dst)).st_dev)
1072 os.stat(os.path.dirname(dst)).st_dev)
1069 if hardlink:
1073 if hardlink:
1070 topic = _('linking')
1074 topic = _('linking')
1071 else:
1075 else:
1072 topic = _('copying')
1076 topic = _('copying')
1073
1077
1074 if os.path.isdir(src):
1078 if os.path.isdir(src):
1075 os.mkdir(dst)
1079 os.mkdir(dst)
1076 for name, kind in osutil.listdir(src):
1080 for name, kind in osutil.listdir(src):
1077 srcname = os.path.join(src, name)
1081 srcname = os.path.join(src, name)
1078 dstname = os.path.join(dst, name)
1082 dstname = os.path.join(dst, name)
1079 def nprog(t, pos):
1083 def nprog(t, pos):
1080 if pos is not None:
1084 if pos is not None:
1081 return progress(t, pos + num)
1085 return progress(t, pos + num)
1082 hardlink, n = copyfiles(srcname, dstname, hardlink, progress=nprog)
1086 hardlink, n = copyfiles(srcname, dstname, hardlink, progress=nprog)
1083 num += n
1087 num += n
1084 else:
1088 else:
1085 if hardlink:
1089 if hardlink:
1086 try:
1090 try:
1087 oslink(src, dst)
1091 oslink(src, dst)
1088 except (IOError, OSError):
1092 except (IOError, OSError):
1089 hardlink = False
1093 hardlink = False
1090 shutil.copy(src, dst)
1094 shutil.copy(src, dst)
1091 else:
1095 else:
1092 shutil.copy(src, dst)
1096 shutil.copy(src, dst)
1093 num += 1
1097 num += 1
1094 progress(topic, num)
1098 progress(topic, num)
1095 progress(topic, None)
1099 progress(topic, None)
1096
1100
1097 return hardlink, num
1101 return hardlink, num
1098
1102
1099 _winreservednames = '''con prn aux nul
1103 _winreservednames = '''con prn aux nul
1100 com1 com2 com3 com4 com5 com6 com7 com8 com9
1104 com1 com2 com3 com4 com5 com6 com7 com8 com9
1101 lpt1 lpt2 lpt3 lpt4 lpt5 lpt6 lpt7 lpt8 lpt9'''.split()
1105 lpt1 lpt2 lpt3 lpt4 lpt5 lpt6 lpt7 lpt8 lpt9'''.split()
1102 _winreservedchars = ':*?"<>|'
1106 _winreservedchars = ':*?"<>|'
1103 def checkwinfilename(path):
1107 def checkwinfilename(path):
1104 r'''Check that the base-relative path is a valid filename on Windows.
1108 r'''Check that the base-relative path is a valid filename on Windows.
1105 Returns None if the path is ok, or a UI string describing the problem.
1109 Returns None if the path is ok, or a UI string describing the problem.
1106
1110
1107 >>> checkwinfilename("just/a/normal/path")
1111 >>> checkwinfilename("just/a/normal/path")
1108 >>> checkwinfilename("foo/bar/con.xml")
1112 >>> checkwinfilename("foo/bar/con.xml")
1109 "filename contains 'con', which is reserved on Windows"
1113 "filename contains 'con', which is reserved on Windows"
1110 >>> checkwinfilename("foo/con.xml/bar")
1114 >>> checkwinfilename("foo/con.xml/bar")
1111 "filename contains 'con', which is reserved on Windows"
1115 "filename contains 'con', which is reserved on Windows"
1112 >>> checkwinfilename("foo/bar/xml.con")
1116 >>> checkwinfilename("foo/bar/xml.con")
1113 >>> checkwinfilename("foo/bar/AUX/bla.txt")
1117 >>> checkwinfilename("foo/bar/AUX/bla.txt")
1114 "filename contains 'AUX', which is reserved on Windows"
1118 "filename contains 'AUX', which is reserved on Windows"
1115 >>> checkwinfilename("foo/bar/bla:.txt")
1119 >>> checkwinfilename("foo/bar/bla:.txt")
1116 "filename contains ':', which is reserved on Windows"
1120 "filename contains ':', which is reserved on Windows"
1117 >>> checkwinfilename("foo/bar/b\07la.txt")
1121 >>> checkwinfilename("foo/bar/b\07la.txt")
1118 "filename contains '\\x07', which is invalid on Windows"
1122 "filename contains '\\x07', which is invalid on Windows"
1119 >>> checkwinfilename("foo/bar/bla ")
1123 >>> checkwinfilename("foo/bar/bla ")
1120 "filename ends with ' ', which is not allowed on Windows"
1124 "filename ends with ' ', which is not allowed on Windows"
1121 >>> checkwinfilename("../bar")
1125 >>> checkwinfilename("../bar")
1122 >>> checkwinfilename("foo\\")
1126 >>> checkwinfilename("foo\\")
1123 "filename ends with '\\', which is invalid on Windows"
1127 "filename ends with '\\', which is invalid on Windows"
1124 >>> checkwinfilename("foo\\/bar")
1128 >>> checkwinfilename("foo\\/bar")
1125 "directory name ends with '\\', which is invalid on Windows"
1129 "directory name ends with '\\', which is invalid on Windows"
1126 '''
1130 '''
1127 if path.endswith('\\'):
1131 if path.endswith('\\'):
1128 return _("filename ends with '\\', which is invalid on Windows")
1132 return _("filename ends with '\\', which is invalid on Windows")
1129 if '\\/' in path:
1133 if '\\/' in path:
1130 return _("directory name ends with '\\', which is invalid on Windows")
1134 return _("directory name ends with '\\', which is invalid on Windows")
1131 for n in path.replace('\\', '/').split('/'):
1135 for n in path.replace('\\', '/').split('/'):
1132 if not n:
1136 if not n:
1133 continue
1137 continue
1134 for c in n:
1138 for c in n:
1135 if c in _winreservedchars:
1139 if c in _winreservedchars:
1136 return _("filename contains '%s', which is reserved "
1140 return _("filename contains '%s', which is reserved "
1137 "on Windows") % c
1141 "on Windows") % c
1138 if ord(c) <= 31:
1142 if ord(c) <= 31:
1139 return _("filename contains %r, which is invalid "
1143 return _("filename contains %r, which is invalid "
1140 "on Windows") % c
1144 "on Windows") % c
1141 base = n.split('.')[0]
1145 base = n.split('.')[0]
1142 if base and base.lower() in _winreservednames:
1146 if base and base.lower() in _winreservednames:
1143 return _("filename contains '%s', which is reserved "
1147 return _("filename contains '%s', which is reserved "
1144 "on Windows") % base
1148 "on Windows") % base
1145 t = n[-1]
1149 t = n[-1]
1146 if t in '. ' and n not in '..':
1150 if t in '. ' and n not in '..':
1147 return _("filename ends with '%s', which is not allowed "
1151 return _("filename ends with '%s', which is not allowed "
1148 "on Windows") % t
1152 "on Windows") % t
1149
1153
1150 if os.name == 'nt':
1154 if os.name == 'nt':
1151 checkosfilename = checkwinfilename
1155 checkosfilename = checkwinfilename
1152 else:
1156 else:
1153 checkosfilename = platform.checkosfilename
1157 checkosfilename = platform.checkosfilename
1154
1158
1155 def makelock(info, pathname):
1159 def makelock(info, pathname):
1156 try:
1160 try:
1157 return os.symlink(info, pathname)
1161 return os.symlink(info, pathname)
1158 except OSError as why:
1162 except OSError as why:
1159 if why.errno == errno.EEXIST:
1163 if why.errno == errno.EEXIST:
1160 raise
1164 raise
1161 except AttributeError: # no symlink in os
1165 except AttributeError: # no symlink in os
1162 pass
1166 pass
1163
1167
1164 ld = os.open(pathname, os.O_CREAT | os.O_WRONLY | os.O_EXCL)
1168 ld = os.open(pathname, os.O_CREAT | os.O_WRONLY | os.O_EXCL)
1165 os.write(ld, info)
1169 os.write(ld, info)
1166 os.close(ld)
1170 os.close(ld)
1167
1171
1168 def readlock(pathname):
1172 def readlock(pathname):
1169 try:
1173 try:
1170 return os.readlink(pathname)
1174 return os.readlink(pathname)
1171 except OSError as why:
1175 except OSError as why:
1172 if why.errno not in (errno.EINVAL, errno.ENOSYS):
1176 if why.errno not in (errno.EINVAL, errno.ENOSYS):
1173 raise
1177 raise
1174 except AttributeError: # no symlink in os
1178 except AttributeError: # no symlink in os
1175 pass
1179 pass
1176 fp = posixfile(pathname)
1180 fp = posixfile(pathname)
1177 r = fp.read()
1181 r = fp.read()
1178 fp.close()
1182 fp.close()
1179 return r
1183 return r
1180
1184
1181 def fstat(fp):
1185 def fstat(fp):
1182 '''stat file object that may not have fileno method.'''
1186 '''stat file object that may not have fileno method.'''
1183 try:
1187 try:
1184 return os.fstat(fp.fileno())
1188 return os.fstat(fp.fileno())
1185 except AttributeError:
1189 except AttributeError:
1186 return os.stat(fp.name)
1190 return os.stat(fp.name)
1187
1191
1188 # File system features
1192 # File system features
1189
1193
1190 def checkcase(path):
1194 def checkcase(path):
1191 """
1195 """
1192 Return true if the given path is on a case-sensitive filesystem
1196 Return true if the given path is on a case-sensitive filesystem
1193
1197
1194 Requires a path (like /foo/.hg) ending with a foldable final
1198 Requires a path (like /foo/.hg) ending with a foldable final
1195 directory component.
1199 directory component.
1196 """
1200 """
1197 s1 = os.lstat(path)
1201 s1 = os.lstat(path)
1198 d, b = os.path.split(path)
1202 d, b = os.path.split(path)
1199 b2 = b.upper()
1203 b2 = b.upper()
1200 if b == b2:
1204 if b == b2:
1201 b2 = b.lower()
1205 b2 = b.lower()
1202 if b == b2:
1206 if b == b2:
1203 return True # no evidence against case sensitivity
1207 return True # no evidence against case sensitivity
1204 p2 = os.path.join(d, b2)
1208 p2 = os.path.join(d, b2)
1205 try:
1209 try:
1206 s2 = os.lstat(p2)
1210 s2 = os.lstat(p2)
1207 if s2 == s1:
1211 if s2 == s1:
1208 return False
1212 return False
1209 return True
1213 return True
1210 except OSError:
1214 except OSError:
1211 return True
1215 return True
1212
1216
1213 try:
1217 try:
1214 import re2
1218 import re2
1215 _re2 = None
1219 _re2 = None
1216 except ImportError:
1220 except ImportError:
1217 _re2 = False
1221 _re2 = False
1218
1222
1219 class _re(object):
1223 class _re(object):
1220 def _checkre2(self):
1224 def _checkre2(self):
1221 global _re2
1225 global _re2
1222 try:
1226 try:
1223 # check if match works, see issue3964
1227 # check if match works, see issue3964
1224 _re2 = bool(re2.match(r'\[([^\[]+)\]', '[ui]'))
1228 _re2 = bool(re2.match(r'\[([^\[]+)\]', '[ui]'))
1225 except ImportError:
1229 except ImportError:
1226 _re2 = False
1230 _re2 = False
1227
1231
1228 def compile(self, pat, flags=0):
1232 def compile(self, pat, flags=0):
1229 '''Compile a regular expression, using re2 if possible
1233 '''Compile a regular expression, using re2 if possible
1230
1234
1231 For best performance, use only re2-compatible regexp features. The
1235 For best performance, use only re2-compatible regexp features. The
1232 only flags from the re module that are re2-compatible are
1236 only flags from the re module that are re2-compatible are
1233 IGNORECASE and MULTILINE.'''
1237 IGNORECASE and MULTILINE.'''
1234 if _re2 is None:
1238 if _re2 is None:
1235 self._checkre2()
1239 self._checkre2()
1236 if _re2 and (flags & ~(remod.IGNORECASE | remod.MULTILINE)) == 0:
1240 if _re2 and (flags & ~(remod.IGNORECASE | remod.MULTILINE)) == 0:
1237 if flags & remod.IGNORECASE:
1241 if flags & remod.IGNORECASE:
1238 pat = '(?i)' + pat
1242 pat = '(?i)' + pat
1239 if flags & remod.MULTILINE:
1243 if flags & remod.MULTILINE:
1240 pat = '(?m)' + pat
1244 pat = '(?m)' + pat
1241 try:
1245 try:
1242 return re2.compile(pat)
1246 return re2.compile(pat)
1243 except re2.error:
1247 except re2.error:
1244 pass
1248 pass
1245 return remod.compile(pat, flags)
1249 return remod.compile(pat, flags)
1246
1250
1247 @propertycache
1251 @propertycache
1248 def escape(self):
1252 def escape(self):
1249 '''Return the version of escape corresponding to self.compile.
1253 '''Return the version of escape corresponding to self.compile.
1250
1254
1251 This is imperfect because whether re2 or re is used for a particular
1255 This is imperfect because whether re2 or re is used for a particular
1252 function depends on the flags, etc, but it's the best we can do.
1256 function depends on the flags, etc, but it's the best we can do.
1253 '''
1257 '''
1254 global _re2
1258 global _re2
1255 if _re2 is None:
1259 if _re2 is None:
1256 self._checkre2()
1260 self._checkre2()
1257 if _re2:
1261 if _re2:
1258 return re2.escape
1262 return re2.escape
1259 else:
1263 else:
1260 return remod.escape
1264 return remod.escape
1261
1265
1262 re = _re()
1266 re = _re()
1263
1267
1264 _fspathcache = {}
1268 _fspathcache = {}
1265 def fspath(name, root):
1269 def fspath(name, root):
1266 '''Get name in the case stored in the filesystem
1270 '''Get name in the case stored in the filesystem
1267
1271
1268 The name should be relative to root, and be normcase-ed for efficiency.
1272 The name should be relative to root, and be normcase-ed for efficiency.
1269
1273
1270 Note that this function is unnecessary, and should not be
1274 Note that this function is unnecessary, and should not be
1271 called, for case-sensitive filesystems (simply because it's expensive).
1275 called, for case-sensitive filesystems (simply because it's expensive).
1272
1276
1273 The root should be normcase-ed, too.
1277 The root should be normcase-ed, too.
1274 '''
1278 '''
1275 def _makefspathcacheentry(dir):
1279 def _makefspathcacheentry(dir):
1276 return dict((normcase(n), n) for n in os.listdir(dir))
1280 return dict((normcase(n), n) for n in os.listdir(dir))
1277
1281
1278 seps = os.sep
1282 seps = os.sep
1279 if os.altsep:
1283 if os.altsep:
1280 seps = seps + os.altsep
1284 seps = seps + os.altsep
1281 # Protect backslashes. This gets silly very quickly.
1285 # Protect backslashes. This gets silly very quickly.
1282 seps.replace('\\','\\\\')
1286 seps.replace('\\','\\\\')
1283 pattern = remod.compile(r'([^%s]+)|([%s]+)' % (seps, seps))
1287 pattern = remod.compile(r'([^%s]+)|([%s]+)' % (seps, seps))
1284 dir = os.path.normpath(root)
1288 dir = os.path.normpath(root)
1285 result = []
1289 result = []
1286 for part, sep in pattern.findall(name):
1290 for part, sep in pattern.findall(name):
1287 if sep:
1291 if sep:
1288 result.append(sep)
1292 result.append(sep)
1289 continue
1293 continue
1290
1294
1291 if dir not in _fspathcache:
1295 if dir not in _fspathcache:
1292 _fspathcache[dir] = _makefspathcacheentry(dir)
1296 _fspathcache[dir] = _makefspathcacheentry(dir)
1293 contents = _fspathcache[dir]
1297 contents = _fspathcache[dir]
1294
1298
1295 found = contents.get(part)
1299 found = contents.get(part)
1296 if not found:
1300 if not found:
1297 # retry "once per directory" per "dirstate.walk" which
1301 # retry "once per directory" per "dirstate.walk" which
1298 # may take place for each patches of "hg qpush", for example
1302 # may take place for each patches of "hg qpush", for example
1299 _fspathcache[dir] = contents = _makefspathcacheentry(dir)
1303 _fspathcache[dir] = contents = _makefspathcacheentry(dir)
1300 found = contents.get(part)
1304 found = contents.get(part)
1301
1305
1302 result.append(found or part)
1306 result.append(found or part)
1303 dir = os.path.join(dir, part)
1307 dir = os.path.join(dir, part)
1304
1308
1305 return ''.join(result)
1309 return ''.join(result)
1306
1310
1307 def checknlink(testfile):
1311 def checknlink(testfile):
1308 '''check whether hardlink count reporting works properly'''
1312 '''check whether hardlink count reporting works properly'''
1309
1313
1310 # testfile may be open, so we need a separate file for checking to
1314 # testfile may be open, so we need a separate file for checking to
1311 # work around issue2543 (or testfile may get lost on Samba shares)
1315 # work around issue2543 (or testfile may get lost on Samba shares)
1312 f1 = testfile + ".hgtmp1"
1316 f1 = testfile + ".hgtmp1"
1313 if os.path.lexists(f1):
1317 if os.path.lexists(f1):
1314 return False
1318 return False
1315 try:
1319 try:
1316 posixfile(f1, 'w').close()
1320 posixfile(f1, 'w').close()
1317 except IOError:
1321 except IOError:
1318 return False
1322 return False
1319
1323
1320 f2 = testfile + ".hgtmp2"
1324 f2 = testfile + ".hgtmp2"
1321 fd = None
1325 fd = None
1322 try:
1326 try:
1323 oslink(f1, f2)
1327 oslink(f1, f2)
1324 # nlinks() may behave differently for files on Windows shares if
1328 # nlinks() may behave differently for files on Windows shares if
1325 # the file is open.
1329 # the file is open.
1326 fd = posixfile(f2)
1330 fd = posixfile(f2)
1327 return nlinks(f2) > 1
1331 return nlinks(f2) > 1
1328 except OSError:
1332 except OSError:
1329 return False
1333 return False
1330 finally:
1334 finally:
1331 if fd is not None:
1335 if fd is not None:
1332 fd.close()
1336 fd.close()
1333 for f in (f1, f2):
1337 for f in (f1, f2):
1334 try:
1338 try:
1335 os.unlink(f)
1339 os.unlink(f)
1336 except OSError:
1340 except OSError:
1337 pass
1341 pass
1338
1342
1339 def endswithsep(path):
1343 def endswithsep(path):
1340 '''Check path ends with os.sep or os.altsep.'''
1344 '''Check path ends with os.sep or os.altsep.'''
1341 return path.endswith(os.sep) or os.altsep and path.endswith(os.altsep)
1345 return path.endswith(os.sep) or os.altsep and path.endswith(os.altsep)
1342
1346
1343 def splitpath(path):
1347 def splitpath(path):
1344 '''Split path by os.sep.
1348 '''Split path by os.sep.
1345 Note that this function does not use os.altsep because this is
1349 Note that this function does not use os.altsep because this is
1346 an alternative of simple "xxx.split(os.sep)".
1350 an alternative of simple "xxx.split(os.sep)".
1347 It is recommended to use os.path.normpath() before using this
1351 It is recommended to use os.path.normpath() before using this
1348 function if need.'''
1352 function if need.'''
1349 return path.split(os.sep)
1353 return path.split(os.sep)
1350
1354
1351 def gui():
1355 def gui():
1352 '''Are we running in a GUI?'''
1356 '''Are we running in a GUI?'''
1353 if sys.platform == 'darwin':
1357 if sys.platform == 'darwin':
1354 if 'SSH_CONNECTION' in os.environ:
1358 if 'SSH_CONNECTION' in os.environ:
1355 # handle SSH access to a box where the user is logged in
1359 # handle SSH access to a box where the user is logged in
1356 return False
1360 return False
1357 elif getattr(osutil, 'isgui', None):
1361 elif getattr(osutil, 'isgui', None):
1358 # check if a CoreGraphics session is available
1362 # check if a CoreGraphics session is available
1359 return osutil.isgui()
1363 return osutil.isgui()
1360 else:
1364 else:
1361 # pure build; use a safe default
1365 # pure build; use a safe default
1362 return True
1366 return True
1363 else:
1367 else:
1364 return os.name == "nt" or os.environ.get("DISPLAY")
1368 return os.name == "nt" or os.environ.get("DISPLAY")
1365
1369
1366 def mktempcopy(name, emptyok=False, createmode=None):
1370 def mktempcopy(name, emptyok=False, createmode=None):
1367 """Create a temporary file with the same contents from name
1371 """Create a temporary file with the same contents from name
1368
1372
1369 The permission bits are copied from the original file.
1373 The permission bits are copied from the original file.
1370
1374
1371 If the temporary file is going to be truncated immediately, you
1375 If the temporary file is going to be truncated immediately, you
1372 can use emptyok=True as an optimization.
1376 can use emptyok=True as an optimization.
1373
1377
1374 Returns the name of the temporary file.
1378 Returns the name of the temporary file.
1375 """
1379 """
1376 d, fn = os.path.split(name)
1380 d, fn = os.path.split(name)
1377 fd, temp = tempfile.mkstemp(prefix='.%s-' % fn, dir=d)
1381 fd, temp = tempfile.mkstemp(prefix='.%s-' % fn, dir=d)
1378 os.close(fd)
1382 os.close(fd)
1379 # Temporary files are created with mode 0600, which is usually not
1383 # Temporary files are created with mode 0600, which is usually not
1380 # what we want. If the original file already exists, just copy
1384 # what we want. If the original file already exists, just copy
1381 # its mode. Otherwise, manually obey umask.
1385 # its mode. Otherwise, manually obey umask.
1382 copymode(name, temp, createmode)
1386 copymode(name, temp, createmode)
1383 if emptyok:
1387 if emptyok:
1384 return temp
1388 return temp
1385 try:
1389 try:
1386 try:
1390 try:
1387 ifp = posixfile(name, "rb")
1391 ifp = posixfile(name, "rb")
1388 except IOError as inst:
1392 except IOError as inst:
1389 if inst.errno == errno.ENOENT:
1393 if inst.errno == errno.ENOENT:
1390 return temp
1394 return temp
1391 if not getattr(inst, 'filename', None):
1395 if not getattr(inst, 'filename', None):
1392 inst.filename = name
1396 inst.filename = name
1393 raise
1397 raise
1394 ofp = posixfile(temp, "wb")
1398 ofp = posixfile(temp, "wb")
1395 for chunk in filechunkiter(ifp):
1399 for chunk in filechunkiter(ifp):
1396 ofp.write(chunk)
1400 ofp.write(chunk)
1397 ifp.close()
1401 ifp.close()
1398 ofp.close()
1402 ofp.close()
1399 except: # re-raises
1403 except: # re-raises
1400 try: os.unlink(temp)
1404 try: os.unlink(temp)
1401 except OSError: pass
1405 except OSError: pass
1402 raise
1406 raise
1403 return temp
1407 return temp
1404
1408
1405 class filestat(object):
1409 class filestat(object):
1406 """help to exactly detect change of a file
1410 """help to exactly detect change of a file
1407
1411
1408 'stat' attribute is result of 'os.stat()' if specified 'path'
1412 'stat' attribute is result of 'os.stat()' if specified 'path'
1409 exists. Otherwise, it is None. This can avoid preparative
1413 exists. Otherwise, it is None. This can avoid preparative
1410 'exists()' examination on client side of this class.
1414 'exists()' examination on client side of this class.
1411 """
1415 """
1412 def __init__(self, path):
1416 def __init__(self, path):
1413 try:
1417 try:
1414 self.stat = os.stat(path)
1418 self.stat = os.stat(path)
1415 except OSError as err:
1419 except OSError as err:
1416 if err.errno != errno.ENOENT:
1420 if err.errno != errno.ENOENT:
1417 raise
1421 raise
1418 self.stat = None
1422 self.stat = None
1419
1423
1420 __hash__ = object.__hash__
1424 __hash__ = object.__hash__
1421
1425
1422 def __eq__(self, old):
1426 def __eq__(self, old):
1423 try:
1427 try:
1424 # if ambiguity between stat of new and old file is
1428 # if ambiguity between stat of new and old file is
1425 # avoided, comparision of size, ctime and mtime is enough
1429 # avoided, comparision of size, ctime and mtime is enough
1426 # to exactly detect change of a file regardless of platform
1430 # to exactly detect change of a file regardless of platform
1427 return (self.stat.st_size == old.stat.st_size and
1431 return (self.stat.st_size == old.stat.st_size and
1428 self.stat.st_ctime == old.stat.st_ctime and
1432 self.stat.st_ctime == old.stat.st_ctime and
1429 self.stat.st_mtime == old.stat.st_mtime)
1433 self.stat.st_mtime == old.stat.st_mtime)
1430 except AttributeError:
1434 except AttributeError:
1431 return False
1435 return False
1432
1436
1433 def isambig(self, old):
1437 def isambig(self, old):
1434 """Examine whether new (= self) stat is ambiguous against old one
1438 """Examine whether new (= self) stat is ambiguous against old one
1435
1439
1436 "S[N]" below means stat of a file at N-th change:
1440 "S[N]" below means stat of a file at N-th change:
1437
1441
1438 - S[n-1].ctime < S[n].ctime: can detect change of a file
1442 - S[n-1].ctime < S[n].ctime: can detect change of a file
1439 - S[n-1].ctime == S[n].ctime
1443 - S[n-1].ctime == S[n].ctime
1440 - S[n-1].ctime < S[n].mtime: means natural advancing (*1)
1444 - S[n-1].ctime < S[n].mtime: means natural advancing (*1)
1441 - S[n-1].ctime == S[n].mtime: is ambiguous (*2)
1445 - S[n-1].ctime == S[n].mtime: is ambiguous (*2)
1442 - S[n-1].ctime > S[n].mtime: never occurs naturally (don't care)
1446 - S[n-1].ctime > S[n].mtime: never occurs naturally (don't care)
1443 - S[n-1].ctime > S[n].ctime: never occurs naturally (don't care)
1447 - S[n-1].ctime > S[n].ctime: never occurs naturally (don't care)
1444
1448
1445 Case (*2) above means that a file was changed twice or more at
1449 Case (*2) above means that a file was changed twice or more at
1446 same time in sec (= S[n-1].ctime), and comparison of timestamp
1450 same time in sec (= S[n-1].ctime), and comparison of timestamp
1447 is ambiguous.
1451 is ambiguous.
1448
1452
1449 Base idea to avoid such ambiguity is "advance mtime 1 sec, if
1453 Base idea to avoid such ambiguity is "advance mtime 1 sec, if
1450 timestamp is ambiguous".
1454 timestamp is ambiguous".
1451
1455
1452 But advancing mtime only in case (*2) doesn't work as
1456 But advancing mtime only in case (*2) doesn't work as
1453 expected, because naturally advanced S[n].mtime in case (*1)
1457 expected, because naturally advanced S[n].mtime in case (*1)
1454 might be equal to manually advanced S[n-1 or earlier].mtime.
1458 might be equal to manually advanced S[n-1 or earlier].mtime.
1455
1459
1456 Therefore, all "S[n-1].ctime == S[n].ctime" cases should be
1460 Therefore, all "S[n-1].ctime == S[n].ctime" cases should be
1457 treated as ambiguous regardless of mtime, to avoid overlooking
1461 treated as ambiguous regardless of mtime, to avoid overlooking
1458 by confliction between such mtime.
1462 by confliction between such mtime.
1459
1463
1460 Advancing mtime "if isambig(oldstat)" ensures "S[n-1].mtime !=
1464 Advancing mtime "if isambig(oldstat)" ensures "S[n-1].mtime !=
1461 S[n].mtime", even if size of a file isn't changed.
1465 S[n].mtime", even if size of a file isn't changed.
1462 """
1466 """
1463 try:
1467 try:
1464 return (self.stat.st_ctime == old.stat.st_ctime)
1468 return (self.stat.st_ctime == old.stat.st_ctime)
1465 except AttributeError:
1469 except AttributeError:
1466 return False
1470 return False
1467
1471
1468 def __ne__(self, other):
1472 def __ne__(self, other):
1469 return not self == other
1473 return not self == other
1470
1474
1471 class atomictempfile(object):
1475 class atomictempfile(object):
1472 '''writable file object that atomically updates a file
1476 '''writable file object that atomically updates a file
1473
1477
1474 All writes will go to a temporary copy of the original file. Call
1478 All writes will go to a temporary copy of the original file. Call
1475 close() when you are done writing, and atomictempfile will rename
1479 close() when you are done writing, and atomictempfile will rename
1476 the temporary copy to the original name, making the changes
1480 the temporary copy to the original name, making the changes
1477 visible. If the object is destroyed without being closed, all your
1481 visible. If the object is destroyed without being closed, all your
1478 writes are discarded.
1482 writes are discarded.
1479
1483
1480 checkambig argument of constructor is used with filestat, and is
1484 checkambig argument of constructor is used with filestat, and is
1481 useful only if target file is guarded by any lock (e.g. repo.lock
1485 useful only if target file is guarded by any lock (e.g. repo.lock
1482 or repo.wlock).
1486 or repo.wlock).
1483 '''
1487 '''
1484 def __init__(self, name, mode='w+b', createmode=None, checkambig=False):
1488 def __init__(self, name, mode='w+b', createmode=None, checkambig=False):
1485 self.__name = name # permanent name
1489 self.__name = name # permanent name
1486 self._tempname = mktempcopy(name, emptyok=('w' in mode),
1490 self._tempname = mktempcopy(name, emptyok=('w' in mode),
1487 createmode=createmode)
1491 createmode=createmode)
1488 self._fp = posixfile(self._tempname, mode)
1492 self._fp = posixfile(self._tempname, mode)
1489 self._checkambig = checkambig
1493 self._checkambig = checkambig
1490
1494
1491 # delegated methods
1495 # delegated methods
1492 self.read = self._fp.read
1496 self.read = self._fp.read
1493 self.write = self._fp.write
1497 self.write = self._fp.write
1494 self.seek = self._fp.seek
1498 self.seek = self._fp.seek
1495 self.tell = self._fp.tell
1499 self.tell = self._fp.tell
1496 self.fileno = self._fp.fileno
1500 self.fileno = self._fp.fileno
1497
1501
1498 def close(self):
1502 def close(self):
1499 if not self._fp.closed:
1503 if not self._fp.closed:
1500 self._fp.close()
1504 self._fp.close()
1501 filename = localpath(self.__name)
1505 filename = localpath(self.__name)
1502 oldstat = self._checkambig and filestat(filename)
1506 oldstat = self._checkambig and filestat(filename)
1503 if oldstat and oldstat.stat:
1507 if oldstat and oldstat.stat:
1504 rename(self._tempname, filename)
1508 rename(self._tempname, filename)
1505 newstat = filestat(filename)
1509 newstat = filestat(filename)
1506 if newstat.isambig(oldstat):
1510 if newstat.isambig(oldstat):
1507 # stat of changed file is ambiguous to original one
1511 # stat of changed file is ambiguous to original one
1508 advanced = (oldstat.stat.st_mtime + 1) & 0x7fffffff
1512 advanced = (oldstat.stat.st_mtime + 1) & 0x7fffffff
1509 os.utime(filename, (advanced, advanced))
1513 os.utime(filename, (advanced, advanced))
1510 else:
1514 else:
1511 rename(self._tempname, filename)
1515 rename(self._tempname, filename)
1512
1516
1513 def discard(self):
1517 def discard(self):
1514 if not self._fp.closed:
1518 if not self._fp.closed:
1515 try:
1519 try:
1516 os.unlink(self._tempname)
1520 os.unlink(self._tempname)
1517 except OSError:
1521 except OSError:
1518 pass
1522 pass
1519 self._fp.close()
1523 self._fp.close()
1520
1524
1521 def __del__(self):
1525 def __del__(self):
1522 if safehasattr(self, '_fp'): # constructor actually did something
1526 if safehasattr(self, '_fp'): # constructor actually did something
1523 self.discard()
1527 self.discard()
1524
1528
1525 def __enter__(self):
1529 def __enter__(self):
1526 return self
1530 return self
1527
1531
1528 def __exit__(self, exctype, excvalue, traceback):
1532 def __exit__(self, exctype, excvalue, traceback):
1529 if exctype is not None:
1533 if exctype is not None:
1530 self.discard()
1534 self.discard()
1531 else:
1535 else:
1532 self.close()
1536 self.close()
1533
1537
1534 def makedirs(name, mode=None, notindexed=False):
1538 def makedirs(name, mode=None, notindexed=False):
1535 """recursive directory creation with parent mode inheritance
1539 """recursive directory creation with parent mode inheritance
1536
1540
1537 Newly created directories are marked as "not to be indexed by
1541 Newly created directories are marked as "not to be indexed by
1538 the content indexing service", if ``notindexed`` is specified
1542 the content indexing service", if ``notindexed`` is specified
1539 for "write" mode access.
1543 for "write" mode access.
1540 """
1544 """
1541 try:
1545 try:
1542 makedir(name, notindexed)
1546 makedir(name, notindexed)
1543 except OSError as err:
1547 except OSError as err:
1544 if err.errno == errno.EEXIST:
1548 if err.errno == errno.EEXIST:
1545 return
1549 return
1546 if err.errno != errno.ENOENT or not name:
1550 if err.errno != errno.ENOENT or not name:
1547 raise
1551 raise
1548 parent = os.path.dirname(os.path.abspath(name))
1552 parent = os.path.dirname(os.path.abspath(name))
1549 if parent == name:
1553 if parent == name:
1550 raise
1554 raise
1551 makedirs(parent, mode, notindexed)
1555 makedirs(parent, mode, notindexed)
1552 try:
1556 try:
1553 makedir(name, notindexed)
1557 makedir(name, notindexed)
1554 except OSError as err:
1558 except OSError as err:
1555 # Catch EEXIST to handle races
1559 # Catch EEXIST to handle races
1556 if err.errno == errno.EEXIST:
1560 if err.errno == errno.EEXIST:
1557 return
1561 return
1558 raise
1562 raise
1559 if mode is not None:
1563 if mode is not None:
1560 os.chmod(name, mode)
1564 os.chmod(name, mode)
1561
1565
1562 def readfile(path):
1566 def readfile(path):
1563 with open(path, 'rb') as fp:
1567 with open(path, 'rb') as fp:
1564 return fp.read()
1568 return fp.read()
1565
1569
1566 def writefile(path, text):
1570 def writefile(path, text):
1567 with open(path, 'wb') as fp:
1571 with open(path, 'wb') as fp:
1568 fp.write(text)
1572 fp.write(text)
1569
1573
1570 def appendfile(path, text):
1574 def appendfile(path, text):
1571 with open(path, 'ab') as fp:
1575 with open(path, 'ab') as fp:
1572 fp.write(text)
1576 fp.write(text)
1573
1577
1574 class chunkbuffer(object):
1578 class chunkbuffer(object):
1575 """Allow arbitrary sized chunks of data to be efficiently read from an
1579 """Allow arbitrary sized chunks of data to be efficiently read from an
1576 iterator over chunks of arbitrary size."""
1580 iterator over chunks of arbitrary size."""
1577
1581
1578 def __init__(self, in_iter):
1582 def __init__(self, in_iter):
1579 """in_iter is the iterator that's iterating over the input chunks.
1583 """in_iter is the iterator that's iterating over the input chunks.
1580 targetsize is how big a buffer to try to maintain."""
1584 targetsize is how big a buffer to try to maintain."""
1581 def splitbig(chunks):
1585 def splitbig(chunks):
1582 for chunk in chunks:
1586 for chunk in chunks:
1583 if len(chunk) > 2**20:
1587 if len(chunk) > 2**20:
1584 pos = 0
1588 pos = 0
1585 while pos < len(chunk):
1589 while pos < len(chunk):
1586 end = pos + 2 ** 18
1590 end = pos + 2 ** 18
1587 yield chunk[pos:end]
1591 yield chunk[pos:end]
1588 pos = end
1592 pos = end
1589 else:
1593 else:
1590 yield chunk
1594 yield chunk
1591 self.iter = splitbig(in_iter)
1595 self.iter = splitbig(in_iter)
1592 self._queue = collections.deque()
1596 self._queue = collections.deque()
1593 self._chunkoffset = 0
1597 self._chunkoffset = 0
1594
1598
1595 def read(self, l=None):
1599 def read(self, l=None):
1596 """Read L bytes of data from the iterator of chunks of data.
1600 """Read L bytes of data from the iterator of chunks of data.
1597 Returns less than L bytes if the iterator runs dry.
1601 Returns less than L bytes if the iterator runs dry.
1598
1602
1599 If size parameter is omitted, read everything"""
1603 If size parameter is omitted, read everything"""
1600 if l is None:
1604 if l is None:
1601 return ''.join(self.iter)
1605 return ''.join(self.iter)
1602
1606
1603 left = l
1607 left = l
1604 buf = []
1608 buf = []
1605 queue = self._queue
1609 queue = self._queue
1606 while left > 0:
1610 while left > 0:
1607 # refill the queue
1611 # refill the queue
1608 if not queue:
1612 if not queue:
1609 target = 2**18
1613 target = 2**18
1610 for chunk in self.iter:
1614 for chunk in self.iter:
1611 queue.append(chunk)
1615 queue.append(chunk)
1612 target -= len(chunk)
1616 target -= len(chunk)
1613 if target <= 0:
1617 if target <= 0:
1614 break
1618 break
1615 if not queue:
1619 if not queue:
1616 break
1620 break
1617
1621
1618 # The easy way to do this would be to queue.popleft(), modify the
1622 # The easy way to do this would be to queue.popleft(), modify the
1619 # chunk (if necessary), then queue.appendleft(). However, for cases
1623 # chunk (if necessary), then queue.appendleft(). However, for cases
1620 # where we read partial chunk content, this incurs 2 dequeue
1624 # where we read partial chunk content, this incurs 2 dequeue
1621 # mutations and creates a new str for the remaining chunk in the
1625 # mutations and creates a new str for the remaining chunk in the
1622 # queue. Our code below avoids this overhead.
1626 # queue. Our code below avoids this overhead.
1623
1627
1624 chunk = queue[0]
1628 chunk = queue[0]
1625 chunkl = len(chunk)
1629 chunkl = len(chunk)
1626 offset = self._chunkoffset
1630 offset = self._chunkoffset
1627
1631
1628 # Use full chunk.
1632 # Use full chunk.
1629 if offset == 0 and left >= chunkl:
1633 if offset == 0 and left >= chunkl:
1630 left -= chunkl
1634 left -= chunkl
1631 queue.popleft()
1635 queue.popleft()
1632 buf.append(chunk)
1636 buf.append(chunk)
1633 # self._chunkoffset remains at 0.
1637 # self._chunkoffset remains at 0.
1634 continue
1638 continue
1635
1639
1636 chunkremaining = chunkl - offset
1640 chunkremaining = chunkl - offset
1637
1641
1638 # Use all of unconsumed part of chunk.
1642 # Use all of unconsumed part of chunk.
1639 if left >= chunkremaining:
1643 if left >= chunkremaining:
1640 left -= chunkremaining
1644 left -= chunkremaining
1641 queue.popleft()
1645 queue.popleft()
1642 # offset == 0 is enabled by block above, so this won't merely
1646 # offset == 0 is enabled by block above, so this won't merely
1643 # copy via ``chunk[0:]``.
1647 # copy via ``chunk[0:]``.
1644 buf.append(chunk[offset:])
1648 buf.append(chunk[offset:])
1645 self._chunkoffset = 0
1649 self._chunkoffset = 0
1646
1650
1647 # Partial chunk needed.
1651 # Partial chunk needed.
1648 else:
1652 else:
1649 buf.append(chunk[offset:offset + left])
1653 buf.append(chunk[offset:offset + left])
1650 self._chunkoffset += left
1654 self._chunkoffset += left
1651 left -= chunkremaining
1655 left -= chunkremaining
1652
1656
1653 return ''.join(buf)
1657 return ''.join(buf)
1654
1658
1655 def filechunkiter(f, size=65536, limit=None):
1659 def filechunkiter(f, size=65536, limit=None):
1656 """Create a generator that produces the data in the file size
1660 """Create a generator that produces the data in the file size
1657 (default 65536) bytes at a time, up to optional limit (default is
1661 (default 65536) bytes at a time, up to optional limit (default is
1658 to read all data). Chunks may be less than size bytes if the
1662 to read all data). Chunks may be less than size bytes if the
1659 chunk is the last chunk in the file, or the file is a socket or
1663 chunk is the last chunk in the file, or the file is a socket or
1660 some other type of file that sometimes reads less data than is
1664 some other type of file that sometimes reads less data than is
1661 requested."""
1665 requested."""
1662 assert size >= 0
1666 assert size >= 0
1663 assert limit is None or limit >= 0
1667 assert limit is None or limit >= 0
1664 while True:
1668 while True:
1665 if limit is None:
1669 if limit is None:
1666 nbytes = size
1670 nbytes = size
1667 else:
1671 else:
1668 nbytes = min(limit, size)
1672 nbytes = min(limit, size)
1669 s = nbytes and f.read(nbytes)
1673 s = nbytes and f.read(nbytes)
1670 if not s:
1674 if not s:
1671 break
1675 break
1672 if limit:
1676 if limit:
1673 limit -= len(s)
1677 limit -= len(s)
1674 yield s
1678 yield s
1675
1679
1676 def makedate(timestamp=None):
1680 def makedate(timestamp=None):
1677 '''Return a unix timestamp (or the current time) as a (unixtime,
1681 '''Return a unix timestamp (or the current time) as a (unixtime,
1678 offset) tuple based off the local timezone.'''
1682 offset) tuple based off the local timezone.'''
1679 if timestamp is None:
1683 if timestamp is None:
1680 timestamp = time.time()
1684 timestamp = time.time()
1681 if timestamp < 0:
1685 if timestamp < 0:
1682 hint = _("check your clock")
1686 hint = _("check your clock")
1683 raise Abort(_("negative timestamp: %d") % timestamp, hint=hint)
1687 raise Abort(_("negative timestamp: %d") % timestamp, hint=hint)
1684 delta = (datetime.datetime.utcfromtimestamp(timestamp) -
1688 delta = (datetime.datetime.utcfromtimestamp(timestamp) -
1685 datetime.datetime.fromtimestamp(timestamp))
1689 datetime.datetime.fromtimestamp(timestamp))
1686 tz = delta.days * 86400 + delta.seconds
1690 tz = delta.days * 86400 + delta.seconds
1687 return timestamp, tz
1691 return timestamp, tz
1688
1692
1689 def datestr(date=None, format='%a %b %d %H:%M:%S %Y %1%2'):
1693 def datestr(date=None, format='%a %b %d %H:%M:%S %Y %1%2'):
1690 """represent a (unixtime, offset) tuple as a localized time.
1694 """represent a (unixtime, offset) tuple as a localized time.
1691 unixtime is seconds since the epoch, and offset is the time zone's
1695 unixtime is seconds since the epoch, and offset is the time zone's
1692 number of seconds away from UTC.
1696 number of seconds away from UTC.
1693
1697
1694 >>> datestr((0, 0))
1698 >>> datestr((0, 0))
1695 'Thu Jan 01 00:00:00 1970 +0000'
1699 'Thu Jan 01 00:00:00 1970 +0000'
1696 >>> datestr((42, 0))
1700 >>> datestr((42, 0))
1697 'Thu Jan 01 00:00:42 1970 +0000'
1701 'Thu Jan 01 00:00:42 1970 +0000'
1698 >>> datestr((-42, 0))
1702 >>> datestr((-42, 0))
1699 'Wed Dec 31 23:59:18 1969 +0000'
1703 'Wed Dec 31 23:59:18 1969 +0000'
1700 >>> datestr((0x7fffffff, 0))
1704 >>> datestr((0x7fffffff, 0))
1701 'Tue Jan 19 03:14:07 2038 +0000'
1705 'Tue Jan 19 03:14:07 2038 +0000'
1702 >>> datestr((-0x80000000, 0))
1706 >>> datestr((-0x80000000, 0))
1703 'Fri Dec 13 20:45:52 1901 +0000'
1707 'Fri Dec 13 20:45:52 1901 +0000'
1704 """
1708 """
1705 t, tz = date or makedate()
1709 t, tz = date or makedate()
1706 if "%1" in format or "%2" in format or "%z" in format:
1710 if "%1" in format or "%2" in format or "%z" in format:
1707 sign = (tz > 0) and "-" or "+"
1711 sign = (tz > 0) and "-" or "+"
1708 minutes = abs(tz) // 60
1712 minutes = abs(tz) // 60
1709 q, r = divmod(minutes, 60)
1713 q, r = divmod(minutes, 60)
1710 format = format.replace("%z", "%1%2")
1714 format = format.replace("%z", "%1%2")
1711 format = format.replace("%1", "%c%02d" % (sign, q))
1715 format = format.replace("%1", "%c%02d" % (sign, q))
1712 format = format.replace("%2", "%02d" % r)
1716 format = format.replace("%2", "%02d" % r)
1713 d = t - tz
1717 d = t - tz
1714 if d > 0x7fffffff:
1718 if d > 0x7fffffff:
1715 d = 0x7fffffff
1719 d = 0x7fffffff
1716 elif d < -0x80000000:
1720 elif d < -0x80000000:
1717 d = -0x80000000
1721 d = -0x80000000
1718 # Never use time.gmtime() and datetime.datetime.fromtimestamp()
1722 # Never use time.gmtime() and datetime.datetime.fromtimestamp()
1719 # because they use the gmtime() system call which is buggy on Windows
1723 # because they use the gmtime() system call which is buggy on Windows
1720 # for negative values.
1724 # for negative values.
1721 t = datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=d)
1725 t = datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=d)
1722 s = t.strftime(format)
1726 s = t.strftime(format)
1723 return s
1727 return s
1724
1728
1725 def shortdate(date=None):
1729 def shortdate(date=None):
1726 """turn (timestamp, tzoff) tuple into iso 8631 date."""
1730 """turn (timestamp, tzoff) tuple into iso 8631 date."""
1727 return datestr(date, format='%Y-%m-%d')
1731 return datestr(date, format='%Y-%m-%d')
1728
1732
1729 def parsetimezone(tz):
1733 def parsetimezone(tz):
1730 """parse a timezone string and return an offset integer"""
1734 """parse a timezone string and return an offset integer"""
1731 if tz[0] in "+-" and len(tz) == 5 and tz[1:].isdigit():
1735 if tz[0] in "+-" and len(tz) == 5 and tz[1:].isdigit():
1732 sign = (tz[0] == "+") and 1 or -1
1736 sign = (tz[0] == "+") and 1 or -1
1733 hours = int(tz[1:3])
1737 hours = int(tz[1:3])
1734 minutes = int(tz[3:5])
1738 minutes = int(tz[3:5])
1735 return -sign * (hours * 60 + minutes) * 60
1739 return -sign * (hours * 60 + minutes) * 60
1736 if tz == "GMT" or tz == "UTC":
1740 if tz == "GMT" or tz == "UTC":
1737 return 0
1741 return 0
1738 return None
1742 return None
1739
1743
1740 def strdate(string, format, defaults=[]):
1744 def strdate(string, format, defaults=[]):
1741 """parse a localized time string and return a (unixtime, offset) tuple.
1745 """parse a localized time string and return a (unixtime, offset) tuple.
1742 if the string cannot be parsed, ValueError is raised."""
1746 if the string cannot be parsed, ValueError is raised."""
1743 # NOTE: unixtime = localunixtime + offset
1747 # NOTE: unixtime = localunixtime + offset
1744 offset, date = parsetimezone(string.split()[-1]), string
1748 offset, date = parsetimezone(string.split()[-1]), string
1745 if offset is not None:
1749 if offset is not None:
1746 date = " ".join(string.split()[:-1])
1750 date = " ".join(string.split()[:-1])
1747
1751
1748 # add missing elements from defaults
1752 # add missing elements from defaults
1749 usenow = False # default to using biased defaults
1753 usenow = False # default to using biased defaults
1750 for part in ("S", "M", "HI", "d", "mb", "yY"): # decreasing specificity
1754 for part in ("S", "M", "HI", "d", "mb", "yY"): # decreasing specificity
1751 found = [True for p in part if ("%"+p) in format]
1755 found = [True for p in part if ("%"+p) in format]
1752 if not found:
1756 if not found:
1753 date += "@" + defaults[part][usenow]
1757 date += "@" + defaults[part][usenow]
1754 format += "@%" + part[0]
1758 format += "@%" + part[0]
1755 else:
1759 else:
1756 # We've found a specific time element, less specific time
1760 # We've found a specific time element, less specific time
1757 # elements are relative to today
1761 # elements are relative to today
1758 usenow = True
1762 usenow = True
1759
1763
1760 timetuple = time.strptime(date, format)
1764 timetuple = time.strptime(date, format)
1761 localunixtime = int(calendar.timegm(timetuple))
1765 localunixtime = int(calendar.timegm(timetuple))
1762 if offset is None:
1766 if offset is None:
1763 # local timezone
1767 # local timezone
1764 unixtime = int(time.mktime(timetuple))
1768 unixtime = int(time.mktime(timetuple))
1765 offset = unixtime - localunixtime
1769 offset = unixtime - localunixtime
1766 else:
1770 else:
1767 unixtime = localunixtime + offset
1771 unixtime = localunixtime + offset
1768 return unixtime, offset
1772 return unixtime, offset
1769
1773
1770 def parsedate(date, formats=None, bias=None):
1774 def parsedate(date, formats=None, bias=None):
1771 """parse a localized date/time and return a (unixtime, offset) tuple.
1775 """parse a localized date/time and return a (unixtime, offset) tuple.
1772
1776
1773 The date may be a "unixtime offset" string or in one of the specified
1777 The date may be a "unixtime offset" string or in one of the specified
1774 formats. If the date already is a (unixtime, offset) tuple, it is returned.
1778 formats. If the date already is a (unixtime, offset) tuple, it is returned.
1775
1779
1776 >>> parsedate(' today ') == parsedate(\
1780 >>> parsedate(' today ') == parsedate(\
1777 datetime.date.today().strftime('%b %d'))
1781 datetime.date.today().strftime('%b %d'))
1778 True
1782 True
1779 >>> parsedate( 'yesterday ') == parsedate((datetime.date.today() -\
1783 >>> parsedate( 'yesterday ') == parsedate((datetime.date.today() -\
1780 datetime.timedelta(days=1)\
1784 datetime.timedelta(days=1)\
1781 ).strftime('%b %d'))
1785 ).strftime('%b %d'))
1782 True
1786 True
1783 >>> now, tz = makedate()
1787 >>> now, tz = makedate()
1784 >>> strnow, strtz = parsedate('now')
1788 >>> strnow, strtz = parsedate('now')
1785 >>> (strnow - now) < 1
1789 >>> (strnow - now) < 1
1786 True
1790 True
1787 >>> tz == strtz
1791 >>> tz == strtz
1788 True
1792 True
1789 """
1793 """
1790 if bias is None:
1794 if bias is None:
1791 bias = {}
1795 bias = {}
1792 if not date:
1796 if not date:
1793 return 0, 0
1797 return 0, 0
1794 if isinstance(date, tuple) and len(date) == 2:
1798 if isinstance(date, tuple) and len(date) == 2:
1795 return date
1799 return date
1796 if not formats:
1800 if not formats:
1797 formats = defaultdateformats
1801 formats = defaultdateformats
1798 date = date.strip()
1802 date = date.strip()
1799
1803
1800 if date == 'now' or date == _('now'):
1804 if date == 'now' or date == _('now'):
1801 return makedate()
1805 return makedate()
1802 if date == 'today' or date == _('today'):
1806 if date == 'today' or date == _('today'):
1803 date = datetime.date.today().strftime('%b %d')
1807 date = datetime.date.today().strftime('%b %d')
1804 elif date == 'yesterday' or date == _('yesterday'):
1808 elif date == 'yesterday' or date == _('yesterday'):
1805 date = (datetime.date.today() -
1809 date = (datetime.date.today() -
1806 datetime.timedelta(days=1)).strftime('%b %d')
1810 datetime.timedelta(days=1)).strftime('%b %d')
1807
1811
1808 try:
1812 try:
1809 when, offset = map(int, date.split(' '))
1813 when, offset = map(int, date.split(' '))
1810 except ValueError:
1814 except ValueError:
1811 # fill out defaults
1815 # fill out defaults
1812 now = makedate()
1816 now = makedate()
1813 defaults = {}
1817 defaults = {}
1814 for part in ("d", "mb", "yY", "HI", "M", "S"):
1818 for part in ("d", "mb", "yY", "HI", "M", "S"):
1815 # this piece is for rounding the specific end of unknowns
1819 # this piece is for rounding the specific end of unknowns
1816 b = bias.get(part)
1820 b = bias.get(part)
1817 if b is None:
1821 if b is None:
1818 if part[0] in "HMS":
1822 if part[0] in "HMS":
1819 b = "00"
1823 b = "00"
1820 else:
1824 else:
1821 b = "0"
1825 b = "0"
1822
1826
1823 # this piece is for matching the generic end to today's date
1827 # this piece is for matching the generic end to today's date
1824 n = datestr(now, "%" + part[0])
1828 n = datestr(now, "%" + part[0])
1825
1829
1826 defaults[part] = (b, n)
1830 defaults[part] = (b, n)
1827
1831
1828 for format in formats:
1832 for format in formats:
1829 try:
1833 try:
1830 when, offset = strdate(date, format, defaults)
1834 when, offset = strdate(date, format, defaults)
1831 except (ValueError, OverflowError):
1835 except (ValueError, OverflowError):
1832 pass
1836 pass
1833 else:
1837 else:
1834 break
1838 break
1835 else:
1839 else:
1836 raise Abort(_('invalid date: %r') % date)
1840 raise Abort(_('invalid date: %r') % date)
1837 # validate explicit (probably user-specified) date and
1841 # validate explicit (probably user-specified) date and
1838 # time zone offset. values must fit in signed 32 bits for
1842 # time zone offset. values must fit in signed 32 bits for
1839 # current 32-bit linux runtimes. timezones go from UTC-12
1843 # current 32-bit linux runtimes. timezones go from UTC-12
1840 # to UTC+14
1844 # to UTC+14
1841 if when < -0x80000000 or when > 0x7fffffff:
1845 if when < -0x80000000 or when > 0x7fffffff:
1842 raise Abort(_('date exceeds 32 bits: %d') % when)
1846 raise Abort(_('date exceeds 32 bits: %d') % when)
1843 if offset < -50400 or offset > 43200:
1847 if offset < -50400 or offset > 43200:
1844 raise Abort(_('impossible time zone offset: %d') % offset)
1848 raise Abort(_('impossible time zone offset: %d') % offset)
1845 return when, offset
1849 return when, offset
1846
1850
1847 def matchdate(date):
1851 def matchdate(date):
1848 """Return a function that matches a given date match specifier
1852 """Return a function that matches a given date match specifier
1849
1853
1850 Formats include:
1854 Formats include:
1851
1855
1852 '{date}' match a given date to the accuracy provided
1856 '{date}' match a given date to the accuracy provided
1853
1857
1854 '<{date}' on or before a given date
1858 '<{date}' on or before a given date
1855
1859
1856 '>{date}' on or after a given date
1860 '>{date}' on or after a given date
1857
1861
1858 >>> p1 = parsedate("10:29:59")
1862 >>> p1 = parsedate("10:29:59")
1859 >>> p2 = parsedate("10:30:00")
1863 >>> p2 = parsedate("10:30:00")
1860 >>> p3 = parsedate("10:30:59")
1864 >>> p3 = parsedate("10:30:59")
1861 >>> p4 = parsedate("10:31:00")
1865 >>> p4 = parsedate("10:31:00")
1862 >>> p5 = parsedate("Sep 15 10:30:00 1999")
1866 >>> p5 = parsedate("Sep 15 10:30:00 1999")
1863 >>> f = matchdate("10:30")
1867 >>> f = matchdate("10:30")
1864 >>> f(p1[0])
1868 >>> f(p1[0])
1865 False
1869 False
1866 >>> f(p2[0])
1870 >>> f(p2[0])
1867 True
1871 True
1868 >>> f(p3[0])
1872 >>> f(p3[0])
1869 True
1873 True
1870 >>> f(p4[0])
1874 >>> f(p4[0])
1871 False
1875 False
1872 >>> f(p5[0])
1876 >>> f(p5[0])
1873 False
1877 False
1874 """
1878 """
1875
1879
1876 def lower(date):
1880 def lower(date):
1877 d = {'mb': "1", 'd': "1"}
1881 d = {'mb': "1", 'd': "1"}
1878 return parsedate(date, extendeddateformats, d)[0]
1882 return parsedate(date, extendeddateformats, d)[0]
1879
1883
1880 def upper(date):
1884 def upper(date):
1881 d = {'mb': "12", 'HI': "23", 'M': "59", 'S': "59"}
1885 d = {'mb': "12", 'HI': "23", 'M': "59", 'S': "59"}
1882 for days in ("31", "30", "29"):
1886 for days in ("31", "30", "29"):
1883 try:
1887 try:
1884 d["d"] = days
1888 d["d"] = days
1885 return parsedate(date, extendeddateformats, d)[0]
1889 return parsedate(date, extendeddateformats, d)[0]
1886 except Abort:
1890 except Abort:
1887 pass
1891 pass
1888 d["d"] = "28"
1892 d["d"] = "28"
1889 return parsedate(date, extendeddateformats, d)[0]
1893 return parsedate(date, extendeddateformats, d)[0]
1890
1894
1891 date = date.strip()
1895 date = date.strip()
1892
1896
1893 if not date:
1897 if not date:
1894 raise Abort(_("dates cannot consist entirely of whitespace"))
1898 raise Abort(_("dates cannot consist entirely of whitespace"))
1895 elif date[0] == "<":
1899 elif date[0] == "<":
1896 if not date[1:]:
1900 if not date[1:]:
1897 raise Abort(_("invalid day spec, use '<DATE'"))
1901 raise Abort(_("invalid day spec, use '<DATE'"))
1898 when = upper(date[1:])
1902 when = upper(date[1:])
1899 return lambda x: x <= when
1903 return lambda x: x <= when
1900 elif date[0] == ">":
1904 elif date[0] == ">":
1901 if not date[1:]:
1905 if not date[1:]:
1902 raise Abort(_("invalid day spec, use '>DATE'"))
1906 raise Abort(_("invalid day spec, use '>DATE'"))
1903 when = lower(date[1:])
1907 when = lower(date[1:])
1904 return lambda x: x >= when
1908 return lambda x: x >= when
1905 elif date[0] == "-":
1909 elif date[0] == "-":
1906 try:
1910 try:
1907 days = int(date[1:])
1911 days = int(date[1:])
1908 except ValueError:
1912 except ValueError:
1909 raise Abort(_("invalid day spec: %s") % date[1:])
1913 raise Abort(_("invalid day spec: %s") % date[1:])
1910 if days < 0:
1914 if days < 0:
1911 raise Abort(_('%s must be nonnegative (see "hg help dates")')
1915 raise Abort(_('%s must be nonnegative (see "hg help dates")')
1912 % date[1:])
1916 % date[1:])
1913 when = makedate()[0] - days * 3600 * 24
1917 when = makedate()[0] - days * 3600 * 24
1914 return lambda x: x >= when
1918 return lambda x: x >= when
1915 elif " to " in date:
1919 elif " to " in date:
1916 a, b = date.split(" to ")
1920 a, b = date.split(" to ")
1917 start, stop = lower(a), upper(b)
1921 start, stop = lower(a), upper(b)
1918 return lambda x: x >= start and x <= stop
1922 return lambda x: x >= start and x <= stop
1919 else:
1923 else:
1920 start, stop = lower(date), upper(date)
1924 start, stop = lower(date), upper(date)
1921 return lambda x: x >= start and x <= stop
1925 return lambda x: x >= start and x <= stop
1922
1926
1923 def stringmatcher(pattern):
1927 def stringmatcher(pattern):
1924 """
1928 """
1925 accepts a string, possibly starting with 're:' or 'literal:' prefix.
1929 accepts a string, possibly starting with 're:' or 'literal:' prefix.
1926 returns the matcher name, pattern, and matcher function.
1930 returns the matcher name, pattern, and matcher function.
1927 missing or unknown prefixes are treated as literal matches.
1931 missing or unknown prefixes are treated as literal matches.
1928
1932
1929 helper for tests:
1933 helper for tests:
1930 >>> def test(pattern, *tests):
1934 >>> def test(pattern, *tests):
1931 ... kind, pattern, matcher = stringmatcher(pattern)
1935 ... kind, pattern, matcher = stringmatcher(pattern)
1932 ... return (kind, pattern, [bool(matcher(t)) for t in tests])
1936 ... return (kind, pattern, [bool(matcher(t)) for t in tests])
1933
1937
1934 exact matching (no prefix):
1938 exact matching (no prefix):
1935 >>> test('abcdefg', 'abc', 'def', 'abcdefg')
1939 >>> test('abcdefg', 'abc', 'def', 'abcdefg')
1936 ('literal', 'abcdefg', [False, False, True])
1940 ('literal', 'abcdefg', [False, False, True])
1937
1941
1938 regex matching ('re:' prefix)
1942 regex matching ('re:' prefix)
1939 >>> test('re:a.+b', 'nomatch', 'fooadef', 'fooadefbar')
1943 >>> test('re:a.+b', 'nomatch', 'fooadef', 'fooadefbar')
1940 ('re', 'a.+b', [False, False, True])
1944 ('re', 'a.+b', [False, False, True])
1941
1945
1942 force exact matches ('literal:' prefix)
1946 force exact matches ('literal:' prefix)
1943 >>> test('literal:re:foobar', 'foobar', 're:foobar')
1947 >>> test('literal:re:foobar', 'foobar', 're:foobar')
1944 ('literal', 're:foobar', [False, True])
1948 ('literal', 're:foobar', [False, True])
1945
1949
1946 unknown prefixes are ignored and treated as literals
1950 unknown prefixes are ignored and treated as literals
1947 >>> test('foo:bar', 'foo', 'bar', 'foo:bar')
1951 >>> test('foo:bar', 'foo', 'bar', 'foo:bar')
1948 ('literal', 'foo:bar', [False, False, True])
1952 ('literal', 'foo:bar', [False, False, True])
1949 """
1953 """
1950 if pattern.startswith('re:'):
1954 if pattern.startswith('re:'):
1951 pattern = pattern[3:]
1955 pattern = pattern[3:]
1952 try:
1956 try:
1953 regex = remod.compile(pattern)
1957 regex = remod.compile(pattern)
1954 except remod.error as e:
1958 except remod.error as e:
1955 raise error.ParseError(_('invalid regular expression: %s')
1959 raise error.ParseError(_('invalid regular expression: %s')
1956 % e)
1960 % e)
1957 return 're', pattern, regex.search
1961 return 're', pattern, regex.search
1958 elif pattern.startswith('literal:'):
1962 elif pattern.startswith('literal:'):
1959 pattern = pattern[8:]
1963 pattern = pattern[8:]
1960 return 'literal', pattern, pattern.__eq__
1964 return 'literal', pattern, pattern.__eq__
1961
1965
1962 def shortuser(user):
1966 def shortuser(user):
1963 """Return a short representation of a user name or email address."""
1967 """Return a short representation of a user name or email address."""
1964 f = user.find('@')
1968 f = user.find('@')
1965 if f >= 0:
1969 if f >= 0:
1966 user = user[:f]
1970 user = user[:f]
1967 f = user.find('<')
1971 f = user.find('<')
1968 if f >= 0:
1972 if f >= 0:
1969 user = user[f + 1:]
1973 user = user[f + 1:]
1970 f = user.find(' ')
1974 f = user.find(' ')
1971 if f >= 0:
1975 if f >= 0:
1972 user = user[:f]
1976 user = user[:f]
1973 f = user.find('.')
1977 f = user.find('.')
1974 if f >= 0:
1978 if f >= 0:
1975 user = user[:f]
1979 user = user[:f]
1976 return user
1980 return user
1977
1981
1978 def emailuser(user):
1982 def emailuser(user):
1979 """Return the user portion of an email address."""
1983 """Return the user portion of an email address."""
1980 f = user.find('@')
1984 f = user.find('@')
1981 if f >= 0:
1985 if f >= 0:
1982 user = user[:f]
1986 user = user[:f]
1983 f = user.find('<')
1987 f = user.find('<')
1984 if f >= 0:
1988 if f >= 0:
1985 user = user[f + 1:]
1989 user = user[f + 1:]
1986 return user
1990 return user
1987
1991
1988 def email(author):
1992 def email(author):
1989 '''get email of author.'''
1993 '''get email of author.'''
1990 r = author.find('>')
1994 r = author.find('>')
1991 if r == -1:
1995 if r == -1:
1992 r = None
1996 r = None
1993 return author[author.find('<') + 1:r]
1997 return author[author.find('<') + 1:r]
1994
1998
1995 def ellipsis(text, maxlength=400):
1999 def ellipsis(text, maxlength=400):
1996 """Trim string to at most maxlength (default: 400) columns in display."""
2000 """Trim string to at most maxlength (default: 400) columns in display."""
1997 return encoding.trim(text, maxlength, ellipsis='...')
2001 return encoding.trim(text, maxlength, ellipsis='...')
1998
2002
1999 def unitcountfn(*unittable):
2003 def unitcountfn(*unittable):
2000 '''return a function that renders a readable count of some quantity'''
2004 '''return a function that renders a readable count of some quantity'''
2001
2005
2002 def go(count):
2006 def go(count):
2003 for multiplier, divisor, format in unittable:
2007 for multiplier, divisor, format in unittable:
2004 if count >= divisor * multiplier:
2008 if count >= divisor * multiplier:
2005 return format % (count / float(divisor))
2009 return format % (count / float(divisor))
2006 return unittable[-1][2] % count
2010 return unittable[-1][2] % count
2007
2011
2008 return go
2012 return go
2009
2013
2010 bytecount = unitcountfn(
2014 bytecount = unitcountfn(
2011 (100, 1 << 30, _('%.0f GB')),
2015 (100, 1 << 30, _('%.0f GB')),
2012 (10, 1 << 30, _('%.1f GB')),
2016 (10, 1 << 30, _('%.1f GB')),
2013 (1, 1 << 30, _('%.2f GB')),
2017 (1, 1 << 30, _('%.2f GB')),
2014 (100, 1 << 20, _('%.0f MB')),
2018 (100, 1 << 20, _('%.0f MB')),
2015 (10, 1 << 20, _('%.1f MB')),
2019 (10, 1 << 20, _('%.1f MB')),
2016 (1, 1 << 20, _('%.2f MB')),
2020 (1, 1 << 20, _('%.2f MB')),
2017 (100, 1 << 10, _('%.0f KB')),
2021 (100, 1 << 10, _('%.0f KB')),
2018 (10, 1 << 10, _('%.1f KB')),
2022 (10, 1 << 10, _('%.1f KB')),
2019 (1, 1 << 10, _('%.2f KB')),
2023 (1, 1 << 10, _('%.2f KB')),
2020 (1, 1, _('%.0f bytes')),
2024 (1, 1, _('%.0f bytes')),
2021 )
2025 )
2022
2026
2023 def uirepr(s):
2027 def uirepr(s):
2024 # Avoid double backslash in Windows path repr()
2028 # Avoid double backslash in Windows path repr()
2025 return repr(s).replace('\\\\', '\\')
2029 return repr(s).replace('\\\\', '\\')
2026
2030
2027 # delay import of textwrap
2031 # delay import of textwrap
2028 def MBTextWrapper(**kwargs):
2032 def MBTextWrapper(**kwargs):
2029 class tw(textwrap.TextWrapper):
2033 class tw(textwrap.TextWrapper):
2030 """
2034 """
2031 Extend TextWrapper for width-awareness.
2035 Extend TextWrapper for width-awareness.
2032
2036
2033 Neither number of 'bytes' in any encoding nor 'characters' is
2037 Neither number of 'bytes' in any encoding nor 'characters' is
2034 appropriate to calculate terminal columns for specified string.
2038 appropriate to calculate terminal columns for specified string.
2035
2039
2036 Original TextWrapper implementation uses built-in 'len()' directly,
2040 Original TextWrapper implementation uses built-in 'len()' directly,
2037 so overriding is needed to use width information of each characters.
2041 so overriding is needed to use width information of each characters.
2038
2042
2039 In addition, characters classified into 'ambiguous' width are
2043 In addition, characters classified into 'ambiguous' width are
2040 treated as wide in East Asian area, but as narrow in other.
2044 treated as wide in East Asian area, but as narrow in other.
2041
2045
2042 This requires use decision to determine width of such characters.
2046 This requires use decision to determine width of such characters.
2043 """
2047 """
2044 def _cutdown(self, ucstr, space_left):
2048 def _cutdown(self, ucstr, space_left):
2045 l = 0
2049 l = 0
2046 colwidth = encoding.ucolwidth
2050 colwidth = encoding.ucolwidth
2047 for i in xrange(len(ucstr)):
2051 for i in xrange(len(ucstr)):
2048 l += colwidth(ucstr[i])
2052 l += colwidth(ucstr[i])
2049 if space_left < l:
2053 if space_left < l:
2050 return (ucstr[:i], ucstr[i:])
2054 return (ucstr[:i], ucstr[i:])
2051 return ucstr, ''
2055 return ucstr, ''
2052
2056
2053 # overriding of base class
2057 # overriding of base class
2054 def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
2058 def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
2055 space_left = max(width - cur_len, 1)
2059 space_left = max(width - cur_len, 1)
2056
2060
2057 if self.break_long_words:
2061 if self.break_long_words:
2058 cut, res = self._cutdown(reversed_chunks[-1], space_left)
2062 cut, res = self._cutdown(reversed_chunks[-1], space_left)
2059 cur_line.append(cut)
2063 cur_line.append(cut)
2060 reversed_chunks[-1] = res
2064 reversed_chunks[-1] = res
2061 elif not cur_line:
2065 elif not cur_line:
2062 cur_line.append(reversed_chunks.pop())
2066 cur_line.append(reversed_chunks.pop())
2063
2067
2064 # this overriding code is imported from TextWrapper of Python 2.6
2068 # this overriding code is imported from TextWrapper of Python 2.6
2065 # to calculate columns of string by 'encoding.ucolwidth()'
2069 # to calculate columns of string by 'encoding.ucolwidth()'
2066 def _wrap_chunks(self, chunks):
2070 def _wrap_chunks(self, chunks):
2067 colwidth = encoding.ucolwidth
2071 colwidth = encoding.ucolwidth
2068
2072
2069 lines = []
2073 lines = []
2070 if self.width <= 0:
2074 if self.width <= 0:
2071 raise ValueError("invalid width %r (must be > 0)" % self.width)
2075 raise ValueError("invalid width %r (must be > 0)" % self.width)
2072
2076
2073 # Arrange in reverse order so items can be efficiently popped
2077 # Arrange in reverse order so items can be efficiently popped
2074 # from a stack of chucks.
2078 # from a stack of chucks.
2075 chunks.reverse()
2079 chunks.reverse()
2076
2080
2077 while chunks:
2081 while chunks:
2078
2082
2079 # Start the list of chunks that will make up the current line.
2083 # Start the list of chunks that will make up the current line.
2080 # cur_len is just the length of all the chunks in cur_line.
2084 # cur_len is just the length of all the chunks in cur_line.
2081 cur_line = []
2085 cur_line = []
2082 cur_len = 0
2086 cur_len = 0
2083
2087
2084 # Figure out which static string will prefix this line.
2088 # Figure out which static string will prefix this line.
2085 if lines:
2089 if lines:
2086 indent = self.subsequent_indent
2090 indent = self.subsequent_indent
2087 else:
2091 else:
2088 indent = self.initial_indent
2092 indent = self.initial_indent
2089
2093
2090 # Maximum width for this line.
2094 # Maximum width for this line.
2091 width = self.width - len(indent)
2095 width = self.width - len(indent)
2092
2096
2093 # First chunk on line is whitespace -- drop it, unless this
2097 # First chunk on line is whitespace -- drop it, unless this
2094 # is the very beginning of the text (i.e. no lines started yet).
2098 # is the very beginning of the text (i.e. no lines started yet).
2095 if self.drop_whitespace and chunks[-1].strip() == '' and lines:
2099 if self.drop_whitespace and chunks[-1].strip() == '' and lines:
2096 del chunks[-1]
2100 del chunks[-1]
2097
2101
2098 while chunks:
2102 while chunks:
2099 l = colwidth(chunks[-1])
2103 l = colwidth(chunks[-1])
2100
2104
2101 # Can at least squeeze this chunk onto the current line.
2105 # Can at least squeeze this chunk onto the current line.
2102 if cur_len + l <= width:
2106 if cur_len + l <= width:
2103 cur_line.append(chunks.pop())
2107 cur_line.append(chunks.pop())
2104 cur_len += l
2108 cur_len += l
2105
2109
2106 # Nope, this line is full.
2110 # Nope, this line is full.
2107 else:
2111 else:
2108 break
2112 break
2109
2113
2110 # The current line is full, and the next chunk is too big to
2114 # The current line is full, and the next chunk is too big to
2111 # fit on *any* line (not just this one).
2115 # fit on *any* line (not just this one).
2112 if chunks and colwidth(chunks[-1]) > width:
2116 if chunks and colwidth(chunks[-1]) > width:
2113 self._handle_long_word(chunks, cur_line, cur_len, width)
2117 self._handle_long_word(chunks, cur_line, cur_len, width)
2114
2118
2115 # If the last chunk on this line is all whitespace, drop it.
2119 # If the last chunk on this line is all whitespace, drop it.
2116 if (self.drop_whitespace and
2120 if (self.drop_whitespace and
2117 cur_line and cur_line[-1].strip() == ''):
2121 cur_line and cur_line[-1].strip() == ''):
2118 del cur_line[-1]
2122 del cur_line[-1]
2119
2123
2120 # Convert current line back to a string and store it in list
2124 # Convert current line back to a string and store it in list
2121 # of all lines (return value).
2125 # of all lines (return value).
2122 if cur_line:
2126 if cur_line:
2123 lines.append(indent + ''.join(cur_line))
2127 lines.append(indent + ''.join(cur_line))
2124
2128
2125 return lines
2129 return lines
2126
2130
2127 global MBTextWrapper
2131 global MBTextWrapper
2128 MBTextWrapper = tw
2132 MBTextWrapper = tw
2129 return tw(**kwargs)
2133 return tw(**kwargs)
2130
2134
2131 def wrap(line, width, initindent='', hangindent=''):
2135 def wrap(line, width, initindent='', hangindent=''):
2132 maxindent = max(len(hangindent), len(initindent))
2136 maxindent = max(len(hangindent), len(initindent))
2133 if width <= maxindent:
2137 if width <= maxindent:
2134 # adjust for weird terminal size
2138 # adjust for weird terminal size
2135 width = max(78, maxindent + 1)
2139 width = max(78, maxindent + 1)
2136 line = line.decode(encoding.encoding, encoding.encodingmode)
2140 line = line.decode(encoding.encoding, encoding.encodingmode)
2137 initindent = initindent.decode(encoding.encoding, encoding.encodingmode)
2141 initindent = initindent.decode(encoding.encoding, encoding.encodingmode)
2138 hangindent = hangindent.decode(encoding.encoding, encoding.encodingmode)
2142 hangindent = hangindent.decode(encoding.encoding, encoding.encodingmode)
2139 wrapper = MBTextWrapper(width=width,
2143 wrapper = MBTextWrapper(width=width,
2140 initial_indent=initindent,
2144 initial_indent=initindent,
2141 subsequent_indent=hangindent)
2145 subsequent_indent=hangindent)
2142 return wrapper.fill(line).encode(encoding.encoding)
2146 return wrapper.fill(line).encode(encoding.encoding)
2143
2147
2144 def iterlines(iterator):
2148 def iterlines(iterator):
2145 for chunk in iterator:
2149 for chunk in iterator:
2146 for line in chunk.splitlines():
2150 for line in chunk.splitlines():
2147 yield line
2151 yield line
2148
2152
2149 def expandpath(path):
2153 def expandpath(path):
2150 return os.path.expanduser(os.path.expandvars(path))
2154 return os.path.expanduser(os.path.expandvars(path))
2151
2155
2152 def hgcmd():
2156 def hgcmd():
2153 """Return the command used to execute current hg
2157 """Return the command used to execute current hg
2154
2158
2155 This is different from hgexecutable() because on Windows we want
2159 This is different from hgexecutable() because on Windows we want
2156 to avoid things opening new shell windows like batch files, so we
2160 to avoid things opening new shell windows like batch files, so we
2157 get either the python call or current executable.
2161 get either the python call or current executable.
2158 """
2162 """
2159 if mainfrozen():
2163 if mainfrozen():
2160 if getattr(sys, 'frozen', None) == 'macosx_app':
2164 if getattr(sys, 'frozen', None) == 'macosx_app':
2161 # Env variable set by py2app
2165 # Env variable set by py2app
2162 return [os.environ['EXECUTABLEPATH']]
2166 return [os.environ['EXECUTABLEPATH']]
2163 else:
2167 else:
2164 return [sys.executable]
2168 return [sys.executable]
2165 return gethgcmd()
2169 return gethgcmd()
2166
2170
2167 def rundetached(args, condfn):
2171 def rundetached(args, condfn):
2168 """Execute the argument list in a detached process.
2172 """Execute the argument list in a detached process.
2169
2173
2170 condfn is a callable which is called repeatedly and should return
2174 condfn is a callable which is called repeatedly and should return
2171 True once the child process is known to have started successfully.
2175 True once the child process is known to have started successfully.
2172 At this point, the child process PID is returned. If the child
2176 At this point, the child process PID is returned. If the child
2173 process fails to start or finishes before condfn() evaluates to
2177 process fails to start or finishes before condfn() evaluates to
2174 True, return -1.
2178 True, return -1.
2175 """
2179 """
2176 # Windows case is easier because the child process is either
2180 # Windows case is easier because the child process is either
2177 # successfully starting and validating the condition or exiting
2181 # successfully starting and validating the condition or exiting
2178 # on failure. We just poll on its PID. On Unix, if the child
2182 # on failure. We just poll on its PID. On Unix, if the child
2179 # process fails to start, it will be left in a zombie state until
2183 # process fails to start, it will be left in a zombie state until
2180 # the parent wait on it, which we cannot do since we expect a long
2184 # the parent wait on it, which we cannot do since we expect a long
2181 # running process on success. Instead we listen for SIGCHLD telling
2185 # running process on success. Instead we listen for SIGCHLD telling
2182 # us our child process terminated.
2186 # us our child process terminated.
2183 terminated = set()
2187 terminated = set()
2184 def handler(signum, frame):
2188 def handler(signum, frame):
2185 terminated.add(os.wait())
2189 terminated.add(os.wait())
2186 prevhandler = None
2190 prevhandler = None
2187 SIGCHLD = getattr(signal, 'SIGCHLD', None)
2191 SIGCHLD = getattr(signal, 'SIGCHLD', None)
2188 if SIGCHLD is not None:
2192 if SIGCHLD is not None:
2189 prevhandler = signal.signal(SIGCHLD, handler)
2193 prevhandler = signal.signal(SIGCHLD, handler)
2190 try:
2194 try:
2191 pid = spawndetached(args)
2195 pid = spawndetached(args)
2192 while not condfn():
2196 while not condfn():
2193 if ((pid in terminated or not testpid(pid))
2197 if ((pid in terminated or not testpid(pid))
2194 and not condfn()):
2198 and not condfn()):
2195 return -1
2199 return -1
2196 time.sleep(0.1)
2200 time.sleep(0.1)
2197 return pid
2201 return pid
2198 finally:
2202 finally:
2199 if prevhandler is not None:
2203 if prevhandler is not None:
2200 signal.signal(signal.SIGCHLD, prevhandler)
2204 signal.signal(signal.SIGCHLD, prevhandler)
2201
2205
2202 def interpolate(prefix, mapping, s, fn=None, escape_prefix=False):
2206 def interpolate(prefix, mapping, s, fn=None, escape_prefix=False):
2203 """Return the result of interpolating items in the mapping into string s.
2207 """Return the result of interpolating items in the mapping into string s.
2204
2208
2205 prefix is a single character string, or a two character string with
2209 prefix is a single character string, or a two character string with
2206 a backslash as the first character if the prefix needs to be escaped in
2210 a backslash as the first character if the prefix needs to be escaped in
2207 a regular expression.
2211 a regular expression.
2208
2212
2209 fn is an optional function that will be applied to the replacement text
2213 fn is an optional function that will be applied to the replacement text
2210 just before replacement.
2214 just before replacement.
2211
2215
2212 escape_prefix is an optional flag that allows using doubled prefix for
2216 escape_prefix is an optional flag that allows using doubled prefix for
2213 its escaping.
2217 its escaping.
2214 """
2218 """
2215 fn = fn or (lambda s: s)
2219 fn = fn or (lambda s: s)
2216 patterns = '|'.join(mapping.keys())
2220 patterns = '|'.join(mapping.keys())
2217 if escape_prefix:
2221 if escape_prefix:
2218 patterns += '|' + prefix
2222 patterns += '|' + prefix
2219 if len(prefix) > 1:
2223 if len(prefix) > 1:
2220 prefix_char = prefix[1:]
2224 prefix_char = prefix[1:]
2221 else:
2225 else:
2222 prefix_char = prefix
2226 prefix_char = prefix
2223 mapping[prefix_char] = prefix_char
2227 mapping[prefix_char] = prefix_char
2224 r = remod.compile(r'%s(%s)' % (prefix, patterns))
2228 r = remod.compile(r'%s(%s)' % (prefix, patterns))
2225 return r.sub(lambda x: fn(mapping[x.group()[1:]]), s)
2229 return r.sub(lambda x: fn(mapping[x.group()[1:]]), s)
2226
2230
2227 def getport(port):
2231 def getport(port):
2228 """Return the port for a given network service.
2232 """Return the port for a given network service.
2229
2233
2230 If port is an integer, it's returned as is. If it's a string, it's
2234 If port is an integer, it's returned as is. If it's a string, it's
2231 looked up using socket.getservbyname(). If there's no matching
2235 looked up using socket.getservbyname(). If there's no matching
2232 service, error.Abort is raised.
2236 service, error.Abort is raised.
2233 """
2237 """
2234 try:
2238 try:
2235 return int(port)
2239 return int(port)
2236 except ValueError:
2240 except ValueError:
2237 pass
2241 pass
2238
2242
2239 try:
2243 try:
2240 return socket.getservbyname(port)
2244 return socket.getservbyname(port)
2241 except socket.error:
2245 except socket.error:
2242 raise Abort(_("no port number associated with service '%s'") % port)
2246 raise Abort(_("no port number associated with service '%s'") % port)
2243
2247
2244 _booleans = {'1': True, 'yes': True, 'true': True, 'on': True, 'always': True,
2248 _booleans = {'1': True, 'yes': True, 'true': True, 'on': True, 'always': True,
2245 '0': False, 'no': False, 'false': False, 'off': False,
2249 '0': False, 'no': False, 'false': False, 'off': False,
2246 'never': False}
2250 'never': False}
2247
2251
2248 def parsebool(s):
2252 def parsebool(s):
2249 """Parse s into a boolean.
2253 """Parse s into a boolean.
2250
2254
2251 If s is not a valid boolean, returns None.
2255 If s is not a valid boolean, returns None.
2252 """
2256 """
2253 return _booleans.get(s.lower(), None)
2257 return _booleans.get(s.lower(), None)
2254
2258
2255 _hexdig = '0123456789ABCDEFabcdef'
2259 _hexdig = '0123456789ABCDEFabcdef'
2256 _hextochr = dict((a + b, chr(int(a + b, 16)))
2260 _hextochr = dict((a + b, chr(int(a + b, 16)))
2257 for a in _hexdig for b in _hexdig)
2261 for a in _hexdig for b in _hexdig)
2258
2262
2259 def _urlunquote(s):
2263 def _urlunquote(s):
2260 """Decode HTTP/HTML % encoding.
2264 """Decode HTTP/HTML % encoding.
2261
2265
2262 >>> _urlunquote('abc%20def')
2266 >>> _urlunquote('abc%20def')
2263 'abc def'
2267 'abc def'
2264 """
2268 """
2265 res = s.split('%')
2269 res = s.split('%')
2266 # fastpath
2270 # fastpath
2267 if len(res) == 1:
2271 if len(res) == 1:
2268 return s
2272 return s
2269 s = res[0]
2273 s = res[0]
2270 for item in res[1:]:
2274 for item in res[1:]:
2271 try:
2275 try:
2272 s += _hextochr[item[:2]] + item[2:]
2276 s += _hextochr[item[:2]] + item[2:]
2273 except KeyError:
2277 except KeyError:
2274 s += '%' + item
2278 s += '%' + item
2275 except UnicodeDecodeError:
2279 except UnicodeDecodeError:
2276 s += unichr(int(item[:2], 16)) + item[2:]
2280 s += unichr(int(item[:2], 16)) + item[2:]
2277 return s
2281 return s
2278
2282
2279 class url(object):
2283 class url(object):
2280 r"""Reliable URL parser.
2284 r"""Reliable URL parser.
2281
2285
2282 This parses URLs and provides attributes for the following
2286 This parses URLs and provides attributes for the following
2283 components:
2287 components:
2284
2288
2285 <scheme>://<user>:<passwd>@<host>:<port>/<path>?<query>#<fragment>
2289 <scheme>://<user>:<passwd>@<host>:<port>/<path>?<query>#<fragment>
2286
2290
2287 Missing components are set to None. The only exception is
2291 Missing components are set to None. The only exception is
2288 fragment, which is set to '' if present but empty.
2292 fragment, which is set to '' if present but empty.
2289
2293
2290 If parsefragment is False, fragment is included in query. If
2294 If parsefragment is False, fragment is included in query. If
2291 parsequery is False, query is included in path. If both are
2295 parsequery is False, query is included in path. If both are
2292 False, both fragment and query are included in path.
2296 False, both fragment and query are included in path.
2293
2297
2294 See http://www.ietf.org/rfc/rfc2396.txt for more information.
2298 See http://www.ietf.org/rfc/rfc2396.txt for more information.
2295
2299
2296 Note that for backward compatibility reasons, bundle URLs do not
2300 Note that for backward compatibility reasons, bundle URLs do not
2297 take host names. That means 'bundle://../' has a path of '../'.
2301 take host names. That means 'bundle://../' has a path of '../'.
2298
2302
2299 Examples:
2303 Examples:
2300
2304
2301 >>> url('http://www.ietf.org/rfc/rfc2396.txt')
2305 >>> url('http://www.ietf.org/rfc/rfc2396.txt')
2302 <url scheme: 'http', host: 'www.ietf.org', path: 'rfc/rfc2396.txt'>
2306 <url scheme: 'http', host: 'www.ietf.org', path: 'rfc/rfc2396.txt'>
2303 >>> url('ssh://[::1]:2200//home/joe/repo')
2307 >>> url('ssh://[::1]:2200//home/joe/repo')
2304 <url scheme: 'ssh', host: '[::1]', port: '2200', path: '/home/joe/repo'>
2308 <url scheme: 'ssh', host: '[::1]', port: '2200', path: '/home/joe/repo'>
2305 >>> url('file:///home/joe/repo')
2309 >>> url('file:///home/joe/repo')
2306 <url scheme: 'file', path: '/home/joe/repo'>
2310 <url scheme: 'file', path: '/home/joe/repo'>
2307 >>> url('file:///c:/temp/foo/')
2311 >>> url('file:///c:/temp/foo/')
2308 <url scheme: 'file', path: 'c:/temp/foo/'>
2312 <url scheme: 'file', path: 'c:/temp/foo/'>
2309 >>> url('bundle:foo')
2313 >>> url('bundle:foo')
2310 <url scheme: 'bundle', path: 'foo'>
2314 <url scheme: 'bundle', path: 'foo'>
2311 >>> url('bundle://../foo')
2315 >>> url('bundle://../foo')
2312 <url scheme: 'bundle', path: '../foo'>
2316 <url scheme: 'bundle', path: '../foo'>
2313 >>> url(r'c:\foo\bar')
2317 >>> url(r'c:\foo\bar')
2314 <url path: 'c:\\foo\\bar'>
2318 <url path: 'c:\\foo\\bar'>
2315 >>> url(r'\\blah\blah\blah')
2319 >>> url(r'\\blah\blah\blah')
2316 <url path: '\\\\blah\\blah\\blah'>
2320 <url path: '\\\\blah\\blah\\blah'>
2317 >>> url(r'\\blah\blah\blah#baz')
2321 >>> url(r'\\blah\blah\blah#baz')
2318 <url path: '\\\\blah\\blah\\blah', fragment: 'baz'>
2322 <url path: '\\\\blah\\blah\\blah', fragment: 'baz'>
2319 >>> url(r'file:///C:\users\me')
2323 >>> url(r'file:///C:\users\me')
2320 <url scheme: 'file', path: 'C:\\users\\me'>
2324 <url scheme: 'file', path: 'C:\\users\\me'>
2321
2325
2322 Authentication credentials:
2326 Authentication credentials:
2323
2327
2324 >>> url('ssh://joe:xyz@x/repo')
2328 >>> url('ssh://joe:xyz@x/repo')
2325 <url scheme: 'ssh', user: 'joe', passwd: 'xyz', host: 'x', path: 'repo'>
2329 <url scheme: 'ssh', user: 'joe', passwd: 'xyz', host: 'x', path: 'repo'>
2326 >>> url('ssh://joe@x/repo')
2330 >>> url('ssh://joe@x/repo')
2327 <url scheme: 'ssh', user: 'joe', host: 'x', path: 'repo'>
2331 <url scheme: 'ssh', user: 'joe', host: 'x', path: 'repo'>
2328
2332
2329 Query strings and fragments:
2333 Query strings and fragments:
2330
2334
2331 >>> url('http://host/a?b#c')
2335 >>> url('http://host/a?b#c')
2332 <url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'>
2336 <url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'>
2333 >>> url('http://host/a?b#c', parsequery=False, parsefragment=False)
2337 >>> url('http://host/a?b#c', parsequery=False, parsefragment=False)
2334 <url scheme: 'http', host: 'host', path: 'a?b#c'>
2338 <url scheme: 'http', host: 'host', path: 'a?b#c'>
2335 """
2339 """
2336
2340
2337 _safechars = "!~*'()+"
2341 _safechars = "!~*'()+"
2338 _safepchars = "/!~*'()+:\\"
2342 _safepchars = "/!~*'()+:\\"
2339 _matchscheme = remod.compile(r'^[a-zA-Z0-9+.\-]+:').match
2343 _matchscheme = remod.compile(r'^[a-zA-Z0-9+.\-]+:').match
2340
2344
2341 def __init__(self, path, parsequery=True, parsefragment=True):
2345 def __init__(self, path, parsequery=True, parsefragment=True):
2342 # We slowly chomp away at path until we have only the path left
2346 # We slowly chomp away at path until we have only the path left
2343 self.scheme = self.user = self.passwd = self.host = None
2347 self.scheme = self.user = self.passwd = self.host = None
2344 self.port = self.path = self.query = self.fragment = None
2348 self.port = self.path = self.query = self.fragment = None
2345 self._localpath = True
2349 self._localpath = True
2346 self._hostport = ''
2350 self._hostport = ''
2347 self._origpath = path
2351 self._origpath = path
2348
2352
2349 if parsefragment and '#' in path:
2353 if parsefragment and '#' in path:
2350 path, self.fragment = path.split('#', 1)
2354 path, self.fragment = path.split('#', 1)
2351 if not path:
2355 if not path:
2352 path = None
2356 path = None
2353
2357
2354 # special case for Windows drive letters and UNC paths
2358 # special case for Windows drive letters and UNC paths
2355 if hasdriveletter(path) or path.startswith(r'\\'):
2359 if hasdriveletter(path) or path.startswith(r'\\'):
2356 self.path = path
2360 self.path = path
2357 return
2361 return
2358
2362
2359 # For compatibility reasons, we can't handle bundle paths as
2363 # For compatibility reasons, we can't handle bundle paths as
2360 # normal URLS
2364 # normal URLS
2361 if path.startswith('bundle:'):
2365 if path.startswith('bundle:'):
2362 self.scheme = 'bundle'
2366 self.scheme = 'bundle'
2363 path = path[7:]
2367 path = path[7:]
2364 if path.startswith('//'):
2368 if path.startswith('//'):
2365 path = path[2:]
2369 path = path[2:]
2366 self.path = path
2370 self.path = path
2367 return
2371 return
2368
2372
2369 if self._matchscheme(path):
2373 if self._matchscheme(path):
2370 parts = path.split(':', 1)
2374 parts = path.split(':', 1)
2371 if parts[0]:
2375 if parts[0]:
2372 self.scheme, path = parts
2376 self.scheme, path = parts
2373 self._localpath = False
2377 self._localpath = False
2374
2378
2375 if not path:
2379 if not path:
2376 path = None
2380 path = None
2377 if self._localpath:
2381 if self._localpath:
2378 self.path = ''
2382 self.path = ''
2379 return
2383 return
2380 else:
2384 else:
2381 if self._localpath:
2385 if self._localpath:
2382 self.path = path
2386 self.path = path
2383 return
2387 return
2384
2388
2385 if parsequery and '?' in path:
2389 if parsequery and '?' in path:
2386 path, self.query = path.split('?', 1)
2390 path, self.query = path.split('?', 1)
2387 if not path:
2391 if not path:
2388 path = None
2392 path = None
2389 if not self.query:
2393 if not self.query:
2390 self.query = None
2394 self.query = None
2391
2395
2392 # // is required to specify a host/authority
2396 # // is required to specify a host/authority
2393 if path and path.startswith('//'):
2397 if path and path.startswith('//'):
2394 parts = path[2:].split('/', 1)
2398 parts = path[2:].split('/', 1)
2395 if len(parts) > 1:
2399 if len(parts) > 1:
2396 self.host, path = parts
2400 self.host, path = parts
2397 else:
2401 else:
2398 self.host = parts[0]
2402 self.host = parts[0]
2399 path = None
2403 path = None
2400 if not self.host:
2404 if not self.host:
2401 self.host = None
2405 self.host = None
2402 # path of file:///d is /d
2406 # path of file:///d is /d
2403 # path of file:///d:/ is d:/, not /d:/
2407 # path of file:///d:/ is d:/, not /d:/
2404 if path and not hasdriveletter(path):
2408 if path and not hasdriveletter(path):
2405 path = '/' + path
2409 path = '/' + path
2406
2410
2407 if self.host and '@' in self.host:
2411 if self.host and '@' in self.host:
2408 self.user, self.host = self.host.rsplit('@', 1)
2412 self.user, self.host = self.host.rsplit('@', 1)
2409 if ':' in self.user:
2413 if ':' in self.user:
2410 self.user, self.passwd = self.user.split(':', 1)
2414 self.user, self.passwd = self.user.split(':', 1)
2411 if not self.host:
2415 if not self.host:
2412 self.host = None
2416 self.host = None
2413
2417
2414 # Don't split on colons in IPv6 addresses without ports
2418 # Don't split on colons in IPv6 addresses without ports
2415 if (self.host and ':' in self.host and
2419 if (self.host and ':' in self.host and
2416 not (self.host.startswith('[') and self.host.endswith(']'))):
2420 not (self.host.startswith('[') and self.host.endswith(']'))):
2417 self._hostport = self.host
2421 self._hostport = self.host
2418 self.host, self.port = self.host.rsplit(':', 1)
2422 self.host, self.port = self.host.rsplit(':', 1)
2419 if not self.host:
2423 if not self.host:
2420 self.host = None
2424 self.host = None
2421
2425
2422 if (self.host and self.scheme == 'file' and
2426 if (self.host and self.scheme == 'file' and
2423 self.host not in ('localhost', '127.0.0.1', '[::1]')):
2427 self.host not in ('localhost', '127.0.0.1', '[::1]')):
2424 raise Abort(_('file:// URLs can only refer to localhost'))
2428 raise Abort(_('file:// URLs can only refer to localhost'))
2425
2429
2426 self.path = path
2430 self.path = path
2427
2431
2428 # leave the query string escaped
2432 # leave the query string escaped
2429 for a in ('user', 'passwd', 'host', 'port',
2433 for a in ('user', 'passwd', 'host', 'port',
2430 'path', 'fragment'):
2434 'path', 'fragment'):
2431 v = getattr(self, a)
2435 v = getattr(self, a)
2432 if v is not None:
2436 if v is not None:
2433 setattr(self, a, _urlunquote(v))
2437 setattr(self, a, _urlunquote(v))
2434
2438
2435 def __repr__(self):
2439 def __repr__(self):
2436 attrs = []
2440 attrs = []
2437 for a in ('scheme', 'user', 'passwd', 'host', 'port', 'path',
2441 for a in ('scheme', 'user', 'passwd', 'host', 'port', 'path',
2438 'query', 'fragment'):
2442 'query', 'fragment'):
2439 v = getattr(self, a)
2443 v = getattr(self, a)
2440 if v is not None:
2444 if v is not None:
2441 attrs.append('%s: %r' % (a, v))
2445 attrs.append('%s: %r' % (a, v))
2442 return '<url %s>' % ', '.join(attrs)
2446 return '<url %s>' % ', '.join(attrs)
2443
2447
2444 def __str__(self):
2448 def __str__(self):
2445 r"""Join the URL's components back into a URL string.
2449 r"""Join the URL's components back into a URL string.
2446
2450
2447 Examples:
2451 Examples:
2448
2452
2449 >>> str(url('http://user:pw@host:80/c:/bob?fo:oo#ba:ar'))
2453 >>> str(url('http://user:pw@host:80/c:/bob?fo:oo#ba:ar'))
2450 'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'
2454 'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'
2451 >>> str(url('http://user:pw@host:80/?foo=bar&baz=42'))
2455 >>> str(url('http://user:pw@host:80/?foo=bar&baz=42'))
2452 'http://user:pw@host:80/?foo=bar&baz=42'
2456 'http://user:pw@host:80/?foo=bar&baz=42'
2453 >>> str(url('http://user:pw@host:80/?foo=bar%3dbaz'))
2457 >>> str(url('http://user:pw@host:80/?foo=bar%3dbaz'))
2454 'http://user:pw@host:80/?foo=bar%3dbaz'
2458 'http://user:pw@host:80/?foo=bar%3dbaz'
2455 >>> str(url('ssh://user:pw@[::1]:2200//home/joe#'))
2459 >>> str(url('ssh://user:pw@[::1]:2200//home/joe#'))
2456 'ssh://user:pw@[::1]:2200//home/joe#'
2460 'ssh://user:pw@[::1]:2200//home/joe#'
2457 >>> str(url('http://localhost:80//'))
2461 >>> str(url('http://localhost:80//'))
2458 'http://localhost:80//'
2462 'http://localhost:80//'
2459 >>> str(url('http://localhost:80/'))
2463 >>> str(url('http://localhost:80/'))
2460 'http://localhost:80/'
2464 'http://localhost:80/'
2461 >>> str(url('http://localhost:80'))
2465 >>> str(url('http://localhost:80'))
2462 'http://localhost:80/'
2466 'http://localhost:80/'
2463 >>> str(url('bundle:foo'))
2467 >>> str(url('bundle:foo'))
2464 'bundle:foo'
2468 'bundle:foo'
2465 >>> str(url('bundle://../foo'))
2469 >>> str(url('bundle://../foo'))
2466 'bundle:../foo'
2470 'bundle:../foo'
2467 >>> str(url('path'))
2471 >>> str(url('path'))
2468 'path'
2472 'path'
2469 >>> str(url('file:///tmp/foo/bar'))
2473 >>> str(url('file:///tmp/foo/bar'))
2470 'file:///tmp/foo/bar'
2474 'file:///tmp/foo/bar'
2471 >>> str(url('file:///c:/tmp/foo/bar'))
2475 >>> str(url('file:///c:/tmp/foo/bar'))
2472 'file:///c:/tmp/foo/bar'
2476 'file:///c:/tmp/foo/bar'
2473 >>> print url(r'bundle:foo\bar')
2477 >>> print url(r'bundle:foo\bar')
2474 bundle:foo\bar
2478 bundle:foo\bar
2475 >>> print url(r'file:///D:\data\hg')
2479 >>> print url(r'file:///D:\data\hg')
2476 file:///D:\data\hg
2480 file:///D:\data\hg
2477 """
2481 """
2478 if self._localpath:
2482 if self._localpath:
2479 s = self.path
2483 s = self.path
2480 if self.scheme == 'bundle':
2484 if self.scheme == 'bundle':
2481 s = 'bundle:' + s
2485 s = 'bundle:' + s
2482 if self.fragment:
2486 if self.fragment:
2483 s += '#' + self.fragment
2487 s += '#' + self.fragment
2484 return s
2488 return s
2485
2489
2486 s = self.scheme + ':'
2490 s = self.scheme + ':'
2487 if self.user or self.passwd or self.host:
2491 if self.user or self.passwd or self.host:
2488 s += '//'
2492 s += '//'
2489 elif self.scheme and (not self.path or self.path.startswith('/')
2493 elif self.scheme and (not self.path or self.path.startswith('/')
2490 or hasdriveletter(self.path)):
2494 or hasdriveletter(self.path)):
2491 s += '//'
2495 s += '//'
2492 if hasdriveletter(self.path):
2496 if hasdriveletter(self.path):
2493 s += '/'
2497 s += '/'
2494 if self.user:
2498 if self.user:
2495 s += urlreq.quote(self.user, safe=self._safechars)
2499 s += urlreq.quote(self.user, safe=self._safechars)
2496 if self.passwd:
2500 if self.passwd:
2497 s += ':' + urlreq.quote(self.passwd, safe=self._safechars)
2501 s += ':' + urlreq.quote(self.passwd, safe=self._safechars)
2498 if self.user or self.passwd:
2502 if self.user or self.passwd:
2499 s += '@'
2503 s += '@'
2500 if self.host:
2504 if self.host:
2501 if not (self.host.startswith('[') and self.host.endswith(']')):
2505 if not (self.host.startswith('[') and self.host.endswith(']')):
2502 s += urlreq.quote(self.host)
2506 s += urlreq.quote(self.host)
2503 else:
2507 else:
2504 s += self.host
2508 s += self.host
2505 if self.port:
2509 if self.port:
2506 s += ':' + urlreq.quote(self.port)
2510 s += ':' + urlreq.quote(self.port)
2507 if self.host:
2511 if self.host:
2508 s += '/'
2512 s += '/'
2509 if self.path:
2513 if self.path:
2510 # TODO: similar to the query string, we should not unescape the
2514 # TODO: similar to the query string, we should not unescape the
2511 # path when we store it, the path might contain '%2f' = '/',
2515 # path when we store it, the path might contain '%2f' = '/',
2512 # which we should *not* escape.
2516 # which we should *not* escape.
2513 s += urlreq.quote(self.path, safe=self._safepchars)
2517 s += urlreq.quote(self.path, safe=self._safepchars)
2514 if self.query:
2518 if self.query:
2515 # we store the query in escaped form.
2519 # we store the query in escaped form.
2516 s += '?' + self.query
2520 s += '?' + self.query
2517 if self.fragment is not None:
2521 if self.fragment is not None:
2518 s += '#' + urlreq.quote(self.fragment, safe=self._safepchars)
2522 s += '#' + urlreq.quote(self.fragment, safe=self._safepchars)
2519 return s
2523 return s
2520
2524
2521 def authinfo(self):
2525 def authinfo(self):
2522 user, passwd = self.user, self.passwd
2526 user, passwd = self.user, self.passwd
2523 try:
2527 try:
2524 self.user, self.passwd = None, None
2528 self.user, self.passwd = None, None
2525 s = str(self)
2529 s = str(self)
2526 finally:
2530 finally:
2527 self.user, self.passwd = user, passwd
2531 self.user, self.passwd = user, passwd
2528 if not self.user:
2532 if not self.user:
2529 return (s, None)
2533 return (s, None)
2530 # authinfo[1] is passed to urllib2 password manager, and its
2534 # authinfo[1] is passed to urllib2 password manager, and its
2531 # URIs must not contain credentials. The host is passed in the
2535 # URIs must not contain credentials. The host is passed in the
2532 # URIs list because Python < 2.4.3 uses only that to search for
2536 # URIs list because Python < 2.4.3 uses only that to search for
2533 # a password.
2537 # a password.
2534 return (s, (None, (s, self.host),
2538 return (s, (None, (s, self.host),
2535 self.user, self.passwd or ''))
2539 self.user, self.passwd or ''))
2536
2540
2537 def isabs(self):
2541 def isabs(self):
2538 if self.scheme and self.scheme != 'file':
2542 if self.scheme and self.scheme != 'file':
2539 return True # remote URL
2543 return True # remote URL
2540 if hasdriveletter(self.path):
2544 if hasdriveletter(self.path):
2541 return True # absolute for our purposes - can't be joined()
2545 return True # absolute for our purposes - can't be joined()
2542 if self.path.startswith(r'\\'):
2546 if self.path.startswith(r'\\'):
2543 return True # Windows UNC path
2547 return True # Windows UNC path
2544 if self.path.startswith('/'):
2548 if self.path.startswith('/'):
2545 return True # POSIX-style
2549 return True # POSIX-style
2546 return False
2550 return False
2547
2551
2548 def localpath(self):
2552 def localpath(self):
2549 if self.scheme == 'file' or self.scheme == 'bundle':
2553 if self.scheme == 'file' or self.scheme == 'bundle':
2550 path = self.path or '/'
2554 path = self.path or '/'
2551 # For Windows, we need to promote hosts containing drive
2555 # For Windows, we need to promote hosts containing drive
2552 # letters to paths with drive letters.
2556 # letters to paths with drive letters.
2553 if hasdriveletter(self._hostport):
2557 if hasdriveletter(self._hostport):
2554 path = self._hostport + '/' + self.path
2558 path = self._hostport + '/' + self.path
2555 elif (self.host is not None and self.path
2559 elif (self.host is not None and self.path
2556 and not hasdriveletter(path)):
2560 and not hasdriveletter(path)):
2557 path = '/' + path
2561 path = '/' + path
2558 return path
2562 return path
2559 return self._origpath
2563 return self._origpath
2560
2564
2561 def islocal(self):
2565 def islocal(self):
2562 '''whether localpath will return something that posixfile can open'''
2566 '''whether localpath will return something that posixfile can open'''
2563 return (not self.scheme or self.scheme == 'file'
2567 return (not self.scheme or self.scheme == 'file'
2564 or self.scheme == 'bundle')
2568 or self.scheme == 'bundle')
2565
2569
2566 def hasscheme(path):
2570 def hasscheme(path):
2567 return bool(url(path).scheme)
2571 return bool(url(path).scheme)
2568
2572
2569 def hasdriveletter(path):
2573 def hasdriveletter(path):
2570 return path and path[1:2] == ':' and path[0:1].isalpha()
2574 return path and path[1:2] == ':' and path[0:1].isalpha()
2571
2575
2572 def urllocalpath(path):
2576 def urllocalpath(path):
2573 return url(path, parsequery=False, parsefragment=False).localpath()
2577 return url(path, parsequery=False, parsefragment=False).localpath()
2574
2578
2575 def hidepassword(u):
2579 def hidepassword(u):
2576 '''hide user credential in a url string'''
2580 '''hide user credential in a url string'''
2577 u = url(u)
2581 u = url(u)
2578 if u.passwd:
2582 if u.passwd:
2579 u.passwd = '***'
2583 u.passwd = '***'
2580 return str(u)
2584 return str(u)
2581
2585
2582 def removeauth(u):
2586 def removeauth(u):
2583 '''remove all authentication information from a url string'''
2587 '''remove all authentication information from a url string'''
2584 u = url(u)
2588 u = url(u)
2585 u.user = u.passwd = None
2589 u.user = u.passwd = None
2586 return str(u)
2590 return str(u)
2587
2591
2588 def isatty(fp):
2592 def isatty(fp):
2589 try:
2593 try:
2590 return fp.isatty()
2594 return fp.isatty()
2591 except AttributeError:
2595 except AttributeError:
2592 return False
2596 return False
2593
2597
2594 timecount = unitcountfn(
2598 timecount = unitcountfn(
2595 (1, 1e3, _('%.0f s')),
2599 (1, 1e3, _('%.0f s')),
2596 (100, 1, _('%.1f s')),
2600 (100, 1, _('%.1f s')),
2597 (10, 1, _('%.2f s')),
2601 (10, 1, _('%.2f s')),
2598 (1, 1, _('%.3f s')),
2602 (1, 1, _('%.3f s')),
2599 (100, 0.001, _('%.1f ms')),
2603 (100, 0.001, _('%.1f ms')),
2600 (10, 0.001, _('%.2f ms')),
2604 (10, 0.001, _('%.2f ms')),
2601 (1, 0.001, _('%.3f ms')),
2605 (1, 0.001, _('%.3f ms')),
2602 (100, 0.000001, _('%.1f us')),
2606 (100, 0.000001, _('%.1f us')),
2603 (10, 0.000001, _('%.2f us')),
2607 (10, 0.000001, _('%.2f us')),
2604 (1, 0.000001, _('%.3f us')),
2608 (1, 0.000001, _('%.3f us')),
2605 (100, 0.000000001, _('%.1f ns')),
2609 (100, 0.000000001, _('%.1f ns')),
2606 (10, 0.000000001, _('%.2f ns')),
2610 (10, 0.000000001, _('%.2f ns')),
2607 (1, 0.000000001, _('%.3f ns')),
2611 (1, 0.000000001, _('%.3f ns')),
2608 )
2612 )
2609
2613
2610 _timenesting = [0]
2614 _timenesting = [0]
2611
2615
2612 def timed(func):
2616 def timed(func):
2613 '''Report the execution time of a function call to stderr.
2617 '''Report the execution time of a function call to stderr.
2614
2618
2615 During development, use as a decorator when you need to measure
2619 During development, use as a decorator when you need to measure
2616 the cost of a function, e.g. as follows:
2620 the cost of a function, e.g. as follows:
2617
2621
2618 @util.timed
2622 @util.timed
2619 def foo(a, b, c):
2623 def foo(a, b, c):
2620 pass
2624 pass
2621 '''
2625 '''
2622
2626
2623 def wrapper(*args, **kwargs):
2627 def wrapper(*args, **kwargs):
2624 start = time.time()
2628 start = time.time()
2625 indent = 2
2629 indent = 2
2626 _timenesting[0] += indent
2630 _timenesting[0] += indent
2627 try:
2631 try:
2628 return func(*args, **kwargs)
2632 return func(*args, **kwargs)
2629 finally:
2633 finally:
2630 elapsed = time.time() - start
2634 elapsed = time.time() - start
2631 _timenesting[0] -= indent
2635 _timenesting[0] -= indent
2632 sys.stderr.write('%s%s: %s\n' %
2636 sys.stderr.write('%s%s: %s\n' %
2633 (' ' * _timenesting[0], func.__name__,
2637 (' ' * _timenesting[0], func.__name__,
2634 timecount(elapsed)))
2638 timecount(elapsed)))
2635 return wrapper
2639 return wrapper
2636
2640
2637 _sizeunits = (('m', 2**20), ('k', 2**10), ('g', 2**30),
2641 _sizeunits = (('m', 2**20), ('k', 2**10), ('g', 2**30),
2638 ('kb', 2**10), ('mb', 2**20), ('gb', 2**30), ('b', 1))
2642 ('kb', 2**10), ('mb', 2**20), ('gb', 2**30), ('b', 1))
2639
2643
2640 def sizetoint(s):
2644 def sizetoint(s):
2641 '''Convert a space specifier to a byte count.
2645 '''Convert a space specifier to a byte count.
2642
2646
2643 >>> sizetoint('30')
2647 >>> sizetoint('30')
2644 30
2648 30
2645 >>> sizetoint('2.2kb')
2649 >>> sizetoint('2.2kb')
2646 2252
2650 2252
2647 >>> sizetoint('6M')
2651 >>> sizetoint('6M')
2648 6291456
2652 6291456
2649 '''
2653 '''
2650 t = s.strip().lower()
2654 t = s.strip().lower()
2651 try:
2655 try:
2652 for k, u in _sizeunits:
2656 for k, u in _sizeunits:
2653 if t.endswith(k):
2657 if t.endswith(k):
2654 return int(float(t[:-len(k)]) * u)
2658 return int(float(t[:-len(k)]) * u)
2655 return int(t)
2659 return int(t)
2656 except ValueError:
2660 except ValueError:
2657 raise error.ParseError(_("couldn't parse size: %s") % s)
2661 raise error.ParseError(_("couldn't parse size: %s") % s)
2658
2662
2659 class hooks(object):
2663 class hooks(object):
2660 '''A collection of hook functions that can be used to extend a
2664 '''A collection of hook functions that can be used to extend a
2661 function's behavior. Hooks are called in lexicographic order,
2665 function's behavior. Hooks are called in lexicographic order,
2662 based on the names of their sources.'''
2666 based on the names of their sources.'''
2663
2667
2664 def __init__(self):
2668 def __init__(self):
2665 self._hooks = []
2669 self._hooks = []
2666
2670
2667 def add(self, source, hook):
2671 def add(self, source, hook):
2668 self._hooks.append((source, hook))
2672 self._hooks.append((source, hook))
2669
2673
2670 def __call__(self, *args):
2674 def __call__(self, *args):
2671 self._hooks.sort(key=lambda x: x[0])
2675 self._hooks.sort(key=lambda x: x[0])
2672 results = []
2676 results = []
2673 for source, hook in self._hooks:
2677 for source, hook in self._hooks:
2674 results.append(hook(*args))
2678 results.append(hook(*args))
2675 return results
2679 return results
2676
2680
2677 def getstackframes(skip=0, line=' %-*s in %s\n', fileline='%s:%s'):
2681 def getstackframes(skip=0, line=' %-*s in %s\n', fileline='%s:%s'):
2678 '''Yields lines for a nicely formatted stacktrace.
2682 '''Yields lines for a nicely formatted stacktrace.
2679 Skips the 'skip' last entries.
2683 Skips the 'skip' last entries.
2680 Each file+linenumber is formatted according to fileline.
2684 Each file+linenumber is formatted according to fileline.
2681 Each line is formatted according to line.
2685 Each line is formatted according to line.
2682 If line is None, it yields:
2686 If line is None, it yields:
2683 length of longest filepath+line number,
2687 length of longest filepath+line number,
2684 filepath+linenumber,
2688 filepath+linenumber,
2685 function
2689 function
2686
2690
2687 Not be used in production code but very convenient while developing.
2691 Not be used in production code but very convenient while developing.
2688 '''
2692 '''
2689 entries = [(fileline % (fn, ln), func)
2693 entries = [(fileline % (fn, ln), func)
2690 for fn, ln, func, _text in traceback.extract_stack()[:-skip - 1]]
2694 for fn, ln, func, _text in traceback.extract_stack()[:-skip - 1]]
2691 if entries:
2695 if entries:
2692 fnmax = max(len(entry[0]) for entry in entries)
2696 fnmax = max(len(entry[0]) for entry in entries)
2693 for fnln, func in entries:
2697 for fnln, func in entries:
2694 if line is None:
2698 if line is None:
2695 yield (fnmax, fnln, func)
2699 yield (fnmax, fnln, func)
2696 else:
2700 else:
2697 yield line % (fnmax, fnln, func)
2701 yield line % (fnmax, fnln, func)
2698
2702
2699 def debugstacktrace(msg='stacktrace', skip=0, f=sys.stderr, otherf=sys.stdout):
2703 def debugstacktrace(msg='stacktrace', skip=0, f=sys.stderr, otherf=sys.stdout):
2700 '''Writes a message to f (stderr) with a nicely formatted stacktrace.
2704 '''Writes a message to f (stderr) with a nicely formatted stacktrace.
2701 Skips the 'skip' last entries. By default it will flush stdout first.
2705 Skips the 'skip' last entries. By default it will flush stdout first.
2702 It can be used everywhere and intentionally does not require an ui object.
2706 It can be used everywhere and intentionally does not require an ui object.
2703 Not be used in production code but very convenient while developing.
2707 Not be used in production code but very convenient while developing.
2704 '''
2708 '''
2705 if otherf:
2709 if otherf:
2706 otherf.flush()
2710 otherf.flush()
2707 f.write('%s at:\n' % msg)
2711 f.write('%s at:\n' % msg)
2708 for line in getstackframes(skip + 1):
2712 for line in getstackframes(skip + 1):
2709 f.write(line)
2713 f.write(line)
2710 f.flush()
2714 f.flush()
2711
2715
2712 class dirs(object):
2716 class dirs(object):
2713 '''a multiset of directory names from a dirstate or manifest'''
2717 '''a multiset of directory names from a dirstate or manifest'''
2714
2718
2715 def __init__(self, map, skip=None):
2719 def __init__(self, map, skip=None):
2716 self._dirs = {}
2720 self._dirs = {}
2717 addpath = self.addpath
2721 addpath = self.addpath
2718 if safehasattr(map, 'iteritems') and skip is not None:
2722 if safehasattr(map, 'iteritems') and skip is not None:
2719 for f, s in map.iteritems():
2723 for f, s in map.iteritems():
2720 if s[0] != skip:
2724 if s[0] != skip:
2721 addpath(f)
2725 addpath(f)
2722 else:
2726 else:
2723 for f in map:
2727 for f in map:
2724 addpath(f)
2728 addpath(f)
2725
2729
2726 def addpath(self, path):
2730 def addpath(self, path):
2727 dirs = self._dirs
2731 dirs = self._dirs
2728 for base in finddirs(path):
2732 for base in finddirs(path):
2729 if base in dirs:
2733 if base in dirs:
2730 dirs[base] += 1
2734 dirs[base] += 1
2731 return
2735 return
2732 dirs[base] = 1
2736 dirs[base] = 1
2733
2737
2734 def delpath(self, path):
2738 def delpath(self, path):
2735 dirs = self._dirs
2739 dirs = self._dirs
2736 for base in finddirs(path):
2740 for base in finddirs(path):
2737 if dirs[base] > 1:
2741 if dirs[base] > 1:
2738 dirs[base] -= 1
2742 dirs[base] -= 1
2739 return
2743 return
2740 del dirs[base]
2744 del dirs[base]
2741
2745
2742 def __iter__(self):
2746 def __iter__(self):
2743 return self._dirs.iterkeys()
2747 return self._dirs.iterkeys()
2744
2748
2745 def __contains__(self, d):
2749 def __contains__(self, d):
2746 return d in self._dirs
2750 return d in self._dirs
2747
2751
2748 if safehasattr(parsers, 'dirs'):
2752 if safehasattr(parsers, 'dirs'):
2749 dirs = parsers.dirs
2753 dirs = parsers.dirs
2750
2754
2751 def finddirs(path):
2755 def finddirs(path):
2752 pos = path.rfind('/')
2756 pos = path.rfind('/')
2753 while pos != -1:
2757 while pos != -1:
2754 yield path[:pos]
2758 yield path[:pos]
2755 pos = path.rfind('/', 0, pos)
2759 pos = path.rfind('/', 0, pos)
2756
2760
2757 # compression utility
2761 # compression utility
2758
2762
2759 class nocompress(object):
2763 class nocompress(object):
2760 def compress(self, x):
2764 def compress(self, x):
2761 return x
2765 return x
2762 def flush(self):
2766 def flush(self):
2763 return ""
2767 return ""
2764
2768
2765 compressors = {
2769 compressors = {
2766 None: nocompress,
2770 None: nocompress,
2767 # lambda to prevent early import
2771 # lambda to prevent early import
2768 'BZ': lambda: bz2.BZ2Compressor(),
2772 'BZ': lambda: bz2.BZ2Compressor(),
2769 'GZ': lambda: zlib.compressobj(),
2773 'GZ': lambda: zlib.compressobj(),
2770 }
2774 }
2771 # also support the old form by courtesies
2775 # also support the old form by courtesies
2772 compressors['UN'] = compressors[None]
2776 compressors['UN'] = compressors[None]
2773
2777
2774 def _makedecompressor(decompcls):
2778 def _makedecompressor(decompcls):
2775 def generator(f):
2779 def generator(f):
2776 d = decompcls()
2780 d = decompcls()
2777 for chunk in filechunkiter(f):
2781 for chunk in filechunkiter(f):
2778 yield d.decompress(chunk)
2782 yield d.decompress(chunk)
2779 def func(fh):
2783 def func(fh):
2780 return chunkbuffer(generator(fh))
2784 return chunkbuffer(generator(fh))
2781 return func
2785 return func
2782
2786
2783 class ctxmanager(object):
2787 class ctxmanager(object):
2784 '''A context manager for use in 'with' blocks to allow multiple
2788 '''A context manager for use in 'with' blocks to allow multiple
2785 contexts to be entered at once. This is both safer and more
2789 contexts to be entered at once. This is both safer and more
2786 flexible than contextlib.nested.
2790 flexible than contextlib.nested.
2787
2791
2788 Once Mercurial supports Python 2.7+, this will become mostly
2792 Once Mercurial supports Python 2.7+, this will become mostly
2789 unnecessary.
2793 unnecessary.
2790 '''
2794 '''
2791
2795
2792 def __init__(self, *args):
2796 def __init__(self, *args):
2793 '''Accepts a list of no-argument functions that return context
2797 '''Accepts a list of no-argument functions that return context
2794 managers. These will be invoked at __call__ time.'''
2798 managers. These will be invoked at __call__ time.'''
2795 self._pending = args
2799 self._pending = args
2796 self._atexit = []
2800 self._atexit = []
2797
2801
2798 def __enter__(self):
2802 def __enter__(self):
2799 return self
2803 return self
2800
2804
2801 def enter(self):
2805 def enter(self):
2802 '''Create and enter context managers in the order in which they were
2806 '''Create and enter context managers in the order in which they were
2803 passed to the constructor.'''
2807 passed to the constructor.'''
2804 values = []
2808 values = []
2805 for func in self._pending:
2809 for func in self._pending:
2806 obj = func()
2810 obj = func()
2807 values.append(obj.__enter__())
2811 values.append(obj.__enter__())
2808 self._atexit.append(obj.__exit__)
2812 self._atexit.append(obj.__exit__)
2809 del self._pending
2813 del self._pending
2810 return values
2814 return values
2811
2815
2812 def atexit(self, func, *args, **kwargs):
2816 def atexit(self, func, *args, **kwargs):
2813 '''Add a function to call when this context manager exits. The
2817 '''Add a function to call when this context manager exits. The
2814 ordering of multiple atexit calls is unspecified, save that
2818 ordering of multiple atexit calls is unspecified, save that
2815 they will happen before any __exit__ functions.'''
2819 they will happen before any __exit__ functions.'''
2816 def wrapper(exc_type, exc_val, exc_tb):
2820 def wrapper(exc_type, exc_val, exc_tb):
2817 func(*args, **kwargs)
2821 func(*args, **kwargs)
2818 self._atexit.append(wrapper)
2822 self._atexit.append(wrapper)
2819 return func
2823 return func
2820
2824
2821 def __exit__(self, exc_type, exc_val, exc_tb):
2825 def __exit__(self, exc_type, exc_val, exc_tb):
2822 '''Context managers are exited in the reverse order from which
2826 '''Context managers are exited in the reverse order from which
2823 they were created.'''
2827 they were created.'''
2824 received = exc_type is not None
2828 received = exc_type is not None
2825 suppressed = False
2829 suppressed = False
2826 pending = None
2830 pending = None
2827 self._atexit.reverse()
2831 self._atexit.reverse()
2828 for exitfunc in self._atexit:
2832 for exitfunc in self._atexit:
2829 try:
2833 try:
2830 if exitfunc(exc_type, exc_val, exc_tb):
2834 if exitfunc(exc_type, exc_val, exc_tb):
2831 suppressed = True
2835 suppressed = True
2832 exc_type = None
2836 exc_type = None
2833 exc_val = None
2837 exc_val = None
2834 exc_tb = None
2838 exc_tb = None
2835 except BaseException:
2839 except BaseException:
2836 pending = sys.exc_info()
2840 pending = sys.exc_info()
2837 exc_type, exc_val, exc_tb = pending = sys.exc_info()
2841 exc_type, exc_val, exc_tb = pending = sys.exc_info()
2838 del self._atexit
2842 del self._atexit
2839 if pending:
2843 if pending:
2840 raise exc_val
2844 raise exc_val
2841 return received and suppressed
2845 return received and suppressed
2842
2846
2843 def _bz2():
2847 def _bz2():
2844 d = bz2.BZ2Decompressor()
2848 d = bz2.BZ2Decompressor()
2845 # Bzip2 stream start with BZ, but we stripped it.
2849 # Bzip2 stream start with BZ, but we stripped it.
2846 # we put it back for good measure.
2850 # we put it back for good measure.
2847 d.decompress('BZ')
2851 d.decompress('BZ')
2848 return d
2852 return d
2849
2853
2850 decompressors = {None: lambda fh: fh,
2854 decompressors = {None: lambda fh: fh,
2851 '_truncatedBZ': _makedecompressor(_bz2),
2855 '_truncatedBZ': _makedecompressor(_bz2),
2852 'BZ': _makedecompressor(lambda: bz2.BZ2Decompressor()),
2856 'BZ': _makedecompressor(lambda: bz2.BZ2Decompressor()),
2853 'GZ': _makedecompressor(lambda: zlib.decompressobj()),
2857 'GZ': _makedecompressor(lambda: zlib.decompressobj()),
2854 }
2858 }
2855 # also support the old form by courtesies
2859 # also support the old form by courtesies
2856 decompressors['UN'] = decompressors[None]
2860 decompressors['UN'] = decompressors[None]
2857
2861
2858 # convenient shortcut
2862 # convenient shortcut
2859 dst = debugstacktrace
2863 dst = debugstacktrace
@@ -1,128 +1,128 b''
1
1
2 $ cat << EOF >> $HGRCPATH
2 $ cat << EOF >> $HGRCPATH
3 > [format]
3 > [format]
4 > usegeneraldelta=yes
4 > usegeneraldelta=yes
5 > EOF
5 > EOF
6
6
7 bundle w/o type option
7 bundle w/o type option
8
8
9 $ hg init t1
9 $ hg init t1
10 $ hg init t2
10 $ hg init t2
11 $ cd t1
11 $ cd t1
12 $ echo blablablablabla > file.txt
12 $ echo blablablablabla > file.txt
13 $ hg ci -Ama
13 $ hg ci -Ama
14 adding file.txt
14 adding file.txt
15 $ hg log | grep summary
15 $ hg log | grep summary
16 summary: a
16 summary: a
17 $ hg bundle ../b1 ../t2
17 $ hg bundle ../b1 ../t2
18 searching for changes
18 searching for changes
19 1 changesets found
19 1 changesets found
20
20
21 $ cd ../t2
21 $ cd ../t2
22 $ hg pull ../b1
22 $ hg pull ../b1
23 pulling from ../b1
23 pulling from ../b1
24 requesting all changes
24 requesting all changes
25 adding changesets
25 adding changesets
26 adding manifests
26 adding manifests
27 adding file changes
27 adding file changes
28 added 1 changesets with 1 changes to 1 files
28 added 1 changesets with 1 changes to 1 files
29 (run 'hg update' to get a working copy)
29 (run 'hg update' to get a working copy)
30 $ hg up
30 $ hg up
31 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
31 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
32 $ hg log | grep summary
32 $ hg log | grep summary
33 summary: a
33 summary: a
34 $ cd ..
34 $ cd ..
35
35
36 test bundle types
36 test bundle types
37
37
38 $ for t in "None" "bzip2" "gzip" "none-v2" "v2" "v1" "gzip-v1"; do
38 $ for t in "None" "bzip2" "gzip" "none-v2" "v2" "v1" "gzip-v1"; do
39 > echo % test bundle type $t
39 > echo % test bundle type $t
40 > hg init t$t
40 > hg init t$t
41 > cd t1
41 > cd t1
42 > hg bundle -t $t ../b$t ../t$t
42 > hg bundle -t $t ../b$t ../t$t
43 > f -q -B6 -D ../b$t; echo
43 > f -q -B6 -D ../b$t; echo
44 > cd ../t$t
44 > cd ../t$t
45 > hg debugbundle ../b$t
45 > hg debugbundle ../b$t
46 > hg debugbundle --spec ../b$t
46 > hg debugbundle --spec ../b$t
47 > echo
47 > echo
48 > cd ..
48 > cd ..
49 > done
49 > done
50 % test bundle type None
50 % test bundle type None
51 searching for changes
51 searching for changes
52 1 changesets found
52 1 changesets found
53 HG20\x00\x00 (esc)
53 HG20\x00\x00 (esc)
54 Stream params: {}
54 Stream params: {}
55 changegroup -- "{'version': '02'}"
55 changegroup -- "sortdict([('version', '02')])"
56 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
56 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
57 none-v2
57 none-v2
58
58
59 % test bundle type bzip2
59 % test bundle type bzip2
60 searching for changes
60 searching for changes
61 1 changesets found
61 1 changesets found
62 HG20\x00\x00 (esc)
62 HG20\x00\x00 (esc)
63 Stream params: {'Compression': 'BZ'}
63 Stream params: sortdict([('Compression', 'BZ')])
64 changegroup -- "{'version': '02'}"
64 changegroup -- "sortdict([('version', '02')])"
65 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
65 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
66 bzip2-v2
66 bzip2-v2
67
67
68 % test bundle type gzip
68 % test bundle type gzip
69 searching for changes
69 searching for changes
70 1 changesets found
70 1 changesets found
71 HG20\x00\x00 (esc)
71 HG20\x00\x00 (esc)
72 Stream params: {'Compression': 'GZ'}
72 Stream params: sortdict([('Compression', 'GZ')])
73 changegroup -- "{'version': '02'}"
73 changegroup -- "sortdict([('version', '02')])"
74 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
74 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
75 gzip-v2
75 gzip-v2
76
76
77 % test bundle type none-v2
77 % test bundle type none-v2
78 searching for changes
78 searching for changes
79 1 changesets found
79 1 changesets found
80 HG20\x00\x00 (esc)
80 HG20\x00\x00 (esc)
81 Stream params: {}
81 Stream params: {}
82 changegroup -- "{'version': '02'}"
82 changegroup -- "sortdict([('version', '02')])"
83 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
83 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
84 none-v2
84 none-v2
85
85
86 % test bundle type v2
86 % test bundle type v2
87 searching for changes
87 searching for changes
88 1 changesets found
88 1 changesets found
89 HG20\x00\x00 (esc)
89 HG20\x00\x00 (esc)
90 Stream params: {'Compression': 'BZ'}
90 Stream params: sortdict([('Compression', 'BZ')])
91 changegroup -- "{'version': '02'}"
91 changegroup -- "sortdict([('version', '02')])"
92 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
92 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
93 bzip2-v2
93 bzip2-v2
94
94
95 % test bundle type v1
95 % test bundle type v1
96 searching for changes
96 searching for changes
97 1 changesets found
97 1 changesets found
98 HG10BZ
98 HG10BZ
99 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
99 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
100 bzip2-v1
100 bzip2-v1
101
101
102 % test bundle type gzip-v1
102 % test bundle type gzip-v1
103 searching for changes
103 searching for changes
104 1 changesets found
104 1 changesets found
105 HG10GZ
105 HG10GZ
106 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
106 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
107 gzip-v1
107 gzip-v1
108
108
109
109
110 test garbage file
110 test garbage file
111
111
112 $ echo garbage > bgarbage
112 $ echo garbage > bgarbage
113 $ hg init tgarbage
113 $ hg init tgarbage
114 $ cd tgarbage
114 $ cd tgarbage
115 $ hg pull ../bgarbage
115 $ hg pull ../bgarbage
116 pulling from ../bgarbage
116 pulling from ../bgarbage
117 abort: ../bgarbage: not a Mercurial bundle
117 abort: ../bgarbage: not a Mercurial bundle
118 [255]
118 [255]
119 $ cd ..
119 $ cd ..
120
120
121 test invalid bundle type
121 test invalid bundle type
122
122
123 $ cd t1
123 $ cd t1
124 $ hg bundle -a -t garbage ../bgarbage
124 $ hg bundle -a -t garbage ../bgarbage
125 abort: garbage is not a recognized bundle specification
125 abort: garbage is not a recognized bundle specification
126 (see "hg help bundle" for supported values for --type)
126 (see "hg help bundle" for supported values for --type)
127 [255]
127 [255]
128 $ cd ..
128 $ cd ..
@@ -1,1233 +1,1233 b''
1 This test is dedicated to test the bundle2 container format
1 This test is dedicated to test the bundle2 container format
2
2
3 It test multiple existing parts to test different feature of the container. You
3 It test multiple existing parts to test different feature of the container. You
4 probably do not need to touch this test unless you change the binary encoding
4 probably do not need to touch this test unless you change the binary encoding
5 of the bundle2 format itself.
5 of the bundle2 format itself.
6
6
7 Create an extension to test bundle2 API
7 Create an extension to test bundle2 API
8
8
9 $ cat > bundle2.py << EOF
9 $ cat > bundle2.py << EOF
10 > """A small extension to test bundle2 implementation
10 > """A small extension to test bundle2 implementation
11 >
11 >
12 > This extension allows detailed testing of the various bundle2 API and
12 > This extension allows detailed testing of the various bundle2 API and
13 > behaviors.
13 > behaviors.
14 > """
14 > """
15 >
15 >
16 > import sys, os, gc
16 > import sys, os, gc
17 > from mercurial import cmdutil
17 > from mercurial import cmdutil
18 > from mercurial import util
18 > from mercurial import util
19 > from mercurial import bundle2
19 > from mercurial import bundle2
20 > from mercurial import scmutil
20 > from mercurial import scmutil
21 > from mercurial import discovery
21 > from mercurial import discovery
22 > from mercurial import changegroup
22 > from mercurial import changegroup
23 > from mercurial import error
23 > from mercurial import error
24 > from mercurial import obsolete
24 > from mercurial import obsolete
25 >
25 >
26 >
26 >
27 > try:
27 > try:
28 > import msvcrt
28 > import msvcrt
29 > msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
29 > msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
30 > msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
30 > msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
31 > msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
31 > msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
32 > except ImportError:
32 > except ImportError:
33 > pass
33 > pass
34 >
34 >
35 > cmdtable = {}
35 > cmdtable = {}
36 > command = cmdutil.command(cmdtable)
36 > command = cmdutil.command(cmdtable)
37 >
37 >
38 > ELEPHANTSSONG = """Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
38 > ELEPHANTSSONG = """Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
39 > Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
39 > Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
40 > Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko."""
40 > Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko."""
41 > assert len(ELEPHANTSSONG) == 178 # future test say 178 bytes, trust it.
41 > assert len(ELEPHANTSSONG) == 178 # future test say 178 bytes, trust it.
42 >
42 >
43 > @bundle2.parthandler('test:song')
43 > @bundle2.parthandler('test:song')
44 > def songhandler(op, part):
44 > def songhandler(op, part):
45 > """handle a "test:song" bundle2 part, printing the lyrics on stdin"""
45 > """handle a "test:song" bundle2 part, printing the lyrics on stdin"""
46 > op.ui.write('The choir starts singing:\n')
46 > op.ui.write('The choir starts singing:\n')
47 > verses = 0
47 > verses = 0
48 > for line in part.read().split('\n'):
48 > for line in part.read().split('\n'):
49 > op.ui.write(' %s\n' % line)
49 > op.ui.write(' %s\n' % line)
50 > verses += 1
50 > verses += 1
51 > op.records.add('song', {'verses': verses})
51 > op.records.add('song', {'verses': verses})
52 >
52 >
53 > @bundle2.parthandler('test:ping')
53 > @bundle2.parthandler('test:ping')
54 > def pinghandler(op, part):
54 > def pinghandler(op, part):
55 > op.ui.write('received ping request (id %i)\n' % part.id)
55 > op.ui.write('received ping request (id %i)\n' % part.id)
56 > if op.reply is not None and 'ping-pong' in op.reply.capabilities:
56 > if op.reply is not None and 'ping-pong' in op.reply.capabilities:
57 > op.ui.write_err('replying to ping request (id %i)\n' % part.id)
57 > op.ui.write_err('replying to ping request (id %i)\n' % part.id)
58 > op.reply.newpart('test:pong', [('in-reply-to', str(part.id))],
58 > op.reply.newpart('test:pong', [('in-reply-to', str(part.id))],
59 > mandatory=False)
59 > mandatory=False)
60 >
60 >
61 > @bundle2.parthandler('test:debugreply')
61 > @bundle2.parthandler('test:debugreply')
62 > def debugreply(op, part):
62 > def debugreply(op, part):
63 > """print data about the capacity of the bundle reply"""
63 > """print data about the capacity of the bundle reply"""
64 > if op.reply is None:
64 > if op.reply is None:
65 > op.ui.write('debugreply: no reply\n')
65 > op.ui.write('debugreply: no reply\n')
66 > else:
66 > else:
67 > op.ui.write('debugreply: capabilities:\n')
67 > op.ui.write('debugreply: capabilities:\n')
68 > for cap in sorted(op.reply.capabilities):
68 > for cap in sorted(op.reply.capabilities):
69 > op.ui.write('debugreply: %r\n' % cap)
69 > op.ui.write('debugreply: %r\n' % cap)
70 > for val in op.reply.capabilities[cap]:
70 > for val in op.reply.capabilities[cap]:
71 > op.ui.write('debugreply: %r\n' % val)
71 > op.ui.write('debugreply: %r\n' % val)
72 >
72 >
73 > @command('bundle2',
73 > @command('bundle2',
74 > [('', 'param', [], 'stream level parameter'),
74 > [('', 'param', [], 'stream level parameter'),
75 > ('', 'unknown', False, 'include an unknown mandatory part in the bundle'),
75 > ('', 'unknown', False, 'include an unknown mandatory part in the bundle'),
76 > ('', 'unknownparams', False, 'include an unknown part parameters in the bundle'),
76 > ('', 'unknownparams', False, 'include an unknown part parameters in the bundle'),
77 > ('', 'parts', False, 'include some arbitrary parts to the bundle'),
77 > ('', 'parts', False, 'include some arbitrary parts to the bundle'),
78 > ('', 'reply', False, 'produce a reply bundle'),
78 > ('', 'reply', False, 'produce a reply bundle'),
79 > ('', 'pushrace', False, 'includes a check:head part with unknown nodes'),
79 > ('', 'pushrace', False, 'includes a check:head part with unknown nodes'),
80 > ('', 'genraise', False, 'includes a part that raise an exception during generation'),
80 > ('', 'genraise', False, 'includes a part that raise an exception during generation'),
81 > ('', 'timeout', False, 'emulate a timeout during bundle generation'),
81 > ('', 'timeout', False, 'emulate a timeout during bundle generation'),
82 > ('r', 'rev', [], 'includes those changeset in the bundle'),
82 > ('r', 'rev', [], 'includes those changeset in the bundle'),
83 > ('', 'compress', '', 'compress the stream'),],
83 > ('', 'compress', '', 'compress the stream'),],
84 > '[OUTPUTFILE]')
84 > '[OUTPUTFILE]')
85 > def cmdbundle2(ui, repo, path=None, **opts):
85 > def cmdbundle2(ui, repo, path=None, **opts):
86 > """write a bundle2 container on standard output"""
86 > """write a bundle2 container on standard output"""
87 > bundler = bundle2.bundle20(ui)
87 > bundler = bundle2.bundle20(ui)
88 > for p in opts['param']:
88 > for p in opts['param']:
89 > p = p.split('=', 1)
89 > p = p.split('=', 1)
90 > try:
90 > try:
91 > bundler.addparam(*p)
91 > bundler.addparam(*p)
92 > except ValueError, exc:
92 > except ValueError, exc:
93 > raise error.Abort('%s' % exc)
93 > raise error.Abort('%s' % exc)
94 >
94 >
95 > if opts['compress']:
95 > if opts['compress']:
96 > bundler.setcompression(opts['compress'])
96 > bundler.setcompression(opts['compress'])
97 >
97 >
98 > if opts['reply']:
98 > if opts['reply']:
99 > capsstring = 'ping-pong\nelephants=babar,celeste\ncity%3D%21=celeste%2Cville'
99 > capsstring = 'ping-pong\nelephants=babar,celeste\ncity%3D%21=celeste%2Cville'
100 > bundler.newpart('replycaps', data=capsstring)
100 > bundler.newpart('replycaps', data=capsstring)
101 >
101 >
102 > if opts['pushrace']:
102 > if opts['pushrace']:
103 > # also serve to test the assignement of data outside of init
103 > # also serve to test the assignement of data outside of init
104 > part = bundler.newpart('check:heads')
104 > part = bundler.newpart('check:heads')
105 > part.data = '01234567890123456789'
105 > part.data = '01234567890123456789'
106 >
106 >
107 > revs = opts['rev']
107 > revs = opts['rev']
108 > if 'rev' in opts:
108 > if 'rev' in opts:
109 > revs = scmutil.revrange(repo, opts['rev'])
109 > revs = scmutil.revrange(repo, opts['rev'])
110 > if revs:
110 > if revs:
111 > # very crude version of a changegroup part creation
111 > # very crude version of a changegroup part creation
112 > bundled = repo.revs('%ld::%ld', revs, revs)
112 > bundled = repo.revs('%ld::%ld', revs, revs)
113 > headmissing = [c.node() for c in repo.set('heads(%ld)', revs)]
113 > headmissing = [c.node() for c in repo.set('heads(%ld)', revs)]
114 > headcommon = [c.node() for c in repo.set('parents(%ld) - %ld', revs, revs)]
114 > headcommon = [c.node() for c in repo.set('parents(%ld) - %ld', revs, revs)]
115 > outgoing = discovery.outgoing(repo.changelog, headcommon, headmissing)
115 > outgoing = discovery.outgoing(repo.changelog, headcommon, headmissing)
116 > cg = changegroup.getlocalchangegroup(repo, 'test:bundle2', outgoing, None)
116 > cg = changegroup.getlocalchangegroup(repo, 'test:bundle2', outgoing, None)
117 > bundler.newpart('changegroup', data=cg.getchunks(),
117 > bundler.newpart('changegroup', data=cg.getchunks(),
118 > mandatory=False)
118 > mandatory=False)
119 >
119 >
120 > if opts['parts']:
120 > if opts['parts']:
121 > bundler.newpart('test:empty', mandatory=False)
121 > bundler.newpart('test:empty', mandatory=False)
122 > # add a second one to make sure we handle multiple parts
122 > # add a second one to make sure we handle multiple parts
123 > bundler.newpart('test:empty', mandatory=False)
123 > bundler.newpart('test:empty', mandatory=False)
124 > bundler.newpart('test:song', data=ELEPHANTSSONG, mandatory=False)
124 > bundler.newpart('test:song', data=ELEPHANTSSONG, mandatory=False)
125 > bundler.newpart('test:debugreply', mandatory=False)
125 > bundler.newpart('test:debugreply', mandatory=False)
126 > mathpart = bundler.newpart('test:math')
126 > mathpart = bundler.newpart('test:math')
127 > mathpart.addparam('pi', '3.14')
127 > mathpart.addparam('pi', '3.14')
128 > mathpart.addparam('e', '2.72')
128 > mathpart.addparam('e', '2.72')
129 > mathpart.addparam('cooking', 'raw', mandatory=False)
129 > mathpart.addparam('cooking', 'raw', mandatory=False)
130 > mathpart.data = '42'
130 > mathpart.data = '42'
131 > mathpart.mandatory = False
131 > mathpart.mandatory = False
132 > # advisory known part with unknown mandatory param
132 > # advisory known part with unknown mandatory param
133 > bundler.newpart('test:song', [('randomparam','')], mandatory=False)
133 > bundler.newpart('test:song', [('randomparam','')], mandatory=False)
134 > if opts['unknown']:
134 > if opts['unknown']:
135 > bundler.newpart('test:unknown', data='some random content')
135 > bundler.newpart('test:unknown', data='some random content')
136 > if opts['unknownparams']:
136 > if opts['unknownparams']:
137 > bundler.newpart('test:song', [('randomparams', '')])
137 > bundler.newpart('test:song', [('randomparams', '')])
138 > if opts['parts']:
138 > if opts['parts']:
139 > bundler.newpart('test:ping', mandatory=False)
139 > bundler.newpart('test:ping', mandatory=False)
140 > if opts['genraise']:
140 > if opts['genraise']:
141 > def genraise():
141 > def genraise():
142 > yield 'first line\n'
142 > yield 'first line\n'
143 > raise RuntimeError('Someone set up us the bomb!')
143 > raise RuntimeError('Someone set up us the bomb!')
144 > bundler.newpart('output', data=genraise(), mandatory=False)
144 > bundler.newpart('output', data=genraise(), mandatory=False)
145 >
145 >
146 > if path is None:
146 > if path is None:
147 > file = sys.stdout
147 > file = sys.stdout
148 > else:
148 > else:
149 > file = open(path, 'wb')
149 > file = open(path, 'wb')
150 >
150 >
151 > if opts['timeout']:
151 > if opts['timeout']:
152 > bundler.newpart('test:song', data=ELEPHANTSSONG, mandatory=False)
152 > bundler.newpart('test:song', data=ELEPHANTSSONG, mandatory=False)
153 > for idx, junk in enumerate(bundler.getchunks()):
153 > for idx, junk in enumerate(bundler.getchunks()):
154 > ui.write('%d chunk\n' % idx)
154 > ui.write('%d chunk\n' % idx)
155 > if idx > 4:
155 > if idx > 4:
156 > # This throws a GeneratorExit inside the generator, which
156 > # This throws a GeneratorExit inside the generator, which
157 > # can cause problems if the exception-recovery code is
157 > # can cause problems if the exception-recovery code is
158 > # too zealous. It's important for this test that the break
158 > # too zealous. It's important for this test that the break
159 > # occur while we're in the middle of a part.
159 > # occur while we're in the middle of a part.
160 > break
160 > break
161 > gc.collect()
161 > gc.collect()
162 > ui.write('fake timeout complete.\n')
162 > ui.write('fake timeout complete.\n')
163 > return
163 > return
164 > try:
164 > try:
165 > for chunk in bundler.getchunks():
165 > for chunk in bundler.getchunks():
166 > file.write(chunk)
166 > file.write(chunk)
167 > except RuntimeError, exc:
167 > except RuntimeError, exc:
168 > raise error.Abort(exc)
168 > raise error.Abort(exc)
169 > finally:
169 > finally:
170 > file.flush()
170 > file.flush()
171 >
171 >
172 > @command('unbundle2', [], '')
172 > @command('unbundle2', [], '')
173 > def cmdunbundle2(ui, repo, replypath=None):
173 > def cmdunbundle2(ui, repo, replypath=None):
174 > """process a bundle2 stream from stdin on the current repo"""
174 > """process a bundle2 stream from stdin on the current repo"""
175 > try:
175 > try:
176 > tr = None
176 > tr = None
177 > lock = repo.lock()
177 > lock = repo.lock()
178 > tr = repo.transaction('processbundle')
178 > tr = repo.transaction('processbundle')
179 > try:
179 > try:
180 > unbundler = bundle2.getunbundler(ui, sys.stdin)
180 > unbundler = bundle2.getunbundler(ui, sys.stdin)
181 > op = bundle2.processbundle(repo, unbundler, lambda: tr)
181 > op = bundle2.processbundle(repo, unbundler, lambda: tr)
182 > tr.close()
182 > tr.close()
183 > except error.BundleValueError, exc:
183 > except error.BundleValueError, exc:
184 > raise error.Abort('missing support for %s' % exc)
184 > raise error.Abort('missing support for %s' % exc)
185 > except error.PushRaced, exc:
185 > except error.PushRaced, exc:
186 > raise error.Abort('push race: %s' % exc)
186 > raise error.Abort('push race: %s' % exc)
187 > finally:
187 > finally:
188 > if tr is not None:
188 > if tr is not None:
189 > tr.release()
189 > tr.release()
190 > lock.release()
190 > lock.release()
191 > remains = sys.stdin.read()
191 > remains = sys.stdin.read()
192 > ui.write('%i unread bytes\n' % len(remains))
192 > ui.write('%i unread bytes\n' % len(remains))
193 > if op.records['song']:
193 > if op.records['song']:
194 > totalverses = sum(r['verses'] for r in op.records['song'])
194 > totalverses = sum(r['verses'] for r in op.records['song'])
195 > ui.write('%i total verses sung\n' % totalverses)
195 > ui.write('%i total verses sung\n' % totalverses)
196 > for rec in op.records['changegroup']:
196 > for rec in op.records['changegroup']:
197 > ui.write('addchangegroup return: %i\n' % rec['return'])
197 > ui.write('addchangegroup return: %i\n' % rec['return'])
198 > if op.reply is not None and replypath is not None:
198 > if op.reply is not None and replypath is not None:
199 > with open(replypath, 'wb') as file:
199 > with open(replypath, 'wb') as file:
200 > for chunk in op.reply.getchunks():
200 > for chunk in op.reply.getchunks():
201 > file.write(chunk)
201 > file.write(chunk)
202 >
202 >
203 > @command('statbundle2', [], '')
203 > @command('statbundle2', [], '')
204 > def cmdstatbundle2(ui, repo):
204 > def cmdstatbundle2(ui, repo):
205 > """print statistic on the bundle2 container read from stdin"""
205 > """print statistic on the bundle2 container read from stdin"""
206 > unbundler = bundle2.getunbundler(ui, sys.stdin)
206 > unbundler = bundle2.getunbundler(ui, sys.stdin)
207 > try:
207 > try:
208 > params = unbundler.params
208 > params = unbundler.params
209 > except error.BundleValueError, exc:
209 > except error.BundleValueError, exc:
210 > raise error.Abort('unknown parameters: %s' % exc)
210 > raise error.Abort('unknown parameters: %s' % exc)
211 > ui.write('options count: %i\n' % len(params))
211 > ui.write('options count: %i\n' % len(params))
212 > for key in sorted(params):
212 > for key in sorted(params):
213 > ui.write('- %s\n' % key)
213 > ui.write('- %s\n' % key)
214 > value = params[key]
214 > value = params[key]
215 > if value is not None:
215 > if value is not None:
216 > ui.write(' %s\n' % value)
216 > ui.write(' %s\n' % value)
217 > count = 0
217 > count = 0
218 > for p in unbundler.iterparts():
218 > for p in unbundler.iterparts():
219 > count += 1
219 > count += 1
220 > ui.write(' :%s:\n' % p.type)
220 > ui.write(' :%s:\n' % p.type)
221 > ui.write(' mandatory: %i\n' % len(p.mandatoryparams))
221 > ui.write(' mandatory: %i\n' % len(p.mandatoryparams))
222 > ui.write(' advisory: %i\n' % len(p.advisoryparams))
222 > ui.write(' advisory: %i\n' % len(p.advisoryparams))
223 > ui.write(' payload: %i bytes\n' % len(p.read()))
223 > ui.write(' payload: %i bytes\n' % len(p.read()))
224 > ui.write('parts count: %i\n' % count)
224 > ui.write('parts count: %i\n' % count)
225 > EOF
225 > EOF
226 $ cat >> $HGRCPATH << EOF
226 $ cat >> $HGRCPATH << EOF
227 > [extensions]
227 > [extensions]
228 > bundle2=$TESTTMP/bundle2.py
228 > bundle2=$TESTTMP/bundle2.py
229 > [experimental]
229 > [experimental]
230 > bundle2-exp=True
230 > bundle2-exp=True
231 > evolution=createmarkers
231 > evolution=createmarkers
232 > [ui]
232 > [ui]
233 > ssh=python "$TESTDIR/dummyssh"
233 > ssh=python "$TESTDIR/dummyssh"
234 > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
234 > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
235 > [web]
235 > [web]
236 > push_ssl = false
236 > push_ssl = false
237 > allow_push = *
237 > allow_push = *
238 > [phases]
238 > [phases]
239 > publish=False
239 > publish=False
240 > EOF
240 > EOF
241
241
242 The extension requires a repo (currently unused)
242 The extension requires a repo (currently unused)
243
243
244 $ hg init main
244 $ hg init main
245 $ cd main
245 $ cd main
246 $ touch a
246 $ touch a
247 $ hg add a
247 $ hg add a
248 $ hg commit -m 'a'
248 $ hg commit -m 'a'
249
249
250
250
251 Empty bundle
251 Empty bundle
252 =================
252 =================
253
253
254 - no option
254 - no option
255 - no parts
255 - no parts
256
256
257 Test bundling
257 Test bundling
258
258
259 $ hg bundle2 | f --hexdump
259 $ hg bundle2 | f --hexdump
260
260
261 0000: 48 47 32 30 00 00 00 00 00 00 00 00 |HG20........|
261 0000: 48 47 32 30 00 00 00 00 00 00 00 00 |HG20........|
262
262
263 Test timeouts during bundling
263 Test timeouts during bundling
264 $ hg bundle2 --timeout --debug --config devel.bundle2.debug=yes
264 $ hg bundle2 --timeout --debug --config devel.bundle2.debug=yes
265 bundle2-output-bundle: "HG20", 1 parts total
265 bundle2-output-bundle: "HG20", 1 parts total
266 bundle2-output: start emission of HG20 stream
266 bundle2-output: start emission of HG20 stream
267 0 chunk
267 0 chunk
268 bundle2-output: bundle parameter:
268 bundle2-output: bundle parameter:
269 1 chunk
269 1 chunk
270 bundle2-output: start of parts
270 bundle2-output: start of parts
271 bundle2-output: bundle part: "test:song"
271 bundle2-output: bundle part: "test:song"
272 bundle2-output-part: "test:song" (advisory) 178 bytes payload
272 bundle2-output-part: "test:song" (advisory) 178 bytes payload
273 bundle2-output: part 0: "test:song"
273 bundle2-output: part 0: "test:song"
274 bundle2-output: header chunk size: 16
274 bundle2-output: header chunk size: 16
275 2 chunk
275 2 chunk
276 3 chunk
276 3 chunk
277 bundle2-output: payload chunk size: 178
277 bundle2-output: payload chunk size: 178
278 4 chunk
278 4 chunk
279 5 chunk
279 5 chunk
280 bundle2-generatorexit
280 bundle2-generatorexit
281 fake timeout complete.
281 fake timeout complete.
282
282
283 Test unbundling
283 Test unbundling
284
284
285 $ hg bundle2 | hg statbundle2
285 $ hg bundle2 | hg statbundle2
286 options count: 0
286 options count: 0
287 parts count: 0
287 parts count: 0
288
288
289 Test old style bundle are detected and refused
289 Test old style bundle are detected and refused
290
290
291 $ hg bundle --all --type v1 ../bundle.hg
291 $ hg bundle --all --type v1 ../bundle.hg
292 1 changesets found
292 1 changesets found
293 $ hg statbundle2 < ../bundle.hg
293 $ hg statbundle2 < ../bundle.hg
294 abort: unknown bundle version 10
294 abort: unknown bundle version 10
295 [255]
295 [255]
296
296
297 Test parameters
297 Test parameters
298 =================
298 =================
299
299
300 - some options
300 - some options
301 - no parts
301 - no parts
302
302
303 advisory parameters, no value
303 advisory parameters, no value
304 -------------------------------
304 -------------------------------
305
305
306 Simplest possible parameters form
306 Simplest possible parameters form
307
307
308 Test generation simple option
308 Test generation simple option
309
309
310 $ hg bundle2 --param 'caution' | f --hexdump
310 $ hg bundle2 --param 'caution' | f --hexdump
311
311
312 0000: 48 47 32 30 00 00 00 07 63 61 75 74 69 6f 6e 00 |HG20....caution.|
312 0000: 48 47 32 30 00 00 00 07 63 61 75 74 69 6f 6e 00 |HG20....caution.|
313 0010: 00 00 00 |...|
313 0010: 00 00 00 |...|
314
314
315 Test unbundling
315 Test unbundling
316
316
317 $ hg bundle2 --param 'caution' | hg statbundle2
317 $ hg bundle2 --param 'caution' | hg statbundle2
318 options count: 1
318 options count: 1
319 - caution
319 - caution
320 parts count: 0
320 parts count: 0
321
321
322 Test generation multiple option
322 Test generation multiple option
323
323
324 $ hg bundle2 --param 'caution' --param 'meal' | f --hexdump
324 $ hg bundle2 --param 'caution' --param 'meal' | f --hexdump
325
325
326 0000: 48 47 32 30 00 00 00 0c 63 61 75 74 69 6f 6e 20 |HG20....caution |
326 0000: 48 47 32 30 00 00 00 0c 63 61 75 74 69 6f 6e 20 |HG20....caution |
327 0010: 6d 65 61 6c 00 00 00 00 |meal....|
327 0010: 6d 65 61 6c 00 00 00 00 |meal....|
328
328
329 Test unbundling
329 Test unbundling
330
330
331 $ hg bundle2 --param 'caution' --param 'meal' | hg statbundle2
331 $ hg bundle2 --param 'caution' --param 'meal' | hg statbundle2
332 options count: 2
332 options count: 2
333 - caution
333 - caution
334 - meal
334 - meal
335 parts count: 0
335 parts count: 0
336
336
337 advisory parameters, with value
337 advisory parameters, with value
338 -------------------------------
338 -------------------------------
339
339
340 Test generation
340 Test generation
341
341
342 $ hg bundle2 --param 'caution' --param 'meal=vegan' --param 'elephants' | f --hexdump
342 $ hg bundle2 --param 'caution' --param 'meal=vegan' --param 'elephants' | f --hexdump
343
343
344 0000: 48 47 32 30 00 00 00 1c 63 61 75 74 69 6f 6e 20 |HG20....caution |
344 0000: 48 47 32 30 00 00 00 1c 63 61 75 74 69 6f 6e 20 |HG20....caution |
345 0010: 6d 65 61 6c 3d 76 65 67 61 6e 20 65 6c 65 70 68 |meal=vegan eleph|
345 0010: 6d 65 61 6c 3d 76 65 67 61 6e 20 65 6c 65 70 68 |meal=vegan eleph|
346 0020: 61 6e 74 73 00 00 00 00 |ants....|
346 0020: 61 6e 74 73 00 00 00 00 |ants....|
347
347
348 Test unbundling
348 Test unbundling
349
349
350 $ hg bundle2 --param 'caution' --param 'meal=vegan' --param 'elephants' | hg statbundle2
350 $ hg bundle2 --param 'caution' --param 'meal=vegan' --param 'elephants' | hg statbundle2
351 options count: 3
351 options count: 3
352 - caution
352 - caution
353 - elephants
353 - elephants
354 - meal
354 - meal
355 vegan
355 vegan
356 parts count: 0
356 parts count: 0
357
357
358 parameter with special char in value
358 parameter with special char in value
359 ---------------------------------------------------
359 ---------------------------------------------------
360
360
361 Test generation
361 Test generation
362
362
363 $ hg bundle2 --param 'e|! 7/=babar%#==tutu' --param simple | f --hexdump
363 $ hg bundle2 --param 'e|! 7/=babar%#==tutu' --param simple | f --hexdump
364
364
365 0000: 48 47 32 30 00 00 00 29 65 25 37 43 25 32 31 25 |HG20...)e%7C%21%|
365 0000: 48 47 32 30 00 00 00 29 65 25 37 43 25 32 31 25 |HG20...)e%7C%21%|
366 0010: 32 30 37 2f 3d 62 61 62 61 72 25 32 35 25 32 33 |207/=babar%25%23|
366 0010: 32 30 37 2f 3d 62 61 62 61 72 25 32 35 25 32 33 |207/=babar%25%23|
367 0020: 25 33 44 25 33 44 74 75 74 75 20 73 69 6d 70 6c |%3D%3Dtutu simpl|
367 0020: 25 33 44 25 33 44 74 75 74 75 20 73 69 6d 70 6c |%3D%3Dtutu simpl|
368 0030: 65 00 00 00 00 |e....|
368 0030: 65 00 00 00 00 |e....|
369
369
370 Test unbundling
370 Test unbundling
371
371
372 $ hg bundle2 --param 'e|! 7/=babar%#==tutu' --param simple | hg statbundle2
372 $ hg bundle2 --param 'e|! 7/=babar%#==tutu' --param simple | hg statbundle2
373 options count: 2
373 options count: 2
374 - e|! 7/
374 - e|! 7/
375 babar%#==tutu
375 babar%#==tutu
376 - simple
376 - simple
377 parts count: 0
377 parts count: 0
378
378
379 Test unknown mandatory option
379 Test unknown mandatory option
380 ---------------------------------------------------
380 ---------------------------------------------------
381
381
382 $ hg bundle2 --param 'Gravity' | hg statbundle2
382 $ hg bundle2 --param 'Gravity' | hg statbundle2
383 abort: unknown parameters: Stream Parameter - Gravity
383 abort: unknown parameters: Stream Parameter - Gravity
384 [255]
384 [255]
385
385
386 Test debug output
386 Test debug output
387 ---------------------------------------------------
387 ---------------------------------------------------
388
388
389 bundling debug
389 bundling debug
390
390
391 $ hg bundle2 --debug --param 'e|! 7/=babar%#==tutu' --param simple ../out.hg2 --config progress.debug=true --config devel.bundle2.debug=true
391 $ hg bundle2 --debug --param 'e|! 7/=babar%#==tutu' --param simple ../out.hg2 --config progress.debug=true --config devel.bundle2.debug=true
392 bundle2-output-bundle: "HG20", (2 params) 0 parts total
392 bundle2-output-bundle: "HG20", (2 params) 0 parts total
393 bundle2-output: start emission of HG20 stream
393 bundle2-output: start emission of HG20 stream
394 bundle2-output: bundle parameter: e%7C%21%207/=babar%25%23%3D%3Dtutu simple
394 bundle2-output: bundle parameter: e%7C%21%207/=babar%25%23%3D%3Dtutu simple
395 bundle2-output: start of parts
395 bundle2-output: start of parts
396 bundle2-output: end of bundle
396 bundle2-output: end of bundle
397
397
398 file content is ok
398 file content is ok
399
399
400 $ f --hexdump ../out.hg2
400 $ f --hexdump ../out.hg2
401 ../out.hg2:
401 ../out.hg2:
402 0000: 48 47 32 30 00 00 00 29 65 25 37 43 25 32 31 25 |HG20...)e%7C%21%|
402 0000: 48 47 32 30 00 00 00 29 65 25 37 43 25 32 31 25 |HG20...)e%7C%21%|
403 0010: 32 30 37 2f 3d 62 61 62 61 72 25 32 35 25 32 33 |207/=babar%25%23|
403 0010: 32 30 37 2f 3d 62 61 62 61 72 25 32 35 25 32 33 |207/=babar%25%23|
404 0020: 25 33 44 25 33 44 74 75 74 75 20 73 69 6d 70 6c |%3D%3Dtutu simpl|
404 0020: 25 33 44 25 33 44 74 75 74 75 20 73 69 6d 70 6c |%3D%3Dtutu simpl|
405 0030: 65 00 00 00 00 |e....|
405 0030: 65 00 00 00 00 |e....|
406
406
407 unbundling debug
407 unbundling debug
408
408
409 $ hg statbundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true < ../out.hg2
409 $ hg statbundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true < ../out.hg2
410 bundle2-input: start processing of HG20 stream
410 bundle2-input: start processing of HG20 stream
411 bundle2-input: reading bundle2 stream parameters
411 bundle2-input: reading bundle2 stream parameters
412 bundle2-input: ignoring unknown parameter 'e|! 7/'
412 bundle2-input: ignoring unknown parameter 'e|! 7/'
413 bundle2-input: ignoring unknown parameter 'simple'
413 bundle2-input: ignoring unknown parameter 'simple'
414 options count: 2
414 options count: 2
415 - e|! 7/
415 - e|! 7/
416 babar%#==tutu
416 babar%#==tutu
417 - simple
417 - simple
418 bundle2-input: start extraction of bundle2 parts
418 bundle2-input: start extraction of bundle2 parts
419 bundle2-input: part header size: 0
419 bundle2-input: part header size: 0
420 bundle2-input: end of bundle2 stream
420 bundle2-input: end of bundle2 stream
421 parts count: 0
421 parts count: 0
422
422
423
423
424 Test buggy input
424 Test buggy input
425 ---------------------------------------------------
425 ---------------------------------------------------
426
426
427 empty parameter name
427 empty parameter name
428
428
429 $ hg bundle2 --param '' --quiet
429 $ hg bundle2 --param '' --quiet
430 abort: empty parameter name
430 abort: empty parameter name
431 [255]
431 [255]
432
432
433 bad parameter name
433 bad parameter name
434
434
435 $ hg bundle2 --param 42babar
435 $ hg bundle2 --param 42babar
436 abort: non letter first character: '42babar'
436 abort: non letter first character: '42babar'
437 [255]
437 [255]
438
438
439
439
440 Test part
440 Test part
441 =================
441 =================
442
442
443 $ hg bundle2 --parts ../parts.hg2 --debug --config progress.debug=true --config devel.bundle2.debug=true
443 $ hg bundle2 --parts ../parts.hg2 --debug --config progress.debug=true --config devel.bundle2.debug=true
444 bundle2-output-bundle: "HG20", 7 parts total
444 bundle2-output-bundle: "HG20", 7 parts total
445 bundle2-output: start emission of HG20 stream
445 bundle2-output: start emission of HG20 stream
446 bundle2-output: bundle parameter:
446 bundle2-output: bundle parameter:
447 bundle2-output: start of parts
447 bundle2-output: start of parts
448 bundle2-output: bundle part: "test:empty"
448 bundle2-output: bundle part: "test:empty"
449 bundle2-output-part: "test:empty" (advisory) empty payload
449 bundle2-output-part: "test:empty" (advisory) empty payload
450 bundle2-output: part 0: "test:empty"
450 bundle2-output: part 0: "test:empty"
451 bundle2-output: header chunk size: 17
451 bundle2-output: header chunk size: 17
452 bundle2-output: closing payload chunk
452 bundle2-output: closing payload chunk
453 bundle2-output: bundle part: "test:empty"
453 bundle2-output: bundle part: "test:empty"
454 bundle2-output-part: "test:empty" (advisory) empty payload
454 bundle2-output-part: "test:empty" (advisory) empty payload
455 bundle2-output: part 1: "test:empty"
455 bundle2-output: part 1: "test:empty"
456 bundle2-output: header chunk size: 17
456 bundle2-output: header chunk size: 17
457 bundle2-output: closing payload chunk
457 bundle2-output: closing payload chunk
458 bundle2-output: bundle part: "test:song"
458 bundle2-output: bundle part: "test:song"
459 bundle2-output-part: "test:song" (advisory) 178 bytes payload
459 bundle2-output-part: "test:song" (advisory) 178 bytes payload
460 bundle2-output: part 2: "test:song"
460 bundle2-output: part 2: "test:song"
461 bundle2-output: header chunk size: 16
461 bundle2-output: header chunk size: 16
462 bundle2-output: payload chunk size: 178
462 bundle2-output: payload chunk size: 178
463 bundle2-output: closing payload chunk
463 bundle2-output: closing payload chunk
464 bundle2-output: bundle part: "test:debugreply"
464 bundle2-output: bundle part: "test:debugreply"
465 bundle2-output-part: "test:debugreply" (advisory) empty payload
465 bundle2-output-part: "test:debugreply" (advisory) empty payload
466 bundle2-output: part 3: "test:debugreply"
466 bundle2-output: part 3: "test:debugreply"
467 bundle2-output: header chunk size: 22
467 bundle2-output: header chunk size: 22
468 bundle2-output: closing payload chunk
468 bundle2-output: closing payload chunk
469 bundle2-output: bundle part: "test:math"
469 bundle2-output: bundle part: "test:math"
470 bundle2-output-part: "test:math" (advisory) (params: 2 mandatory 2 advisory) 2 bytes payload
470 bundle2-output-part: "test:math" (advisory) (params: 2 mandatory 2 advisory) 2 bytes payload
471 bundle2-output: part 4: "test:math"
471 bundle2-output: part 4: "test:math"
472 bundle2-output: header chunk size: 43
472 bundle2-output: header chunk size: 43
473 bundle2-output: payload chunk size: 2
473 bundle2-output: payload chunk size: 2
474 bundle2-output: closing payload chunk
474 bundle2-output: closing payload chunk
475 bundle2-output: bundle part: "test:song"
475 bundle2-output: bundle part: "test:song"
476 bundle2-output-part: "test:song" (advisory) (params: 1 mandatory) empty payload
476 bundle2-output-part: "test:song" (advisory) (params: 1 mandatory) empty payload
477 bundle2-output: part 5: "test:song"
477 bundle2-output: part 5: "test:song"
478 bundle2-output: header chunk size: 29
478 bundle2-output: header chunk size: 29
479 bundle2-output: closing payload chunk
479 bundle2-output: closing payload chunk
480 bundle2-output: bundle part: "test:ping"
480 bundle2-output: bundle part: "test:ping"
481 bundle2-output-part: "test:ping" (advisory) empty payload
481 bundle2-output-part: "test:ping" (advisory) empty payload
482 bundle2-output: part 6: "test:ping"
482 bundle2-output: part 6: "test:ping"
483 bundle2-output: header chunk size: 16
483 bundle2-output: header chunk size: 16
484 bundle2-output: closing payload chunk
484 bundle2-output: closing payload chunk
485 bundle2-output: end of bundle
485 bundle2-output: end of bundle
486
486
487 $ f --hexdump ../parts.hg2
487 $ f --hexdump ../parts.hg2
488 ../parts.hg2:
488 ../parts.hg2:
489 0000: 48 47 32 30 00 00 00 00 00 00 00 11 0a 74 65 73 |HG20.........tes|
489 0000: 48 47 32 30 00 00 00 00 00 00 00 11 0a 74 65 73 |HG20.........tes|
490 0010: 74 3a 65 6d 70 74 79 00 00 00 00 00 00 00 00 00 |t:empty.........|
490 0010: 74 3a 65 6d 70 74 79 00 00 00 00 00 00 00 00 00 |t:empty.........|
491 0020: 00 00 00 00 11 0a 74 65 73 74 3a 65 6d 70 74 79 |......test:empty|
491 0020: 00 00 00 00 11 0a 74 65 73 74 3a 65 6d 70 74 79 |......test:empty|
492 0030: 00 00 00 01 00 00 00 00 00 00 00 00 00 10 09 74 |...............t|
492 0030: 00 00 00 01 00 00 00 00 00 00 00 00 00 10 09 74 |...............t|
493 0040: 65 73 74 3a 73 6f 6e 67 00 00 00 02 00 00 00 00 |est:song........|
493 0040: 65 73 74 3a 73 6f 6e 67 00 00 00 02 00 00 00 00 |est:song........|
494 0050: 00 b2 50 61 74 61 6c 69 20 44 69 72 61 70 61 74 |..Patali Dirapat|
494 0050: 00 b2 50 61 74 61 6c 69 20 44 69 72 61 70 61 74 |..Patali Dirapat|
495 0060: 61 2c 20 43 72 6f 6d 64 61 20 43 72 6f 6d 64 61 |a, Cromda Cromda|
495 0060: 61 2c 20 43 72 6f 6d 64 61 20 43 72 6f 6d 64 61 |a, Cromda Cromda|
496 0070: 20 52 69 70 61 6c 6f 2c 20 50 61 74 61 20 50 61 | Ripalo, Pata Pa|
496 0070: 20 52 69 70 61 6c 6f 2c 20 50 61 74 61 20 50 61 | Ripalo, Pata Pa|
497 0080: 74 61 2c 20 4b 6f 20 4b 6f 20 4b 6f 0a 42 6f 6b |ta, Ko Ko Ko.Bok|
497 0080: 74 61 2c 20 4b 6f 20 4b 6f 20 4b 6f 0a 42 6f 6b |ta, Ko Ko Ko.Bok|
498 0090: 6f 72 6f 20 44 69 70 6f 75 6c 69 74 6f 2c 20 52 |oro Dipoulito, R|
498 0090: 6f 72 6f 20 44 69 70 6f 75 6c 69 74 6f 2c 20 52 |oro Dipoulito, R|
499 00a0: 6f 6e 64 69 20 52 6f 6e 64 69 20 50 65 70 69 6e |ondi Rondi Pepin|
499 00a0: 6f 6e 64 69 20 52 6f 6e 64 69 20 50 65 70 69 6e |ondi Rondi Pepin|
500 00b0: 6f 2c 20 50 61 74 61 20 50 61 74 61 2c 20 4b 6f |o, Pata Pata, Ko|
500 00b0: 6f 2c 20 50 61 74 61 20 50 61 74 61 2c 20 4b 6f |o, Pata Pata, Ko|
501 00c0: 20 4b 6f 20 4b 6f 0a 45 6d 61 6e 61 20 4b 61 72 | Ko Ko.Emana Kar|
501 00c0: 20 4b 6f 20 4b 6f 0a 45 6d 61 6e 61 20 4b 61 72 | Ko Ko.Emana Kar|
502 00d0: 61 73 73 6f 6c 69 2c 20 4c 6f 75 63 72 61 20 4c |assoli, Loucra L|
502 00d0: 61 73 73 6f 6c 69 2c 20 4c 6f 75 63 72 61 20 4c |assoli, Loucra L|
503 00e0: 6f 75 63 72 61 20 50 6f 6e 70 6f 6e 74 6f 2c 20 |oucra Ponponto, |
503 00e0: 6f 75 63 72 61 20 50 6f 6e 70 6f 6e 74 6f 2c 20 |oucra Ponponto, |
504 00f0: 50 61 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f |Pata Pata, Ko Ko|
504 00f0: 50 61 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f |Pata Pata, Ko Ko|
505 0100: 20 4b 6f 2e 00 00 00 00 00 00 00 16 0f 74 65 73 | Ko..........tes|
505 0100: 20 4b 6f 2e 00 00 00 00 00 00 00 16 0f 74 65 73 | Ko..........tes|
506 0110: 74 3a 64 65 62 75 67 72 65 70 6c 79 00 00 00 03 |t:debugreply....|
506 0110: 74 3a 64 65 62 75 67 72 65 70 6c 79 00 00 00 03 |t:debugreply....|
507 0120: 00 00 00 00 00 00 00 00 00 2b 09 74 65 73 74 3a |.........+.test:|
507 0120: 00 00 00 00 00 00 00 00 00 2b 09 74 65 73 74 3a |.........+.test:|
508 0130: 6d 61 74 68 00 00 00 04 02 01 02 04 01 04 07 03 |math............|
508 0130: 6d 61 74 68 00 00 00 04 02 01 02 04 01 04 07 03 |math............|
509 0140: 70 69 33 2e 31 34 65 32 2e 37 32 63 6f 6f 6b 69 |pi3.14e2.72cooki|
509 0140: 70 69 33 2e 31 34 65 32 2e 37 32 63 6f 6f 6b 69 |pi3.14e2.72cooki|
510 0150: 6e 67 72 61 77 00 00 00 02 34 32 00 00 00 00 00 |ngraw....42.....|
510 0150: 6e 67 72 61 77 00 00 00 02 34 32 00 00 00 00 00 |ngraw....42.....|
511 0160: 00 00 1d 09 74 65 73 74 3a 73 6f 6e 67 00 00 00 |....test:song...|
511 0160: 00 00 1d 09 74 65 73 74 3a 73 6f 6e 67 00 00 00 |....test:song...|
512 0170: 05 01 00 0b 00 72 61 6e 64 6f 6d 70 61 72 61 6d |.....randomparam|
512 0170: 05 01 00 0b 00 72 61 6e 64 6f 6d 70 61 72 61 6d |.....randomparam|
513 0180: 00 00 00 00 00 00 00 10 09 74 65 73 74 3a 70 69 |.........test:pi|
513 0180: 00 00 00 00 00 00 00 10 09 74 65 73 74 3a 70 69 |.........test:pi|
514 0190: 6e 67 00 00 00 06 00 00 00 00 00 00 00 00 00 00 |ng..............|
514 0190: 6e 67 00 00 00 06 00 00 00 00 00 00 00 00 00 00 |ng..............|
515
515
516
516
517 $ hg statbundle2 < ../parts.hg2
517 $ hg statbundle2 < ../parts.hg2
518 options count: 0
518 options count: 0
519 :test:empty:
519 :test:empty:
520 mandatory: 0
520 mandatory: 0
521 advisory: 0
521 advisory: 0
522 payload: 0 bytes
522 payload: 0 bytes
523 :test:empty:
523 :test:empty:
524 mandatory: 0
524 mandatory: 0
525 advisory: 0
525 advisory: 0
526 payload: 0 bytes
526 payload: 0 bytes
527 :test:song:
527 :test:song:
528 mandatory: 0
528 mandatory: 0
529 advisory: 0
529 advisory: 0
530 payload: 178 bytes
530 payload: 178 bytes
531 :test:debugreply:
531 :test:debugreply:
532 mandatory: 0
532 mandatory: 0
533 advisory: 0
533 advisory: 0
534 payload: 0 bytes
534 payload: 0 bytes
535 :test:math:
535 :test:math:
536 mandatory: 2
536 mandatory: 2
537 advisory: 1
537 advisory: 1
538 payload: 2 bytes
538 payload: 2 bytes
539 :test:song:
539 :test:song:
540 mandatory: 1
540 mandatory: 1
541 advisory: 0
541 advisory: 0
542 payload: 0 bytes
542 payload: 0 bytes
543 :test:ping:
543 :test:ping:
544 mandatory: 0
544 mandatory: 0
545 advisory: 0
545 advisory: 0
546 payload: 0 bytes
546 payload: 0 bytes
547 parts count: 7
547 parts count: 7
548
548
549 $ hg statbundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true < ../parts.hg2
549 $ hg statbundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true < ../parts.hg2
550 bundle2-input: start processing of HG20 stream
550 bundle2-input: start processing of HG20 stream
551 bundle2-input: reading bundle2 stream parameters
551 bundle2-input: reading bundle2 stream parameters
552 options count: 0
552 options count: 0
553 bundle2-input: start extraction of bundle2 parts
553 bundle2-input: start extraction of bundle2 parts
554 bundle2-input: part header size: 17
554 bundle2-input: part header size: 17
555 bundle2-input: part type: "test:empty"
555 bundle2-input: part type: "test:empty"
556 bundle2-input: part id: "0"
556 bundle2-input: part id: "0"
557 bundle2-input: part parameters: 0
557 bundle2-input: part parameters: 0
558 :test:empty:
558 :test:empty:
559 mandatory: 0
559 mandatory: 0
560 advisory: 0
560 advisory: 0
561 bundle2-input: payload chunk size: 0
561 bundle2-input: payload chunk size: 0
562 payload: 0 bytes
562 payload: 0 bytes
563 bundle2-input: part header size: 17
563 bundle2-input: part header size: 17
564 bundle2-input: part type: "test:empty"
564 bundle2-input: part type: "test:empty"
565 bundle2-input: part id: "1"
565 bundle2-input: part id: "1"
566 bundle2-input: part parameters: 0
566 bundle2-input: part parameters: 0
567 :test:empty:
567 :test:empty:
568 mandatory: 0
568 mandatory: 0
569 advisory: 0
569 advisory: 0
570 bundle2-input: payload chunk size: 0
570 bundle2-input: payload chunk size: 0
571 payload: 0 bytes
571 payload: 0 bytes
572 bundle2-input: part header size: 16
572 bundle2-input: part header size: 16
573 bundle2-input: part type: "test:song"
573 bundle2-input: part type: "test:song"
574 bundle2-input: part id: "2"
574 bundle2-input: part id: "2"
575 bundle2-input: part parameters: 0
575 bundle2-input: part parameters: 0
576 :test:song:
576 :test:song:
577 mandatory: 0
577 mandatory: 0
578 advisory: 0
578 advisory: 0
579 bundle2-input: payload chunk size: 178
579 bundle2-input: payload chunk size: 178
580 bundle2-input: payload chunk size: 0
580 bundle2-input: payload chunk size: 0
581 bundle2-input-part: total payload size 178
581 bundle2-input-part: total payload size 178
582 payload: 178 bytes
582 payload: 178 bytes
583 bundle2-input: part header size: 22
583 bundle2-input: part header size: 22
584 bundle2-input: part type: "test:debugreply"
584 bundle2-input: part type: "test:debugreply"
585 bundle2-input: part id: "3"
585 bundle2-input: part id: "3"
586 bundle2-input: part parameters: 0
586 bundle2-input: part parameters: 0
587 :test:debugreply:
587 :test:debugreply:
588 mandatory: 0
588 mandatory: 0
589 advisory: 0
589 advisory: 0
590 bundle2-input: payload chunk size: 0
590 bundle2-input: payload chunk size: 0
591 payload: 0 bytes
591 payload: 0 bytes
592 bundle2-input: part header size: 43
592 bundle2-input: part header size: 43
593 bundle2-input: part type: "test:math"
593 bundle2-input: part type: "test:math"
594 bundle2-input: part id: "4"
594 bundle2-input: part id: "4"
595 bundle2-input: part parameters: 3
595 bundle2-input: part parameters: 3
596 :test:math:
596 :test:math:
597 mandatory: 2
597 mandatory: 2
598 advisory: 1
598 advisory: 1
599 bundle2-input: payload chunk size: 2
599 bundle2-input: payload chunk size: 2
600 bundle2-input: payload chunk size: 0
600 bundle2-input: payload chunk size: 0
601 bundle2-input-part: total payload size 2
601 bundle2-input-part: total payload size 2
602 payload: 2 bytes
602 payload: 2 bytes
603 bundle2-input: part header size: 29
603 bundle2-input: part header size: 29
604 bundle2-input: part type: "test:song"
604 bundle2-input: part type: "test:song"
605 bundle2-input: part id: "5"
605 bundle2-input: part id: "5"
606 bundle2-input: part parameters: 1
606 bundle2-input: part parameters: 1
607 :test:song:
607 :test:song:
608 mandatory: 1
608 mandatory: 1
609 advisory: 0
609 advisory: 0
610 bundle2-input: payload chunk size: 0
610 bundle2-input: payload chunk size: 0
611 payload: 0 bytes
611 payload: 0 bytes
612 bundle2-input: part header size: 16
612 bundle2-input: part header size: 16
613 bundle2-input: part type: "test:ping"
613 bundle2-input: part type: "test:ping"
614 bundle2-input: part id: "6"
614 bundle2-input: part id: "6"
615 bundle2-input: part parameters: 0
615 bundle2-input: part parameters: 0
616 :test:ping:
616 :test:ping:
617 mandatory: 0
617 mandatory: 0
618 advisory: 0
618 advisory: 0
619 bundle2-input: payload chunk size: 0
619 bundle2-input: payload chunk size: 0
620 payload: 0 bytes
620 payload: 0 bytes
621 bundle2-input: part header size: 0
621 bundle2-input: part header size: 0
622 bundle2-input: end of bundle2 stream
622 bundle2-input: end of bundle2 stream
623 parts count: 7
623 parts count: 7
624
624
625 Test actual unbundling of test part
625 Test actual unbundling of test part
626 =======================================
626 =======================================
627
627
628 Process the bundle
628 Process the bundle
629
629
630 $ hg unbundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true < ../parts.hg2
630 $ hg unbundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true < ../parts.hg2
631 bundle2-input: start processing of HG20 stream
631 bundle2-input: start processing of HG20 stream
632 bundle2-input: reading bundle2 stream parameters
632 bundle2-input: reading bundle2 stream parameters
633 bundle2-input-bundle: with-transaction
633 bundle2-input-bundle: with-transaction
634 bundle2-input: start extraction of bundle2 parts
634 bundle2-input: start extraction of bundle2 parts
635 bundle2-input: part header size: 17
635 bundle2-input: part header size: 17
636 bundle2-input: part type: "test:empty"
636 bundle2-input: part type: "test:empty"
637 bundle2-input: part id: "0"
637 bundle2-input: part id: "0"
638 bundle2-input: part parameters: 0
638 bundle2-input: part parameters: 0
639 bundle2-input: ignoring unsupported advisory part test:empty
639 bundle2-input: ignoring unsupported advisory part test:empty
640 bundle2-input-part: "test:empty" (advisory) unsupported-type
640 bundle2-input-part: "test:empty" (advisory) unsupported-type
641 bundle2-input: payload chunk size: 0
641 bundle2-input: payload chunk size: 0
642 bundle2-input: part header size: 17
642 bundle2-input: part header size: 17
643 bundle2-input: part type: "test:empty"
643 bundle2-input: part type: "test:empty"
644 bundle2-input: part id: "1"
644 bundle2-input: part id: "1"
645 bundle2-input: part parameters: 0
645 bundle2-input: part parameters: 0
646 bundle2-input: ignoring unsupported advisory part test:empty
646 bundle2-input: ignoring unsupported advisory part test:empty
647 bundle2-input-part: "test:empty" (advisory) unsupported-type
647 bundle2-input-part: "test:empty" (advisory) unsupported-type
648 bundle2-input: payload chunk size: 0
648 bundle2-input: payload chunk size: 0
649 bundle2-input: part header size: 16
649 bundle2-input: part header size: 16
650 bundle2-input: part type: "test:song"
650 bundle2-input: part type: "test:song"
651 bundle2-input: part id: "2"
651 bundle2-input: part id: "2"
652 bundle2-input: part parameters: 0
652 bundle2-input: part parameters: 0
653 bundle2-input: found a handler for part 'test:song'
653 bundle2-input: found a handler for part 'test:song'
654 bundle2-input-part: "test:song" (advisory) supported
654 bundle2-input-part: "test:song" (advisory) supported
655 The choir starts singing:
655 The choir starts singing:
656 bundle2-input: payload chunk size: 178
656 bundle2-input: payload chunk size: 178
657 bundle2-input: payload chunk size: 0
657 bundle2-input: payload chunk size: 0
658 bundle2-input-part: total payload size 178
658 bundle2-input-part: total payload size 178
659 Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
659 Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
660 Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
660 Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
661 Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.
661 Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.
662 bundle2-input: part header size: 22
662 bundle2-input: part header size: 22
663 bundle2-input: part type: "test:debugreply"
663 bundle2-input: part type: "test:debugreply"
664 bundle2-input: part id: "3"
664 bundle2-input: part id: "3"
665 bundle2-input: part parameters: 0
665 bundle2-input: part parameters: 0
666 bundle2-input: found a handler for part 'test:debugreply'
666 bundle2-input: found a handler for part 'test:debugreply'
667 bundle2-input-part: "test:debugreply" (advisory) supported
667 bundle2-input-part: "test:debugreply" (advisory) supported
668 debugreply: no reply
668 debugreply: no reply
669 bundle2-input: payload chunk size: 0
669 bundle2-input: payload chunk size: 0
670 bundle2-input: part header size: 43
670 bundle2-input: part header size: 43
671 bundle2-input: part type: "test:math"
671 bundle2-input: part type: "test:math"
672 bundle2-input: part id: "4"
672 bundle2-input: part id: "4"
673 bundle2-input: part parameters: 3
673 bundle2-input: part parameters: 3
674 bundle2-input: ignoring unsupported advisory part test:math
674 bundle2-input: ignoring unsupported advisory part test:math
675 bundle2-input-part: "test:math" (advisory) (params: 2 mandatory 2 advisory) unsupported-type
675 bundle2-input-part: "test:math" (advisory) (params: 2 mandatory 2 advisory) unsupported-type
676 bundle2-input: payload chunk size: 2
676 bundle2-input: payload chunk size: 2
677 bundle2-input: payload chunk size: 0
677 bundle2-input: payload chunk size: 0
678 bundle2-input-part: total payload size 2
678 bundle2-input-part: total payload size 2
679 bundle2-input: part header size: 29
679 bundle2-input: part header size: 29
680 bundle2-input: part type: "test:song"
680 bundle2-input: part type: "test:song"
681 bundle2-input: part id: "5"
681 bundle2-input: part id: "5"
682 bundle2-input: part parameters: 1
682 bundle2-input: part parameters: 1
683 bundle2-input: found a handler for part 'test:song'
683 bundle2-input: found a handler for part 'test:song'
684 bundle2-input: ignoring unsupported advisory part test:song - randomparam
684 bundle2-input: ignoring unsupported advisory part test:song - randomparam
685 bundle2-input-part: "test:song" (advisory) (params: 1 mandatory) unsupported-params (['randomparam'])
685 bundle2-input-part: "test:song" (advisory) (params: 1 mandatory) unsupported-params (['randomparam'])
686 bundle2-input: payload chunk size: 0
686 bundle2-input: payload chunk size: 0
687 bundle2-input: part header size: 16
687 bundle2-input: part header size: 16
688 bundle2-input: part type: "test:ping"
688 bundle2-input: part type: "test:ping"
689 bundle2-input: part id: "6"
689 bundle2-input: part id: "6"
690 bundle2-input: part parameters: 0
690 bundle2-input: part parameters: 0
691 bundle2-input: found a handler for part 'test:ping'
691 bundle2-input: found a handler for part 'test:ping'
692 bundle2-input-part: "test:ping" (advisory) supported
692 bundle2-input-part: "test:ping" (advisory) supported
693 received ping request (id 6)
693 received ping request (id 6)
694 bundle2-input: payload chunk size: 0
694 bundle2-input: payload chunk size: 0
695 bundle2-input: part header size: 0
695 bundle2-input: part header size: 0
696 bundle2-input: end of bundle2 stream
696 bundle2-input: end of bundle2 stream
697 bundle2-input-bundle: 6 parts total
697 bundle2-input-bundle: 6 parts total
698 0 unread bytes
698 0 unread bytes
699 3 total verses sung
699 3 total verses sung
700
700
701 Unbundle with an unknown mandatory part
701 Unbundle with an unknown mandatory part
702 (should abort)
702 (should abort)
703
703
704 $ hg bundle2 --parts --unknown ../unknown.hg2
704 $ hg bundle2 --parts --unknown ../unknown.hg2
705
705
706 $ hg unbundle2 < ../unknown.hg2
706 $ hg unbundle2 < ../unknown.hg2
707 The choir starts singing:
707 The choir starts singing:
708 Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
708 Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
709 Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
709 Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
710 Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.
710 Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.
711 debugreply: no reply
711 debugreply: no reply
712 0 unread bytes
712 0 unread bytes
713 abort: missing support for test:unknown
713 abort: missing support for test:unknown
714 [255]
714 [255]
715
715
716 Unbundle with an unknown mandatory part parameters
716 Unbundle with an unknown mandatory part parameters
717 (should abort)
717 (should abort)
718
718
719 $ hg bundle2 --unknownparams ../unknown.hg2
719 $ hg bundle2 --unknownparams ../unknown.hg2
720
720
721 $ hg unbundle2 < ../unknown.hg2
721 $ hg unbundle2 < ../unknown.hg2
722 0 unread bytes
722 0 unread bytes
723 abort: missing support for test:song - randomparams
723 abort: missing support for test:song - randomparams
724 [255]
724 [255]
725
725
726 unbundle with a reply
726 unbundle with a reply
727
727
728 $ hg bundle2 --parts --reply ../parts-reply.hg2
728 $ hg bundle2 --parts --reply ../parts-reply.hg2
729 $ hg unbundle2 ../reply.hg2 < ../parts-reply.hg2
729 $ hg unbundle2 ../reply.hg2 < ../parts-reply.hg2
730 0 unread bytes
730 0 unread bytes
731 3 total verses sung
731 3 total verses sung
732
732
733 The reply is a bundle
733 The reply is a bundle
734
734
735 $ f --hexdump ../reply.hg2
735 $ f --hexdump ../reply.hg2
736 ../reply.hg2:
736 ../reply.hg2:
737 0000: 48 47 32 30 00 00 00 00 00 00 00 1b 06 6f 75 74 |HG20.........out|
737 0000: 48 47 32 30 00 00 00 00 00 00 00 1b 06 6f 75 74 |HG20.........out|
738 0010: 70 75 74 00 00 00 00 00 01 0b 01 69 6e 2d 72 65 |put........in-re|
738 0010: 70 75 74 00 00 00 00 00 01 0b 01 69 6e 2d 72 65 |put........in-re|
739 0020: 70 6c 79 2d 74 6f 33 00 00 00 d9 54 68 65 20 63 |ply-to3....The c|
739 0020: 70 6c 79 2d 74 6f 33 00 00 00 d9 54 68 65 20 63 |ply-to3....The c|
740 0030: 68 6f 69 72 20 73 74 61 72 74 73 20 73 69 6e 67 |hoir starts sing|
740 0030: 68 6f 69 72 20 73 74 61 72 74 73 20 73 69 6e 67 |hoir starts sing|
741 0040: 69 6e 67 3a 0a 20 20 20 20 50 61 74 61 6c 69 20 |ing:. Patali |
741 0040: 69 6e 67 3a 0a 20 20 20 20 50 61 74 61 6c 69 20 |ing:. Patali |
742 0050: 44 69 72 61 70 61 74 61 2c 20 43 72 6f 6d 64 61 |Dirapata, Cromda|
742 0050: 44 69 72 61 70 61 74 61 2c 20 43 72 6f 6d 64 61 |Dirapata, Cromda|
743 0060: 20 43 72 6f 6d 64 61 20 52 69 70 61 6c 6f 2c 20 | Cromda Ripalo, |
743 0060: 20 43 72 6f 6d 64 61 20 52 69 70 61 6c 6f 2c 20 | Cromda Ripalo, |
744 0070: 50 61 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f |Pata Pata, Ko Ko|
744 0070: 50 61 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f |Pata Pata, Ko Ko|
745 0080: 20 4b 6f 0a 20 20 20 20 42 6f 6b 6f 72 6f 20 44 | Ko. Bokoro D|
745 0080: 20 4b 6f 0a 20 20 20 20 42 6f 6b 6f 72 6f 20 44 | Ko. Bokoro D|
746 0090: 69 70 6f 75 6c 69 74 6f 2c 20 52 6f 6e 64 69 20 |ipoulito, Rondi |
746 0090: 69 70 6f 75 6c 69 74 6f 2c 20 52 6f 6e 64 69 20 |ipoulito, Rondi |
747 00a0: 52 6f 6e 64 69 20 50 65 70 69 6e 6f 2c 20 50 61 |Rondi Pepino, Pa|
747 00a0: 52 6f 6e 64 69 20 50 65 70 69 6e 6f 2c 20 50 61 |Rondi Pepino, Pa|
748 00b0: 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f 20 4b |ta Pata, Ko Ko K|
748 00b0: 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f 20 4b |ta Pata, Ko Ko K|
749 00c0: 6f 0a 20 20 20 20 45 6d 61 6e 61 20 4b 61 72 61 |o. Emana Kara|
749 00c0: 6f 0a 20 20 20 20 45 6d 61 6e 61 20 4b 61 72 61 |o. Emana Kara|
750 00d0: 73 73 6f 6c 69 2c 20 4c 6f 75 63 72 61 20 4c 6f |ssoli, Loucra Lo|
750 00d0: 73 73 6f 6c 69 2c 20 4c 6f 75 63 72 61 20 4c 6f |ssoli, Loucra Lo|
751 00e0: 75 63 72 61 20 50 6f 6e 70 6f 6e 74 6f 2c 20 50 |ucra Ponponto, P|
751 00e0: 75 63 72 61 20 50 6f 6e 70 6f 6e 74 6f 2c 20 50 |ucra Ponponto, P|
752 00f0: 61 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f 20 |ata Pata, Ko Ko |
752 00f0: 61 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f 20 |ata Pata, Ko Ko |
753 0100: 4b 6f 2e 0a 00 00 00 00 00 00 00 1b 06 6f 75 74 |Ko...........out|
753 0100: 4b 6f 2e 0a 00 00 00 00 00 00 00 1b 06 6f 75 74 |Ko...........out|
754 0110: 70 75 74 00 00 00 01 00 01 0b 01 69 6e 2d 72 65 |put........in-re|
754 0110: 70 75 74 00 00 00 01 00 01 0b 01 69 6e 2d 72 65 |put........in-re|
755 0120: 70 6c 79 2d 74 6f 34 00 00 00 c9 64 65 62 75 67 |ply-to4....debug|
755 0120: 70 6c 79 2d 74 6f 34 00 00 00 c9 64 65 62 75 67 |ply-to4....debug|
756 0130: 72 65 70 6c 79 3a 20 63 61 70 61 62 69 6c 69 74 |reply: capabilit|
756 0130: 72 65 70 6c 79 3a 20 63 61 70 61 62 69 6c 69 74 |reply: capabilit|
757 0140: 69 65 73 3a 0a 64 65 62 75 67 72 65 70 6c 79 3a |ies:.debugreply:|
757 0140: 69 65 73 3a 0a 64 65 62 75 67 72 65 70 6c 79 3a |ies:.debugreply:|
758 0150: 20 20 20 20 20 27 63 69 74 79 3d 21 27 0a 64 65 | 'city=!'.de|
758 0150: 20 20 20 20 20 27 63 69 74 79 3d 21 27 0a 64 65 | 'city=!'.de|
759 0160: 62 75 67 72 65 70 6c 79 3a 20 20 20 20 20 20 20 |bugreply: |
759 0160: 62 75 67 72 65 70 6c 79 3a 20 20 20 20 20 20 20 |bugreply: |
760 0170: 20 20 27 63 65 6c 65 73 74 65 2c 76 69 6c 6c 65 | 'celeste,ville|
760 0170: 20 20 27 63 65 6c 65 73 74 65 2c 76 69 6c 6c 65 | 'celeste,ville|
761 0180: 27 0a 64 65 62 75 67 72 65 70 6c 79 3a 20 20 20 |'.debugreply: |
761 0180: 27 0a 64 65 62 75 67 72 65 70 6c 79 3a 20 20 20 |'.debugreply: |
762 0190: 20 20 27 65 6c 65 70 68 61 6e 74 73 27 0a 64 65 | 'elephants'.de|
762 0190: 20 20 27 65 6c 65 70 68 61 6e 74 73 27 0a 64 65 | 'elephants'.de|
763 01a0: 62 75 67 72 65 70 6c 79 3a 20 20 20 20 20 20 20 |bugreply: |
763 01a0: 62 75 67 72 65 70 6c 79 3a 20 20 20 20 20 20 20 |bugreply: |
764 01b0: 20 20 27 62 61 62 61 72 27 0a 64 65 62 75 67 72 | 'babar'.debugr|
764 01b0: 20 20 27 62 61 62 61 72 27 0a 64 65 62 75 67 72 | 'babar'.debugr|
765 01c0: 65 70 6c 79 3a 20 20 20 20 20 20 20 20 20 27 63 |eply: 'c|
765 01c0: 65 70 6c 79 3a 20 20 20 20 20 20 20 20 20 27 63 |eply: 'c|
766 01d0: 65 6c 65 73 74 65 27 0a 64 65 62 75 67 72 65 70 |eleste'.debugrep|
766 01d0: 65 6c 65 73 74 65 27 0a 64 65 62 75 67 72 65 70 |eleste'.debugrep|
767 01e0: 6c 79 3a 20 20 20 20 20 27 70 69 6e 67 2d 70 6f |ly: 'ping-po|
767 01e0: 6c 79 3a 20 20 20 20 20 27 70 69 6e 67 2d 70 6f |ly: 'ping-po|
768 01f0: 6e 67 27 0a 00 00 00 00 00 00 00 1e 09 74 65 73 |ng'..........tes|
768 01f0: 6e 67 27 0a 00 00 00 00 00 00 00 1e 09 74 65 73 |ng'..........tes|
769 0200: 74 3a 70 6f 6e 67 00 00 00 02 01 00 0b 01 69 6e |t:pong........in|
769 0200: 74 3a 70 6f 6e 67 00 00 00 02 01 00 0b 01 69 6e |t:pong........in|
770 0210: 2d 72 65 70 6c 79 2d 74 6f 37 00 00 00 00 00 00 |-reply-to7......|
770 0210: 2d 72 65 70 6c 79 2d 74 6f 37 00 00 00 00 00 00 |-reply-to7......|
771 0220: 00 1b 06 6f 75 74 70 75 74 00 00 00 03 00 01 0b |...output.......|
771 0220: 00 1b 06 6f 75 74 70 75 74 00 00 00 03 00 01 0b |...output.......|
772 0230: 01 69 6e 2d 72 65 70 6c 79 2d 74 6f 37 00 00 00 |.in-reply-to7...|
772 0230: 01 69 6e 2d 72 65 70 6c 79 2d 74 6f 37 00 00 00 |.in-reply-to7...|
773 0240: 3d 72 65 63 65 69 76 65 64 20 70 69 6e 67 20 72 |=received ping r|
773 0240: 3d 72 65 63 65 69 76 65 64 20 70 69 6e 67 20 72 |=received ping r|
774 0250: 65 71 75 65 73 74 20 28 69 64 20 37 29 0a 72 65 |equest (id 7).re|
774 0250: 65 71 75 65 73 74 20 28 69 64 20 37 29 0a 72 65 |equest (id 7).re|
775 0260: 70 6c 79 69 6e 67 20 74 6f 20 70 69 6e 67 20 72 |plying to ping r|
775 0260: 70 6c 79 69 6e 67 20 74 6f 20 70 69 6e 67 20 72 |plying to ping r|
776 0270: 65 71 75 65 73 74 20 28 69 64 20 37 29 0a 00 00 |equest (id 7)...|
776 0270: 65 71 75 65 73 74 20 28 69 64 20 37 29 0a 00 00 |equest (id 7)...|
777 0280: 00 00 00 00 00 00 |......|
777 0280: 00 00 00 00 00 00 |......|
778
778
779 The reply is valid
779 The reply is valid
780
780
781 $ hg statbundle2 < ../reply.hg2
781 $ hg statbundle2 < ../reply.hg2
782 options count: 0
782 options count: 0
783 :output:
783 :output:
784 mandatory: 0
784 mandatory: 0
785 advisory: 1
785 advisory: 1
786 payload: 217 bytes
786 payload: 217 bytes
787 :output:
787 :output:
788 mandatory: 0
788 mandatory: 0
789 advisory: 1
789 advisory: 1
790 payload: 201 bytes
790 payload: 201 bytes
791 :test:pong:
791 :test:pong:
792 mandatory: 1
792 mandatory: 1
793 advisory: 0
793 advisory: 0
794 payload: 0 bytes
794 payload: 0 bytes
795 :output:
795 :output:
796 mandatory: 0
796 mandatory: 0
797 advisory: 1
797 advisory: 1
798 payload: 61 bytes
798 payload: 61 bytes
799 parts count: 4
799 parts count: 4
800
800
801 Unbundle the reply to get the output:
801 Unbundle the reply to get the output:
802
802
803 $ hg unbundle2 < ../reply.hg2
803 $ hg unbundle2 < ../reply.hg2
804 remote: The choir starts singing:
804 remote: The choir starts singing:
805 remote: Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
805 remote: Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
806 remote: Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
806 remote: Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
807 remote: Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.
807 remote: Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.
808 remote: debugreply: capabilities:
808 remote: debugreply: capabilities:
809 remote: debugreply: 'city=!'
809 remote: debugreply: 'city=!'
810 remote: debugreply: 'celeste,ville'
810 remote: debugreply: 'celeste,ville'
811 remote: debugreply: 'elephants'
811 remote: debugreply: 'elephants'
812 remote: debugreply: 'babar'
812 remote: debugreply: 'babar'
813 remote: debugreply: 'celeste'
813 remote: debugreply: 'celeste'
814 remote: debugreply: 'ping-pong'
814 remote: debugreply: 'ping-pong'
815 remote: received ping request (id 7)
815 remote: received ping request (id 7)
816 remote: replying to ping request (id 7)
816 remote: replying to ping request (id 7)
817 0 unread bytes
817 0 unread bytes
818
818
819 Test push race detection
819 Test push race detection
820
820
821 $ hg bundle2 --pushrace ../part-race.hg2
821 $ hg bundle2 --pushrace ../part-race.hg2
822
822
823 $ hg unbundle2 < ../part-race.hg2
823 $ hg unbundle2 < ../part-race.hg2
824 0 unread bytes
824 0 unread bytes
825 abort: push race: repository changed while pushing - please try again
825 abort: push race: repository changed while pushing - please try again
826 [255]
826 [255]
827
827
828 Support for changegroup
828 Support for changegroup
829 ===================================
829 ===================================
830
830
831 $ hg unbundle $TESTDIR/bundles/rebase.hg
831 $ hg unbundle $TESTDIR/bundles/rebase.hg
832 adding changesets
832 adding changesets
833 adding manifests
833 adding manifests
834 adding file changes
834 adding file changes
835 added 8 changesets with 7 changes to 7 files (+3 heads)
835 added 8 changesets with 7 changes to 7 files (+3 heads)
836 (run 'hg heads' to see heads, 'hg merge' to merge)
836 (run 'hg heads' to see heads, 'hg merge' to merge)
837
837
838 $ hg log -G
838 $ hg log -G
839 o 8:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> H
839 o 8:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> H
840 |
840 |
841 | o 7:eea13746799a draft Nicolas Dumazet <nicdumz.commits@gmail.com> G
841 | o 7:eea13746799a draft Nicolas Dumazet <nicdumz.commits@gmail.com> G
842 |/|
842 |/|
843 o | 6:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F
843 o | 6:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F
844 | |
844 | |
845 | o 5:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
845 | o 5:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
846 |/
846 |/
847 | o 4:32af7686d403 draft Nicolas Dumazet <nicdumz.commits@gmail.com> D
847 | o 4:32af7686d403 draft Nicolas Dumazet <nicdumz.commits@gmail.com> D
848 | |
848 | |
849 | o 3:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> C
849 | o 3:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> C
850 | |
850 | |
851 | o 2:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> B
851 | o 2:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> B
852 |/
852 |/
853 o 1:cd010b8cd998 draft Nicolas Dumazet <nicdumz.commits@gmail.com> A
853 o 1:cd010b8cd998 draft Nicolas Dumazet <nicdumz.commits@gmail.com> A
854
854
855 @ 0:3903775176ed draft test a
855 @ 0:3903775176ed draft test a
856
856
857
857
858 $ hg bundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true --rev '8+7+5+4' ../rev.hg2
858 $ hg bundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true --rev '8+7+5+4' ../rev.hg2
859 4 changesets found
859 4 changesets found
860 list of changesets:
860 list of changesets:
861 32af7686d403cf45b5d95f2d70cebea587ac806a
861 32af7686d403cf45b5d95f2d70cebea587ac806a
862 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
862 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
863 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
863 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
864 02de42196ebee42ef284b6780a87cdc96e8eaab6
864 02de42196ebee42ef284b6780a87cdc96e8eaab6
865 bundle2-output-bundle: "HG20", 1 parts total
865 bundle2-output-bundle: "HG20", 1 parts total
866 bundle2-output: start emission of HG20 stream
866 bundle2-output: start emission of HG20 stream
867 bundle2-output: bundle parameter:
867 bundle2-output: bundle parameter:
868 bundle2-output: start of parts
868 bundle2-output: start of parts
869 bundle2-output: bundle part: "changegroup"
869 bundle2-output: bundle part: "changegroup"
870 bundle2-output-part: "changegroup" (advisory) streamed payload
870 bundle2-output-part: "changegroup" (advisory) streamed payload
871 bundle2-output: part 0: "changegroup"
871 bundle2-output: part 0: "changegroup"
872 bundle2-output: header chunk size: 18
872 bundle2-output: header chunk size: 18
873 bundling: 1/4 changesets (25.00%)
873 bundling: 1/4 changesets (25.00%)
874 bundling: 2/4 changesets (50.00%)
874 bundling: 2/4 changesets (50.00%)
875 bundling: 3/4 changesets (75.00%)
875 bundling: 3/4 changesets (75.00%)
876 bundling: 4/4 changesets (100.00%)
876 bundling: 4/4 changesets (100.00%)
877 bundling: 1/4 manifests (25.00%)
877 bundling: 1/4 manifests (25.00%)
878 bundling: 2/4 manifests (50.00%)
878 bundling: 2/4 manifests (50.00%)
879 bundling: 3/4 manifests (75.00%)
879 bundling: 3/4 manifests (75.00%)
880 bundling: 4/4 manifests (100.00%)
880 bundling: 4/4 manifests (100.00%)
881 bundling: D 1/3 files (33.33%)
881 bundling: D 1/3 files (33.33%)
882 bundling: E 2/3 files (66.67%)
882 bundling: E 2/3 files (66.67%)
883 bundling: H 3/3 files (100.00%)
883 bundling: H 3/3 files (100.00%)
884 bundle2-output: payload chunk size: 1555
884 bundle2-output: payload chunk size: 1555
885 bundle2-output: closing payload chunk
885 bundle2-output: closing payload chunk
886 bundle2-output: end of bundle
886 bundle2-output: end of bundle
887
887
888 $ f --hexdump ../rev.hg2
888 $ f --hexdump ../rev.hg2
889 ../rev.hg2:
889 ../rev.hg2:
890 0000: 48 47 32 30 00 00 00 00 00 00 00 12 0b 63 68 61 |HG20.........cha|
890 0000: 48 47 32 30 00 00 00 00 00 00 00 12 0b 63 68 61 |HG20.........cha|
891 0010: 6e 67 65 67 72 6f 75 70 00 00 00 00 00 00 00 00 |ngegroup........|
891 0010: 6e 67 65 67 72 6f 75 70 00 00 00 00 00 00 00 00 |ngegroup........|
892 0020: 06 13 00 00 00 a4 32 af 76 86 d4 03 cf 45 b5 d9 |......2.v....E..|
892 0020: 06 13 00 00 00 a4 32 af 76 86 d4 03 cf 45 b5 d9 |......2.v....E..|
893 0030: 5f 2d 70 ce be a5 87 ac 80 6a 5f dd d9 89 57 c8 |_-p......j_...W.|
893 0030: 5f 2d 70 ce be a5 87 ac 80 6a 5f dd d9 89 57 c8 |_-p......j_...W.|
894 0040: a5 4a 4d 43 6d fe 1d a9 d8 7f 21 a1 b9 7b 00 00 |.JMCm.....!..{..|
894 0040: a5 4a 4d 43 6d fe 1d a9 d8 7f 21 a1 b9 7b 00 00 |.JMCm.....!..{..|
895 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
895 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
896 0060: 00 00 32 af 76 86 d4 03 cf 45 b5 d9 5f 2d 70 ce |..2.v....E.._-p.|
896 0060: 00 00 32 af 76 86 d4 03 cf 45 b5 d9 5f 2d 70 ce |..2.v....E.._-p.|
897 0070: be a5 87 ac 80 6a 00 00 00 00 00 00 00 29 00 00 |.....j.......)..|
897 0070: be a5 87 ac 80 6a 00 00 00 00 00 00 00 29 00 00 |.....j.......)..|
898 0080: 00 29 36 65 31 66 34 63 34 37 65 63 62 35 33 33 |.)6e1f4c47ecb533|
898 0080: 00 29 36 65 31 66 34 63 34 37 65 63 62 35 33 33 |.)6e1f4c47ecb533|
899 0090: 66 66 64 30 63 38 65 35 32 63 64 63 38 38 61 66 |ffd0c8e52cdc88af|
899 0090: 66 66 64 30 63 38 65 35 32 63 64 63 38 38 61 66 |ffd0c8e52cdc88af|
900 00a0: 62 36 63 64 33 39 65 32 30 63 0a 00 00 00 66 00 |b6cd39e20c....f.|
900 00a0: 62 36 63 64 33 39 65 32 30 63 0a 00 00 00 66 00 |b6cd39e20c....f.|
901 00b0: 00 00 68 00 00 00 02 44 0a 00 00 00 69 00 00 00 |..h....D....i...|
901 00b0: 00 00 68 00 00 00 02 44 0a 00 00 00 69 00 00 00 |..h....D....i...|
902 00c0: 6a 00 00 00 01 44 00 00 00 a4 95 20 ee a7 81 bc |j....D..... ....|
902 00c0: 6a 00 00 00 01 44 00 00 00 a4 95 20 ee a7 81 bc |j....D..... ....|
903 00d0: ca 16 c1 e1 5a cc 0b a1 43 35 a0 e8 e5 ba cd 01 |....Z...C5......|
903 00d0: ca 16 c1 e1 5a cc 0b a1 43 35 a0 e8 e5 ba cd 01 |....Z...C5......|
904 00e0: 0b 8c d9 98 f3 98 1a 5a 81 15 f9 4f 8d a4 ab 50 |.......Z...O...P|
904 00e0: 0b 8c d9 98 f3 98 1a 5a 81 15 f9 4f 8d a4 ab 50 |.......Z...O...P|
905 00f0: 60 89 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |`...............|
905 00f0: 60 89 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |`...............|
906 0100: 00 00 00 00 00 00 95 20 ee a7 81 bc ca 16 c1 e1 |....... ........|
906 0100: 00 00 00 00 00 00 95 20 ee a7 81 bc ca 16 c1 e1 |....... ........|
907 0110: 5a cc 0b a1 43 35 a0 e8 e5 ba 00 00 00 00 00 00 |Z...C5..........|
907 0110: 5a cc 0b a1 43 35 a0 e8 e5 ba 00 00 00 00 00 00 |Z...C5..........|
908 0120: 00 29 00 00 00 29 34 64 65 63 65 39 63 38 32 36 |.)...)4dece9c826|
908 0120: 00 29 00 00 00 29 34 64 65 63 65 39 63 38 32 36 |.)...)4dece9c826|
909 0130: 66 36 39 34 39 30 35 30 37 62 39 38 63 36 33 38 |f69490507b98c638|
909 0130: 66 36 39 34 39 30 35 30 37 62 39 38 63 36 33 38 |f69490507b98c638|
910 0140: 33 61 33 30 30 39 62 32 39 35 38 33 37 64 0a 00 |3a3009b295837d..|
910 0140: 33 61 33 30 30 39 62 32 39 35 38 33 37 64 0a 00 |3a3009b295837d..|
911 0150: 00 00 66 00 00 00 68 00 00 00 02 45 0a 00 00 00 |..f...h....E....|
911 0150: 00 00 66 00 00 00 68 00 00 00 02 45 0a 00 00 00 |..f...h....E....|
912 0160: 69 00 00 00 6a 00 00 00 01 45 00 00 00 a2 ee a1 |i...j....E......|
912 0160: 69 00 00 00 6a 00 00 00 01 45 00 00 00 a2 ee a1 |i...j....E......|
913 0170: 37 46 79 9a 9e 0b fd 88 f2 9d 3c 2e 9d c9 38 9f |7Fy.......<...8.|
913 0170: 37 46 79 9a 9e 0b fd 88 f2 9d 3c 2e 9d c9 38 9f |7Fy.......<...8.|
914 0180: 52 4f 24 b6 38 7c 8c 8c ae 37 17 88 80 f3 fa 95 |RO$.8|...7......|
914 0180: 52 4f 24 b6 38 7c 8c 8c ae 37 17 88 80 f3 fa 95 |RO$.8|...7......|
915 0190: de d3 cb 1c f7 85 95 20 ee a7 81 bc ca 16 c1 e1 |....... ........|
915 0190: de d3 cb 1c f7 85 95 20 ee a7 81 bc ca 16 c1 e1 |....... ........|
916 01a0: 5a cc 0b a1 43 35 a0 e8 e5 ba ee a1 37 46 79 9a |Z...C5......7Fy.|
916 01a0: 5a cc 0b a1 43 35 a0 e8 e5 ba ee a1 37 46 79 9a |Z...C5......7Fy.|
917 01b0: 9e 0b fd 88 f2 9d 3c 2e 9d c9 38 9f 52 4f 00 00 |......<...8.RO..|
917 01b0: 9e 0b fd 88 f2 9d 3c 2e 9d c9 38 9f 52 4f 00 00 |......<...8.RO..|
918 01c0: 00 00 00 00 00 29 00 00 00 29 33 36 35 62 39 33 |.....)...)365b93|
918 01c0: 00 00 00 00 00 29 00 00 00 29 33 36 35 62 39 33 |.....)...)365b93|
919 01d0: 64 35 37 66 64 66 34 38 31 34 65 32 62 35 39 31 |d57fdf4814e2b591|
919 01d0: 64 35 37 66 64 66 34 38 31 34 65 32 62 35 39 31 |d57fdf4814e2b591|
920 01e0: 31 64 36 62 61 63 66 66 32 62 31 32 30 31 34 34 |1d6bacff2b120144|
920 01e0: 31 64 36 62 61 63 66 66 32 62 31 32 30 31 34 34 |1d6bacff2b120144|
921 01f0: 34 31 0a 00 00 00 66 00 00 00 68 00 00 00 00 00 |41....f...h.....|
921 01f0: 34 31 0a 00 00 00 66 00 00 00 68 00 00 00 00 00 |41....f...h.....|
922 0200: 00 00 69 00 00 00 6a 00 00 00 01 47 00 00 00 a4 |..i...j....G....|
922 0200: 00 00 69 00 00 00 6a 00 00 00 01 47 00 00 00 a4 |..i...j....G....|
923 0210: 02 de 42 19 6e be e4 2e f2 84 b6 78 0a 87 cd c9 |..B.n......x....|
923 0210: 02 de 42 19 6e be e4 2e f2 84 b6 78 0a 87 cd c9 |..B.n......x....|
924 0220: 6e 8e aa b6 24 b6 38 7c 8c 8c ae 37 17 88 80 f3 |n...$.8|...7....|
924 0220: 6e 8e aa b6 24 b6 38 7c 8c 8c ae 37 17 88 80 f3 |n...$.8|...7....|
925 0230: fa 95 de d3 cb 1c f7 85 00 00 00 00 00 00 00 00 |................|
925 0230: fa 95 de d3 cb 1c f7 85 00 00 00 00 00 00 00 00 |................|
926 0240: 00 00 00 00 00 00 00 00 00 00 00 00 02 de 42 19 |..............B.|
926 0240: 00 00 00 00 00 00 00 00 00 00 00 00 02 de 42 19 |..............B.|
927 0250: 6e be e4 2e f2 84 b6 78 0a 87 cd c9 6e 8e aa b6 |n......x....n...|
927 0250: 6e be e4 2e f2 84 b6 78 0a 87 cd c9 6e 8e aa b6 |n......x....n...|
928 0260: 00 00 00 00 00 00 00 29 00 00 00 29 38 62 65 65 |.......)...)8bee|
928 0260: 00 00 00 00 00 00 00 29 00 00 00 29 38 62 65 65 |.......)...)8bee|
929 0270: 34 38 65 64 63 37 33 31 38 35 34 31 66 63 30 30 |48edc7318541fc00|
929 0270: 34 38 65 64 63 37 33 31 38 35 34 31 66 63 30 30 |48edc7318541fc00|
930 0280: 31 33 65 65 34 31 62 30 38 39 32 37 36 61 38 63 |13ee41b089276a8c|
930 0280: 31 33 65 65 34 31 62 30 38 39 32 37 36 61 38 63 |13ee41b089276a8c|
931 0290: 32 34 62 66 0a 00 00 00 66 00 00 00 66 00 00 00 |24bf....f...f...|
931 0290: 32 34 62 66 0a 00 00 00 66 00 00 00 66 00 00 00 |24bf....f...f...|
932 02a0: 02 48 0a 00 00 00 67 00 00 00 68 00 00 00 01 48 |.H....g...h....H|
932 02a0: 02 48 0a 00 00 00 67 00 00 00 68 00 00 00 01 48 |.H....g...h....H|
933 02b0: 00 00 00 00 00 00 00 8b 6e 1f 4c 47 ec b5 33 ff |........n.LG..3.|
933 02b0: 00 00 00 00 00 00 00 8b 6e 1f 4c 47 ec b5 33 ff |........n.LG..3.|
934 02c0: d0 c8 e5 2c dc 88 af b6 cd 39 e2 0c 66 a5 a0 18 |...,.....9..f...|
934 02c0: d0 c8 e5 2c dc 88 af b6 cd 39 e2 0c 66 a5 a0 18 |...,.....9..f...|
935 02d0: 17 fd f5 23 9c 27 38 02 b5 b7 61 8d 05 1c 89 e4 |...#.'8...a.....|
935 02d0: 17 fd f5 23 9c 27 38 02 b5 b7 61 8d 05 1c 89 e4 |...#.'8...a.....|
936 02e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
936 02e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
937 02f0: 00 00 00 00 32 af 76 86 d4 03 cf 45 b5 d9 5f 2d |....2.v....E.._-|
937 02f0: 00 00 00 00 32 af 76 86 d4 03 cf 45 b5 d9 5f 2d |....2.v....E.._-|
938 0300: 70 ce be a5 87 ac 80 6a 00 00 00 81 00 00 00 81 |p......j........|
938 0300: 70 ce be a5 87 ac 80 6a 00 00 00 81 00 00 00 81 |p......j........|
939 0310: 00 00 00 2b 44 00 63 33 66 31 63 61 32 39 32 34 |...+D.c3f1ca2924|
939 0310: 00 00 00 2b 44 00 63 33 66 31 63 61 32 39 32 34 |...+D.c3f1ca2924|
940 0320: 63 31 36 61 31 39 62 30 36 35 36 61 38 34 39 30 |c16a19b0656a8490|
940 0320: 63 31 36 61 31 39 62 30 36 35 36 61 38 34 39 30 |c16a19b0656a8490|
941 0330: 30 65 35 30 34 65 35 62 30 61 65 63 32 64 0a 00 |0e504e5b0aec2d..|
941 0330: 30 65 35 30 34 65 35 62 30 61 65 63 32 64 0a 00 |0e504e5b0aec2d..|
942 0340: 00 00 8b 4d ec e9 c8 26 f6 94 90 50 7b 98 c6 38 |...M...&...P{..8|
942 0340: 00 00 8b 4d ec e9 c8 26 f6 94 90 50 7b 98 c6 38 |...M...&...P{..8|
943 0350: 3a 30 09 b2 95 83 7d 00 7d 8c 9d 88 84 13 25 f5 |:0....}.}.....%.|
943 0350: 3a 30 09 b2 95 83 7d 00 7d 8c 9d 88 84 13 25 f5 |:0....}.}.....%.|
944 0360: c6 b0 63 71 b3 5b 4e 8a 2b 1a 83 00 00 00 00 00 |..cq.[N.+.......|
944 0360: c6 b0 63 71 b3 5b 4e 8a 2b 1a 83 00 00 00 00 00 |..cq.[N.+.......|
945 0370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 95 |................|
945 0370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 95 |................|
946 0380: 20 ee a7 81 bc ca 16 c1 e1 5a cc 0b a1 43 35 a0 | ........Z...C5.|
946 0380: 20 ee a7 81 bc ca 16 c1 e1 5a cc 0b a1 43 35 a0 | ........Z...C5.|
947 0390: e8 e5 ba 00 00 00 2b 00 00 00 ac 00 00 00 2b 45 |......+.......+E|
947 0390: e8 e5 ba 00 00 00 2b 00 00 00 ac 00 00 00 2b 45 |......+.......+E|
948 03a0: 00 39 63 36 66 64 30 33 35 30 61 36 63 30 64 30 |.9c6fd0350a6c0d0|
948 03a0: 00 39 63 36 66 64 30 33 35 30 61 36 63 30 64 30 |.9c6fd0350a6c0d0|
949 03b0: 63 34 39 64 34 61 39 63 35 30 31 37 63 66 30 37 |c49d4a9c5017cf07|
949 03b0: 63 34 39 64 34 61 39 63 35 30 31 37 63 66 30 37 |c49d4a9c5017cf07|
950 03c0: 30 34 33 66 35 34 65 35 38 0a 00 00 00 8b 36 5b |043f54e58.....6[|
950 03c0: 30 34 33 66 35 34 65 35 38 0a 00 00 00 8b 36 5b |043f54e58.....6[|
951 03d0: 93 d5 7f df 48 14 e2 b5 91 1d 6b ac ff 2b 12 01 |....H.....k..+..|
951 03d0: 93 d5 7f df 48 14 e2 b5 91 1d 6b ac ff 2b 12 01 |....H.....k..+..|
952 03e0: 44 41 28 a5 84 c6 5e f1 21 f8 9e b6 6a b7 d0 bc |DA(...^.!...j...|
952 03e0: 44 41 28 a5 84 c6 5e f1 21 f8 9e b6 6a b7 d0 bc |DA(...^.!...j...|
953 03f0: 15 3d 80 99 e7 ce 4d ec e9 c8 26 f6 94 90 50 7b |.=....M...&...P{|
953 03f0: 15 3d 80 99 e7 ce 4d ec e9 c8 26 f6 94 90 50 7b |.=....M...&...P{|
954 0400: 98 c6 38 3a 30 09 b2 95 83 7d ee a1 37 46 79 9a |..8:0....}..7Fy.|
954 0400: 98 c6 38 3a 30 09 b2 95 83 7d ee a1 37 46 79 9a |..8:0....}..7Fy.|
955 0410: 9e 0b fd 88 f2 9d 3c 2e 9d c9 38 9f 52 4f 00 00 |......<...8.RO..|
955 0410: 9e 0b fd 88 f2 9d 3c 2e 9d c9 38 9f 52 4f 00 00 |......<...8.RO..|
956 0420: 00 56 00 00 00 56 00 00 00 2b 46 00 32 32 62 66 |.V...V...+F.22bf|
956 0420: 00 56 00 00 00 56 00 00 00 2b 46 00 32 32 62 66 |.V...V...+F.22bf|
957 0430: 63 66 64 36 32 61 32 31 61 33 32 38 37 65 64 62 |cfd62a21a3287edb|
957 0430: 63 66 64 36 32 61 32 31 61 33 32 38 37 65 64 62 |cfd62a21a3287edb|
958 0440: 64 34 64 36 35 36 32 31 38 64 30 66 35 32 35 65 |d4d656218d0f525e|
958 0440: 64 34 64 36 35 36 32 31 38 64 30 66 35 32 35 65 |d4d656218d0f525e|
959 0450: 64 37 36 61 0a 00 00 00 97 8b ee 48 ed c7 31 85 |d76a.......H..1.|
959 0450: 64 37 36 61 0a 00 00 00 97 8b ee 48 ed c7 31 85 |d76a.......H..1.|
960 0460: 41 fc 00 13 ee 41 b0 89 27 6a 8c 24 bf 28 a5 84 |A....A..'j.$.(..|
960 0460: 41 fc 00 13 ee 41 b0 89 27 6a 8c 24 bf 28 a5 84 |A....A..'j.$.(..|
961 0470: c6 5e f1 21 f8 9e b6 6a b7 d0 bc 15 3d 80 99 e7 |.^.!...j....=...|
961 0470: c6 5e f1 21 f8 9e b6 6a b7 d0 bc 15 3d 80 99 e7 |.^.!...j....=...|
962 0480: ce 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
962 0480: ce 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
963 0490: 00 00 00 00 00 02 de 42 19 6e be e4 2e f2 84 b6 |.......B.n......|
963 0490: 00 00 00 00 00 02 de 42 19 6e be e4 2e f2 84 b6 |.......B.n......|
964 04a0: 78 0a 87 cd c9 6e 8e aa b6 00 00 00 2b 00 00 00 |x....n......+...|
964 04a0: 78 0a 87 cd c9 6e 8e aa b6 00 00 00 2b 00 00 00 |x....n......+...|
965 04b0: 56 00 00 00 00 00 00 00 81 00 00 00 81 00 00 00 |V...............|
965 04b0: 56 00 00 00 00 00 00 00 81 00 00 00 81 00 00 00 |V...............|
966 04c0: 2b 48 00 38 35 30 30 31 38 39 65 37 34 61 39 65 |+H.8500189e74a9e|
966 04c0: 2b 48 00 38 35 30 30 31 38 39 65 37 34 61 39 65 |+H.8500189e74a9e|
967 04d0: 30 34 37 35 65 38 32 32 30 39 33 62 63 37 64 62 |0475e822093bc7db|
967 04d0: 30 34 37 35 65 38 32 32 30 39 33 62 63 37 64 62 |0475e822093bc7db|
968 04e0: 30 64 36 33 31 61 65 62 30 62 34 0a 00 00 00 00 |0d631aeb0b4.....|
968 04e0: 30 64 36 33 31 61 65 62 30 62 34 0a 00 00 00 00 |0d631aeb0b4.....|
969 04f0: 00 00 00 05 44 00 00 00 62 c3 f1 ca 29 24 c1 6a |....D...b...)$.j|
969 04f0: 00 00 00 05 44 00 00 00 62 c3 f1 ca 29 24 c1 6a |....D...b...)$.j|
970 0500: 19 b0 65 6a 84 90 0e 50 4e 5b 0a ec 2d 00 00 00 |..ej...PN[..-...|
970 0500: 19 b0 65 6a 84 90 0e 50 4e 5b 0a ec 2d 00 00 00 |..ej...PN[..-...|
971 0510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
971 0510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
972 0520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
972 0520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
973 0530: 00 00 00 00 00 32 af 76 86 d4 03 cf 45 b5 d9 5f |.....2.v....E.._|
973 0530: 00 00 00 00 00 32 af 76 86 d4 03 cf 45 b5 d9 5f |.....2.v....E.._|
974 0540: 2d 70 ce be a5 87 ac 80 6a 00 00 00 00 00 00 00 |-p......j.......|
974 0540: 2d 70 ce be a5 87 ac 80 6a 00 00 00 00 00 00 00 |-p......j.......|
975 0550: 00 00 00 00 02 44 0a 00 00 00 00 00 00 00 05 45 |.....D.........E|
975 0550: 00 00 00 00 02 44 0a 00 00 00 00 00 00 00 05 45 |.....D.........E|
976 0560: 00 00 00 62 9c 6f d0 35 0a 6c 0d 0c 49 d4 a9 c5 |...b.o.5.l..I...|
976 0560: 00 00 00 62 9c 6f d0 35 0a 6c 0d 0c 49 d4 a9 c5 |...b.o.5.l..I...|
977 0570: 01 7c f0 70 43 f5 4e 58 00 00 00 00 00 00 00 00 |.|.pC.NX........|
977 0570: 01 7c f0 70 43 f5 4e 58 00 00 00 00 00 00 00 00 |.|.pC.NX........|
978 0580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
978 0580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
979 0590: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
979 0590: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
980 05a0: 95 20 ee a7 81 bc ca 16 c1 e1 5a cc 0b a1 43 35 |. ........Z...C5|
980 05a0: 95 20 ee a7 81 bc ca 16 c1 e1 5a cc 0b a1 43 35 |. ........Z...C5|
981 05b0: a0 e8 e5 ba 00 00 00 00 00 00 00 00 00 00 00 02 |................|
981 05b0: a0 e8 e5 ba 00 00 00 00 00 00 00 00 00 00 00 02 |................|
982 05c0: 45 0a 00 00 00 00 00 00 00 05 48 00 00 00 62 85 |E.........H...b.|
982 05c0: 45 0a 00 00 00 00 00 00 00 05 48 00 00 00 62 85 |E.........H...b.|
983 05d0: 00 18 9e 74 a9 e0 47 5e 82 20 93 bc 7d b0 d6 31 |...t..G^. ..}..1|
983 05d0: 00 18 9e 74 a9 e0 47 5e 82 20 93 bc 7d b0 d6 31 |...t..G^. ..}..1|
984 05e0: ae b0 b4 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
984 05e0: ae b0 b4 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
985 05f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
985 05f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
986 0600: 00 00 00 00 00 00 00 00 00 00 00 02 de 42 19 6e |.............B.n|
986 0600: 00 00 00 00 00 00 00 00 00 00 00 02 de 42 19 6e |.............B.n|
987 0610: be e4 2e f2 84 b6 78 0a 87 cd c9 6e 8e aa b6 00 |......x....n....|
987 0610: be e4 2e f2 84 b6 78 0a 87 cd c9 6e 8e aa b6 00 |......x....n....|
988 0620: 00 00 00 00 00 00 00 00 00 00 02 48 0a 00 00 00 |...........H....|
988 0620: 00 00 00 00 00 00 00 00 00 00 02 48 0a 00 00 00 |...........H....|
989 0630: 00 00 00 00 00 00 00 00 00 00 00 00 00 |.............|
989 0630: 00 00 00 00 00 00 00 00 00 00 00 00 00 |.............|
990
990
991 $ hg debugbundle ../rev.hg2
991 $ hg debugbundle ../rev.hg2
992 Stream params: {}
992 Stream params: {}
993 changegroup -- '{}'
993 changegroup -- 'sortdict()'
994 32af7686d403cf45b5d95f2d70cebea587ac806a
994 32af7686d403cf45b5d95f2d70cebea587ac806a
995 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
995 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
996 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
996 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
997 02de42196ebee42ef284b6780a87cdc96e8eaab6
997 02de42196ebee42ef284b6780a87cdc96e8eaab6
998 $ hg unbundle ../rev.hg2
998 $ hg unbundle ../rev.hg2
999 adding changesets
999 adding changesets
1000 adding manifests
1000 adding manifests
1001 adding file changes
1001 adding file changes
1002 added 0 changesets with 0 changes to 3 files
1002 added 0 changesets with 0 changes to 3 files
1003 (run 'hg update' to get a working copy)
1003 (run 'hg update' to get a working copy)
1004
1004
1005 with reply
1005 with reply
1006
1006
1007 $ hg bundle2 --rev '8+7+5+4' --reply ../rev-rr.hg2
1007 $ hg bundle2 --rev '8+7+5+4' --reply ../rev-rr.hg2
1008 $ hg unbundle2 ../rev-reply.hg2 < ../rev-rr.hg2
1008 $ hg unbundle2 ../rev-reply.hg2 < ../rev-rr.hg2
1009 0 unread bytes
1009 0 unread bytes
1010 addchangegroup return: 1
1010 addchangegroup return: 1
1011
1011
1012 $ f --hexdump ../rev-reply.hg2
1012 $ f --hexdump ../rev-reply.hg2
1013 ../rev-reply.hg2:
1013 ../rev-reply.hg2:
1014 0000: 48 47 32 30 00 00 00 00 00 00 00 2f 11 72 65 70 |HG20......./.rep|
1014 0000: 48 47 32 30 00 00 00 00 00 00 00 2f 11 72 65 70 |HG20......./.rep|
1015 0010: 6c 79 3a 63 68 61 6e 67 65 67 72 6f 75 70 00 00 |ly:changegroup..|
1015 0010: 6c 79 3a 63 68 61 6e 67 65 67 72 6f 75 70 00 00 |ly:changegroup..|
1016 0020: 00 00 00 02 0b 01 06 01 69 6e 2d 72 65 70 6c 79 |........in-reply|
1016 0020: 00 00 00 02 0b 01 06 01 69 6e 2d 72 65 70 6c 79 |........in-reply|
1017 0030: 2d 74 6f 31 72 65 74 75 72 6e 31 00 00 00 00 00 |-to1return1.....|
1017 0030: 2d 74 6f 31 72 65 74 75 72 6e 31 00 00 00 00 00 |-to1return1.....|
1018 0040: 00 00 1b 06 6f 75 74 70 75 74 00 00 00 01 00 01 |....output......|
1018 0040: 00 00 1b 06 6f 75 74 70 75 74 00 00 00 01 00 01 |....output......|
1019 0050: 0b 01 69 6e 2d 72 65 70 6c 79 2d 74 6f 31 00 00 |..in-reply-to1..|
1019 0050: 0b 01 69 6e 2d 72 65 70 6c 79 2d 74 6f 31 00 00 |..in-reply-to1..|
1020 0060: 00 64 61 64 64 69 6e 67 20 63 68 61 6e 67 65 73 |.dadding changes|
1020 0060: 00 64 61 64 64 69 6e 67 20 63 68 61 6e 67 65 73 |.dadding changes|
1021 0070: 65 74 73 0a 61 64 64 69 6e 67 20 6d 61 6e 69 66 |ets.adding manif|
1021 0070: 65 74 73 0a 61 64 64 69 6e 67 20 6d 61 6e 69 66 |ets.adding manif|
1022 0080: 65 73 74 73 0a 61 64 64 69 6e 67 20 66 69 6c 65 |ests.adding file|
1022 0080: 65 73 74 73 0a 61 64 64 69 6e 67 20 66 69 6c 65 |ests.adding file|
1023 0090: 20 63 68 61 6e 67 65 73 0a 61 64 64 65 64 20 30 | changes.added 0|
1023 0090: 20 63 68 61 6e 67 65 73 0a 61 64 64 65 64 20 30 | changes.added 0|
1024 00a0: 20 63 68 61 6e 67 65 73 65 74 73 20 77 69 74 68 | changesets with|
1024 00a0: 20 63 68 61 6e 67 65 73 65 74 73 20 77 69 74 68 | changesets with|
1025 00b0: 20 30 20 63 68 61 6e 67 65 73 20 74 6f 20 33 20 | 0 changes to 3 |
1025 00b0: 20 30 20 63 68 61 6e 67 65 73 20 74 6f 20 33 20 | 0 changes to 3 |
1026 00c0: 66 69 6c 65 73 0a 00 00 00 00 00 00 00 00 |files.........|
1026 00c0: 66 69 6c 65 73 0a 00 00 00 00 00 00 00 00 |files.........|
1027
1027
1028 Check handling of exception during generation.
1028 Check handling of exception during generation.
1029 ----------------------------------------------
1029 ----------------------------------------------
1030
1030
1031 $ hg bundle2 --genraise > ../genfailed.hg2
1031 $ hg bundle2 --genraise > ../genfailed.hg2
1032 abort: Someone set up us the bomb!
1032 abort: Someone set up us the bomb!
1033 [255]
1033 [255]
1034
1034
1035 Should still be a valid bundle
1035 Should still be a valid bundle
1036
1036
1037 $ f --hexdump ../genfailed.hg2
1037 $ f --hexdump ../genfailed.hg2
1038 ../genfailed.hg2:
1038 ../genfailed.hg2:
1039 0000: 48 47 32 30 00 00 00 00 00 00 00 0d 06 6f 75 74 |HG20.........out|
1039 0000: 48 47 32 30 00 00 00 00 00 00 00 0d 06 6f 75 74 |HG20.........out|
1040 0010: 70 75 74 00 00 00 00 00 00 ff ff ff ff 00 00 00 |put.............|
1040 0010: 70 75 74 00 00 00 00 00 00 ff ff ff ff 00 00 00 |put.............|
1041 0020: 48 0b 65 72 72 6f 72 3a 61 62 6f 72 74 00 00 00 |H.error:abort...|
1041 0020: 48 0b 65 72 72 6f 72 3a 61 62 6f 72 74 00 00 00 |H.error:abort...|
1042 0030: 00 01 00 07 2d 6d 65 73 73 61 67 65 75 6e 65 78 |....-messageunex|
1042 0030: 00 01 00 07 2d 6d 65 73 73 61 67 65 75 6e 65 78 |....-messageunex|
1043 0040: 70 65 63 74 65 64 20 65 72 72 6f 72 3a 20 53 6f |pected error: So|
1043 0040: 70 65 63 74 65 64 20 65 72 72 6f 72 3a 20 53 6f |pected error: So|
1044 0050: 6d 65 6f 6e 65 20 73 65 74 20 75 70 20 75 73 20 |meone set up us |
1044 0050: 6d 65 6f 6e 65 20 73 65 74 20 75 70 20 75 73 20 |meone set up us |
1045 0060: 74 68 65 20 62 6f 6d 62 21 00 00 00 00 00 00 00 |the bomb!.......|
1045 0060: 74 68 65 20 62 6f 6d 62 21 00 00 00 00 00 00 00 |the bomb!.......|
1046 0070: 00 |.|
1046 0070: 00 |.|
1047
1047
1048 And its handling on the other size raise a clean exception
1048 And its handling on the other size raise a clean exception
1049
1049
1050 $ cat ../genfailed.hg2 | hg unbundle2
1050 $ cat ../genfailed.hg2 | hg unbundle2
1051 0 unread bytes
1051 0 unread bytes
1052 abort: unexpected error: Someone set up us the bomb!
1052 abort: unexpected error: Someone set up us the bomb!
1053 [255]
1053 [255]
1054
1054
1055 Test compression
1055 Test compression
1056 ================
1056 ================
1057
1057
1058 Simple case where it just work: GZ
1058 Simple case where it just work: GZ
1059 ----------------------------------
1059 ----------------------------------
1060
1060
1061 $ hg bundle2 --compress GZ --rev '8+7+5+4' ../rev.hg2.bz
1061 $ hg bundle2 --compress GZ --rev '8+7+5+4' ../rev.hg2.bz
1062 $ f --hexdump ../rev.hg2.bz
1062 $ f --hexdump ../rev.hg2.bz
1063 ../rev.hg2.bz:
1063 ../rev.hg2.bz:
1064 0000: 48 47 32 30 00 00 00 0e 43 6f 6d 70 72 65 73 73 |HG20....Compress|
1064 0000: 48 47 32 30 00 00 00 0e 43 6f 6d 70 72 65 73 73 |HG20....Compress|
1065 0010: 69 6f 6e 3d 47 5a 78 9c 95 94 7d 68 95 55 1c c7 |ion=GZx...}h.U..|
1065 0010: 69 6f 6e 3d 47 5a 78 9c 95 94 7d 68 95 55 1c c7 |ion=GZx...}h.U..|
1066 0020: 9f 3b 31 e8 ce fa c3 65 be a0 a4 b4 52 b9 29 e7 |.;1....e....R.).|
1066 0020: 9f 3b 31 e8 ce fa c3 65 be a0 a4 b4 52 b9 29 e7 |.;1....e....R.).|
1067 0030: f5 79 ce 89 fa 63 ed 5e 77 8b 9c c3 3f 2a 1c 68 |.y...c.^w...?*.h|
1067 0030: f5 79 ce 89 fa 63 ed 5e 77 8b 9c c3 3f 2a 1c 68 |.y...c.^w...?*.h|
1068 0040: cf 79 9b dd 6a ae b0 28 74 b8 e5 96 5b bb 86 61 |.y..j..(t...[..a|
1068 0040: cf 79 9b dd 6a ae b0 28 74 b8 e5 96 5b bb 86 61 |.y..j..(t...[..a|
1069 0050: a3 15 6e 3a 71 c8 6a e8 a5 da 95 64 28 22 ce 69 |..n:q.j....d(".i|
1069 0050: a3 15 6e 3a 71 c8 6a e8 a5 da 95 64 28 22 ce 69 |..n:q.j....d(".i|
1070 0060: cd 06 59 34 28 2b 51 2a 58 c3 17 56 2a 9a 9d 67 |..Y4(+Q*X..V*..g|
1070 0060: cd 06 59 34 28 2b 51 2a 58 c3 17 56 2a 9a 9d 67 |..Y4(+Q*X..V*..g|
1071 0070: dc c6 35 9e c4 1d f8 9e 87 f3 9c f3 3b bf 0f bf |..5.........;...|
1071 0070: dc c6 35 9e c4 1d f8 9e 87 f3 9c f3 3b bf 0f bf |..5.........;...|
1072 0080: 97 e3 38 ce f4 42 b9 d6 af ae d2 55 af ae 7b ad |..8..B.....U..{.|
1072 0080: 97 e3 38 ce f4 42 b9 d6 af ae d2 55 af ae 7b ad |..8..B.....U..{.|
1073 0090: c6 c9 8d bb 8a ec b4 07 ed 7f fd ed d3 53 be 4e |.............S.N|
1073 0090: c6 c9 8d bb 8a ec b4 07 ed 7f fd ed d3 53 be 4e |.............S.N|
1074 00a0: f4 0e af 59 52 73 ea 50 d7 96 9e ba d4 9a 1f 87 |...YRs.P........|
1074 00a0: f4 0e af 59 52 73 ea 50 d7 96 9e ba d4 9a 1f 87 |...YRs.P........|
1075 00b0: 9b 9f 1d e8 7a 6a 79 e9 cb 7f cf eb fe 7e d3 82 |....zjy......~..|
1075 00b0: 9b 9f 1d e8 7a 6a 79 e9 cb 7f cf eb fe 7e d3 82 |....zjy......~..|
1076 00c0: ce 2f 36 38 21 23 cc 36 b7 b5 38 90 ab a1 21 92 |./68!#.6..8...!.|
1076 00c0: ce 2f 36 38 21 23 cc 36 b7 b5 38 90 ab a1 21 92 |./68!#.6..8...!.|
1077 00d0: 78 5a 0a 8a b1 31 0a 48 a6 29 92 4a 32 e6 1b e1 |xZ...1.H.).J2...|
1077 00d0: 78 5a 0a 8a b1 31 0a 48 a6 29 92 4a 32 e6 1b e1 |xZ...1.H.).J2...|
1078 00e0: 4a 85 b9 46 40 46 ed 61 63 b5 d6 aa 20 1e ac 5e |J..F@F.ac... ..^|
1078 00e0: 4a 85 b9 46 40 46 ed 61 63 b5 d6 aa 20 1e ac 5e |J..F@F.ac... ..^|
1079 00f0: b0 0a ae 8a c4 03 c6 d6 f9 a3 7b eb fb 4e de 7f |..........{..N..|
1079 00f0: b0 0a ae 8a c4 03 c6 d6 f9 a3 7b eb fb 4e de 7f |..........{..N..|
1080 0100: e4 97 55 5f 15 76 96 d2 5d bf 9d 3f 38 18 29 4c |..U_.v..]..?8.)L|
1080 0100: e4 97 55 5f 15 76 96 d2 5d bf 9d 3f 38 18 29 4c |..U_.v..]..?8.)L|
1081 0110: 0f b7 5d 6e 9b b3 aa 7e c6 d5 15 5b f7 7c 52 f1 |..]n...~...[.|R.|
1081 0110: 0f b7 5d 6e 9b b3 aa 7e c6 d5 15 5b f7 7c 52 f1 |..]n...~...[.|R.|
1082 0120: 7c 73 18 63 98 6d 3e 23 51 5a 6a 2e 19 72 8d cb ||s.c.m>#QZj..r..|
1082 0120: 7c 73 18 63 98 6d 3e 23 51 5a 6a 2e 19 72 8d cb ||s.c.m>#QZj..r..|
1083 0130: 09 07 14 78 82 33 e9 62 86 7d 0c 00 17 88 53 86 |...x.3.b.}....S.|
1083 0130: 09 07 14 78 82 33 e9 62 86 7d 0c 00 17 88 53 86 |...x.3.b.}....S.|
1084 0140: 3d 75 0b 63 e2 16 c6 84 9d 76 8f 76 7a cb de fc |=u.c.....v.vz...|
1084 0140: 3d 75 0b 63 e2 16 c6 84 9d 76 8f 76 7a cb de fc |=u.c.....v.vz...|
1085 0150: a8 a3 f0 46 d3 a5 f6 c7 96 b6 9f 60 3b 57 ae 28 |...F.......`;W.(|
1085 0150: a8 a3 f0 46 d3 a5 f6 c7 96 b6 9f 60 3b 57 ae 28 |...F.......`;W.(|
1086 0160: ce b2 8d e9 f4 3e 6f 66 53 dd e5 6b ad 67 be f9 |.....>ofS..k.g..|
1086 0160: ce b2 8d e9 f4 3e 6f 66 53 dd e5 6b ad 67 be f9 |.....>ofS..k.g..|
1087 0170: 72 ee 5f 8d 61 3c 61 b6 f9 8c d8 a5 82 63 45 3d |r._.a<a......cE=|
1087 0170: 72 ee 5f 8d 61 3c 61 b6 f9 8c d8 a5 82 63 45 3d |r._.a<a......cE=|
1088 0180: a3 0c 61 90 68 24 28 87 50 b9 c2 97 c6 20 01 11 |..a.h$(.P.... ..|
1088 0180: a3 0c 61 90 68 24 28 87 50 b9 c2 97 c6 20 01 11 |..a.h$(.P.... ..|
1089 0190: 80 84 10 98 cf e8 e4 13 96 05 51 2c 38 f3 c4 ec |..........Q,8...|
1089 0190: 80 84 10 98 cf e8 e4 13 96 05 51 2c 38 f3 c4 ec |..........Q,8...|
1090 01a0: ea 43 e7 96 5e 6a c8 be 11 dd 32 78 a2 fa dd 8f |.C..^j....2x....|
1090 01a0: ea 43 e7 96 5e 6a c8 be 11 dd 32 78 a2 fa dd 8f |.C..^j....2x....|
1091 01b0: b3 61 84 61 51 0c b3 cd 27 64 42 6b c2 b4 92 1e |.a.aQ...'dBk....|
1091 01b0: b3 61 84 61 51 0c b3 cd 27 64 42 6b c2 b4 92 1e |.a.aQ...'dBk....|
1092 01c0: 86 8c 12 68 24 00 10 db 7f 50 00 c6 91 e7 fa 4c |...h$....P.....L|
1092 01c0: 86 8c 12 68 24 00 10 db 7f 50 00 c6 91 e7 fa 4c |...h$....P.....L|
1093 01d0: 22 22 cc bf 84 81 0a 92 c1 aa 2a c7 1b 49 e6 ee |""........*..I..|
1093 01d0: 22 22 cc bf 84 81 0a 92 c1 aa 2a c7 1b 49 e6 ee |""........*..I..|
1094 01e0: 6b a9 7e e0 e9 b2 91 5e 7c 73 68 e0 fc 23 3f 34 |k.~....^|sh..#?4|
1094 01e0: 6b a9 7e e0 e9 b2 91 5e 7c 73 68 e0 fc 23 3f 34 |k.~....^|sh..#?4|
1095 01f0: ed cf 0e f2 b3 d3 4c d7 ae 59 33 6f 8c 3d b8 63 |......L..Y3o.=.c|
1095 01f0: ed cf 0e f2 b3 d3 4c d7 ae 59 33 6f 8c 3d b8 63 |......L..Y3o.=.c|
1096 0200: 21 2b e8 3d e0 6f 9d 3a b7 f9 dc 24 2a b2 3e a7 |!+.=.o.:...$*.>.|
1096 0200: 21 2b e8 3d e0 6f 9d 3a b7 f9 dc 24 2a b2 3e a7 |!+.=.o.:...$*.>.|
1097 0210: 58 dc 91 d8 40 e9 23 8e 88 84 ae 0f b9 00 2e b5 |X...@.#.........|
1097 0210: 58 dc 91 d8 40 e9 23 8e 88 84 ae 0f b9 00 2e b5 |X...@.#.........|
1098 0220: 74 36 f3 40 53 40 34 15 c0 d7 12 8d e7 bb 65 f9 |t6.@S@4.......e.|
1098 0220: 74 36 f3 40 53 40 34 15 c0 d7 12 8d e7 bb 65 f9 |t6.@S@4.......e.|
1099 0230: c8 ef 03 0f ff f9 fe b6 8a 0d 6d fd ec 51 70 f7 |..........m..Qp.|
1099 0230: c8 ef 03 0f ff f9 fe b6 8a 0d 6d fd ec 51 70 f7 |..........m..Qp.|
1100 0240: a7 ad 9b 6b 9d da 74 7b 53 43 d1 43 63 fd 19 f9 |...k..t{SC.Cc...|
1100 0240: a7 ad 9b 6b 9d da 74 7b 53 43 d1 43 63 fd 19 f9 |...k..t{SC.Cc...|
1101 0250: ca 67 95 e5 ef c4 e6 6c 9e 44 e1 c5 ac 7a 82 6f |.g.....l.D...z.o|
1101 0250: ca 67 95 e5 ef c4 e6 6c 9e 44 e1 c5 ac 7a 82 6f |.g.....l.D...z.o|
1102 0260: c2 e1 d2 b5 2d 81 29 f0 5d 09 6c 6f 10 ae 88 cf |....-.).].lo....|
1102 0260: c2 e1 d2 b5 2d 81 29 f0 5d 09 6c 6f 10 ae 88 cf |....-.).].lo....|
1103 0270: 25 05 d0 93 06 78 80 60 43 2d 10 1b 47 71 2b b7 |%....x.`C-..Gq+.|
1103 0270: 25 05 d0 93 06 78 80 60 43 2d 10 1b 47 71 2b b7 |%....x.`C-..Gq+.|
1104 0280: 7f bb e9 a7 e4 7d 67 7b df 9b f7 62 cf cd d8 f4 |.....}g{...b....|
1104 0280: 7f bb e9 a7 e4 7d 67 7b df 9b f7 62 cf cd d8 f4 |.....}g{...b....|
1105 0290: 48 bc 64 51 57 43 ff ea 8b 0b ae 74 64 53 07 86 |H.dQWC.....tdS..|
1105 0290: 48 bc 64 51 57 43 ff ea 8b 0b ae 74 64 53 07 86 |H.dQWC.....tdS..|
1106 02a0: fa 66 3c 5e f7 e1 af a7 c2 90 ff a7 be 9e c9 29 |.f<^...........)|
1106 02a0: fa 66 3c 5e f7 e1 af a7 c2 90 ff a7 be 9e c9 29 |.f<^...........)|
1107 02b0: b6 cc 41 48 18 69 94 8b 7c 04 7d 8c 98 a7 95 50 |..AH.i..|.}....P|
1107 02b0: b6 cc 41 48 18 69 94 8b 7c 04 7d 8c 98 a7 95 50 |..AH.i..|.}....P|
1108 02c0: 44 d9 d0 20 c8 14 30 14 51 ad 6c 16 03 94 0f 5a |D.. ..0.Q.l....Z|
1108 02c0: 44 d9 d0 20 c8 14 30 14 51 ad 6c 16 03 94 0f 5a |D.. ..0.Q.l....Z|
1109 02d0: 46 93 7f 1c 87 8d 25 d7 9d a2 d1 92 4c f3 c2 54 |F.....%.....L..T|
1109 02d0: 46 93 7f 1c 87 8d 25 d7 9d a2 d1 92 4c f3 c2 54 |F.....%.....L..T|
1110 02e0: ba f8 70 18 ca 24 0a 29 96 43 71 f2 93 95 74 18 |..p..$.).Cq...t.|
1110 02e0: ba f8 70 18 ca 24 0a 29 96 43 71 f2 93 95 74 18 |..p..$.).Cq...t.|
1111 02f0: b5 65 c4 b8 f6 6c 5c 34 20 1e d5 0c 21 c0 b1 90 |.e...l\4 ...!...|
1111 02f0: b5 65 c4 b8 f6 6c 5c 34 20 1e d5 0c 21 c0 b1 90 |.e...l\4 ...!...|
1112 0300: 9e 12 40 b9 18 fa 5a 00 41 a2 39 d3 a9 c1 73 21 |..@...Z.A.9...s!|
1112 0300: 9e 12 40 b9 18 fa 5a 00 41 a2 39 d3 a9 c1 73 21 |..@...Z.A.9...s!|
1113 0310: 8e 5e 3c b9 b8 f8 48 6a 76 46 a7 1a b6 dd 5b 51 |.^<...HjvF....[Q|
1113 0310: 8e 5e 3c b9 b8 f8 48 6a 76 46 a7 1a b6 dd 5b 51 |.^<...HjvF....[Q|
1114 0320: 5e 19 1d 59 12 c6 32 89 02 9a c0 8f 4f b8 0a ba |^..Y..2.....O...|
1114 0320: 5e 19 1d 59 12 c6 32 89 02 9a c0 8f 4f b8 0a ba |^..Y..2.....O...|
1115 0330: 5e ec 58 37 44 a3 2f dd 33 ed c9 d3 dd c7 22 1b |^.X7D./.3.....".|
1115 0330: 5e ec 58 37 44 a3 2f dd 33 ed c9 d3 dd c7 22 1b |^.X7D./.3.....".|
1116 0340: 2f d4 94 8e 95 3f 77 a7 ae 6e f3 32 8d bb 4a 4c |/....?w..n.2..JL|
1116 0340: 2f d4 94 8e 95 3f 77 a7 ae 6e f3 32 8d bb 4a 4c |/....?w..n.2..JL|
1117 0350: b8 0a 5a 43 34 3a b3 3a d6 77 ff 5c b6 fa ad f9 |..ZC4:.:.w.\....|
1117 0350: b8 0a 5a 43 34 3a b3 3a d6 77 ff 5c b6 fa ad f9 |..ZC4:.:.w.\....|
1118 0360: db fb 6a 33 df c1 7d 99 cf ef d4 d5 6d da 77 7c |..j3..}.....m.w||
1118 0360: db fb 6a 33 df c1 7d 99 cf ef d4 d5 6d da 77 7c |..j3..}.....m.w||
1119 0370: 3b 19 fd af c5 3f f1 60 c3 17 |;....?.`..|
1119 0370: 3b 19 fd af c5 3f f1 60 c3 17 |;....?.`..|
1120 $ hg debugbundle ../rev.hg2.bz
1120 $ hg debugbundle ../rev.hg2.bz
1121 Stream params: {'Compression': 'GZ'}
1121 Stream params: sortdict([('Compression', 'GZ')])
1122 changegroup -- '{}'
1122 changegroup -- 'sortdict()'
1123 32af7686d403cf45b5d95f2d70cebea587ac806a
1123 32af7686d403cf45b5d95f2d70cebea587ac806a
1124 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
1124 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
1125 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
1125 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
1126 02de42196ebee42ef284b6780a87cdc96e8eaab6
1126 02de42196ebee42ef284b6780a87cdc96e8eaab6
1127 $ hg unbundle ../rev.hg2.bz
1127 $ hg unbundle ../rev.hg2.bz
1128 adding changesets
1128 adding changesets
1129 adding manifests
1129 adding manifests
1130 adding file changes
1130 adding file changes
1131 added 0 changesets with 0 changes to 3 files
1131 added 0 changesets with 0 changes to 3 files
1132 (run 'hg update' to get a working copy)
1132 (run 'hg update' to get a working copy)
1133 Simple case where it just work: BZ
1133 Simple case where it just work: BZ
1134 ----------------------------------
1134 ----------------------------------
1135
1135
1136 $ hg bundle2 --compress BZ --rev '8+7+5+4' ../rev.hg2.bz
1136 $ hg bundle2 --compress BZ --rev '8+7+5+4' ../rev.hg2.bz
1137 $ f --hexdump ../rev.hg2.bz
1137 $ f --hexdump ../rev.hg2.bz
1138 ../rev.hg2.bz:
1138 ../rev.hg2.bz:
1139 0000: 48 47 32 30 00 00 00 0e 43 6f 6d 70 72 65 73 73 |HG20....Compress|
1139 0000: 48 47 32 30 00 00 00 0e 43 6f 6d 70 72 65 73 73 |HG20....Compress|
1140 0010: 69 6f 6e 3d 42 5a 42 5a 68 39 31 41 59 26 53 59 |ion=BZBZh91AY&SY|
1140 0010: 69 6f 6e 3d 42 5a 42 5a 68 39 31 41 59 26 53 59 |ion=BZBZh91AY&SY|
1141 0020: a3 4b 18 3d 00 00 1a 7f ff ff bf 5f f6 ef ef 7f |.K.=......._....|
1141 0020: a3 4b 18 3d 00 00 1a 7f ff ff bf 5f f6 ef ef 7f |.K.=......._....|
1142 0030: f6 3f f7 d1 d9 ff ff f7 6e ff ff 6e f7 f6 bd df |.?......n..n....|
1142 0030: f6 3f f7 d1 d9 ff ff f7 6e ff ff 6e f7 f6 bd df |.?......n..n....|
1143 0040: b5 ab ff cf 67 f6 e7 7b f7 c0 02 d7 33 82 8b 51 |....g..{....3..Q|
1143 0040: b5 ab ff cf 67 f6 e7 7b f7 c0 02 d7 33 82 8b 51 |....g..{....3..Q|
1144 0050: 04 a5 53 d5 3d 27 a0 99 18 4d 0d 34 00 d1 a1 e8 |..S.='...M.4....|
1144 0050: 04 a5 53 d5 3d 27 a0 99 18 4d 0d 34 00 d1 a1 e8 |..S.='...M.4....|
1145 0060: 80 c8 7a 87 a9 a3 43 6a 3d 46 86 26 80 34 3d 40 |..z...Cj=F.&.4=@|
1145 0060: 80 c8 7a 87 a9 a3 43 6a 3d 46 86 26 80 34 3d 40 |..z...Cj=F.&.4=@|
1146 0070: c8 c9 b5 34 f4 8f 48 0f 51 ea 34 34 fd 4d aa 19 |...4..H.Q.44.M..|
1146 0070: c8 c9 b5 34 f4 8f 48 0f 51 ea 34 34 fd 4d aa 19 |...4..H.Q.44.M..|
1147 0080: 03 40 0c 08 da 86 43 d4 f5 0f 42 1e a0 f3 54 33 |.@....C...B...T3|
1147 0080: 03 40 0c 08 da 86 43 d4 f5 0f 42 1e a0 f3 54 33 |.@....C...B...T3|
1148 0090: 54 d3 13 4d 03 40 32 00 00 32 03 26 80 0d 00 0d |T..M.@2..2.&....|
1148 0090: 54 d3 13 4d 03 40 32 00 00 32 03 26 80 0d 00 0d |T..M.@2..2.&....|
1149 00a0: 00 68 c8 c8 03 20 32 30 98 8c 80 00 00 03 4d 00 |.h... 20......M.|
1149 00a0: 00 68 c8 c8 03 20 32 30 98 8c 80 00 00 03 4d 00 |.h... 20......M.|
1150 00b0: c8 00 00 0d 00 00 22 99 a1 34 c2 64 a6 d5 34 1a |......"..4.d..4.|
1150 00b0: c8 00 00 0d 00 00 22 99 a1 34 c2 64 a6 d5 34 1a |......"..4.d..4.|
1151 00c0: 00 00 06 86 83 4d 07 a8 d1 a0 68 01 a0 00 00 00 |.....M....h.....|
1151 00c0: 00 00 06 86 83 4d 07 a8 d1 a0 68 01 a0 00 00 00 |.....M....h.....|
1152 00d0: 00 0d 06 80 00 00 00 0d 00 03 40 00 00 04 a4 a1 |..........@.....|
1152 00d0: 00 0d 06 80 00 00 00 0d 00 03 40 00 00 04 a4 a1 |..........@.....|
1153 00e0: 4d a9 89 89 b4 9a 32 0c 43 46 86 87 a9 8d 41 9a |M.....2.CF....A.|
1153 00e0: 4d a9 89 89 b4 9a 32 0c 43 46 86 87 a9 8d 41 9a |M.....2.CF....A.|
1154 00f0: 98 46 9a 0d 31 32 1a 34 0d 0c 8d a2 0c 98 4d 06 |.F..12.4......M.|
1154 00f0: 98 46 9a 0d 31 32 1a 34 0d 0c 8d a2 0c 98 4d 06 |.F..12.4......M.|
1155 0100: 8c 40 c2 60 8d 0d 0c 20 c9 89 fa a0 d0 d3 21 a1 |.@.`... ......!.|
1155 0100: 8c 40 c2 60 8d 0d 0c 20 c9 89 fa a0 d0 d3 21 a1 |.@.`... ......!.|
1156 0110: ea 34 d3 68 9e a6 d1 74 05 33 cb 66 96 93 28 64 |.4.h...t.3.f..(d|
1156 0110: ea 34 d3 68 9e a6 d1 74 05 33 cb 66 96 93 28 64 |.4.h...t.3.f..(d|
1157 0120: 40 91 22 ac 55 9b ea 40 7b 38 94 e2 f8 06 00 cb |@.".U..@{8......|
1157 0120: 40 91 22 ac 55 9b ea 40 7b 38 94 e2 f8 06 00 cb |@.".U..@{8......|
1158 0130: 28 02 00 4d ab 40 24 10 43 18 cf 64 b4 06 83 0c |(..M.@$.C..d....|
1158 0130: 28 02 00 4d ab 40 24 10 43 18 cf 64 b4 06 83 0c |(..M.@$.C..d....|
1159 0140: 34 6c b4 a3 d4 0a 0a e4 a8 5c 4e 23 c0 c9 7a 31 |4l.......\N#..z1|
1159 0140: 34 6c b4 a3 d4 0a 0a e4 a8 5c 4e 23 c0 c9 7a 31 |4l.......\N#..z1|
1160 0150: 97 87 77 7a 64 88 80 8e 60 97 20 93 0f 8e eb c4 |..wzd...`. .....|
1160 0150: 97 87 77 7a 64 88 80 8e 60 97 20 93 0f 8e eb c4 |..wzd...`. .....|
1161 0160: 62 a4 44 a3 52 20 b2 99 a9 2e e1 d7 29 4a 54 ac |b.D.R ......)JT.|
1161 0160: 62 a4 44 a3 52 20 b2 99 a9 2e e1 d7 29 4a 54 ac |b.D.R ......)JT.|
1162 0170: 44 7a bb cc 04 3d e0 aa bd 6a 33 5e 9b a2 57 36 |Dz...=...j3^..W6|
1162 0170: 44 7a bb cc 04 3d e0 aa bd 6a 33 5e 9b a2 57 36 |Dz...=...j3^..W6|
1163 0180: fa cb 45 bb 6d 3e c1 d9 d9 f5 83 69 8a d0 e0 e2 |..E.m>.....i....|
1163 0180: fa cb 45 bb 6d 3e c1 d9 d9 f5 83 69 8a d0 e0 e2 |..E.m>.....i....|
1164 0190: e7 ae 90 55 24 da 3f ab 78 c0 4c b4 56 a3 9e a4 |...U$.?.x.L.V...|
1164 0190: e7 ae 90 55 24 da 3f ab 78 c0 4c b4 56 a3 9e a4 |...U$.?.x.L.V...|
1165 01a0: af 9c 65 74 86 ec 6d dc 62 dc 33 ca c8 50 dd 9d |..et..m.b.3..P..|
1165 01a0: af 9c 65 74 86 ec 6d dc 62 dc 33 ca c8 50 dd 9d |..et..m.b.3..P..|
1166 01b0: 98 8e 9e 59 20 f3 f0 42 91 4a 09 f5 75 8d 3d a5 |...Y ..B.J..u.=.|
1166 01b0: 98 8e 9e 59 20 f3 f0 42 91 4a 09 f5 75 8d 3d a5 |...Y ..B.J..u.=.|
1167 01c0: a5 15 cb 8d 10 63 b0 c2 2e b2 81 f7 c1 76 0e 53 |.....c.......v.S|
1167 01c0: a5 15 cb 8d 10 63 b0 c2 2e b2 81 f7 c1 76 0e 53 |.....c.......v.S|
1168 01d0: 6c 0e 46 73 b5 ae 67 f9 4c 0b 45 6b a8 32 2a 2f |l.Fs..g.L.Ek.2*/|
1168 01d0: 6c 0e 46 73 b5 ae 67 f9 4c 0b 45 6b a8 32 2a 2f |l.Fs..g.L.Ek.2*/|
1169 01e0: a2 54 a4 44 05 20 a1 38 d1 a4 c6 09 a8 2b 08 99 |.T.D. .8.....+..|
1169 01e0: a2 54 a4 44 05 20 a1 38 d1 a4 c6 09 a8 2b 08 99 |.T.D. .8.....+..|
1170 01f0: a4 14 ae 8d a3 e3 aa 34 27 d8 44 ca c3 5d 21 8b |.......4'.D..]!.|
1170 01f0: a4 14 ae 8d a3 e3 aa 34 27 d8 44 ca c3 5d 21 8b |.......4'.D..]!.|
1171 0200: 1a 1e 97 29 71 2b 09 4a 4a 55 55 94 58 65 b2 bc |...)q+.JJUU.Xe..|
1171 0200: 1a 1e 97 29 71 2b 09 4a 4a 55 55 94 58 65 b2 bc |...)q+.JJUU.Xe..|
1172 0210: f3 a5 90 26 36 76 67 7a 51 98 d6 8a 4a 99 50 b5 |...&6vgzQ...J.P.|
1172 0210: f3 a5 90 26 36 76 67 7a 51 98 d6 8a 4a 99 50 b5 |...&6vgzQ...J.P.|
1173 0220: 99 8f 94 21 17 a9 8b f3 ad 4c 33 d4 2e 40 c8 0c |...!.....L3..@..|
1173 0220: 99 8f 94 21 17 a9 8b f3 ad 4c 33 d4 2e 40 c8 0c |...!.....L3..@..|
1174 0230: 3b 90 53 39 db 48 02 34 83 48 d6 b3 99 13 d2 58 |;.S9.H.4.H.....X|
1174 0230: 3b 90 53 39 db 48 02 34 83 48 d6 b3 99 13 d2 58 |;.S9.H.4.H.....X|
1175 0240: 65 8e 71 ac a9 06 95 f2 c4 8e b4 08 6b d3 0c ae |e.q.........k...|
1175 0240: 65 8e 71 ac a9 06 95 f2 c4 8e b4 08 6b d3 0c ae |e.q.........k...|
1176 0250: d9 90 56 71 43 a7 a2 62 16 3e 50 63 d3 57 3c 2d |..VqC..b.>Pc.W<-|
1176 0250: d9 90 56 71 43 a7 a2 62 16 3e 50 63 d3 57 3c 2d |..VqC..b.>Pc.W<-|
1177 0260: 9f 0f 34 05 08 d8 a6 4b 59 31 54 66 3a 45 0c 8a |..4....KY1Tf:E..|
1177 0260: 9f 0f 34 05 08 d8 a6 4b 59 31 54 66 3a 45 0c 8a |..4....KY1Tf:E..|
1178 0270: c7 90 3a f0 6a 83 1b f5 ca fb 80 2b 50 06 fb 51 |..:.j......+P..Q|
1178 0270: c7 90 3a f0 6a 83 1b f5 ca fb 80 2b 50 06 fb 51 |..:.j......+P..Q|
1179 0280: 7e a6 a4 d4 81 44 82 21 54 00 5b 1a 30 83 62 a3 |~....D.!T.[.0.b.|
1179 0280: 7e a6 a4 d4 81 44 82 21 54 00 5b 1a 30 83 62 a3 |~....D.!T.[.0.b.|
1180 0290: 18 b6 24 19 1e 45 df 4d 5c db a6 af 5b ac 90 fa |..$..E.M\...[...|
1180 0290: 18 b6 24 19 1e 45 df 4d 5c db a6 af 5b ac 90 fa |..$..E.M\...[...|
1181 02a0: 3e ed f9 ec 4c ba 36 ee d8 60 20 a7 c7 3b cb d1 |>...L.6..` ..;..|
1181 02a0: 3e ed f9 ec 4c ba 36 ee d8 60 20 a7 c7 3b cb d1 |>...L.6..` ..;..|
1182 02b0: 90 43 7d 27 16 50 5d ad f4 14 07 0b 90 5c cc 6b |.C}'.P]......\.k|
1182 02b0: 90 43 7d 27 16 50 5d ad f4 14 07 0b 90 5c cc 6b |.C}'.P]......\.k|
1183 02c0: 8d 3f a6 88 f4 34 37 a8 cf 14 63 36 19 f7 3e 28 |.?...47...c6..>(|
1183 02c0: 8d 3f a6 88 f4 34 37 a8 cf 14 63 36 19 f7 3e 28 |.?...47...c6..>(|
1184 02d0: de 99 e8 16 a4 9d 0d 40 a1 a7 24 52 14 a6 72 62 |.......@..$R..rb|
1184 02d0: de 99 e8 16 a4 9d 0d 40 a1 a7 24 52 14 a6 72 62 |.......@..$R..rb|
1185 02e0: 59 5a ca 2d e5 51 90 78 88 d9 c6 c7 21 d0 f7 46 |YZ.-.Q.x....!..F|
1185 02e0: 59 5a ca 2d e5 51 90 78 88 d9 c6 c7 21 d0 f7 46 |YZ.-.Q.x....!..F|
1186 02f0: b2 04 46 44 4e 20 9c 12 b1 03 4e 25 e0 a9 0c 58 |..FDN ....N%...X|
1186 02f0: b2 04 46 44 4e 20 9c 12 b1 03 4e 25 e0 a9 0c 58 |..FDN ....N%...X|
1187 0300: 5b 1d 3c 93 20 01 51 de a9 1c 69 23 32 46 14 b4 |[.<. .Q...i#2F..|
1187 0300: 5b 1d 3c 93 20 01 51 de a9 1c 69 23 32 46 14 b4 |[.<. .Q...i#2F..|
1188 0310: 90 db 17 98 98 50 03 90 29 aa 40 b0 13 d8 43 d2 |.....P..).@...C.|
1188 0310: 90 db 17 98 98 50 03 90 29 aa 40 b0 13 d8 43 d2 |.....P..).@...C.|
1189 0320: 5f c5 9d eb f3 f2 ad 41 e8 7a a9 ed a1 58 84 a6 |_......A.z...X..|
1189 0320: 5f c5 9d eb f3 f2 ad 41 e8 7a a9 ed a1 58 84 a6 |_......A.z...X..|
1190 0330: 42 bf d6 fc 24 82 c1 20 32 26 4a 15 a6 1d 29 7f |B...$.. 2&J...).|
1190 0330: 42 bf d6 fc 24 82 c1 20 32 26 4a 15 a6 1d 29 7f |B...$.. 2&J...).|
1191 0340: 7e f4 3d 07 bc 62 9a 5b ec 44 3d 72 1d 41 8b 5c |~.=..b.[.D=r.A.\|
1191 0340: 7e f4 3d 07 bc 62 9a 5b ec 44 3d 72 1d 41 8b 5c |~.=..b.[.D=r.A.\|
1192 0350: 80 de 0e 62 9a 2e f8 83 00 d5 07 a0 9c c6 74 98 |...b..........t.|
1192 0350: 80 de 0e 62 9a 2e f8 83 00 d5 07 a0 9c c6 74 98 |...b..........t.|
1193 0360: 11 b2 5e a9 38 02 03 ee fd 86 5c f4 86 b3 ae da |..^.8.....\.....|
1193 0360: 11 b2 5e a9 38 02 03 ee fd 86 5c f4 86 b3 ae da |..^.8.....\.....|
1194 0370: 05 94 01 c5 c6 ea 18 e6 ba 2a ba b3 04 5c 96 89 |.........*...\..|
1194 0370: 05 94 01 c5 c6 ea 18 e6 ba 2a ba b3 04 5c 96 89 |.........*...\..|
1195 0380: 72 63 5b 10 11 f6 67 34 98 cb e4 c0 4e fa e6 99 |rc[...g4....N...|
1195 0380: 72 63 5b 10 11 f6 67 34 98 cb e4 c0 4e fa e6 99 |rc[...g4....N...|
1196 0390: 19 6e 50 e8 26 8d 0c 17 e0 be ef e1 8e 02 6f 32 |.nP.&.........o2|
1196 0390: 19 6e 50 e8 26 8d 0c 17 e0 be ef e1 8e 02 6f 32 |.nP.&.........o2|
1197 03a0: 82 dc 26 f8 a1 08 f3 8a 0d f3 c4 75 00 48 73 b8 |..&........u.Hs.|
1197 03a0: 82 dc 26 f8 a1 08 f3 8a 0d f3 c4 75 00 48 73 b8 |..&........u.Hs.|
1198 03b0: be 3b 0d 7f d0 fd c7 78 96 ec e0 03 80 68 4d 8d |.;.....x.....hM.|
1198 03b0: be 3b 0d 7f d0 fd c7 78 96 ec e0 03 80 68 4d 8d |.;.....x.....hM.|
1199 03c0: 43 8c d7 68 58 f9 50 f0 18 cb 21 58 1b 60 cd 1f |C..hX.P...!X.`..|
1199 03c0: 43 8c d7 68 58 f9 50 f0 18 cb 21 58 1b 60 cd 1f |C..hX.P...!X.`..|
1200 03d0: 84 36 2e 16 1f 0a f7 4e 8f eb df 01 2d c2 79 0b |.6.....N....-.y.|
1200 03d0: 84 36 2e 16 1f 0a f7 4e 8f eb df 01 2d c2 79 0b |.6.....N....-.y.|
1201 03e0: f7 24 ea 0d e8 59 86 51 6e 1c 30 a3 ad 2f ee 8c |.$...Y.Qn.0../..|
1201 03e0: f7 24 ea 0d e8 59 86 51 6e 1c 30 a3 ad 2f ee 8c |.$...Y.Qn.0../..|
1202 03f0: 90 c8 84 d5 e8 34 c1 95 b2 c9 f6 4d 87 1c 7d 19 |.....4.....M..}.|
1202 03f0: 90 c8 84 d5 e8 34 c1 95 b2 c9 f6 4d 87 1c 7d 19 |.....4.....M..}.|
1203 0400: d6 41 58 56 7a e0 6c ba 10 c7 e8 33 39 36 96 e7 |.AXVz.l....396..|
1203 0400: d6 41 58 56 7a e0 6c ba 10 c7 e8 33 39 36 96 e7 |.AXVz.l....396..|
1204 0410: d2 f9 59 9a 08 95 48 38 e7 0b b7 0a 24 67 c4 39 |..Y...H8....$g.9|
1204 0410: d2 f9 59 9a 08 95 48 38 e7 0b b7 0a 24 67 c4 39 |..Y...H8....$g.9|
1205 0420: 8b 43 88 57 9c 01 f5 61 b5 e1 27 41 7e af 83 fe |.C.W...a..'A~...|
1205 0420: 8b 43 88 57 9c 01 f5 61 b5 e1 27 41 7e af 83 fe |.C.W...a..'A~...|
1206 0430: 2e e4 8a 70 a1 21 46 96 30 7a |...p.!F.0z|
1206 0430: 2e e4 8a 70 a1 21 46 96 30 7a |...p.!F.0z|
1207 $ hg debugbundle ../rev.hg2.bz
1207 $ hg debugbundle ../rev.hg2.bz
1208 Stream params: {'Compression': 'BZ'}
1208 Stream params: sortdict([('Compression', 'BZ')])
1209 changegroup -- '{}'
1209 changegroup -- 'sortdict()'
1210 32af7686d403cf45b5d95f2d70cebea587ac806a
1210 32af7686d403cf45b5d95f2d70cebea587ac806a
1211 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
1211 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
1212 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
1212 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
1213 02de42196ebee42ef284b6780a87cdc96e8eaab6
1213 02de42196ebee42ef284b6780a87cdc96e8eaab6
1214 $ hg unbundle ../rev.hg2.bz
1214 $ hg unbundle ../rev.hg2.bz
1215 adding changesets
1215 adding changesets
1216 adding manifests
1216 adding manifests
1217 adding file changes
1217 adding file changes
1218 added 0 changesets with 0 changes to 3 files
1218 added 0 changesets with 0 changes to 3 files
1219 (run 'hg update' to get a working copy)
1219 (run 'hg update' to get a working copy)
1220
1220
1221 unknown compression while unbundling
1221 unknown compression while unbundling
1222 -----------------------------
1222 -----------------------------
1223
1223
1224 $ hg bundle2 --param Compression=FooBarUnknown --rev '8+7+5+4' ../rev.hg2.bz
1224 $ hg bundle2 --param Compression=FooBarUnknown --rev '8+7+5+4' ../rev.hg2.bz
1225 $ cat ../rev.hg2.bz | hg statbundle2
1225 $ cat ../rev.hg2.bz | hg statbundle2
1226 abort: unknown parameters: Stream Parameter - Compression='FooBarUnknown'
1226 abort: unknown parameters: Stream Parameter - Compression='FooBarUnknown'
1227 [255]
1227 [255]
1228 $ hg unbundle ../rev.hg2.bz
1228 $ hg unbundle ../rev.hg2.bz
1229 abort: ../rev.hg2.bz: unknown bundle feature, Stream Parameter - Compression='FooBarUnknown'
1229 abort: ../rev.hg2.bz: unknown bundle feature, Stream Parameter - Compression='FooBarUnknown'
1230 (see https://mercurial-scm.org/wiki/BundleFeature for more information)
1230 (see https://mercurial-scm.org/wiki/BundleFeature for more information)
1231 [255]
1231 [255]
1232
1232
1233 $ cd ..
1233 $ cd ..
@@ -1,76 +1,76 b''
1
1
2 Create a test repository:
2 Create a test repository:
3
3
4 $ hg init repo
4 $ hg init repo
5 $ cd repo
5 $ cd repo
6 $ touch a ; hg add a ; hg ci -ma
6 $ touch a ; hg add a ; hg ci -ma
7 $ touch b ; hg add b ; hg ci -mb
7 $ touch b ; hg add b ; hg ci -mb
8 $ touch c ; hg add c ; hg ci -mc
8 $ touch c ; hg add c ; hg ci -mc
9 $ hg bundle --base 0 --rev tip bundle.hg -v --type v1
9 $ hg bundle --base 0 --rev tip bundle.hg -v --type v1
10 2 changesets found
10 2 changesets found
11 uncompressed size of bundle content:
11 uncompressed size of bundle content:
12 332 (changelog)
12 332 (changelog)
13 282 (manifests)
13 282 (manifests)
14 93 b
14 93 b
15 93 c
15 93 c
16 $ hg bundle --base 0 --rev tip bundle2.hg -v --type none-v2
16 $ hg bundle --base 0 --rev tip bundle2.hg -v --type none-v2
17 2 changesets found
17 2 changesets found
18 uncompressed size of bundle content:
18 uncompressed size of bundle content:
19 372 (changelog)
19 372 (changelog)
20 322 (manifests)
20 322 (manifests)
21 113 b
21 113 b
22 113 c
22 113 c
23
23
24 Terse output:
24 Terse output:
25
25
26 $ hg debugbundle bundle.hg
26 $ hg debugbundle bundle.hg
27 0e067c57feba1a5694ca4844f05588bb1bf82342
27 0e067c57feba1a5694ca4844f05588bb1bf82342
28 991a3460af53952d10ec8a295d3d2cc2e5fa9690
28 991a3460af53952d10ec8a295d3d2cc2e5fa9690
29
29
30 Terse output:
30 Terse output:
31
31
32 $ hg debugbundle bundle2.hg
32 $ hg debugbundle bundle2.hg
33 Stream params: {}
33 Stream params: {}
34 changegroup -- "{'version': '02'}"
34 changegroup -- "sortdict([('version', '02')])"
35 0e067c57feba1a5694ca4844f05588bb1bf82342
35 0e067c57feba1a5694ca4844f05588bb1bf82342
36 991a3460af53952d10ec8a295d3d2cc2e5fa9690
36 991a3460af53952d10ec8a295d3d2cc2e5fa9690
37
37
38 Verbose output:
38 Verbose output:
39
39
40 $ hg debugbundle --all bundle.hg
40 $ hg debugbundle --all bundle.hg
41 format: id, p1, p2, cset, delta base, len(delta)
41 format: id, p1, p2, cset, delta base, len(delta)
42
42
43 changelog
43 changelog
44 0e067c57feba1a5694ca4844f05588bb1bf82342 3903775176ed42b1458a6281db4a0ccf4d9f287a 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 3903775176ed42b1458a6281db4a0ccf4d9f287a 80
44 0e067c57feba1a5694ca4844f05588bb1bf82342 3903775176ed42b1458a6281db4a0ccf4d9f287a 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 3903775176ed42b1458a6281db4a0ccf4d9f287a 80
45 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 80
45 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 80
46
46
47 manifest
47 manifest
48 686dbf0aeca417636fa26a9121c681eabbb15a20 8515d4bfda768e04af4c13a69a72e28c7effbea7 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 8515d4bfda768e04af4c13a69a72e28c7effbea7 55
48 686dbf0aeca417636fa26a9121c681eabbb15a20 8515d4bfda768e04af4c13a69a72e28c7effbea7 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 8515d4bfda768e04af4c13a69a72e28c7effbea7 55
49 ae25a31b30b3490a981e7b96a3238cc69583fda1 686dbf0aeca417636fa26a9121c681eabbb15a20 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 686dbf0aeca417636fa26a9121c681eabbb15a20 55
49 ae25a31b30b3490a981e7b96a3238cc69583fda1 686dbf0aeca417636fa26a9121c681eabbb15a20 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 686dbf0aeca417636fa26a9121c681eabbb15a20 55
50
50
51 b
51 b
52 b80de5d138758541c5f05265ad144ab9fa86d1db 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 0000000000000000000000000000000000000000 0
52 b80de5d138758541c5f05265ad144ab9fa86d1db 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 0000000000000000000000000000000000000000 0
53
53
54 c
54 c
55 b80de5d138758541c5f05265ad144ab9fa86d1db 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0000000000000000000000000000000000000000 0
55 b80de5d138758541c5f05265ad144ab9fa86d1db 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0000000000000000000000000000000000000000 0
56
56
57 $ hg debugbundle --all bundle2.hg
57 $ hg debugbundle --all bundle2.hg
58 Stream params: {}
58 Stream params: {}
59 changegroup -- "{'version': '02'}"
59 changegroup -- "sortdict([('version', '02')])"
60 format: id, p1, p2, cset, delta base, len(delta)
60 format: id, p1, p2, cset, delta base, len(delta)
61
61
62 changelog
62 changelog
63 0e067c57feba1a5694ca4844f05588bb1bf82342 3903775176ed42b1458a6281db4a0ccf4d9f287a 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 3903775176ed42b1458a6281db4a0ccf4d9f287a 80
63 0e067c57feba1a5694ca4844f05588bb1bf82342 3903775176ed42b1458a6281db4a0ccf4d9f287a 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 3903775176ed42b1458a6281db4a0ccf4d9f287a 80
64 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 80
64 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 80
65
65
66 manifest
66 manifest
67 686dbf0aeca417636fa26a9121c681eabbb15a20 8515d4bfda768e04af4c13a69a72e28c7effbea7 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 8515d4bfda768e04af4c13a69a72e28c7effbea7 55
67 686dbf0aeca417636fa26a9121c681eabbb15a20 8515d4bfda768e04af4c13a69a72e28c7effbea7 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 8515d4bfda768e04af4c13a69a72e28c7effbea7 55
68 ae25a31b30b3490a981e7b96a3238cc69583fda1 686dbf0aeca417636fa26a9121c681eabbb15a20 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 686dbf0aeca417636fa26a9121c681eabbb15a20 55
68 ae25a31b30b3490a981e7b96a3238cc69583fda1 686dbf0aeca417636fa26a9121c681eabbb15a20 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 686dbf0aeca417636fa26a9121c681eabbb15a20 55
69
69
70 b
70 b
71 b80de5d138758541c5f05265ad144ab9fa86d1db 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 0000000000000000000000000000000000000000 0
71 b80de5d138758541c5f05265ad144ab9fa86d1db 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 0000000000000000000000000000000000000000 0
72
72
73 c
73 c
74 b80de5d138758541c5f05265ad144ab9fa86d1db 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0000000000000000000000000000000000000000 0
74 b80de5d138758541c5f05265ad144ab9fa86d1db 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0000000000000000000000000000000000000000 0
75
75
76 $ cd ..
76 $ cd ..
@@ -1,161 +1,161 b''
1 Check whether size of generaldelta revlog is not bigger than its
1 Check whether size of generaldelta revlog is not bigger than its
2 regular equivalent. Test would fail if generaldelta was naive
2 regular equivalent. Test would fail if generaldelta was naive
3 implementation of parentdelta: third manifest revision would be fully
3 implementation of parentdelta: third manifest revision would be fully
4 inserted due to big distance from its paren revision (zero).
4 inserted due to big distance from its paren revision (zero).
5
5
6 $ hg init repo --config format.generaldelta=no --config format.usegeneraldelta=no
6 $ hg init repo --config format.generaldelta=no --config format.usegeneraldelta=no
7 $ cd repo
7 $ cd repo
8 $ echo foo > foo
8 $ echo foo > foo
9 $ echo bar > bar
9 $ echo bar > bar
10 $ echo baz > baz
10 $ echo baz > baz
11 $ hg commit -q -Am boo
11 $ hg commit -q -Am boo
12 $ hg clone --pull . ../gdrepo -q --config format.generaldelta=yes
12 $ hg clone --pull . ../gdrepo -q --config format.generaldelta=yes
13 $ for r in 1 2 3; do
13 $ for r in 1 2 3; do
14 > echo $r > foo
14 > echo $r > foo
15 > hg commit -q -m $r
15 > hg commit -q -m $r
16 > hg up -q -r 0
16 > hg up -q -r 0
17 > hg pull . -q -r $r -R ../gdrepo
17 > hg pull . -q -r $r -R ../gdrepo
18 > done
18 > done
19
19
20 $ cd ..
20 $ cd ..
21 >>> from __future__ import print_function
21 >>> from __future__ import print_function
22 >>> import os
22 >>> import os
23 >>> regsize = os.stat("repo/.hg/store/00manifest.i").st_size
23 >>> regsize = os.stat("repo/.hg/store/00manifest.i").st_size
24 >>> gdsize = os.stat("gdrepo/.hg/store/00manifest.i").st_size
24 >>> gdsize = os.stat("gdrepo/.hg/store/00manifest.i").st_size
25 >>> if regsize < gdsize:
25 >>> if regsize < gdsize:
26 ... print('generaldata increased size of manifest')
26 ... print('generaldata increased size of manifest')
27
27
28 Verify rev reordering doesnt create invalid bundles (issue4462)
28 Verify rev reordering doesnt create invalid bundles (issue4462)
29 This requires a commit tree that when pulled will reorder manifest revs such
29 This requires a commit tree that when pulled will reorder manifest revs such
30 that the second manifest to create a file rev will be ordered before the first
30 that the second manifest to create a file rev will be ordered before the first
31 manifest to create that file rev. We also need to do a partial pull to ensure
31 manifest to create that file rev. We also need to do a partial pull to ensure
32 reordering happens. At the end we verify the linkrev points at the earliest
32 reordering happens. At the end we verify the linkrev points at the earliest
33 commit.
33 commit.
34
34
35 $ hg init server --config format.generaldelta=True
35 $ hg init server --config format.generaldelta=True
36 $ cd server
36 $ cd server
37 $ touch a
37 $ touch a
38 $ hg commit -Aqm a
38 $ hg commit -Aqm a
39 $ echo x > x
39 $ echo x > x
40 $ echo y > y
40 $ echo y > y
41 $ hg commit -Aqm xy
41 $ hg commit -Aqm xy
42 $ hg up -q '.^'
42 $ hg up -q '.^'
43 $ echo x > x
43 $ echo x > x
44 $ echo z > z
44 $ echo z > z
45 $ hg commit -Aqm xz
45 $ hg commit -Aqm xz
46 $ hg up -q 1
46 $ hg up -q 1
47 $ echo b > b
47 $ echo b > b
48 $ hg commit -Aqm b
48 $ hg commit -Aqm b
49 $ hg merge -q 2
49 $ hg merge -q 2
50 $ hg commit -Aqm merge
50 $ hg commit -Aqm merge
51 $ echo c > c
51 $ echo c > c
52 $ hg commit -Aqm c
52 $ hg commit -Aqm c
53 $ hg log -G -T '{rev} {shortest(node)} {desc}'
53 $ hg log -G -T '{rev} {shortest(node)} {desc}'
54 @ 5 ebb8 c
54 @ 5 ebb8 c
55 |
55 |
56 o 4 baf7 merge
56 o 4 baf7 merge
57 |\
57 |\
58 | o 3 a129 b
58 | o 3 a129 b
59 | |
59 | |
60 o | 2 958c xz
60 o | 2 958c xz
61 | |
61 | |
62 | o 1 f00c xy
62 | o 1 f00c xy
63 |/
63 |/
64 o 0 3903 a
64 o 0 3903 a
65
65
66 $ cd ..
66 $ cd ..
67 $ hg init client --config format.generaldelta=false --config format.usegeneraldelta=false
67 $ hg init client --config format.generaldelta=false --config format.usegeneraldelta=false
68 $ cd client
68 $ cd client
69 $ hg pull -q ../server -r 4
69 $ hg pull -q ../server -r 4
70 $ hg debugindex x
70 $ hg debugindex x
71 rev offset length base linkrev nodeid p1 p2
71 rev offset length base linkrev nodeid p1 p2
72 0 0 3 0 1 1406e7411862 000000000000 000000000000
72 0 0 3 0 1 1406e7411862 000000000000 000000000000
73
73
74 $ cd ..
74 $ cd ..
75
75
76 Test "usegeneraldelta" config
76 Test "usegeneraldelta" config
77 (repo are general delta, but incoming bundle are not re-deltified)
77 (repo are general delta, but incoming bundle are not re-deltified)
78
78
79 delta coming from the server base delta server are not recompressed.
79 delta coming from the server base delta server are not recompressed.
80 (also include the aggressive version for comparison)
80 (also include the aggressive version for comparison)
81
81
82 $ hg clone repo --pull --config format.usegeneraldelta=1 usegd
82 $ hg clone repo --pull --config format.usegeneraldelta=1 usegd
83 requesting all changes
83 requesting all changes
84 adding changesets
84 adding changesets
85 adding manifests
85 adding manifests
86 adding file changes
86 adding file changes
87 added 4 changesets with 6 changes to 3 files (+2 heads)
87 added 4 changesets with 6 changes to 3 files (+2 heads)
88 updating to branch default
88 updating to branch default
89 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 $ hg clone repo --pull --config format.generaldelta=1 full
90 $ hg clone repo --pull --config format.generaldelta=1 full
91 requesting all changes
91 requesting all changes
92 adding changesets
92 adding changesets
93 adding manifests
93 adding manifests
94 adding file changes
94 adding file changes
95 added 4 changesets with 6 changes to 3 files (+2 heads)
95 added 4 changesets with 6 changes to 3 files (+2 heads)
96 updating to branch default
96 updating to branch default
97 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
97 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
98 $ hg -R repo debugindex -m
98 $ hg -R repo debugindex -m
99 rev offset length base linkrev nodeid p1 p2
99 rev offset length base linkrev nodeid p1 p2
100 0 0 104 0 0 cef96823c800 000000000000 000000000000
100 0 0 104 0 0 cef96823c800 000000000000 000000000000
101 1 104 57 0 1 58ab9a8d541d cef96823c800 000000000000
101 1 104 57 0 1 58ab9a8d541d cef96823c800 000000000000
102 2 161 57 0 2 134fdc6fd680 cef96823c800 000000000000
102 2 161 57 0 2 134fdc6fd680 cef96823c800 000000000000
103 3 218 104 3 3 723508934dad cef96823c800 000000000000
103 3 218 104 3 3 723508934dad cef96823c800 000000000000
104 $ hg -R usegd debugindex -m
104 $ hg -R usegd debugindex -m
105 rev offset length delta linkrev nodeid p1 p2
105 rev offset length delta linkrev nodeid p1 p2
106 0 0 104 -1 0 cef96823c800 000000000000 000000000000
106 0 0 104 -1 0 cef96823c800 000000000000 000000000000
107 1 104 57 0 1 58ab9a8d541d cef96823c800 000000000000
107 1 104 57 0 1 58ab9a8d541d cef96823c800 000000000000
108 2 161 57 1 2 134fdc6fd680 cef96823c800 000000000000
108 2 161 57 1 2 134fdc6fd680 cef96823c800 000000000000
109 3 218 57 0 3 723508934dad cef96823c800 000000000000
109 3 218 57 0 3 723508934dad cef96823c800 000000000000
110 $ hg -R full debugindex -m
110 $ hg -R full debugindex -m
111 rev offset length delta linkrev nodeid p1 p2
111 rev offset length delta linkrev nodeid p1 p2
112 0 0 104 -1 0 cef96823c800 000000000000 000000000000
112 0 0 104 -1 0 cef96823c800 000000000000 000000000000
113 1 104 57 0 1 58ab9a8d541d cef96823c800 000000000000
113 1 104 57 0 1 58ab9a8d541d cef96823c800 000000000000
114 2 161 57 0 2 134fdc6fd680 cef96823c800 000000000000
114 2 161 57 0 2 134fdc6fd680 cef96823c800 000000000000
115 3 218 57 0 3 723508934dad cef96823c800 000000000000
115 3 218 57 0 3 723508934dad cef96823c800 000000000000
116
116
117 Test format.aggressivemergedeltas
117 Test format.aggressivemergedeltas
118
118
119 $ hg init --config format.generaldelta=1 aggressive
119 $ hg init --config format.generaldelta=1 aggressive
120 $ cd aggressive
120 $ cd aggressive
121 $ cat << EOF >> .hg/hgrc
121 $ cat << EOF >> .hg/hgrc
122 > [format]
122 > [format]
123 > generaldelta = 1
123 > generaldelta = 1
124 > EOF
124 > EOF
125 $ touch a b c d e
125 $ touch a b c d e
126 $ hg commit -Aqm side1
126 $ hg commit -Aqm side1
127 $ hg up -q null
127 $ hg up -q null
128 $ touch x y
128 $ touch x y
129 $ hg commit -Aqm side2
129 $ hg commit -Aqm side2
130
130
131 - Verify non-aggressive merge uses p1 (commit 1) as delta parent
131 - Verify non-aggressive merge uses p1 (commit 1) as delta parent
132 $ hg merge -q 0
132 $ hg merge -q 0
133 $ hg commit -q -m merge
133 $ hg commit -q -m merge
134 $ hg debugindex -m
134 $ hg debugindex -m
135 rev offset length delta linkrev nodeid p1 p2
135 rev offset length delta linkrev nodeid p1 p2
136 0 0 59 -1 0 8dde941edb6e 000000000000 000000000000
136 0 0 59 -1 0 8dde941edb6e 000000000000 000000000000
137 1 59 61 0 1 315c023f341d 000000000000 000000000000
137 1 59 61 0 1 315c023f341d 000000000000 000000000000
138 2 120 65 1 2 2ab389a983eb 315c023f341d 8dde941edb6e
138 2 120 65 1 2 2ab389a983eb 315c023f341d 8dde941edb6e
139
139
140 $ hg strip -q -r . --config extensions.strip=
140 $ hg strip -q -r . --config extensions.strip=
141
141
142 - Verify aggressive merge uses p2 (commit 0) as delta parent
142 - Verify aggressive merge uses p2 (commit 0) as delta parent
143 $ hg up -q -C 1
143 $ hg up -q -C 1
144 $ hg merge -q 0
144 $ hg merge -q 0
145 $ hg commit -q -m merge --config format.aggressivemergedeltas=True
145 $ hg commit -q -m merge --config format.aggressivemergedeltas=True
146 $ hg debugindex -m
146 $ hg debugindex -m
147 rev offset length delta linkrev nodeid p1 p2
147 rev offset length delta linkrev nodeid p1 p2
148 0 0 59 -1 0 8dde941edb6e 000000000000 000000000000
148 0 0 59 -1 0 8dde941edb6e 000000000000 000000000000
149 1 59 61 0 1 315c023f341d 000000000000 000000000000
149 1 59 61 0 1 315c023f341d 000000000000 000000000000
150 2 120 62 0 2 2ab389a983eb 315c023f341d 8dde941edb6e
150 2 120 62 0 2 2ab389a983eb 315c023f341d 8dde941edb6e
151
151
152 Test that strip bundle use bundle2
152 Test that strip bundle use bundle2
153 $ hg --config extensions.strip= strip .
153 $ hg --config extensions.strip= strip .
154 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
154 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
155 saved backup bundle to $TESTTMP/aggressive/.hg/strip-backup/1c5d4dc9a8b8-6c68e60c-backup.hg (glob)
155 saved backup bundle to $TESTTMP/aggressive/.hg/strip-backup/1c5d4dc9a8b8-6c68e60c-backup.hg (glob)
156 $ hg debugbundle .hg/strip-backup/*
156 $ hg debugbundle .hg/strip-backup/*
157 Stream params: {'Compression': 'BZ'}
157 Stream params: sortdict([('Compression', 'BZ')])
158 changegroup -- "{'version': '02'}"
158 changegroup -- "sortdict([('version', '02')])"
159 1c5d4dc9a8b8d6e1750966d343e94db665e7a1e9
159 1c5d4dc9a8b8d6e1750966d343e94db665e7a1e9
160
160
161 $ cd ..
161 $ cd ..
@@ -1,272 +1,272 b''
1 #require serve
1 #require serve
2
2
3 = Test the getbundle() protocol function =
3 = Test the getbundle() protocol function =
4
4
5 Create a test repository:
5 Create a test repository:
6
6
7 $ hg init repo
7 $ hg init repo
8 $ cd repo
8 $ cd repo
9 $ hg debugbuilddag -n -m '+2 :fork +5 :p1 *fork +6 :p2 /p1 :m1 +3' > /dev/null
9 $ hg debugbuilddag -n -m '+2 :fork +5 :p1 *fork +6 :p2 /p1 :m1 +3' > /dev/null
10 $ hg log -G --template '{node}\n'
10 $ hg log -G --template '{node}\n'
11 o 10c14a2cc935e1d8c31f9e98587dcf27fb08a6da
11 o 10c14a2cc935e1d8c31f9e98587dcf27fb08a6da
12 |
12 |
13 o 4801a72e5d88cb515b0c7e40fae34180f3f837f2
13 o 4801a72e5d88cb515b0c7e40fae34180f3f837f2
14 |
14 |
15 o 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
15 o 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
16 |
16 |
17 o 8365676dbab05860ce0d9110f2af51368b961bbd
17 o 8365676dbab05860ce0d9110f2af51368b961bbd
18 |\
18 |\
19 | o 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
19 | o 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
20 | |
20 | |
21 | o 13c0170174366b441dc68e8e33757232fa744458
21 | o 13c0170174366b441dc68e8e33757232fa744458
22 | |
22 | |
23 | o 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
23 | o 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
24 | |
24 | |
25 | o 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
25 | o 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
26 | |
26 | |
27 | o 928b5f94cdb278bb536eba552de348a4e92ef24d
27 | o 928b5f94cdb278bb536eba552de348a4e92ef24d
28 | |
28 | |
29 | o f34414c64173e0ecb61b25dc55e116dbbcc89bee
29 | o f34414c64173e0ecb61b25dc55e116dbbcc89bee
30 | |
30 | |
31 | o 8931463777131cd73923e560b760061f2aa8a4bc
31 | o 8931463777131cd73923e560b760061f2aa8a4bc
32 | |
32 | |
33 o | 6621d79f61b23ec74cf4b69464343d9e0980ec8b
33 o | 6621d79f61b23ec74cf4b69464343d9e0980ec8b
34 | |
34 | |
35 o | bac16991d12ff45f9dc43c52da1946dfadb83e80
35 o | bac16991d12ff45f9dc43c52da1946dfadb83e80
36 | |
36 | |
37 o | ff42371d57168345fdf1a3aac66a51f6a45d41d2
37 o | ff42371d57168345fdf1a3aac66a51f6a45d41d2
38 | |
38 | |
39 o | d5f6e1ea452285324836a49d7d3c2a63cfed1d31
39 o | d5f6e1ea452285324836a49d7d3c2a63cfed1d31
40 | |
40 | |
41 o | 713346a995c363120712aed1aee7e04afd867638
41 o | 713346a995c363120712aed1aee7e04afd867638
42 |/
42 |/
43 o 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
43 o 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
44 |
44 |
45 o 7704483d56b2a7b5db54dcee7c62378ac629b348
45 o 7704483d56b2a7b5db54dcee7c62378ac629b348
46
46
47 $ cd ..
47 $ cd ..
48
48
49
49
50 = Test locally =
50 = Test locally =
51
51
52 Get everything:
52 Get everything:
53
53
54 $ hg debuggetbundle repo bundle
54 $ hg debuggetbundle repo bundle
55 $ hg debugbundle bundle
55 $ hg debugbundle bundle
56 7704483d56b2a7b5db54dcee7c62378ac629b348
56 7704483d56b2a7b5db54dcee7c62378ac629b348
57 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
57 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
58 713346a995c363120712aed1aee7e04afd867638
58 713346a995c363120712aed1aee7e04afd867638
59 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
59 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
60 ff42371d57168345fdf1a3aac66a51f6a45d41d2
60 ff42371d57168345fdf1a3aac66a51f6a45d41d2
61 bac16991d12ff45f9dc43c52da1946dfadb83e80
61 bac16991d12ff45f9dc43c52da1946dfadb83e80
62 6621d79f61b23ec74cf4b69464343d9e0980ec8b
62 6621d79f61b23ec74cf4b69464343d9e0980ec8b
63 8931463777131cd73923e560b760061f2aa8a4bc
63 8931463777131cd73923e560b760061f2aa8a4bc
64 f34414c64173e0ecb61b25dc55e116dbbcc89bee
64 f34414c64173e0ecb61b25dc55e116dbbcc89bee
65 928b5f94cdb278bb536eba552de348a4e92ef24d
65 928b5f94cdb278bb536eba552de348a4e92ef24d
66 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
66 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
67 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
67 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
68 13c0170174366b441dc68e8e33757232fa744458
68 13c0170174366b441dc68e8e33757232fa744458
69 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
69 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
70 8365676dbab05860ce0d9110f2af51368b961bbd
70 8365676dbab05860ce0d9110f2af51368b961bbd
71 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
71 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
72 4801a72e5d88cb515b0c7e40fae34180f3f837f2
72 4801a72e5d88cb515b0c7e40fae34180f3f837f2
73 10c14a2cc935e1d8c31f9e98587dcf27fb08a6da
73 10c14a2cc935e1d8c31f9e98587dcf27fb08a6da
74
74
75 Get part of linear run:
75 Get part of linear run:
76
76
77 $ hg debuggetbundle repo bundle -H 4801a72e5d88cb515b0c7e40fae34180f3f837f2 -C 8365676dbab05860ce0d9110f2af51368b961bbd
77 $ hg debuggetbundle repo bundle -H 4801a72e5d88cb515b0c7e40fae34180f3f837f2 -C 8365676dbab05860ce0d9110f2af51368b961bbd
78 $ hg debugbundle bundle
78 $ hg debugbundle bundle
79 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
79 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
80 4801a72e5d88cb515b0c7e40fae34180f3f837f2
80 4801a72e5d88cb515b0c7e40fae34180f3f837f2
81
81
82 Get missing branch and merge:
82 Get missing branch and merge:
83
83
84 $ hg debuggetbundle repo bundle -H 4801a72e5d88cb515b0c7e40fae34180f3f837f2 -C 13c0170174366b441dc68e8e33757232fa744458
84 $ hg debuggetbundle repo bundle -H 4801a72e5d88cb515b0c7e40fae34180f3f837f2 -C 13c0170174366b441dc68e8e33757232fa744458
85 $ hg debugbundle bundle
85 $ hg debugbundle bundle
86 713346a995c363120712aed1aee7e04afd867638
86 713346a995c363120712aed1aee7e04afd867638
87 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
87 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
88 ff42371d57168345fdf1a3aac66a51f6a45d41d2
88 ff42371d57168345fdf1a3aac66a51f6a45d41d2
89 bac16991d12ff45f9dc43c52da1946dfadb83e80
89 bac16991d12ff45f9dc43c52da1946dfadb83e80
90 6621d79f61b23ec74cf4b69464343d9e0980ec8b
90 6621d79f61b23ec74cf4b69464343d9e0980ec8b
91 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
91 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
92 8365676dbab05860ce0d9110f2af51368b961bbd
92 8365676dbab05860ce0d9110f2af51368b961bbd
93 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
93 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
94 4801a72e5d88cb515b0c7e40fae34180f3f837f2
94 4801a72e5d88cb515b0c7e40fae34180f3f837f2
95
95
96 Get from only one head:
96 Get from only one head:
97
97
98 $ hg debuggetbundle repo bundle -H 928b5f94cdb278bb536eba552de348a4e92ef24d -C 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
98 $ hg debuggetbundle repo bundle -H 928b5f94cdb278bb536eba552de348a4e92ef24d -C 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
99 $ hg debugbundle bundle
99 $ hg debugbundle bundle
100 8931463777131cd73923e560b760061f2aa8a4bc
100 8931463777131cd73923e560b760061f2aa8a4bc
101 f34414c64173e0ecb61b25dc55e116dbbcc89bee
101 f34414c64173e0ecb61b25dc55e116dbbcc89bee
102 928b5f94cdb278bb536eba552de348a4e92ef24d
102 928b5f94cdb278bb536eba552de348a4e92ef24d
103
103
104 Get parts of two branches:
104 Get parts of two branches:
105
105
106 $ hg debuggetbundle repo bundle -H 13c0170174366b441dc68e8e33757232fa744458 -C 700b7e19db54103633c4bf4a6a6b6d55f4d50c03 -H bac16991d12ff45f9dc43c52da1946dfadb83e80 -C d5f6e1ea452285324836a49d7d3c2a63cfed1d31
106 $ hg debuggetbundle repo bundle -H 13c0170174366b441dc68e8e33757232fa744458 -C 700b7e19db54103633c4bf4a6a6b6d55f4d50c03 -H bac16991d12ff45f9dc43c52da1946dfadb83e80 -C d5f6e1ea452285324836a49d7d3c2a63cfed1d31
107 $ hg debugbundle bundle
107 $ hg debugbundle bundle
108 ff42371d57168345fdf1a3aac66a51f6a45d41d2
108 ff42371d57168345fdf1a3aac66a51f6a45d41d2
109 bac16991d12ff45f9dc43c52da1946dfadb83e80
109 bac16991d12ff45f9dc43c52da1946dfadb83e80
110 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
110 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
111 13c0170174366b441dc68e8e33757232fa744458
111 13c0170174366b441dc68e8e33757232fa744458
112
112
113 Check that we get all needed file changes:
113 Check that we get all needed file changes:
114
114
115 $ hg debugbundle bundle --all
115 $ hg debugbundle bundle --all
116 format: id, p1, p2, cset, delta base, len(delta)
116 format: id, p1, p2, cset, delta base, len(delta)
117
117
118 changelog
118 changelog
119 ff42371d57168345fdf1a3aac66a51f6a45d41d2 d5f6e1ea452285324836a49d7d3c2a63cfed1d31 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 d5f6e1ea452285324836a49d7d3c2a63cfed1d31 99
119 ff42371d57168345fdf1a3aac66a51f6a45d41d2 d5f6e1ea452285324836a49d7d3c2a63cfed1d31 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 d5f6e1ea452285324836a49d7d3c2a63cfed1d31 99
120 bac16991d12ff45f9dc43c52da1946dfadb83e80 ff42371d57168345fdf1a3aac66a51f6a45d41d2 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 ff42371d57168345fdf1a3aac66a51f6a45d41d2 99
120 bac16991d12ff45f9dc43c52da1946dfadb83e80 ff42371d57168345fdf1a3aac66a51f6a45d41d2 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 ff42371d57168345fdf1a3aac66a51f6a45d41d2 99
121 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 700b7e19db54103633c4bf4a6a6b6d55f4d50c03 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 bac16991d12ff45f9dc43c52da1946dfadb83e80 102
121 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 700b7e19db54103633c4bf4a6a6b6d55f4d50c03 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 bac16991d12ff45f9dc43c52da1946dfadb83e80 102
122 13c0170174366b441dc68e8e33757232fa744458 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 102
122 13c0170174366b441dc68e8e33757232fa744458 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 102
123
123
124 manifest
124 manifest
125 dac7984588fc4eea7acbf39693a9c1b06f5b175d 591f732a3faf1fb903815273f3c199a514a61ccb 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 591f732a3faf1fb903815273f3c199a514a61ccb 113
125 dac7984588fc4eea7acbf39693a9c1b06f5b175d 591f732a3faf1fb903815273f3c199a514a61ccb 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 591f732a3faf1fb903815273f3c199a514a61ccb 113
126 0772616e6b48a76afb6c1458e193cbb3dae2e4ff dac7984588fc4eea7acbf39693a9c1b06f5b175d 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 dac7984588fc4eea7acbf39693a9c1b06f5b175d 113
126 0772616e6b48a76afb6c1458e193cbb3dae2e4ff dac7984588fc4eea7acbf39693a9c1b06f5b175d 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 dac7984588fc4eea7acbf39693a9c1b06f5b175d 113
127 eb498cd9af6c44108e43041e951ce829e29f6c80 bff2f4817ced57b386caf7c4e3e36a4bc9af7e93 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0772616e6b48a76afb6c1458e193cbb3dae2e4ff 295
127 eb498cd9af6c44108e43041e951ce829e29f6c80 bff2f4817ced57b386caf7c4e3e36a4bc9af7e93 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0772616e6b48a76afb6c1458e193cbb3dae2e4ff 295
128 b15709c071ddd2d93188508ba156196ab4f19620 eb498cd9af6c44108e43041e951ce829e29f6c80 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 eb498cd9af6c44108e43041e951ce829e29f6c80 114
128 b15709c071ddd2d93188508ba156196ab4f19620 eb498cd9af6c44108e43041e951ce829e29f6c80 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 eb498cd9af6c44108e43041e951ce829e29f6c80 114
129
129
130 mf
130 mf
131 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 301ca08d026bb72cb4258a9d211bdf7ca0bcd810 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 301ca08d026bb72cb4258a9d211bdf7ca0bcd810 17
131 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 301ca08d026bb72cb4258a9d211bdf7ca0bcd810 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 301ca08d026bb72cb4258a9d211bdf7ca0bcd810 17
132 c7b583de053293870e145f45bd2d61643563fd06 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 18
132 c7b583de053293870e145f45bd2d61643563fd06 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 18
133 266ee3c0302a5a18f1cf96817ac79a51836179e9 edc0f6b8db80d68ae6aff2b19f7e5347ab68fa63 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 c7b583de053293870e145f45bd2d61643563fd06 149
133 266ee3c0302a5a18f1cf96817ac79a51836179e9 edc0f6b8db80d68ae6aff2b19f7e5347ab68fa63 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 c7b583de053293870e145f45bd2d61643563fd06 149
134 698c6a36220548cd3903ca7dada27c59aa500c52 266ee3c0302a5a18f1cf96817ac79a51836179e9 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 266ee3c0302a5a18f1cf96817ac79a51836179e9 19
134 698c6a36220548cd3903ca7dada27c59aa500c52 266ee3c0302a5a18f1cf96817ac79a51836179e9 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 266ee3c0302a5a18f1cf96817ac79a51836179e9 19
135
135
136 nf11
136 nf11
137 33fbc651630ffa7ccbebfe4eb91320a873e7291c 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0000000000000000000000000000000000000000 16
137 33fbc651630ffa7ccbebfe4eb91320a873e7291c 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0000000000000000000000000000000000000000 16
138
138
139 nf12
139 nf12
140 ddce0544363f037e9fb889faca058f52dc01c0a5 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 0000000000000000000000000000000000000000 16
140 ddce0544363f037e9fb889faca058f52dc01c0a5 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 0000000000000000000000000000000000000000 16
141
141
142 nf4
142 nf4
143 3c1407305701051cbed9f9cb9a68bdfb5997c235 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 0000000000000000000000000000000000000000 15
143 3c1407305701051cbed9f9cb9a68bdfb5997c235 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 0000000000000000000000000000000000000000 15
144
144
145 nf5
145 nf5
146 0dbd89c185f53a1727c54cd1ce256482fa23968e 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 0000000000000000000000000000000000000000 15
146 0dbd89c185f53a1727c54cd1ce256482fa23968e 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 0000000000000000000000000000000000000000 15
147
147
148 Get branch and merge:
148 Get branch and merge:
149
149
150 $ hg debuggetbundle repo bundle -C 7704483d56b2a7b5db54dcee7c62378ac629b348 -H 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
150 $ hg debuggetbundle repo bundle -C 7704483d56b2a7b5db54dcee7c62378ac629b348 -H 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
151 $ hg debugbundle bundle
151 $ hg debugbundle bundle
152 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
152 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
153 713346a995c363120712aed1aee7e04afd867638
153 713346a995c363120712aed1aee7e04afd867638
154 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
154 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
155 ff42371d57168345fdf1a3aac66a51f6a45d41d2
155 ff42371d57168345fdf1a3aac66a51f6a45d41d2
156 bac16991d12ff45f9dc43c52da1946dfadb83e80
156 bac16991d12ff45f9dc43c52da1946dfadb83e80
157 6621d79f61b23ec74cf4b69464343d9e0980ec8b
157 6621d79f61b23ec74cf4b69464343d9e0980ec8b
158 8931463777131cd73923e560b760061f2aa8a4bc
158 8931463777131cd73923e560b760061f2aa8a4bc
159 f34414c64173e0ecb61b25dc55e116dbbcc89bee
159 f34414c64173e0ecb61b25dc55e116dbbcc89bee
160 928b5f94cdb278bb536eba552de348a4e92ef24d
160 928b5f94cdb278bb536eba552de348a4e92ef24d
161 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
161 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
162 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
162 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
163 13c0170174366b441dc68e8e33757232fa744458
163 13c0170174366b441dc68e8e33757232fa744458
164 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
164 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
165 8365676dbab05860ce0d9110f2af51368b961bbd
165 8365676dbab05860ce0d9110f2af51368b961bbd
166 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
166 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
167
167
168 = Test bundle2 =
168 = Test bundle2 =
169
169
170 $ hg debuggetbundle repo bundle -t bundle2
170 $ hg debuggetbundle repo bundle -t bundle2
171 $ hg debugbundle bundle
171 $ hg debugbundle bundle
172 Stream params: {}
172 Stream params: {}
173 changegroup -- "{'version': '01'}"
173 changegroup -- "sortdict([('version', '01')])"
174 7704483d56b2a7b5db54dcee7c62378ac629b348
174 7704483d56b2a7b5db54dcee7c62378ac629b348
175 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
175 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
176 713346a995c363120712aed1aee7e04afd867638
176 713346a995c363120712aed1aee7e04afd867638
177 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
177 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
178 ff42371d57168345fdf1a3aac66a51f6a45d41d2
178 ff42371d57168345fdf1a3aac66a51f6a45d41d2
179 bac16991d12ff45f9dc43c52da1946dfadb83e80
179 bac16991d12ff45f9dc43c52da1946dfadb83e80
180 6621d79f61b23ec74cf4b69464343d9e0980ec8b
180 6621d79f61b23ec74cf4b69464343d9e0980ec8b
181 8931463777131cd73923e560b760061f2aa8a4bc
181 8931463777131cd73923e560b760061f2aa8a4bc
182 f34414c64173e0ecb61b25dc55e116dbbcc89bee
182 f34414c64173e0ecb61b25dc55e116dbbcc89bee
183 928b5f94cdb278bb536eba552de348a4e92ef24d
183 928b5f94cdb278bb536eba552de348a4e92ef24d
184 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
184 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
185 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
185 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
186 13c0170174366b441dc68e8e33757232fa744458
186 13c0170174366b441dc68e8e33757232fa744458
187 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
187 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
188 8365676dbab05860ce0d9110f2af51368b961bbd
188 8365676dbab05860ce0d9110f2af51368b961bbd
189 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
189 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
190 4801a72e5d88cb515b0c7e40fae34180f3f837f2
190 4801a72e5d88cb515b0c7e40fae34180f3f837f2
191 10c14a2cc935e1d8c31f9e98587dcf27fb08a6da
191 10c14a2cc935e1d8c31f9e98587dcf27fb08a6da
192 = Test via HTTP =
192 = Test via HTTP =
193
193
194 Get everything:
194 Get everything:
195
195
196 $ hg serve -R repo -p $HGPORT -d --pid-file=hg.pid -E error.log -A access.log
196 $ hg serve -R repo -p $HGPORT -d --pid-file=hg.pid -E error.log -A access.log
197 $ cat hg.pid >> $DAEMON_PIDS
197 $ cat hg.pid >> $DAEMON_PIDS
198 $ hg debuggetbundle http://localhost:$HGPORT/ bundle
198 $ hg debuggetbundle http://localhost:$HGPORT/ bundle
199 $ hg debugbundle bundle
199 $ hg debugbundle bundle
200 7704483d56b2a7b5db54dcee7c62378ac629b348
200 7704483d56b2a7b5db54dcee7c62378ac629b348
201 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
201 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
202 713346a995c363120712aed1aee7e04afd867638
202 713346a995c363120712aed1aee7e04afd867638
203 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
203 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
204 ff42371d57168345fdf1a3aac66a51f6a45d41d2
204 ff42371d57168345fdf1a3aac66a51f6a45d41d2
205 bac16991d12ff45f9dc43c52da1946dfadb83e80
205 bac16991d12ff45f9dc43c52da1946dfadb83e80
206 6621d79f61b23ec74cf4b69464343d9e0980ec8b
206 6621d79f61b23ec74cf4b69464343d9e0980ec8b
207 8931463777131cd73923e560b760061f2aa8a4bc
207 8931463777131cd73923e560b760061f2aa8a4bc
208 f34414c64173e0ecb61b25dc55e116dbbcc89bee
208 f34414c64173e0ecb61b25dc55e116dbbcc89bee
209 928b5f94cdb278bb536eba552de348a4e92ef24d
209 928b5f94cdb278bb536eba552de348a4e92ef24d
210 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
210 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
211 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
211 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
212 13c0170174366b441dc68e8e33757232fa744458
212 13c0170174366b441dc68e8e33757232fa744458
213 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
213 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
214 8365676dbab05860ce0d9110f2af51368b961bbd
214 8365676dbab05860ce0d9110f2af51368b961bbd
215 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
215 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
216 4801a72e5d88cb515b0c7e40fae34180f3f837f2
216 4801a72e5d88cb515b0c7e40fae34180f3f837f2
217 10c14a2cc935e1d8c31f9e98587dcf27fb08a6da
217 10c14a2cc935e1d8c31f9e98587dcf27fb08a6da
218
218
219 Get parts of two branches:
219 Get parts of two branches:
220
220
221 $ hg debuggetbundle http://localhost:$HGPORT/ bundle -H 13c0170174366b441dc68e8e33757232fa744458 -C 700b7e19db54103633c4bf4a6a6b6d55f4d50c03 -H bac16991d12ff45f9dc43c52da1946dfadb83e80 -C d5f6e1ea452285324836a49d7d3c2a63cfed1d31
221 $ hg debuggetbundle http://localhost:$HGPORT/ bundle -H 13c0170174366b441dc68e8e33757232fa744458 -C 700b7e19db54103633c4bf4a6a6b6d55f4d50c03 -H bac16991d12ff45f9dc43c52da1946dfadb83e80 -C d5f6e1ea452285324836a49d7d3c2a63cfed1d31
222 $ hg debugbundle bundle
222 $ hg debugbundle bundle
223 ff42371d57168345fdf1a3aac66a51f6a45d41d2
223 ff42371d57168345fdf1a3aac66a51f6a45d41d2
224 bac16991d12ff45f9dc43c52da1946dfadb83e80
224 bac16991d12ff45f9dc43c52da1946dfadb83e80
225 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
225 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
226 13c0170174366b441dc68e8e33757232fa744458
226 13c0170174366b441dc68e8e33757232fa744458
227
227
228 Check that we get all needed file changes:
228 Check that we get all needed file changes:
229
229
230 $ hg debugbundle bundle --all
230 $ hg debugbundle bundle --all
231 format: id, p1, p2, cset, delta base, len(delta)
231 format: id, p1, p2, cset, delta base, len(delta)
232
232
233 changelog
233 changelog
234 ff42371d57168345fdf1a3aac66a51f6a45d41d2 d5f6e1ea452285324836a49d7d3c2a63cfed1d31 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 d5f6e1ea452285324836a49d7d3c2a63cfed1d31 99
234 ff42371d57168345fdf1a3aac66a51f6a45d41d2 d5f6e1ea452285324836a49d7d3c2a63cfed1d31 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 d5f6e1ea452285324836a49d7d3c2a63cfed1d31 99
235 bac16991d12ff45f9dc43c52da1946dfadb83e80 ff42371d57168345fdf1a3aac66a51f6a45d41d2 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 ff42371d57168345fdf1a3aac66a51f6a45d41d2 99
235 bac16991d12ff45f9dc43c52da1946dfadb83e80 ff42371d57168345fdf1a3aac66a51f6a45d41d2 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 ff42371d57168345fdf1a3aac66a51f6a45d41d2 99
236 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 700b7e19db54103633c4bf4a6a6b6d55f4d50c03 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 bac16991d12ff45f9dc43c52da1946dfadb83e80 102
236 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 700b7e19db54103633c4bf4a6a6b6d55f4d50c03 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 bac16991d12ff45f9dc43c52da1946dfadb83e80 102
237 13c0170174366b441dc68e8e33757232fa744458 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 102
237 13c0170174366b441dc68e8e33757232fa744458 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 102
238
238
239 manifest
239 manifest
240 dac7984588fc4eea7acbf39693a9c1b06f5b175d 591f732a3faf1fb903815273f3c199a514a61ccb 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 591f732a3faf1fb903815273f3c199a514a61ccb 113
240 dac7984588fc4eea7acbf39693a9c1b06f5b175d 591f732a3faf1fb903815273f3c199a514a61ccb 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 591f732a3faf1fb903815273f3c199a514a61ccb 113
241 0772616e6b48a76afb6c1458e193cbb3dae2e4ff dac7984588fc4eea7acbf39693a9c1b06f5b175d 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 dac7984588fc4eea7acbf39693a9c1b06f5b175d 113
241 0772616e6b48a76afb6c1458e193cbb3dae2e4ff dac7984588fc4eea7acbf39693a9c1b06f5b175d 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 dac7984588fc4eea7acbf39693a9c1b06f5b175d 113
242 eb498cd9af6c44108e43041e951ce829e29f6c80 bff2f4817ced57b386caf7c4e3e36a4bc9af7e93 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0772616e6b48a76afb6c1458e193cbb3dae2e4ff 295
242 eb498cd9af6c44108e43041e951ce829e29f6c80 bff2f4817ced57b386caf7c4e3e36a4bc9af7e93 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0772616e6b48a76afb6c1458e193cbb3dae2e4ff 295
243 b15709c071ddd2d93188508ba156196ab4f19620 eb498cd9af6c44108e43041e951ce829e29f6c80 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 eb498cd9af6c44108e43041e951ce829e29f6c80 114
243 b15709c071ddd2d93188508ba156196ab4f19620 eb498cd9af6c44108e43041e951ce829e29f6c80 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 eb498cd9af6c44108e43041e951ce829e29f6c80 114
244
244
245 mf
245 mf
246 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 301ca08d026bb72cb4258a9d211bdf7ca0bcd810 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 301ca08d026bb72cb4258a9d211bdf7ca0bcd810 17
246 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 301ca08d026bb72cb4258a9d211bdf7ca0bcd810 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 301ca08d026bb72cb4258a9d211bdf7ca0bcd810 17
247 c7b583de053293870e145f45bd2d61643563fd06 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 18
247 c7b583de053293870e145f45bd2d61643563fd06 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 18
248 266ee3c0302a5a18f1cf96817ac79a51836179e9 edc0f6b8db80d68ae6aff2b19f7e5347ab68fa63 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 c7b583de053293870e145f45bd2d61643563fd06 149
248 266ee3c0302a5a18f1cf96817ac79a51836179e9 edc0f6b8db80d68ae6aff2b19f7e5347ab68fa63 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 c7b583de053293870e145f45bd2d61643563fd06 149
249 698c6a36220548cd3903ca7dada27c59aa500c52 266ee3c0302a5a18f1cf96817ac79a51836179e9 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 266ee3c0302a5a18f1cf96817ac79a51836179e9 19
249 698c6a36220548cd3903ca7dada27c59aa500c52 266ee3c0302a5a18f1cf96817ac79a51836179e9 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 266ee3c0302a5a18f1cf96817ac79a51836179e9 19
250
250
251 nf11
251 nf11
252 33fbc651630ffa7ccbebfe4eb91320a873e7291c 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0000000000000000000000000000000000000000 16
252 33fbc651630ffa7ccbebfe4eb91320a873e7291c 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0000000000000000000000000000000000000000 16
253
253
254 nf12
254 nf12
255 ddce0544363f037e9fb889faca058f52dc01c0a5 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 0000000000000000000000000000000000000000 16
255 ddce0544363f037e9fb889faca058f52dc01c0a5 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 0000000000000000000000000000000000000000 16
256
256
257 nf4
257 nf4
258 3c1407305701051cbed9f9cb9a68bdfb5997c235 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 0000000000000000000000000000000000000000 15
258 3c1407305701051cbed9f9cb9a68bdfb5997c235 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 0000000000000000000000000000000000000000 15
259
259
260 nf5
260 nf5
261 0dbd89c185f53a1727c54cd1ce256482fa23968e 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 0000000000000000000000000000000000000000 15
261 0dbd89c185f53a1727c54cd1ce256482fa23968e 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 0000000000000000000000000000000000000000 15
262
262
263 Verify we hit the HTTP server:
263 Verify we hit the HTTP server:
264
264
265 $ cat access.log
265 $ cat access.log
266 * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
266 * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
267 * - - [*] "GET /?cmd=getbundle HTTP/1.1" 200 - (glob)
267 * - - [*] "GET /?cmd=getbundle HTTP/1.1" 200 - (glob)
268 * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
268 * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
269 * - - [*] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:common=700b7e19db54103633c4bf4a6a6b6d55f4d50c03+d5f6e1ea452285324836a49d7d3c2a63cfed1d31&heads=13c0170174366b441dc68e8e33757232fa744458+bac16991d12ff45f9dc43c52da1946dfadb83e80 (glob)
269 * - - [*] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:common=700b7e19db54103633c4bf4a6a6b6d55f4d50c03+d5f6e1ea452285324836a49d7d3c2a63cfed1d31&heads=13c0170174366b441dc68e8e33757232fa744458+bac16991d12ff45f9dc43c52da1946dfadb83e80 (glob)
270
270
271 $ cat error.log
271 $ cat error.log
272
272
@@ -1,1624 +1,1624 b''
1 $ cat <<EOF >> $HGRCPATH
1 $ cat <<EOF >> $HGRCPATH
2 > [extensions]
2 > [extensions]
3 > mq =
3 > mq =
4 > shelve =
4 > shelve =
5 > [defaults]
5 > [defaults]
6 > diff = --nodates --git
6 > diff = --nodates --git
7 > qnew = --date '0 0'
7 > qnew = --date '0 0'
8 > [shelve]
8 > [shelve]
9 > maxbackups = 2
9 > maxbackups = 2
10 > EOF
10 > EOF
11
11
12 $ hg init repo
12 $ hg init repo
13 $ cd repo
13 $ cd repo
14 $ mkdir a b
14 $ mkdir a b
15 $ echo a > a/a
15 $ echo a > a/a
16 $ echo b > b/b
16 $ echo b > b/b
17 $ echo c > c
17 $ echo c > c
18 $ echo d > d
18 $ echo d > d
19 $ echo x > x
19 $ echo x > x
20 $ hg addremove -q
20 $ hg addremove -q
21
21
22 shelve has a help message
22 shelve has a help message
23 $ hg shelve -h
23 $ hg shelve -h
24 hg shelve [OPTION]... [FILE]...
24 hg shelve [OPTION]... [FILE]...
25
25
26 save and set aside changes from the working directory
26 save and set aside changes from the working directory
27
27
28 Shelving takes files that "hg status" reports as not clean, saves the
28 Shelving takes files that "hg status" reports as not clean, saves the
29 modifications to a bundle (a shelved change), and reverts the files so
29 modifications to a bundle (a shelved change), and reverts the files so
30 that their state in the working directory becomes clean.
30 that their state in the working directory becomes clean.
31
31
32 To restore these changes to the working directory, using "hg unshelve";
32 To restore these changes to the working directory, using "hg unshelve";
33 this will work even if you switch to a different commit.
33 this will work even if you switch to a different commit.
34
34
35 When no files are specified, "hg shelve" saves all not-clean files. If
35 When no files are specified, "hg shelve" saves all not-clean files. If
36 specific files or directories are named, only changes to those files are
36 specific files or directories are named, only changes to those files are
37 shelved.
37 shelved.
38
38
39 In bare shelve(when no files are specified, without interactive, include
39 In bare shelve(when no files are specified, without interactive, include
40 and exclude option), shelving remembers information if the working
40 and exclude option), shelving remembers information if the working
41 directory was on newly created branch, in other words working directory
41 directory was on newly created branch, in other words working directory
42 was on different branch than its first parent. In this situation
42 was on different branch than its first parent. In this situation
43 unshelving restores branch information to the working directory.
43 unshelving restores branch information to the working directory.
44
44
45 Each shelved change has a name that makes it easier to find later. The
45 Each shelved change has a name that makes it easier to find later. The
46 name of a shelved change defaults to being based on the active bookmark,
46 name of a shelved change defaults to being based on the active bookmark,
47 or if there is no active bookmark, the current named branch. To specify a
47 or if there is no active bookmark, the current named branch. To specify a
48 different name, use "--name".
48 different name, use "--name".
49
49
50 To see a list of existing shelved changes, use the "--list" option. For
50 To see a list of existing shelved changes, use the "--list" option. For
51 each shelved change, this will print its name, age, and description; use "
51 each shelved change, this will print its name, age, and description; use "
52 --patch" or "--stat" for more details.
52 --patch" or "--stat" for more details.
53
53
54 To delete specific shelved changes, use "--delete". To delete all shelved
54 To delete specific shelved changes, use "--delete". To delete all shelved
55 changes, use "--cleanup".
55 changes, use "--cleanup".
56
56
57 (use "hg help -e shelve" to show help for the shelve extension)
57 (use "hg help -e shelve" to show help for the shelve extension)
58
58
59 options ([+] can be repeated):
59 options ([+] can be repeated):
60
60
61 -A --addremove mark new/missing files as added/removed before
61 -A --addremove mark new/missing files as added/removed before
62 shelving
62 shelving
63 -u --unknown store unknown files in the shelve
63 -u --unknown store unknown files in the shelve
64 --cleanup delete all shelved changes
64 --cleanup delete all shelved changes
65 --date DATE shelve with the specified commit date
65 --date DATE shelve with the specified commit date
66 -d --delete delete the named shelved change(s)
66 -d --delete delete the named shelved change(s)
67 -e --edit invoke editor on commit messages
67 -e --edit invoke editor on commit messages
68 -l --list list current shelves
68 -l --list list current shelves
69 -m --message TEXT use text as shelve message
69 -m --message TEXT use text as shelve message
70 -n --name NAME use the given name for the shelved commit
70 -n --name NAME use the given name for the shelved commit
71 -p --patch show patch
71 -p --patch show patch
72 -i --interactive interactive mode, only works while creating a shelve
72 -i --interactive interactive mode, only works while creating a shelve
73 --stat output diffstat-style summary of changes
73 --stat output diffstat-style summary of changes
74 -I --include PATTERN [+] include names matching the given patterns
74 -I --include PATTERN [+] include names matching the given patterns
75 -X --exclude PATTERN [+] exclude names matching the given patterns
75 -X --exclude PATTERN [+] exclude names matching the given patterns
76 --mq operate on patch repository
76 --mq operate on patch repository
77
77
78 (some details hidden, use --verbose to show complete help)
78 (some details hidden, use --verbose to show complete help)
79
79
80 shelving in an empty repo should be possible
80 shelving in an empty repo should be possible
81 (this tests also that editor is not invoked, if '--edit' is not
81 (this tests also that editor is not invoked, if '--edit' is not
82 specified)
82 specified)
83
83
84 $ HGEDITOR=cat hg shelve
84 $ HGEDITOR=cat hg shelve
85 shelved as default
85 shelved as default
86 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
86 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
87
87
88 $ hg unshelve
88 $ hg unshelve
89 unshelving change 'default'
89 unshelving change 'default'
90
90
91 $ hg commit -q -m 'initial commit'
91 $ hg commit -q -m 'initial commit'
92
92
93 $ hg shelve
93 $ hg shelve
94 nothing changed
94 nothing changed
95 [1]
95 [1]
96
96
97 make sure shelve files were backed up
97 make sure shelve files were backed up
98
98
99 $ ls .hg/shelve-backup
99 $ ls .hg/shelve-backup
100 default.hg
100 default.hg
101 default.patch
101 default.patch
102
102
103 create an mq patch - shelving should work fine with a patch applied
103 create an mq patch - shelving should work fine with a patch applied
104
104
105 $ echo n > n
105 $ echo n > n
106 $ hg add n
106 $ hg add n
107 $ hg commit n -m second
107 $ hg commit n -m second
108 $ hg qnew second.patch
108 $ hg qnew second.patch
109
109
110 shelve a change that we will delete later
110 shelve a change that we will delete later
111
111
112 $ echo a >> a/a
112 $ echo a >> a/a
113 $ hg shelve
113 $ hg shelve
114 shelved as default
114 shelved as default
115 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
115 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
116
116
117 set up some more complex changes to shelve
117 set up some more complex changes to shelve
118
118
119 $ echo a >> a/a
119 $ echo a >> a/a
120 $ hg mv b b.rename
120 $ hg mv b b.rename
121 moving b/b to b.rename/b (glob)
121 moving b/b to b.rename/b (glob)
122 $ hg cp c c.copy
122 $ hg cp c c.copy
123 $ hg status -C
123 $ hg status -C
124 M a/a
124 M a/a
125 A b.rename/b
125 A b.rename/b
126 b/b
126 b/b
127 A c.copy
127 A c.copy
128 c
128 c
129 R b/b
129 R b/b
130
130
131 prevent some foot-shooting
131 prevent some foot-shooting
132
132
133 $ hg shelve -n foo/bar
133 $ hg shelve -n foo/bar
134 abort: shelved change names may not contain slashes
134 abort: shelved change names may not contain slashes
135 [255]
135 [255]
136 $ hg shelve -n .baz
136 $ hg shelve -n .baz
137 abort: shelved change names may not start with '.'
137 abort: shelved change names may not start with '.'
138 [255]
138 [255]
139
139
140 the common case - no options or filenames
140 the common case - no options or filenames
141
141
142 $ hg shelve
142 $ hg shelve
143 shelved as default-01
143 shelved as default-01
144 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
144 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
145 $ hg status -C
145 $ hg status -C
146
146
147 ensure that our shelved changes exist
147 ensure that our shelved changes exist
148
148
149 $ hg shelve -l
149 $ hg shelve -l
150 default-01 (*)* changes to: [mq]: second.patch (glob)
150 default-01 (*)* changes to: [mq]: second.patch (glob)
151 default (*)* changes to: [mq]: second.patch (glob)
151 default (*)* changes to: [mq]: second.patch (glob)
152
152
153 $ hg shelve -l -p default
153 $ hg shelve -l -p default
154 default (*)* changes to: [mq]: second.patch (glob)
154 default (*)* changes to: [mq]: second.patch (glob)
155
155
156 diff --git a/a/a b/a/a
156 diff --git a/a/a b/a/a
157 --- a/a/a
157 --- a/a/a
158 +++ b/a/a
158 +++ b/a/a
159 @@ -1,1 +1,2 @@
159 @@ -1,1 +1,2 @@
160 a
160 a
161 +a
161 +a
162
162
163 $ hg shelve --list --addremove
163 $ hg shelve --list --addremove
164 abort: options '--list' and '--addremove' may not be used together
164 abort: options '--list' and '--addremove' may not be used together
165 [255]
165 [255]
166
166
167 delete our older shelved change
167 delete our older shelved change
168
168
169 $ hg shelve -d default
169 $ hg shelve -d default
170 $ hg qfinish -a -q
170 $ hg qfinish -a -q
171
171
172 ensure shelve backups aren't overwritten
172 ensure shelve backups aren't overwritten
173
173
174 $ ls .hg/shelve-backup/
174 $ ls .hg/shelve-backup/
175 default-1.hg
175 default-1.hg
176 default-1.patch
176 default-1.patch
177 default.hg
177 default.hg
178 default.patch
178 default.patch
179
179
180 local edits should not prevent a shelved change from applying
180 local edits should not prevent a shelved change from applying
181
181
182 $ printf "z\na\n" > a/a
182 $ printf "z\na\n" > a/a
183 $ hg unshelve --keep
183 $ hg unshelve --keep
184 unshelving change 'default-01'
184 unshelving change 'default-01'
185 temporarily committing pending changes (restore with 'hg unshelve --abort')
185 temporarily committing pending changes (restore with 'hg unshelve --abort')
186 rebasing shelved changes
186 rebasing shelved changes
187 rebasing 4:32c69314e062 "changes to: [mq]: second.patch" (tip)
187 rebasing 4:32c69314e062 "changes to: [mq]: second.patch" (tip)
188 merging a/a
188 merging a/a
189
189
190 $ hg revert --all -q
190 $ hg revert --all -q
191 $ rm a/a.orig b.rename/b c.copy
191 $ rm a/a.orig b.rename/b c.copy
192
192
193 apply it and make sure our state is as expected
193 apply it and make sure our state is as expected
194
194
195 (this also tests that same timestamp prevents backups from being
195 (this also tests that same timestamp prevents backups from being
196 removed, even though there are more than 'maxbackups' backups)
196 removed, even though there are more than 'maxbackups' backups)
197
197
198 $ f -t .hg/shelve-backup/default.hg
198 $ f -t .hg/shelve-backup/default.hg
199 .hg/shelve-backup/default.hg: file
199 .hg/shelve-backup/default.hg: file
200 $ touch -t 200001010000 .hg/shelve-backup/default.hg
200 $ touch -t 200001010000 .hg/shelve-backup/default.hg
201 $ f -t .hg/shelve-backup/default-1.hg
201 $ f -t .hg/shelve-backup/default-1.hg
202 .hg/shelve-backup/default-1.hg: file
202 .hg/shelve-backup/default-1.hg: file
203 $ touch -t 200001010000 .hg/shelve-backup/default-1.hg
203 $ touch -t 200001010000 .hg/shelve-backup/default-1.hg
204
204
205 $ hg unshelve
205 $ hg unshelve
206 unshelving change 'default-01'
206 unshelving change 'default-01'
207 $ hg status -C
207 $ hg status -C
208 M a/a
208 M a/a
209 A b.rename/b
209 A b.rename/b
210 b/b
210 b/b
211 A c.copy
211 A c.copy
212 c
212 c
213 R b/b
213 R b/b
214 $ hg shelve -l
214 $ hg shelve -l
215
215
216 (both of default.hg and default-1.hg should be still kept, because it
216 (both of default.hg and default-1.hg should be still kept, because it
217 is difficult to decide actual order of them from same timestamp)
217 is difficult to decide actual order of them from same timestamp)
218
218
219 $ ls .hg/shelve-backup/
219 $ ls .hg/shelve-backup/
220 default-01.hg
220 default-01.hg
221 default-01.patch
221 default-01.patch
222 default-1.hg
222 default-1.hg
223 default-1.patch
223 default-1.patch
224 default.hg
224 default.hg
225 default.patch
225 default.patch
226
226
227 $ hg unshelve
227 $ hg unshelve
228 abort: no shelved changes to apply!
228 abort: no shelved changes to apply!
229 [255]
229 [255]
230 $ hg unshelve foo
230 $ hg unshelve foo
231 abort: shelved change 'foo' not found
231 abort: shelved change 'foo' not found
232 [255]
232 [255]
233
233
234 named shelves, specific filenames, and "commit messages" should all work
234 named shelves, specific filenames, and "commit messages" should all work
235 (this tests also that editor is invoked, if '--edit' is specified)
235 (this tests also that editor is invoked, if '--edit' is specified)
236
236
237 $ hg status -C
237 $ hg status -C
238 M a/a
238 M a/a
239 A b.rename/b
239 A b.rename/b
240 b/b
240 b/b
241 A c.copy
241 A c.copy
242 c
242 c
243 R b/b
243 R b/b
244 $ HGEDITOR=cat hg shelve -q -n wibble -m wat -e a
244 $ HGEDITOR=cat hg shelve -q -n wibble -m wat -e a
245 wat
245 wat
246
246
247
247
248 HG: Enter commit message. Lines beginning with 'HG:' are removed.
248 HG: Enter commit message. Lines beginning with 'HG:' are removed.
249 HG: Leave message empty to abort commit.
249 HG: Leave message empty to abort commit.
250 HG: --
250 HG: --
251 HG: user: shelve@localhost
251 HG: user: shelve@localhost
252 HG: branch 'default'
252 HG: branch 'default'
253 HG: changed a/a
253 HG: changed a/a
254
254
255 expect "a" to no longer be present, but status otherwise unchanged
255 expect "a" to no longer be present, but status otherwise unchanged
256
256
257 $ hg status -C
257 $ hg status -C
258 A b.rename/b
258 A b.rename/b
259 b/b
259 b/b
260 A c.copy
260 A c.copy
261 c
261 c
262 R b/b
262 R b/b
263 $ hg shelve -l --stat
263 $ hg shelve -l --stat
264 wibble (*) wat (glob)
264 wibble (*) wat (glob)
265 a/a | 1 +
265 a/a | 1 +
266 1 files changed, 1 insertions(+), 0 deletions(-)
266 1 files changed, 1 insertions(+), 0 deletions(-)
267
267
268 and now "a/a" should reappear
268 and now "a/a" should reappear
269
269
270 $ cd a
270 $ cd a
271 $ hg unshelve -q wibble
271 $ hg unshelve -q wibble
272 $ cd ..
272 $ cd ..
273 $ hg status -C
273 $ hg status -C
274 M a/a
274 M a/a
275 A b.rename/b
275 A b.rename/b
276 b/b
276 b/b
277 A c.copy
277 A c.copy
278 c
278 c
279 R b/b
279 R b/b
280
280
281 ensure old shelve backups are being deleted automatically
281 ensure old shelve backups are being deleted automatically
282
282
283 $ ls .hg/shelve-backup/
283 $ ls .hg/shelve-backup/
284 default-01.hg
284 default-01.hg
285 default-01.patch
285 default-01.patch
286 wibble.hg
286 wibble.hg
287 wibble.patch
287 wibble.patch
288
288
289 cause unshelving to result in a merge with 'a' conflicting
289 cause unshelving to result in a merge with 'a' conflicting
290
290
291 $ hg shelve -q
291 $ hg shelve -q
292 $ echo c>>a/a
292 $ echo c>>a/a
293 $ hg commit -m second
293 $ hg commit -m second
294 $ hg tip --template '{files}\n'
294 $ hg tip --template '{files}\n'
295 a/a
295 a/a
296
296
297 add an unrelated change that should be preserved
297 add an unrelated change that should be preserved
298
298
299 $ mkdir foo
299 $ mkdir foo
300 $ echo foo > foo/foo
300 $ echo foo > foo/foo
301 $ hg add foo/foo
301 $ hg add foo/foo
302
302
303 force a conflicted merge to occur
303 force a conflicted merge to occur
304
304
305 $ hg unshelve
305 $ hg unshelve
306 unshelving change 'default'
306 unshelving change 'default'
307 temporarily committing pending changes (restore with 'hg unshelve --abort')
307 temporarily committing pending changes (restore with 'hg unshelve --abort')
308 rebasing shelved changes
308 rebasing shelved changes
309 rebasing 5:32c69314e062 "changes to: [mq]: second.patch" (tip)
309 rebasing 5:32c69314e062 "changes to: [mq]: second.patch" (tip)
310 merging a/a
310 merging a/a
311 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
311 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
312 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
312 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
313 [1]
313 [1]
314
314
315 ensure that we have a merge with unresolved conflicts
315 ensure that we have a merge with unresolved conflicts
316
316
317 $ hg heads -q --template '{rev}\n'
317 $ hg heads -q --template '{rev}\n'
318 5
318 5
319 4
319 4
320 $ hg parents -q --template '{rev}\n'
320 $ hg parents -q --template '{rev}\n'
321 4
321 4
322 5
322 5
323 $ hg status
323 $ hg status
324 M a/a
324 M a/a
325 M b.rename/b
325 M b.rename/b
326 M c.copy
326 M c.copy
327 R b/b
327 R b/b
328 ? a/a.orig
328 ? a/a.orig
329 $ hg diff
329 $ hg diff
330 diff --git a/a/a b/a/a
330 diff --git a/a/a b/a/a
331 --- a/a/a
331 --- a/a/a
332 +++ b/a/a
332 +++ b/a/a
333 @@ -1,2 +1,6 @@
333 @@ -1,2 +1,6 @@
334 a
334 a
335 +<<<<<<< dest: * - shelve: pending changes temporary commit (glob)
335 +<<<<<<< dest: * - shelve: pending changes temporary commit (glob)
336 c
336 c
337 +=======
337 +=======
338 +a
338 +a
339 +>>>>>>> source: 32c69314e062 - shelve: changes to: [mq]: second.patch
339 +>>>>>>> source: 32c69314e062 - shelve: changes to: [mq]: second.patch
340 diff --git a/b/b b/b.rename/b
340 diff --git a/b/b b/b.rename/b
341 rename from b/b
341 rename from b/b
342 rename to b.rename/b
342 rename to b.rename/b
343 diff --git a/c b/c.copy
343 diff --git a/c b/c.copy
344 copy from c
344 copy from c
345 copy to c.copy
345 copy to c.copy
346 $ hg resolve -l
346 $ hg resolve -l
347 U a/a
347 U a/a
348
348
349 $ hg shelve
349 $ hg shelve
350 abort: unshelve already in progress
350 abort: unshelve already in progress
351 (use 'hg unshelve --continue' or 'hg unshelve --abort')
351 (use 'hg unshelve --continue' or 'hg unshelve --abort')
352 [255]
352 [255]
353
353
354 abort the unshelve and be happy
354 abort the unshelve and be happy
355
355
356 $ hg status
356 $ hg status
357 M a/a
357 M a/a
358 M b.rename/b
358 M b.rename/b
359 M c.copy
359 M c.copy
360 R b/b
360 R b/b
361 ? a/a.orig
361 ? a/a.orig
362 $ hg unshelve -a
362 $ hg unshelve -a
363 rebase aborted
363 rebase aborted
364 unshelve of 'default' aborted
364 unshelve of 'default' aborted
365 $ hg heads -q
365 $ hg heads -q
366 3:2e69b451d1ea
366 3:2e69b451d1ea
367 $ hg parents
367 $ hg parents
368 changeset: 3:2e69b451d1ea
368 changeset: 3:2e69b451d1ea
369 tag: tip
369 tag: tip
370 user: test
370 user: test
371 date: Thu Jan 01 00:00:00 1970 +0000
371 date: Thu Jan 01 00:00:00 1970 +0000
372 summary: second
372 summary: second
373
373
374 $ hg resolve -l
374 $ hg resolve -l
375 $ hg status
375 $ hg status
376 A foo/foo
376 A foo/foo
377 ? a/a.orig
377 ? a/a.orig
378
378
379 try to continue with no unshelve underway
379 try to continue with no unshelve underway
380
380
381 $ hg unshelve -c
381 $ hg unshelve -c
382 abort: no unshelve in progress
382 abort: no unshelve in progress
383 [255]
383 [255]
384 $ hg status
384 $ hg status
385 A foo/foo
385 A foo/foo
386 ? a/a.orig
386 ? a/a.orig
387
387
388 redo the unshelve to get a conflict
388 redo the unshelve to get a conflict
389
389
390 $ hg unshelve -q
390 $ hg unshelve -q
391 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
391 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
392 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
392 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
393 [1]
393 [1]
394
394
395 attempt to continue
395 attempt to continue
396
396
397 $ hg unshelve -c
397 $ hg unshelve -c
398 abort: unresolved conflicts, can't continue
398 abort: unresolved conflicts, can't continue
399 (see 'hg resolve', then 'hg unshelve --continue')
399 (see 'hg resolve', then 'hg unshelve --continue')
400 [255]
400 [255]
401
401
402 $ hg revert -r . a/a
402 $ hg revert -r . a/a
403 $ hg resolve -m a/a
403 $ hg resolve -m a/a
404 (no more unresolved files)
404 (no more unresolved files)
405 continue: hg unshelve --continue
405 continue: hg unshelve --continue
406
406
407 $ hg commit -m 'commit while unshelve in progress'
407 $ hg commit -m 'commit while unshelve in progress'
408 abort: unshelve already in progress
408 abort: unshelve already in progress
409 (use 'hg unshelve --continue' or 'hg unshelve --abort')
409 (use 'hg unshelve --continue' or 'hg unshelve --abort')
410 [255]
410 [255]
411
411
412 $ hg graft --continue
412 $ hg graft --continue
413 abort: no graft in progress
413 abort: no graft in progress
414 (continue: hg unshelve --continue)
414 (continue: hg unshelve --continue)
415 [255]
415 [255]
416 $ hg unshelve -c
416 $ hg unshelve -c
417 rebasing 5:32c69314e062 "changes to: [mq]: second.patch" (tip)
417 rebasing 5:32c69314e062 "changes to: [mq]: second.patch" (tip)
418 unshelve of 'default' complete
418 unshelve of 'default' complete
419
419
420 ensure the repo is as we hope
420 ensure the repo is as we hope
421
421
422 $ hg parents
422 $ hg parents
423 changeset: 3:2e69b451d1ea
423 changeset: 3:2e69b451d1ea
424 tag: tip
424 tag: tip
425 user: test
425 user: test
426 date: Thu Jan 01 00:00:00 1970 +0000
426 date: Thu Jan 01 00:00:00 1970 +0000
427 summary: second
427 summary: second
428
428
429 $ hg heads -q
429 $ hg heads -q
430 3:2e69b451d1ea
430 3:2e69b451d1ea
431
431
432 $ hg status -C
432 $ hg status -C
433 A b.rename/b
433 A b.rename/b
434 b/b
434 b/b
435 A c.copy
435 A c.copy
436 c
436 c
437 A foo/foo
437 A foo/foo
438 R b/b
438 R b/b
439 ? a/a.orig
439 ? a/a.orig
440
440
441 there should be no shelves left
441 there should be no shelves left
442
442
443 $ hg shelve -l
443 $ hg shelve -l
444
444
445 #if execbit
445 #if execbit
446
446
447 ensure that metadata-only changes are shelved
447 ensure that metadata-only changes are shelved
448
448
449 $ chmod +x a/a
449 $ chmod +x a/a
450 $ hg shelve -q -n execbit a/a
450 $ hg shelve -q -n execbit a/a
451 $ hg status a/a
451 $ hg status a/a
452 $ hg unshelve -q execbit
452 $ hg unshelve -q execbit
453 $ hg status a/a
453 $ hg status a/a
454 M a/a
454 M a/a
455 $ hg revert a/a
455 $ hg revert a/a
456
456
457 #endif
457 #endif
458
458
459 #if symlink
459 #if symlink
460
460
461 $ rm a/a
461 $ rm a/a
462 $ ln -s foo a/a
462 $ ln -s foo a/a
463 $ hg shelve -q -n symlink a/a
463 $ hg shelve -q -n symlink a/a
464 $ hg status a/a
464 $ hg status a/a
465 $ hg unshelve -q symlink
465 $ hg unshelve -q symlink
466 $ hg status a/a
466 $ hg status a/a
467 M a/a
467 M a/a
468 $ hg revert a/a
468 $ hg revert a/a
469
469
470 #endif
470 #endif
471
471
472 set up another conflict between a commit and a shelved change
472 set up another conflict between a commit and a shelved change
473
473
474 $ hg revert -q -C -a
474 $ hg revert -q -C -a
475 $ rm a/a.orig b.rename/b c.copy
475 $ rm a/a.orig b.rename/b c.copy
476 $ echo a >> a/a
476 $ echo a >> a/a
477 $ hg shelve -q
477 $ hg shelve -q
478 $ echo x >> a/a
478 $ echo x >> a/a
479 $ hg ci -m 'create conflict'
479 $ hg ci -m 'create conflict'
480 $ hg add foo/foo
480 $ hg add foo/foo
481
481
482 if we resolve a conflict while unshelving, the unshelve should succeed
482 if we resolve a conflict while unshelving, the unshelve should succeed
483
483
484 $ hg unshelve --tool :merge-other --keep
484 $ hg unshelve --tool :merge-other --keep
485 unshelving change 'default'
485 unshelving change 'default'
486 temporarily committing pending changes (restore with 'hg unshelve --abort')
486 temporarily committing pending changes (restore with 'hg unshelve --abort')
487 rebasing shelved changes
487 rebasing shelved changes
488 rebasing 6:2f694dd83a13 "changes to: second" (tip)
488 rebasing 6:2f694dd83a13 "changes to: second" (tip)
489 merging a/a
489 merging a/a
490 $ hg parents -q
490 $ hg parents -q
491 4:33f7f61e6c5e
491 4:33f7f61e6c5e
492 $ hg shelve -l
492 $ hg shelve -l
493 default (*)* changes to: second (glob)
493 default (*)* changes to: second (glob)
494 $ hg status
494 $ hg status
495 M a/a
495 M a/a
496 A foo/foo
496 A foo/foo
497 $ cat a/a
497 $ cat a/a
498 a
498 a
499 c
499 c
500 a
500 a
501 $ cat > a/a << EOF
501 $ cat > a/a << EOF
502 > a
502 > a
503 > c
503 > c
504 > x
504 > x
505 > EOF
505 > EOF
506
506
507 $ HGMERGE=true hg unshelve
507 $ HGMERGE=true hg unshelve
508 unshelving change 'default'
508 unshelving change 'default'
509 temporarily committing pending changes (restore with 'hg unshelve --abort')
509 temporarily committing pending changes (restore with 'hg unshelve --abort')
510 rebasing shelved changes
510 rebasing shelved changes
511 rebasing 6:2f694dd83a13 "changes to: second" (tip)
511 rebasing 6:2f694dd83a13 "changes to: second" (tip)
512 merging a/a
512 merging a/a
513 note: rebase of 6:2f694dd83a13 created no changes to commit
513 note: rebase of 6:2f694dd83a13 created no changes to commit
514 $ hg parents -q
514 $ hg parents -q
515 4:33f7f61e6c5e
515 4:33f7f61e6c5e
516 $ hg shelve -l
516 $ hg shelve -l
517 $ hg status
517 $ hg status
518 A foo/foo
518 A foo/foo
519 $ cat a/a
519 $ cat a/a
520 a
520 a
521 c
521 c
522 x
522 x
523
523
524 test keep and cleanup
524 test keep and cleanup
525
525
526 $ hg shelve
526 $ hg shelve
527 shelved as default
527 shelved as default
528 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
528 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
529 $ hg shelve --list
529 $ hg shelve --list
530 default (*)* changes to: create conflict (glob)
530 default (*)* changes to: create conflict (glob)
531 $ hg unshelve -k
531 $ hg unshelve -k
532 unshelving change 'default'
532 unshelving change 'default'
533 $ hg shelve --list
533 $ hg shelve --list
534 default (*)* changes to: create conflict (glob)
534 default (*)* changes to: create conflict (glob)
535 $ hg shelve --cleanup
535 $ hg shelve --cleanup
536 $ hg shelve --list
536 $ hg shelve --list
537
537
538 $ hg shelve --cleanup --delete
538 $ hg shelve --cleanup --delete
539 abort: options '--cleanup' and '--delete' may not be used together
539 abort: options '--cleanup' and '--delete' may not be used together
540 [255]
540 [255]
541 $ hg shelve --cleanup --patch
541 $ hg shelve --cleanup --patch
542 abort: options '--cleanup' and '--patch' may not be used together
542 abort: options '--cleanup' and '--patch' may not be used together
543 [255]
543 [255]
544 $ hg shelve --cleanup --message MESSAGE
544 $ hg shelve --cleanup --message MESSAGE
545 abort: options '--cleanup' and '--message' may not be used together
545 abort: options '--cleanup' and '--message' may not be used together
546 [255]
546 [255]
547
547
548 test bookmarks
548 test bookmarks
549
549
550 $ hg bookmark test
550 $ hg bookmark test
551 $ hg bookmark
551 $ hg bookmark
552 * test 4:33f7f61e6c5e
552 * test 4:33f7f61e6c5e
553 $ hg shelve
553 $ hg shelve
554 shelved as test
554 shelved as test
555 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
555 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
556 $ hg bookmark
556 $ hg bookmark
557 * test 4:33f7f61e6c5e
557 * test 4:33f7f61e6c5e
558 $ hg unshelve
558 $ hg unshelve
559 unshelving change 'test'
559 unshelving change 'test'
560 $ hg bookmark
560 $ hg bookmark
561 * test 4:33f7f61e6c5e
561 * test 4:33f7f61e6c5e
562
562
563 shelve should still work even if mq is disabled
563 shelve should still work even if mq is disabled
564
564
565 $ hg --config extensions.mq=! shelve
565 $ hg --config extensions.mq=! shelve
566 shelved as test
566 shelved as test
567 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
567 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
568 $ hg --config extensions.mq=! shelve --list
568 $ hg --config extensions.mq=! shelve --list
569 test (*)* changes to: create conflict (glob)
569 test (*)* changes to: create conflict (glob)
570 $ hg bookmark
570 $ hg bookmark
571 * test 4:33f7f61e6c5e
571 * test 4:33f7f61e6c5e
572 $ hg --config extensions.mq=! unshelve
572 $ hg --config extensions.mq=! unshelve
573 unshelving change 'test'
573 unshelving change 'test'
574 $ hg bookmark
574 $ hg bookmark
575 * test 4:33f7f61e6c5e
575 * test 4:33f7f61e6c5e
576
576
577 shelve should leave dirstate clean (issue4055)
577 shelve should leave dirstate clean (issue4055)
578
578
579 $ cd ..
579 $ cd ..
580 $ hg init shelverebase
580 $ hg init shelverebase
581 $ cd shelverebase
581 $ cd shelverebase
582 $ printf 'x\ny\n' > x
582 $ printf 'x\ny\n' > x
583 $ echo z > z
583 $ echo z > z
584 $ hg commit -Aqm xy
584 $ hg commit -Aqm xy
585 $ echo z >> x
585 $ echo z >> x
586 $ hg commit -Aqm z
586 $ hg commit -Aqm z
587 $ hg up 0
587 $ hg up 0
588 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
588 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
589 $ printf 'a\nx\ny\nz\n' > x
589 $ printf 'a\nx\ny\nz\n' > x
590 $ hg commit -Aqm xyz
590 $ hg commit -Aqm xyz
591 $ echo c >> z
591 $ echo c >> z
592 $ hg shelve
592 $ hg shelve
593 shelved as default
593 shelved as default
594 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
594 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
595 $ hg rebase -d 1 --config extensions.rebase=
595 $ hg rebase -d 1 --config extensions.rebase=
596 rebasing 2:323bfa07f744 "xyz" (tip)
596 rebasing 2:323bfa07f744 "xyz" (tip)
597 merging x
597 merging x
598 saved backup bundle to $TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-78114325-backup.hg (glob)
598 saved backup bundle to $TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-78114325-backup.hg (glob)
599 $ hg unshelve
599 $ hg unshelve
600 unshelving change 'default'
600 unshelving change 'default'
601 rebasing shelved changes
601 rebasing shelved changes
602 rebasing 4:82a0d7d6ba61 "changes to: xyz" (tip)
602 rebasing 4:82a0d7d6ba61 "changes to: xyz" (tip)
603 $ hg status
603 $ hg status
604 M z
604 M z
605
605
606 $ cd ..
606 $ cd ..
607
607
608 shelve should only unshelve pending changes (issue4068)
608 shelve should only unshelve pending changes (issue4068)
609
609
610 $ hg init onlypendingchanges
610 $ hg init onlypendingchanges
611 $ cd onlypendingchanges
611 $ cd onlypendingchanges
612 $ touch a
612 $ touch a
613 $ hg ci -Aqm a
613 $ hg ci -Aqm a
614 $ touch b
614 $ touch b
615 $ hg ci -Aqm b
615 $ hg ci -Aqm b
616 $ hg up -q 0
616 $ hg up -q 0
617 $ touch c
617 $ touch c
618 $ hg ci -Aqm c
618 $ hg ci -Aqm c
619
619
620 $ touch d
620 $ touch d
621 $ hg add d
621 $ hg add d
622 $ hg shelve
622 $ hg shelve
623 shelved as default
623 shelved as default
624 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
624 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
625 $ hg up -q 1
625 $ hg up -q 1
626 $ hg unshelve
626 $ hg unshelve
627 unshelving change 'default'
627 unshelving change 'default'
628 rebasing shelved changes
628 rebasing shelved changes
629 rebasing 3:958bcbd1776e "changes to: c" (tip)
629 rebasing 3:958bcbd1776e "changes to: c" (tip)
630 $ hg status
630 $ hg status
631 A d
631 A d
632
632
633 unshelve should work on an ancestor of the original commit
633 unshelve should work on an ancestor of the original commit
634
634
635 $ hg shelve
635 $ hg shelve
636 shelved as default
636 shelved as default
637 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
637 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
638 $ hg up 0
638 $ hg up 0
639 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
639 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
640 $ hg unshelve
640 $ hg unshelve
641 unshelving change 'default'
641 unshelving change 'default'
642 rebasing shelved changes
642 rebasing shelved changes
643 rebasing 3:013284d9655e "changes to: b" (tip)
643 rebasing 3:013284d9655e "changes to: b" (tip)
644 $ hg status
644 $ hg status
645 A d
645 A d
646
646
647 test bug 4073 we need to enable obsolete markers for it
647 test bug 4073 we need to enable obsolete markers for it
648
648
649 $ cat >> $HGRCPATH << EOF
649 $ cat >> $HGRCPATH << EOF
650 > [experimental]
650 > [experimental]
651 > evolution=createmarkers
651 > evolution=createmarkers
652 > EOF
652 > EOF
653 $ hg shelve
653 $ hg shelve
654 shelved as default
654 shelved as default
655 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
655 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
656 $ hg debugobsolete `hg --debug id -i -r 1`
656 $ hg debugobsolete `hg --debug id -i -r 1`
657 $ hg unshelve
657 $ hg unshelve
658 unshelving change 'default'
658 unshelving change 'default'
659
659
660 unshelve should leave unknown files alone (issue4113)
660 unshelve should leave unknown files alone (issue4113)
661
661
662 $ echo e > e
662 $ echo e > e
663 $ hg shelve
663 $ hg shelve
664 shelved as default
664 shelved as default
665 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
665 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
666 $ hg status
666 $ hg status
667 ? e
667 ? e
668 $ hg unshelve
668 $ hg unshelve
669 unshelving change 'default'
669 unshelving change 'default'
670 $ hg status
670 $ hg status
671 A d
671 A d
672 ? e
672 ? e
673 $ cat e
673 $ cat e
674 e
674 e
675
675
676 unshelve should keep a copy of unknown files
676 unshelve should keep a copy of unknown files
677
677
678 $ hg add e
678 $ hg add e
679 $ hg shelve
679 $ hg shelve
680 shelved as default
680 shelved as default
681 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
681 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
682 $ echo z > e
682 $ echo z > e
683 $ hg unshelve
683 $ hg unshelve
684 unshelving change 'default'
684 unshelving change 'default'
685 $ cat e
685 $ cat e
686 e
686 e
687 $ cat e.orig
687 $ cat e.orig
688 z
688 z
689
689
690
690
691 unshelve and conflicts with tracked and untracked files
691 unshelve and conflicts with tracked and untracked files
692
692
693 preparing:
693 preparing:
694
694
695 $ rm *.orig
695 $ rm *.orig
696 $ hg ci -qm 'commit stuff'
696 $ hg ci -qm 'commit stuff'
697 $ hg phase -p null:
697 $ hg phase -p null:
698
698
699 no other changes - no merge:
699 no other changes - no merge:
700
700
701 $ echo f > f
701 $ echo f > f
702 $ hg add f
702 $ hg add f
703 $ hg shelve
703 $ hg shelve
704 shelved as default
704 shelved as default
705 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
705 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
706 $ echo g > f
706 $ echo g > f
707 $ hg unshelve
707 $ hg unshelve
708 unshelving change 'default'
708 unshelving change 'default'
709 $ hg st
709 $ hg st
710 A f
710 A f
711 ? f.orig
711 ? f.orig
712 $ cat f
712 $ cat f
713 f
713 f
714 $ cat f.orig
714 $ cat f.orig
715 g
715 g
716
716
717 other uncommitted changes - merge:
717 other uncommitted changes - merge:
718
718
719 $ hg st
719 $ hg st
720 A f
720 A f
721 ? f.orig
721 ? f.orig
722 $ hg shelve
722 $ hg shelve
723 shelved as default
723 shelved as default
724 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
724 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
725 $ hg log -G --template '{rev} {desc|firstline} {author}' -R bundle://.hg/shelved/default.hg -r 'bundle()'
725 $ hg log -G --template '{rev} {desc|firstline} {author}' -R bundle://.hg/shelved/default.hg -r 'bundle()'
726 o 4 changes to: commit stuff shelve@localhost
726 o 4 changes to: commit stuff shelve@localhost
727 |
727 |
728 ~
728 ~
729 $ hg log -G --template '{rev} {desc|firstline} {author}'
729 $ hg log -G --template '{rev} {desc|firstline} {author}'
730 @ 3 commit stuff test
730 @ 3 commit stuff test
731 |
731 |
732 | o 2 c test
732 | o 2 c test
733 |/
733 |/
734 o 0 a test
734 o 0 a test
735
735
736 $ mv f.orig f
736 $ mv f.orig f
737 $ echo 1 > a
737 $ echo 1 > a
738 $ hg unshelve --date '1073741824 0'
738 $ hg unshelve --date '1073741824 0'
739 unshelving change 'default'
739 unshelving change 'default'
740 temporarily committing pending changes (restore with 'hg unshelve --abort')
740 temporarily committing pending changes (restore with 'hg unshelve --abort')
741 rebasing shelved changes
741 rebasing shelved changes
742 rebasing 5:81152db69da7 "changes to: commit stuff" (tip)
742 rebasing 5:81152db69da7 "changes to: commit stuff" (tip)
743 merging f
743 merging f
744 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
744 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
745 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
745 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
746 [1]
746 [1]
747 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
747 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
748 @ 5 changes to: commit stuff shelve@localhost 1970-01-01 00:00 +0000
748 @ 5 changes to: commit stuff shelve@localhost 1970-01-01 00:00 +0000
749 |
749 |
750 | @ 4 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
750 | @ 4 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
751 |/
751 |/
752 o 3 commit stuff test 1970-01-01 00:00 +0000
752 o 3 commit stuff test 1970-01-01 00:00 +0000
753 |
753 |
754 | o 2 c test 1970-01-01 00:00 +0000
754 | o 2 c test 1970-01-01 00:00 +0000
755 |/
755 |/
756 o 0 a test 1970-01-01 00:00 +0000
756 o 0 a test 1970-01-01 00:00 +0000
757
757
758 $ hg st
758 $ hg st
759 M f
759 M f
760 ? f.orig
760 ? f.orig
761 $ cat f
761 $ cat f
762 <<<<<<< dest: 5f6b880e719b - shelve: pending changes temporary commit
762 <<<<<<< dest: 5f6b880e719b - shelve: pending changes temporary commit
763 g
763 g
764 =======
764 =======
765 f
765 f
766 >>>>>>> source: 81152db69da7 - shelve: changes to: commit stuff
766 >>>>>>> source: 81152db69da7 - shelve: changes to: commit stuff
767 $ cat f.orig
767 $ cat f.orig
768 g
768 g
769 $ hg unshelve --abort -t false
769 $ hg unshelve --abort -t false
770 tool option will be ignored
770 tool option will be ignored
771 rebase aborted
771 rebase aborted
772 unshelve of 'default' aborted
772 unshelve of 'default' aborted
773 $ hg st
773 $ hg st
774 M a
774 M a
775 ? f.orig
775 ? f.orig
776 $ cat f.orig
776 $ cat f.orig
777 g
777 g
778 $ hg unshelve
778 $ hg unshelve
779 unshelving change 'default'
779 unshelving change 'default'
780 temporarily committing pending changes (restore with 'hg unshelve --abort')
780 temporarily committing pending changes (restore with 'hg unshelve --abort')
781 rebasing shelved changes
781 rebasing shelved changes
782 rebasing 5:81152db69da7 "changes to: commit stuff" (tip)
782 rebasing 5:81152db69da7 "changes to: commit stuff" (tip)
783 $ hg st
783 $ hg st
784 M a
784 M a
785 A f
785 A f
786 ? f.orig
786 ? f.orig
787
787
788 other committed changes - merge:
788 other committed changes - merge:
789
789
790 $ hg shelve f
790 $ hg shelve f
791 shelved as default
791 shelved as default
792 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
792 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
793 $ hg ci a -m 'intermediate other change'
793 $ hg ci a -m 'intermediate other change'
794 $ mv f.orig f
794 $ mv f.orig f
795 $ hg unshelve
795 $ hg unshelve
796 unshelving change 'default'
796 unshelving change 'default'
797 rebasing shelved changes
797 rebasing shelved changes
798 rebasing 5:81152db69da7 "changes to: commit stuff" (tip)
798 rebasing 5:81152db69da7 "changes to: commit stuff" (tip)
799 merging f
799 merging f
800 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
800 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
801 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
801 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
802 [1]
802 [1]
803 $ hg st
803 $ hg st
804 M f
804 M f
805 ? f.orig
805 ? f.orig
806 $ cat f
806 $ cat f
807 <<<<<<< dest: * - test: intermediate other change (glob)
807 <<<<<<< dest: * - test: intermediate other change (glob)
808 g
808 g
809 =======
809 =======
810 f
810 f
811 >>>>>>> source: 81152db69da7 - shelve: changes to: commit stuff
811 >>>>>>> source: 81152db69da7 - shelve: changes to: commit stuff
812 $ cat f.orig
812 $ cat f.orig
813 g
813 g
814 $ hg unshelve --abort
814 $ hg unshelve --abort
815 rebase aborted
815 rebase aborted
816 unshelve of 'default' aborted
816 unshelve of 'default' aborted
817 $ hg st
817 $ hg st
818 ? f.orig
818 ? f.orig
819 $ cat f.orig
819 $ cat f.orig
820 g
820 g
821 $ hg shelve --delete default
821 $ hg shelve --delete default
822
822
823 Recreate some conflict again
823 Recreate some conflict again
824
824
825 $ cd ../repo
825 $ cd ../repo
826 $ hg up -C -r 3
826 $ hg up -C -r 3
827 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
827 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
828 (leaving bookmark test)
828 (leaving bookmark test)
829 $ echo y >> a/a
829 $ echo y >> a/a
830 $ hg shelve
830 $ hg shelve
831 shelved as default
831 shelved as default
832 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
832 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
833 $ hg up test
833 $ hg up test
834 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
834 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
835 (activating bookmark test)
835 (activating bookmark test)
836 $ hg bookmark
836 $ hg bookmark
837 * test 4:33f7f61e6c5e
837 * test 4:33f7f61e6c5e
838 $ hg unshelve
838 $ hg unshelve
839 unshelving change 'default'
839 unshelving change 'default'
840 rebasing shelved changes
840 rebasing shelved changes
841 rebasing 5:e42a7da90865 "changes to: second" (tip)
841 rebasing 5:e42a7da90865 "changes to: second" (tip)
842 merging a/a
842 merging a/a
843 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
843 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
844 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
844 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
845 [1]
845 [1]
846 $ hg bookmark
846 $ hg bookmark
847 test 4:33f7f61e6c5e
847 test 4:33f7f61e6c5e
848
848
849 Test that resolving all conflicts in one direction (so that the rebase
849 Test that resolving all conflicts in one direction (so that the rebase
850 is a no-op), works (issue4398)
850 is a no-op), works (issue4398)
851
851
852 $ hg revert -a -r .
852 $ hg revert -a -r .
853 reverting a/a (glob)
853 reverting a/a (glob)
854 $ hg resolve -m a/a
854 $ hg resolve -m a/a
855 (no more unresolved files)
855 (no more unresolved files)
856 continue: hg unshelve --continue
856 continue: hg unshelve --continue
857 $ hg unshelve -c
857 $ hg unshelve -c
858 rebasing 5:e42a7da90865 "changes to: second" (tip)
858 rebasing 5:e42a7da90865 "changes to: second" (tip)
859 note: rebase of 5:e42a7da90865 created no changes to commit
859 note: rebase of 5:e42a7da90865 created no changes to commit
860 unshelve of 'default' complete
860 unshelve of 'default' complete
861 $ hg bookmark
861 $ hg bookmark
862 * test 4:33f7f61e6c5e
862 * test 4:33f7f61e6c5e
863 $ hg diff
863 $ hg diff
864 $ hg status
864 $ hg status
865 ? a/a.orig
865 ? a/a.orig
866 ? foo/foo
866 ? foo/foo
867 $ hg summary
867 $ hg summary
868 parent: 4:33f7f61e6c5e tip
868 parent: 4:33f7f61e6c5e tip
869 create conflict
869 create conflict
870 branch: default
870 branch: default
871 bookmarks: *test
871 bookmarks: *test
872 commit: 2 unknown (clean)
872 commit: 2 unknown (clean)
873 update: (current)
873 update: (current)
874 phases: 5 draft
874 phases: 5 draft
875
875
876 $ hg shelve --delete --stat
876 $ hg shelve --delete --stat
877 abort: options '--delete' and '--stat' may not be used together
877 abort: options '--delete' and '--stat' may not be used together
878 [255]
878 [255]
879 $ hg shelve --delete --name NAME
879 $ hg shelve --delete --name NAME
880 abort: options '--delete' and '--name' may not be used together
880 abort: options '--delete' and '--name' may not be used together
881 [255]
881 [255]
882
882
883 Test interactive shelve
883 Test interactive shelve
884 $ cat <<EOF >> $HGRCPATH
884 $ cat <<EOF >> $HGRCPATH
885 > [ui]
885 > [ui]
886 > interactive = true
886 > interactive = true
887 > EOF
887 > EOF
888 $ echo 'a' >> a/b
888 $ echo 'a' >> a/b
889 $ cat a/a >> a/b
889 $ cat a/a >> a/b
890 $ echo 'x' >> a/b
890 $ echo 'x' >> a/b
891 $ mv a/b a/a
891 $ mv a/b a/a
892 $ echo 'a' >> foo/foo
892 $ echo 'a' >> foo/foo
893 $ hg st
893 $ hg st
894 M a/a
894 M a/a
895 ? a/a.orig
895 ? a/a.orig
896 ? foo/foo
896 ? foo/foo
897 $ cat a/a
897 $ cat a/a
898 a
898 a
899 a
899 a
900 c
900 c
901 x
901 x
902 x
902 x
903 $ cat foo/foo
903 $ cat foo/foo
904 foo
904 foo
905 a
905 a
906 $ hg shelve --interactive --config ui.interactive=false
906 $ hg shelve --interactive --config ui.interactive=false
907 abort: running non-interactively
907 abort: running non-interactively
908 [255]
908 [255]
909 $ hg shelve --interactive << EOF
909 $ hg shelve --interactive << EOF
910 > y
910 > y
911 > y
911 > y
912 > n
912 > n
913 > EOF
913 > EOF
914 diff --git a/a/a b/a/a
914 diff --git a/a/a b/a/a
915 2 hunks, 2 lines changed
915 2 hunks, 2 lines changed
916 examine changes to 'a/a'? [Ynesfdaq?] y
916 examine changes to 'a/a'? [Ynesfdaq?] y
917
917
918 @@ -1,3 +1,4 @@
918 @@ -1,3 +1,4 @@
919 +a
919 +a
920 a
920 a
921 c
921 c
922 x
922 x
923 record change 1/2 to 'a/a'? [Ynesfdaq?] y
923 record change 1/2 to 'a/a'? [Ynesfdaq?] y
924
924
925 @@ -1,3 +2,4 @@
925 @@ -1,3 +2,4 @@
926 a
926 a
927 c
927 c
928 x
928 x
929 +x
929 +x
930 record change 2/2 to 'a/a'? [Ynesfdaq?] n
930 record change 2/2 to 'a/a'? [Ynesfdaq?] n
931
931
932 shelved as test
932 shelved as test
933 merging a/a
933 merging a/a
934 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
934 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
935 $ cat a/a
935 $ cat a/a
936 a
936 a
937 c
937 c
938 x
938 x
939 x
939 x
940 $ cat foo/foo
940 $ cat foo/foo
941 foo
941 foo
942 a
942 a
943 $ hg st
943 $ hg st
944 M a/a
944 M a/a
945 ? foo/foo
945 ? foo/foo
946 $ hg bookmark
946 $ hg bookmark
947 * test 4:33f7f61e6c5e
947 * test 4:33f7f61e6c5e
948 $ hg unshelve
948 $ hg unshelve
949 unshelving change 'test'
949 unshelving change 'test'
950 temporarily committing pending changes (restore with 'hg unshelve --abort')
950 temporarily committing pending changes (restore with 'hg unshelve --abort')
951 rebasing shelved changes
951 rebasing shelved changes
952 rebasing 6:96a1354f65f6 "changes to: create conflict" (tip)
952 rebasing 6:96a1354f65f6 "changes to: create conflict" (tip)
953 merging a/a
953 merging a/a
954 $ hg bookmark
954 $ hg bookmark
955 * test 4:33f7f61e6c5e
955 * test 4:33f7f61e6c5e
956 $ cat a/a
956 $ cat a/a
957 a
957 a
958 a
958 a
959 c
959 c
960 x
960 x
961 x
961 x
962
962
963 shelve --patch and shelve --stat should work with a single valid shelfname
963 shelve --patch and shelve --stat should work with a single valid shelfname
964
964
965 $ hg up --clean .
965 $ hg up --clean .
966 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
966 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
967 (leaving bookmark test)
967 (leaving bookmark test)
968 $ hg shelve --list
968 $ hg shelve --list
969 $ echo 'patch a' > shelf-patch-a
969 $ echo 'patch a' > shelf-patch-a
970 $ hg add shelf-patch-a
970 $ hg add shelf-patch-a
971 $ hg shelve
971 $ hg shelve
972 shelved as default
972 shelved as default
973 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
973 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
974 $ echo 'patch b' > shelf-patch-b
974 $ echo 'patch b' > shelf-patch-b
975 $ hg add shelf-patch-b
975 $ hg add shelf-patch-b
976 $ hg shelve
976 $ hg shelve
977 shelved as default-01
977 shelved as default-01
978 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
978 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
979 $ hg shelve --patch default default-01
979 $ hg shelve --patch default default-01
980 abort: --patch expects a single shelf
980 abort: --patch expects a single shelf
981 [255]
981 [255]
982 $ hg shelve --stat default default-01
982 $ hg shelve --stat default default-01
983 abort: --stat expects a single shelf
983 abort: --stat expects a single shelf
984 [255]
984 [255]
985 $ hg shelve --patch default
985 $ hg shelve --patch default
986 default (*)* changes to: create conflict (glob)
986 default (*)* changes to: create conflict (glob)
987
987
988 diff --git a/shelf-patch-a b/shelf-patch-a
988 diff --git a/shelf-patch-a b/shelf-patch-a
989 new file mode 100644
989 new file mode 100644
990 --- /dev/null
990 --- /dev/null
991 +++ b/shelf-patch-a
991 +++ b/shelf-patch-a
992 @@ -0,0 +1,1 @@
992 @@ -0,0 +1,1 @@
993 +patch a
993 +patch a
994 $ hg shelve --stat default
994 $ hg shelve --stat default
995 default (*)* changes to: create conflict (glob)
995 default (*)* changes to: create conflict (glob)
996 shelf-patch-a | 1 +
996 shelf-patch-a | 1 +
997 1 files changed, 1 insertions(+), 0 deletions(-)
997 1 files changed, 1 insertions(+), 0 deletions(-)
998 $ hg shelve --patch nonexistentshelf
998 $ hg shelve --patch nonexistentshelf
999 abort: cannot find shelf nonexistentshelf
999 abort: cannot find shelf nonexistentshelf
1000 [255]
1000 [255]
1001 $ hg shelve --stat nonexistentshelf
1001 $ hg shelve --stat nonexistentshelf
1002 abort: cannot find shelf nonexistentshelf
1002 abort: cannot find shelf nonexistentshelf
1003 [255]
1003 [255]
1004
1004
1005 $ cd ..
1005 $ cd ..
1006
1006
1007 Shelve from general delta repo uses bundle2 on disk
1007 Shelve from general delta repo uses bundle2 on disk
1008 --------------------------------------------------
1008 --------------------------------------------------
1009
1009
1010 no general delta
1010 no general delta
1011
1011
1012 $ hg clone --pull repo bundle1 --config format.usegeneraldelta=0
1012 $ hg clone --pull repo bundle1 --config format.usegeneraldelta=0
1013 requesting all changes
1013 requesting all changes
1014 adding changesets
1014 adding changesets
1015 adding manifests
1015 adding manifests
1016 adding file changes
1016 adding file changes
1017 added 5 changesets with 8 changes to 6 files
1017 added 5 changesets with 8 changes to 6 files
1018 updating to branch default
1018 updating to branch default
1019 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1019 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1020 $ cd bundle1
1020 $ cd bundle1
1021 $ echo babar > jungle
1021 $ echo babar > jungle
1022 $ hg add jungle
1022 $ hg add jungle
1023 $ hg shelve
1023 $ hg shelve
1024 shelved as default
1024 shelved as default
1025 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1025 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1026 $ hg debugbundle .hg/shelved/*.hg
1026 $ hg debugbundle .hg/shelved/*.hg
1027 45993d65fe9dc3c6d8764b9c3b07fa831ee7d92d
1027 45993d65fe9dc3c6d8764b9c3b07fa831ee7d92d
1028 $ cd ..
1028 $ cd ..
1029
1029
1030 with general delta
1030 with general delta
1031
1031
1032 $ hg clone --pull repo bundle2 --config format.usegeneraldelta=1
1032 $ hg clone --pull repo bundle2 --config format.usegeneraldelta=1
1033 requesting all changes
1033 requesting all changes
1034 adding changesets
1034 adding changesets
1035 adding manifests
1035 adding manifests
1036 adding file changes
1036 adding file changes
1037 added 5 changesets with 8 changes to 6 files
1037 added 5 changesets with 8 changes to 6 files
1038 updating to branch default
1038 updating to branch default
1039 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1039 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1040 $ cd bundle2
1040 $ cd bundle2
1041 $ echo babar > jungle
1041 $ echo babar > jungle
1042 $ hg add jungle
1042 $ hg add jungle
1043 $ hg shelve
1043 $ hg shelve
1044 shelved as default
1044 shelved as default
1045 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1045 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1046 $ hg debugbundle .hg/shelved/*.hg
1046 $ hg debugbundle .hg/shelved/*.hg
1047 Stream params: {'Compression': 'BZ'}
1047 Stream params: sortdict([('Compression', 'BZ')])
1048 changegroup -- "{'version': '02'}"
1048 changegroup -- "sortdict([('version', '02')])"
1049 45993d65fe9dc3c6d8764b9c3b07fa831ee7d92d
1049 45993d65fe9dc3c6d8764b9c3b07fa831ee7d92d
1050 $ cd ..
1050 $ cd ..
1051
1051
1052 Test visibility of in-memory changes inside transaction to external hook
1052 Test visibility of in-memory changes inside transaction to external hook
1053 ------------------------------------------------------------------------
1053 ------------------------------------------------------------------------
1054
1054
1055 $ cd repo
1055 $ cd repo
1056
1056
1057 $ echo xxxx >> x
1057 $ echo xxxx >> x
1058 $ hg commit -m "#5: changes to invoke rebase"
1058 $ hg commit -m "#5: changes to invoke rebase"
1059
1059
1060 $ cat > $TESTTMP/checkvisibility.sh <<EOF
1060 $ cat > $TESTTMP/checkvisibility.sh <<EOF
1061 > echo "==== \$1:"
1061 > echo "==== \$1:"
1062 > hg parents --template "VISIBLE {rev}:{node|short}\n"
1062 > hg parents --template "VISIBLE {rev}:{node|short}\n"
1063 > # test that pending changes are hidden
1063 > # test that pending changes are hidden
1064 > unset HG_PENDING
1064 > unset HG_PENDING
1065 > hg parents --template "ACTUAL {rev}:{node|short}\n"
1065 > hg parents --template "ACTUAL {rev}:{node|short}\n"
1066 > echo "===="
1066 > echo "===="
1067 > EOF
1067 > EOF
1068
1068
1069 $ cat >> .hg/hgrc <<EOF
1069 $ cat >> .hg/hgrc <<EOF
1070 > [defaults]
1070 > [defaults]
1071 > # to fix hash id of temporary revisions
1071 > # to fix hash id of temporary revisions
1072 > unshelve = --date '0 0'
1072 > unshelve = --date '0 0'
1073 > EOF
1073 > EOF
1074
1074
1075 "hg unshelve" at REV5 implies steps below:
1075 "hg unshelve" at REV5 implies steps below:
1076
1076
1077 (1) commit changes in the working directory (REV6)
1077 (1) commit changes in the working directory (REV6)
1078 (2) unbundle shelved revision (REV7)
1078 (2) unbundle shelved revision (REV7)
1079 (3) rebase: merge REV7 into REV6 (REV6 => REV6, REV7)
1079 (3) rebase: merge REV7 into REV6 (REV6 => REV6, REV7)
1080 (4) rebase: commit merged revision (REV8)
1080 (4) rebase: commit merged revision (REV8)
1081 (5) rebase: update to REV6 (REV8 => REV6)
1081 (5) rebase: update to REV6 (REV8 => REV6)
1082 (6) update to REV5 (REV6 => REV5)
1082 (6) update to REV5 (REV6 => REV5)
1083 (7) abort transaction
1083 (7) abort transaction
1084
1084
1085 == test visibility to external preupdate hook
1085 == test visibility to external preupdate hook
1086
1086
1087 $ cat >> .hg/hgrc <<EOF
1087 $ cat >> .hg/hgrc <<EOF
1088 > [hooks]
1088 > [hooks]
1089 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
1089 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
1090 > EOF
1090 > EOF
1091
1091
1092 $ echo nnnn >> n
1092 $ echo nnnn >> n
1093
1093
1094 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1094 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1095 ==== before-unshelving:
1095 ==== before-unshelving:
1096 VISIBLE 5:703117a2acfb
1096 VISIBLE 5:703117a2acfb
1097 ACTUAL 5:703117a2acfb
1097 ACTUAL 5:703117a2acfb
1098 ====
1098 ====
1099
1099
1100 $ hg unshelve --keep default
1100 $ hg unshelve --keep default
1101 temporarily committing pending changes (restore with 'hg unshelve --abort')
1101 temporarily committing pending changes (restore with 'hg unshelve --abort')
1102 rebasing shelved changes
1102 rebasing shelved changes
1103 rebasing 7:206bf5d4f922 "changes to: create conflict" (tip)
1103 rebasing 7:206bf5d4f922 "changes to: create conflict" (tip)
1104 ==== preupdate:
1104 ==== preupdate:
1105 VISIBLE 6:66b86db80ee4
1105 VISIBLE 6:66b86db80ee4
1106 ACTUAL 5:703117a2acfb
1106 ACTUAL 5:703117a2acfb
1107 ====
1107 ====
1108 ==== preupdate:
1108 ==== preupdate:
1109 VISIBLE 8:a0e04704317e
1109 VISIBLE 8:a0e04704317e
1110 ACTUAL 5:703117a2acfb
1110 ACTUAL 5:703117a2acfb
1111 ====
1111 ====
1112 ==== preupdate:
1112 ==== preupdate:
1113 VISIBLE 6:66b86db80ee4
1113 VISIBLE 6:66b86db80ee4
1114 ACTUAL 5:703117a2acfb
1114 ACTUAL 5:703117a2acfb
1115 ====
1115 ====
1116
1116
1117 $ cat >> .hg/hgrc <<EOF
1117 $ cat >> .hg/hgrc <<EOF
1118 > [hooks]
1118 > [hooks]
1119 > preupdate.visibility =
1119 > preupdate.visibility =
1120 > EOF
1120 > EOF
1121
1121
1122 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1122 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1123 ==== after-unshelving:
1123 ==== after-unshelving:
1124 VISIBLE 5:703117a2acfb
1124 VISIBLE 5:703117a2acfb
1125 ACTUAL 5:703117a2acfb
1125 ACTUAL 5:703117a2acfb
1126 ====
1126 ====
1127
1127
1128 == test visibility to external update hook
1128 == test visibility to external update hook
1129
1129
1130 $ hg update -q -C 5
1130 $ hg update -q -C 5
1131
1131
1132 $ cat >> .hg/hgrc <<EOF
1132 $ cat >> .hg/hgrc <<EOF
1133 > [hooks]
1133 > [hooks]
1134 > update.visibility = sh $TESTTMP/checkvisibility.sh update
1134 > update.visibility = sh $TESTTMP/checkvisibility.sh update
1135 > EOF
1135 > EOF
1136
1136
1137 $ echo nnnn >> n
1137 $ echo nnnn >> n
1138
1138
1139 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1139 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1140 ==== before-unshelving:
1140 ==== before-unshelving:
1141 VISIBLE 5:703117a2acfb
1141 VISIBLE 5:703117a2acfb
1142 ACTUAL 5:703117a2acfb
1142 ACTUAL 5:703117a2acfb
1143 ====
1143 ====
1144
1144
1145 $ hg unshelve --keep default
1145 $ hg unshelve --keep default
1146 temporarily committing pending changes (restore with 'hg unshelve --abort')
1146 temporarily committing pending changes (restore with 'hg unshelve --abort')
1147 rebasing shelved changes
1147 rebasing shelved changes
1148 rebasing 7:206bf5d4f922 "changes to: create conflict" (tip)
1148 rebasing 7:206bf5d4f922 "changes to: create conflict" (tip)
1149 ==== update:
1149 ==== update:
1150 VISIBLE 6:66b86db80ee4
1150 VISIBLE 6:66b86db80ee4
1151 VISIBLE 7:206bf5d4f922
1151 VISIBLE 7:206bf5d4f922
1152 ACTUAL 5:703117a2acfb
1152 ACTUAL 5:703117a2acfb
1153 ====
1153 ====
1154 ==== update:
1154 ==== update:
1155 VISIBLE 6:66b86db80ee4
1155 VISIBLE 6:66b86db80ee4
1156 ACTUAL 5:703117a2acfb
1156 ACTUAL 5:703117a2acfb
1157 ====
1157 ====
1158 ==== update:
1158 ==== update:
1159 VISIBLE 5:703117a2acfb
1159 VISIBLE 5:703117a2acfb
1160 ACTUAL 5:703117a2acfb
1160 ACTUAL 5:703117a2acfb
1161 ====
1161 ====
1162
1162
1163 $ cat >> .hg/hgrc <<EOF
1163 $ cat >> .hg/hgrc <<EOF
1164 > [hooks]
1164 > [hooks]
1165 > update.visibility =
1165 > update.visibility =
1166 > EOF
1166 > EOF
1167
1167
1168 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1168 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1169 ==== after-unshelving:
1169 ==== after-unshelving:
1170 VISIBLE 5:703117a2acfb
1170 VISIBLE 5:703117a2acfb
1171 ACTUAL 5:703117a2acfb
1171 ACTUAL 5:703117a2acfb
1172 ====
1172 ====
1173
1173
1174 $ cd ..
1174 $ cd ..
1175
1175
1176 test .orig files go where the user wants them to
1176 test .orig files go where the user wants them to
1177 ---------------------------------------------------------------
1177 ---------------------------------------------------------------
1178 $ hg init salvage
1178 $ hg init salvage
1179 $ cd salvage
1179 $ cd salvage
1180 $ echo 'content' > root
1180 $ echo 'content' > root
1181 $ hg commit -A -m 'root' -q
1181 $ hg commit -A -m 'root' -q
1182 $ echo '' > root
1182 $ echo '' > root
1183 $ hg shelve -q
1183 $ hg shelve -q
1184 $ echo 'contADDent' > root
1184 $ echo 'contADDent' > root
1185 $ hg unshelve -q --config 'ui.origbackuppath=.hg/origbackups'
1185 $ hg unshelve -q --config 'ui.origbackuppath=.hg/origbackups'
1186 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1186 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1187 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1187 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1188 [1]
1188 [1]
1189 $ ls .hg/origbackups
1189 $ ls .hg/origbackups
1190 root.orig
1190 root.orig
1191 $ rm -rf .hg/origbackups
1191 $ rm -rf .hg/origbackups
1192
1192
1193 test Abort unshelve always gets user out of the unshelved state
1193 test Abort unshelve always gets user out of the unshelved state
1194 ---------------------------------------------------------------
1194 ---------------------------------------------------------------
1195 Wreak havoc on the unshelve process
1195 Wreak havoc on the unshelve process
1196 $ rm .hg/unshelverebasestate
1196 $ rm .hg/unshelverebasestate
1197 $ hg unshelve --abort
1197 $ hg unshelve --abort
1198 unshelve of 'default' aborted
1198 unshelve of 'default' aborted
1199 abort: (No such file or directory|The system cannot find the file specified) (re)
1199 abort: (No such file or directory|The system cannot find the file specified) (re)
1200 [255]
1200 [255]
1201 Can the user leave the current state?
1201 Can the user leave the current state?
1202 $ hg up -C .
1202 $ hg up -C .
1203 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1203 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1204
1204
1205 Try again but with a corrupted shelve state file
1205 Try again but with a corrupted shelve state file
1206 $ hg strip -r 2 -r 1 -q
1206 $ hg strip -r 2 -r 1 -q
1207 $ hg up -r 0 -q
1207 $ hg up -r 0 -q
1208 $ echo '' > root
1208 $ echo '' > root
1209 $ hg shelve -q
1209 $ hg shelve -q
1210 $ echo 'contADDent' > root
1210 $ echo 'contADDent' > root
1211 $ hg unshelve -q
1211 $ hg unshelve -q
1212 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1212 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1213 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1213 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1214 [1]
1214 [1]
1215 $ sed 's/ae8c668541e8/123456789012/' .hg/shelvedstate > ../corrupt-shelvedstate
1215 $ sed 's/ae8c668541e8/123456789012/' .hg/shelvedstate > ../corrupt-shelvedstate
1216 $ mv ../corrupt-shelvedstate .hg/histedit-state
1216 $ mv ../corrupt-shelvedstate .hg/histedit-state
1217 $ hg unshelve --abort 2>&1 | grep 'rebase aborted'
1217 $ hg unshelve --abort 2>&1 | grep 'rebase aborted'
1218 rebase aborted
1218 rebase aborted
1219 $ hg up -C .
1219 $ hg up -C .
1220 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1220 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1221
1221
1222 $ cd ..
1222 $ cd ..
1223
1223
1224 Keep active bookmark while (un)shelving even on shared repo (issue4940)
1224 Keep active bookmark while (un)shelving even on shared repo (issue4940)
1225 -----------------------------------------------------------------------
1225 -----------------------------------------------------------------------
1226
1226
1227 $ cat <<EOF >> $HGRCPATH
1227 $ cat <<EOF >> $HGRCPATH
1228 > [extensions]
1228 > [extensions]
1229 > share =
1229 > share =
1230 > EOF
1230 > EOF
1231
1231
1232 $ hg bookmarks -R repo
1232 $ hg bookmarks -R repo
1233 test 4:33f7f61e6c5e
1233 test 4:33f7f61e6c5e
1234 $ hg share -B repo share
1234 $ hg share -B repo share
1235 updating working directory
1235 updating working directory
1236 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1236 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1237 $ cd share
1237 $ cd share
1238
1238
1239 $ hg bookmarks
1239 $ hg bookmarks
1240 test 4:33f7f61e6c5e
1240 test 4:33f7f61e6c5e
1241 $ hg bookmarks foo
1241 $ hg bookmarks foo
1242 $ hg bookmarks
1242 $ hg bookmarks
1243 * foo 5:703117a2acfb
1243 * foo 5:703117a2acfb
1244 test 4:33f7f61e6c5e
1244 test 4:33f7f61e6c5e
1245 $ echo x >> x
1245 $ echo x >> x
1246 $ hg shelve
1246 $ hg shelve
1247 shelved as foo
1247 shelved as foo
1248 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1248 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1249 $ hg bookmarks
1249 $ hg bookmarks
1250 * foo 5:703117a2acfb
1250 * foo 5:703117a2acfb
1251 test 4:33f7f61e6c5e
1251 test 4:33f7f61e6c5e
1252
1252
1253 $ hg unshelve
1253 $ hg unshelve
1254 unshelving change 'foo'
1254 unshelving change 'foo'
1255 $ hg bookmarks
1255 $ hg bookmarks
1256 * foo 5:703117a2acfb
1256 * foo 5:703117a2acfb
1257 test 4:33f7f61e6c5e
1257 test 4:33f7f61e6c5e
1258
1258
1259 $ cd ..
1259 $ cd ..
1260
1260
1261 Shelve and unshelve unknown files. For the purposes of unshelve, a shelved
1261 Shelve and unshelve unknown files. For the purposes of unshelve, a shelved
1262 unknown file is the same as a shelved added file, except that it will be in
1262 unknown file is the same as a shelved added file, except that it will be in
1263 unknown state after unshelve if and only if it was either absent or unknown
1263 unknown state after unshelve if and only if it was either absent or unknown
1264 before the unshelve operation.
1264 before the unshelve operation.
1265
1265
1266 $ hg init unknowns
1266 $ hg init unknowns
1267 $ cd unknowns
1267 $ cd unknowns
1268
1268
1269 The simplest case is if I simply have an unknown file that I shelve and unshelve
1269 The simplest case is if I simply have an unknown file that I shelve and unshelve
1270
1270
1271 $ echo unknown > unknown
1271 $ echo unknown > unknown
1272 $ hg status
1272 $ hg status
1273 ? unknown
1273 ? unknown
1274 $ hg shelve --unknown
1274 $ hg shelve --unknown
1275 shelved as default
1275 shelved as default
1276 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1276 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1277 $ hg status
1277 $ hg status
1278 $ hg unshelve
1278 $ hg unshelve
1279 unshelving change 'default'
1279 unshelving change 'default'
1280 $ hg status
1280 $ hg status
1281 ? unknown
1281 ? unknown
1282 $ rm unknown
1282 $ rm unknown
1283
1283
1284 If I shelve, add the file, and unshelve, does it stay added?
1284 If I shelve, add the file, and unshelve, does it stay added?
1285
1285
1286 $ echo unknown > unknown
1286 $ echo unknown > unknown
1287 $ hg shelve -u
1287 $ hg shelve -u
1288 shelved as default
1288 shelved as default
1289 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1289 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1290 $ hg status
1290 $ hg status
1291 $ touch unknown
1291 $ touch unknown
1292 $ hg add unknown
1292 $ hg add unknown
1293 $ hg status
1293 $ hg status
1294 A unknown
1294 A unknown
1295 $ hg unshelve
1295 $ hg unshelve
1296 unshelving change 'default'
1296 unshelving change 'default'
1297 temporarily committing pending changes (restore with 'hg unshelve --abort')
1297 temporarily committing pending changes (restore with 'hg unshelve --abort')
1298 rebasing shelved changes
1298 rebasing shelved changes
1299 rebasing 1:098df96e7410 "(changes in empty repository)" (tip)
1299 rebasing 1:098df96e7410 "(changes in empty repository)" (tip)
1300 merging unknown
1300 merging unknown
1301 $ hg status
1301 $ hg status
1302 A unknown
1302 A unknown
1303 $ hg forget unknown
1303 $ hg forget unknown
1304 $ rm unknown
1304 $ rm unknown
1305
1305
1306 And if I shelve, commit, then unshelve, does it become modified?
1306 And if I shelve, commit, then unshelve, does it become modified?
1307
1307
1308 $ echo unknown > unknown
1308 $ echo unknown > unknown
1309 $ hg shelve -u
1309 $ hg shelve -u
1310 shelved as default
1310 shelved as default
1311 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1311 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1312 $ hg status
1312 $ hg status
1313 $ touch unknown
1313 $ touch unknown
1314 $ hg add unknown
1314 $ hg add unknown
1315 $ hg commit -qm "Add unknown"
1315 $ hg commit -qm "Add unknown"
1316 $ hg status
1316 $ hg status
1317 $ hg unshelve
1317 $ hg unshelve
1318 unshelving change 'default'
1318 unshelving change 'default'
1319 rebasing shelved changes
1319 rebasing shelved changes
1320 rebasing 1:098df96e7410 "(changes in empty repository)" (tip)
1320 rebasing 1:098df96e7410 "(changes in empty repository)" (tip)
1321 merging unknown
1321 merging unknown
1322 $ hg status
1322 $ hg status
1323 M unknown
1323 M unknown
1324 $ hg remove --force unknown
1324 $ hg remove --force unknown
1325 $ hg commit -qm "Remove unknown"
1325 $ hg commit -qm "Remove unknown"
1326
1326
1327 $ cd ..
1327 $ cd ..
1328
1328
1329 We expects that non-bare shelve keeps newly created branch in
1329 We expects that non-bare shelve keeps newly created branch in
1330 working directory.
1330 working directory.
1331
1331
1332 $ hg init shelve-preserve-new-branch
1332 $ hg init shelve-preserve-new-branch
1333 $ cd shelve-preserve-new-branch
1333 $ cd shelve-preserve-new-branch
1334 $ echo "a" >> a
1334 $ echo "a" >> a
1335 $ hg add a
1335 $ hg add a
1336 $ echo "b" >> b
1336 $ echo "b" >> b
1337 $ hg add b
1337 $ hg add b
1338 $ hg commit -m "ab"
1338 $ hg commit -m "ab"
1339 $ echo "aa" >> a
1339 $ echo "aa" >> a
1340 $ echo "bb" >> b
1340 $ echo "bb" >> b
1341 $ hg branch new-branch
1341 $ hg branch new-branch
1342 marked working directory as branch new-branch
1342 marked working directory as branch new-branch
1343 (branches are permanent and global, did you want a bookmark?)
1343 (branches are permanent and global, did you want a bookmark?)
1344 $ hg status
1344 $ hg status
1345 M a
1345 M a
1346 M b
1346 M b
1347 $ hg branch
1347 $ hg branch
1348 new-branch
1348 new-branch
1349 $ hg shelve a
1349 $ hg shelve a
1350 shelved as default
1350 shelved as default
1351 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1351 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1352 $ hg branch
1352 $ hg branch
1353 new-branch
1353 new-branch
1354 $ hg status
1354 $ hg status
1355 M b
1355 M b
1356 $ touch "c" >> c
1356 $ touch "c" >> c
1357 $ hg add c
1357 $ hg add c
1358 $ hg status
1358 $ hg status
1359 M b
1359 M b
1360 A c
1360 A c
1361 $ hg shelve --exclude c
1361 $ hg shelve --exclude c
1362 shelved as default-01
1362 shelved as default-01
1363 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1363 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1364 $ hg branch
1364 $ hg branch
1365 new-branch
1365 new-branch
1366 $ hg status
1366 $ hg status
1367 A c
1367 A c
1368 $ hg shelve --include c
1368 $ hg shelve --include c
1369 shelved as default-02
1369 shelved as default-02
1370 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1370 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1371 $ hg branch
1371 $ hg branch
1372 new-branch
1372 new-branch
1373 $ hg status
1373 $ hg status
1374 $ echo "d" >> d
1374 $ echo "d" >> d
1375 $ hg add d
1375 $ hg add d
1376 $ hg status
1376 $ hg status
1377 A d
1377 A d
1378
1378
1379 We expect that bare-shelve will not keep branch in current working directory.
1379 We expect that bare-shelve will not keep branch in current working directory.
1380
1380
1381 $ hg shelve
1381 $ hg shelve
1382 shelved as default-03
1382 shelved as default-03
1383 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1383 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1384 $ hg branch
1384 $ hg branch
1385 default
1385 default
1386
1386
1387 When i shelve commit on newly created branch i expect
1387 When i shelve commit on newly created branch i expect
1388 that after unshelve newly created branch will be preserved.
1388 that after unshelve newly created branch will be preserved.
1389
1389
1390 $ hg init shelve_on_new_branch_simple
1390 $ hg init shelve_on_new_branch_simple
1391 $ cd shelve_on_new_branch_simple
1391 $ cd shelve_on_new_branch_simple
1392 $ echo "aaa" >> a
1392 $ echo "aaa" >> a
1393 $ hg commit -A -m "a"
1393 $ hg commit -A -m "a"
1394 adding a
1394 adding a
1395 $ hg branch
1395 $ hg branch
1396 default
1396 default
1397 $ hg branch test
1397 $ hg branch test
1398 marked working directory as branch test
1398 marked working directory as branch test
1399 (branches are permanent and global, did you want a bookmark?)
1399 (branches are permanent and global, did you want a bookmark?)
1400 $ echo "bbb" >> a
1400 $ echo "bbb" >> a
1401 $ hg status
1401 $ hg status
1402 M a
1402 M a
1403 $ hg shelve
1403 $ hg shelve
1404 shelved as default
1404 shelved as default
1405 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1405 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1406 $ hg branch
1406 $ hg branch
1407 default
1407 default
1408 $ echo "bbb" >> b
1408 $ echo "bbb" >> b
1409 $ hg status
1409 $ hg status
1410 ? b
1410 ? b
1411 $ hg unshelve
1411 $ hg unshelve
1412 unshelving change 'default'
1412 unshelving change 'default'
1413 marked working directory as branch test
1413 marked working directory as branch test
1414 $ hg status
1414 $ hg status
1415 M a
1415 M a
1416 ? b
1416 ? b
1417 $ hg branch
1417 $ hg branch
1418 test
1418 test
1419
1419
1420 When i shelve commit on newly created branch, make
1420 When i shelve commit on newly created branch, make
1421 some changes, unshelve it and running into merge
1421 some changes, unshelve it and running into merge
1422 conflicts i expect that after fixing them and
1422 conflicts i expect that after fixing them and
1423 running unshelve --continue newly created branch
1423 running unshelve --continue newly created branch
1424 will be preserved.
1424 will be preserved.
1425
1425
1426 $ hg init shelve_on_new_branch_conflict
1426 $ hg init shelve_on_new_branch_conflict
1427 $ cd shelve_on_new_branch_conflict
1427 $ cd shelve_on_new_branch_conflict
1428 $ echo "aaa" >> a
1428 $ echo "aaa" >> a
1429 $ hg commit -A -m "a"
1429 $ hg commit -A -m "a"
1430 adding a
1430 adding a
1431 $ hg branch
1431 $ hg branch
1432 default
1432 default
1433 $ hg branch test
1433 $ hg branch test
1434 marked working directory as branch test
1434 marked working directory as branch test
1435 (branches are permanent and global, did you want a bookmark?)
1435 (branches are permanent and global, did you want a bookmark?)
1436 $ echo "bbb" >> a
1436 $ echo "bbb" >> a
1437 $ hg status
1437 $ hg status
1438 M a
1438 M a
1439 $ hg shelve
1439 $ hg shelve
1440 shelved as default
1440 shelved as default
1441 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1441 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1442 $ hg branch
1442 $ hg branch
1443 default
1443 default
1444 $ echo "ccc" >> a
1444 $ echo "ccc" >> a
1445 $ hg status
1445 $ hg status
1446 M a
1446 M a
1447 $ hg unshelve
1447 $ hg unshelve
1448 unshelving change 'default'
1448 unshelving change 'default'
1449 temporarily committing pending changes (restore with 'hg unshelve --abort')
1449 temporarily committing pending changes (restore with 'hg unshelve --abort')
1450 rebasing shelved changes
1450 rebasing shelved changes
1451 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1451 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1452 merging a
1452 merging a
1453 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
1453 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
1454 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1454 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1455 [1]
1455 [1]
1456 $ echo "aaabbbccc" > a
1456 $ echo "aaabbbccc" > a
1457 $ rm a.orig
1457 $ rm a.orig
1458 $ hg resolve --mark a
1458 $ hg resolve --mark a
1459 (no more unresolved files)
1459 (no more unresolved files)
1460 continue: hg unshelve --continue
1460 continue: hg unshelve --continue
1461 $ hg unshelve --continue
1461 $ hg unshelve --continue
1462 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1462 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1463 marked working directory as branch test
1463 marked working directory as branch test
1464 unshelve of 'default' complete
1464 unshelve of 'default' complete
1465 $ cat a
1465 $ cat a
1466 aaabbbccc
1466 aaabbbccc
1467 $ hg status
1467 $ hg status
1468 M a
1468 M a
1469 $ hg branch
1469 $ hg branch
1470 test
1470 test
1471 $ hg commit -m "test-commit"
1471 $ hg commit -m "test-commit"
1472
1472
1473 When i shelve on test branch, update to default branch
1473 When i shelve on test branch, update to default branch
1474 and unshelve i expect that it will not preserve previous
1474 and unshelve i expect that it will not preserve previous
1475 test branch.
1475 test branch.
1476
1476
1477 $ echo "xxx" > b
1477 $ echo "xxx" > b
1478 $ hg add b
1478 $ hg add b
1479 $ hg shelve
1479 $ hg shelve
1480 shelved as test
1480 shelved as test
1481 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1481 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1482 $ hg update -r default
1482 $ hg update -r default
1483 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1483 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1484 $ hg unshelve
1484 $ hg unshelve
1485 unshelving change 'test'
1485 unshelving change 'test'
1486 rebasing shelved changes
1486 rebasing shelved changes
1487 rebasing 2:357525f34729 "changes to: test-commit" (tip)
1487 rebasing 2:357525f34729 "changes to: test-commit" (tip)
1488 $ hg status
1488 $ hg status
1489 A b
1489 A b
1490 $ hg branch
1490 $ hg branch
1491 default
1491 default
1492
1492
1493 When i unshelve resulting in merge conflicts and makes saved
1493 When i unshelve resulting in merge conflicts and makes saved
1494 file shelvedstate looks like in previous versions in
1494 file shelvedstate looks like in previous versions in
1495 mercurial(without restore branch information in 7th line) i
1495 mercurial(without restore branch information in 7th line) i
1496 expect that after resolving conflicts and succesfully
1496 expect that after resolving conflicts and succesfully
1497 running 'shelve --continue' the branch information won't be
1497 running 'shelve --continue' the branch information won't be
1498 restored and branch will be unchanged.
1498 restored and branch will be unchanged.
1499
1499
1500 shelve on new branch, conflict with previous shelvedstate
1500 shelve on new branch, conflict with previous shelvedstate
1501
1501
1502 $ hg init conflict
1502 $ hg init conflict
1503 $ cd conflict
1503 $ cd conflict
1504 $ echo "aaa" >> a
1504 $ echo "aaa" >> a
1505 $ hg commit -A -m "a"
1505 $ hg commit -A -m "a"
1506 adding a
1506 adding a
1507 $ hg branch
1507 $ hg branch
1508 default
1508 default
1509 $ hg branch test
1509 $ hg branch test
1510 marked working directory as branch test
1510 marked working directory as branch test
1511 (branches are permanent and global, did you want a bookmark?)
1511 (branches are permanent and global, did you want a bookmark?)
1512 $ echo "bbb" >> a
1512 $ echo "bbb" >> a
1513 $ hg status
1513 $ hg status
1514 M a
1514 M a
1515 $ hg shelve
1515 $ hg shelve
1516 shelved as default
1516 shelved as default
1517 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1517 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1518 $ hg branch
1518 $ hg branch
1519 default
1519 default
1520 $ echo "ccc" >> a
1520 $ echo "ccc" >> a
1521 $ hg status
1521 $ hg status
1522 M a
1522 M a
1523 $ hg unshelve
1523 $ hg unshelve
1524 unshelving change 'default'
1524 unshelving change 'default'
1525 temporarily committing pending changes (restore with 'hg unshelve --abort')
1525 temporarily committing pending changes (restore with 'hg unshelve --abort')
1526 rebasing shelved changes
1526 rebasing shelved changes
1527 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1527 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1528 merging a
1528 merging a
1529 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
1529 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
1530 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1530 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1531 [1]
1531 [1]
1532
1532
1533 Removing restore branch information from shelvedstate file(making it looks like
1533 Removing restore branch information from shelvedstate file(making it looks like
1534 in previous versions) and running unshelve --continue
1534 in previous versions) and running unshelve --continue
1535
1535
1536 $ head -n 6 < .hg/shelvedstate > .hg/shelvedstate_oldformat
1536 $ head -n 6 < .hg/shelvedstate > .hg/shelvedstate_oldformat
1537 $ rm .hg/shelvedstate
1537 $ rm .hg/shelvedstate
1538 $ mv .hg/shelvedstate_oldformat .hg/shelvedstate
1538 $ mv .hg/shelvedstate_oldformat .hg/shelvedstate
1539
1539
1540 $ echo "aaabbbccc" > a
1540 $ echo "aaabbbccc" > a
1541 $ rm a.orig
1541 $ rm a.orig
1542 $ hg resolve --mark a
1542 $ hg resolve --mark a
1543 (no more unresolved files)
1543 (no more unresolved files)
1544 continue: hg unshelve --continue
1544 continue: hg unshelve --continue
1545 $ hg unshelve --continue
1545 $ hg unshelve --continue
1546 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1546 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1547 unshelve of 'default' complete
1547 unshelve of 'default' complete
1548 $ cat a
1548 $ cat a
1549 aaabbbccc
1549 aaabbbccc
1550 $ hg status
1550 $ hg status
1551 M a
1551 M a
1552 $ hg branch
1552 $ hg branch
1553 default
1553 default
1554
1554
1555 On non bare shelve the branch information shouldn't be restored
1555 On non bare shelve the branch information shouldn't be restored
1556
1556
1557 $ hg init bare_shelve_on_new_branch
1557 $ hg init bare_shelve_on_new_branch
1558 $ cd bare_shelve_on_new_branch
1558 $ cd bare_shelve_on_new_branch
1559 $ echo "aaa" >> a
1559 $ echo "aaa" >> a
1560 $ hg commit -A -m "a"
1560 $ hg commit -A -m "a"
1561 adding a
1561 adding a
1562 $ hg branch
1562 $ hg branch
1563 default
1563 default
1564 $ hg branch test
1564 $ hg branch test
1565 marked working directory as branch test
1565 marked working directory as branch test
1566 (branches are permanent and global, did you want a bookmark?)
1566 (branches are permanent and global, did you want a bookmark?)
1567 $ echo "bbb" >> a
1567 $ echo "bbb" >> a
1568 $ hg status
1568 $ hg status
1569 M a
1569 M a
1570 $ hg shelve a
1570 $ hg shelve a
1571 shelved as default
1571 shelved as default
1572 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1572 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1573 $ hg branch
1573 $ hg branch
1574 test
1574 test
1575 $ hg branch default
1575 $ hg branch default
1576 marked working directory as branch default
1576 marked working directory as branch default
1577 (branches are permanent and global, did you want a bookmark?)
1577 (branches are permanent and global, did you want a bookmark?)
1578 $ echo "bbb" >> b
1578 $ echo "bbb" >> b
1579 $ hg status
1579 $ hg status
1580 ? b
1580 ? b
1581 $ hg unshelve
1581 $ hg unshelve
1582 unshelving change 'default'
1582 unshelving change 'default'
1583 $ hg status
1583 $ hg status
1584 M a
1584 M a
1585 ? b
1585 ? b
1586 $ hg branch
1586 $ hg branch
1587 default
1587 default
1588 $ cd ..
1588 $ cd ..
1589
1589
1590 Prepare unshleve with a corrupted shelvedstate
1590 Prepare unshleve with a corrupted shelvedstate
1591 $ hg init r1 && cd r1
1591 $ hg init r1 && cd r1
1592 $ echo text1 > file && hg add file
1592 $ echo text1 > file && hg add file
1593 $ hg shelve
1593 $ hg shelve
1594 shelved as default
1594 shelved as default
1595 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1595 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1596 $ echo text2 > file && hg ci -Am text1
1596 $ echo text2 > file && hg ci -Am text1
1597 adding file
1597 adding file
1598 $ hg unshelve
1598 $ hg unshelve
1599 unshelving change 'default'
1599 unshelving change 'default'
1600 rebasing shelved changes
1600 rebasing shelved changes
1601 rebasing 1:396ea74229f9 "(changes in empty repository)" (tip)
1601 rebasing 1:396ea74229f9 "(changes in empty repository)" (tip)
1602 merging file
1602 merging file
1603 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
1603 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
1604 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1604 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1605 [1]
1605 [1]
1606 $ echo somethingsomething > .hg/shelvedstate
1606 $ echo somethingsomething > .hg/shelvedstate
1607
1607
1608 Unshelve --continue fails with appropriate message if shelvedstate is corrupted
1608 Unshelve --continue fails with appropriate message if shelvedstate is corrupted
1609 $ hg unshelve --continue
1609 $ hg unshelve --continue
1610 abort: corrupted shelved state file
1610 abort: corrupted shelved state file
1611 (please run hg unshelve --abort to abort unshelve operation)
1611 (please run hg unshelve --abort to abort unshelve operation)
1612 [255]
1612 [255]
1613
1613
1614 Unshelve --abort works with a corrupted shelvedstate
1614 Unshelve --abort works with a corrupted shelvedstate
1615 $ hg unshelve --abort
1615 $ hg unshelve --abort
1616 could not read shelved state file, your working copy may be in an unexpected state
1616 could not read shelved state file, your working copy may be in an unexpected state
1617 please update to some commit
1617 please update to some commit
1618
1618
1619 Unshelve --abort fails with appropriate message if there's no unshelve in
1619 Unshelve --abort fails with appropriate message if there's no unshelve in
1620 progress
1620 progress
1621 $ hg unshelve --abort
1621 $ hg unshelve --abort
1622 abort: no unshelve in progress
1622 abort: no unshelve in progress
1623 [255]
1623 [255]
1624 $ cd ..
1624 $ cd ..
@@ -1,898 +1,898 b''
1 $ echo "[format]" >> $HGRCPATH
1 $ echo "[format]" >> $HGRCPATH
2 $ echo "usegeneraldelta=yes" >> $HGRCPATH
2 $ echo "usegeneraldelta=yes" >> $HGRCPATH
3 $ echo "[extensions]" >> $HGRCPATH
3 $ echo "[extensions]" >> $HGRCPATH
4 $ echo "strip=" >> $HGRCPATH
4 $ echo "strip=" >> $HGRCPATH
5
5
6 $ restore() {
6 $ restore() {
7 > hg unbundle -q .hg/strip-backup/*
7 > hg unbundle -q .hg/strip-backup/*
8 > rm .hg/strip-backup/*
8 > rm .hg/strip-backup/*
9 > }
9 > }
10 $ teststrip() {
10 $ teststrip() {
11 > hg up -C $1
11 > hg up -C $1
12 > echo % before update $1, strip $2
12 > echo % before update $1, strip $2
13 > hg parents
13 > hg parents
14 > hg --traceback strip $2
14 > hg --traceback strip $2
15 > echo % after update $1, strip $2
15 > echo % after update $1, strip $2
16 > hg parents
16 > hg parents
17 > restore
17 > restore
18 > }
18 > }
19
19
20 $ hg init test
20 $ hg init test
21 $ cd test
21 $ cd test
22
22
23 $ echo foo > bar
23 $ echo foo > bar
24 $ hg ci -Ama
24 $ hg ci -Ama
25 adding bar
25 adding bar
26
26
27 $ echo more >> bar
27 $ echo more >> bar
28 $ hg ci -Amb
28 $ hg ci -Amb
29
29
30 $ echo blah >> bar
30 $ echo blah >> bar
31 $ hg ci -Amc
31 $ hg ci -Amc
32
32
33 $ hg up 1
33 $ hg up 1
34 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
35 $ echo blah >> bar
35 $ echo blah >> bar
36 $ hg ci -Amd
36 $ hg ci -Amd
37 created new head
37 created new head
38
38
39 $ echo final >> bar
39 $ echo final >> bar
40 $ hg ci -Ame
40 $ hg ci -Ame
41
41
42 $ hg log
42 $ hg log
43 changeset: 4:443431ffac4f
43 changeset: 4:443431ffac4f
44 tag: tip
44 tag: tip
45 user: test
45 user: test
46 date: Thu Jan 01 00:00:00 1970 +0000
46 date: Thu Jan 01 00:00:00 1970 +0000
47 summary: e
47 summary: e
48
48
49 changeset: 3:65bd5f99a4a3
49 changeset: 3:65bd5f99a4a3
50 parent: 1:ef3a871183d7
50 parent: 1:ef3a871183d7
51 user: test
51 user: test
52 date: Thu Jan 01 00:00:00 1970 +0000
52 date: Thu Jan 01 00:00:00 1970 +0000
53 summary: d
53 summary: d
54
54
55 changeset: 2:264128213d29
55 changeset: 2:264128213d29
56 user: test
56 user: test
57 date: Thu Jan 01 00:00:00 1970 +0000
57 date: Thu Jan 01 00:00:00 1970 +0000
58 summary: c
58 summary: c
59
59
60 changeset: 1:ef3a871183d7
60 changeset: 1:ef3a871183d7
61 user: test
61 user: test
62 date: Thu Jan 01 00:00:00 1970 +0000
62 date: Thu Jan 01 00:00:00 1970 +0000
63 summary: b
63 summary: b
64
64
65 changeset: 0:9ab35a2d17cb
65 changeset: 0:9ab35a2d17cb
66 user: test
66 user: test
67 date: Thu Jan 01 00:00:00 1970 +0000
67 date: Thu Jan 01 00:00:00 1970 +0000
68 summary: a
68 summary: a
69
69
70
70
71 $ teststrip 4 4
71 $ teststrip 4 4
72 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
72 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
73 % before update 4, strip 4
73 % before update 4, strip 4
74 changeset: 4:443431ffac4f
74 changeset: 4:443431ffac4f
75 tag: tip
75 tag: tip
76 user: test
76 user: test
77 date: Thu Jan 01 00:00:00 1970 +0000
77 date: Thu Jan 01 00:00:00 1970 +0000
78 summary: e
78 summary: e
79
79
80 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
80 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
81 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
81 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
82 % after update 4, strip 4
82 % after update 4, strip 4
83 changeset: 3:65bd5f99a4a3
83 changeset: 3:65bd5f99a4a3
84 tag: tip
84 tag: tip
85 parent: 1:ef3a871183d7
85 parent: 1:ef3a871183d7
86 user: test
86 user: test
87 date: Thu Jan 01 00:00:00 1970 +0000
87 date: Thu Jan 01 00:00:00 1970 +0000
88 summary: d
88 summary: d
89
89
90 $ teststrip 4 3
90 $ teststrip 4 3
91 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 % before update 4, strip 3
92 % before update 4, strip 3
93 changeset: 4:443431ffac4f
93 changeset: 4:443431ffac4f
94 tag: tip
94 tag: tip
95 user: test
95 user: test
96 date: Thu Jan 01 00:00:00 1970 +0000
96 date: Thu Jan 01 00:00:00 1970 +0000
97 summary: e
97 summary: e
98
98
99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
100 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
101 % after update 4, strip 3
101 % after update 4, strip 3
102 changeset: 1:ef3a871183d7
102 changeset: 1:ef3a871183d7
103 user: test
103 user: test
104 date: Thu Jan 01 00:00:00 1970 +0000
104 date: Thu Jan 01 00:00:00 1970 +0000
105 summary: b
105 summary: b
106
106
107 $ teststrip 1 4
107 $ teststrip 1 4
108 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
108 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 % before update 1, strip 4
109 % before update 1, strip 4
110 changeset: 1:ef3a871183d7
110 changeset: 1:ef3a871183d7
111 user: test
111 user: test
112 date: Thu Jan 01 00:00:00 1970 +0000
112 date: Thu Jan 01 00:00:00 1970 +0000
113 summary: b
113 summary: b
114
114
115 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
115 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
116 % after update 1, strip 4
116 % after update 1, strip 4
117 changeset: 1:ef3a871183d7
117 changeset: 1:ef3a871183d7
118 user: test
118 user: test
119 date: Thu Jan 01 00:00:00 1970 +0000
119 date: Thu Jan 01 00:00:00 1970 +0000
120 summary: b
120 summary: b
121
121
122 $ teststrip 4 2
122 $ teststrip 4 2
123 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
123 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
124 % before update 4, strip 2
124 % before update 4, strip 2
125 changeset: 4:443431ffac4f
125 changeset: 4:443431ffac4f
126 tag: tip
126 tag: tip
127 user: test
127 user: test
128 date: Thu Jan 01 00:00:00 1970 +0000
128 date: Thu Jan 01 00:00:00 1970 +0000
129 summary: e
129 summary: e
130
130
131 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
131 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
132 % after update 4, strip 2
132 % after update 4, strip 2
133 changeset: 3:443431ffac4f
133 changeset: 3:443431ffac4f
134 tag: tip
134 tag: tip
135 user: test
135 user: test
136 date: Thu Jan 01 00:00:00 1970 +0000
136 date: Thu Jan 01 00:00:00 1970 +0000
137 summary: e
137 summary: e
138
138
139 $ teststrip 4 1
139 $ teststrip 4 1
140 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 % before update 4, strip 1
141 % before update 4, strip 1
142 changeset: 4:264128213d29
142 changeset: 4:264128213d29
143 tag: tip
143 tag: tip
144 parent: 1:ef3a871183d7
144 parent: 1:ef3a871183d7
145 user: test
145 user: test
146 date: Thu Jan 01 00:00:00 1970 +0000
146 date: Thu Jan 01 00:00:00 1970 +0000
147 summary: c
147 summary: c
148
148
149 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
149 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
150 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
150 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
151 % after update 4, strip 1
151 % after update 4, strip 1
152 changeset: 0:9ab35a2d17cb
152 changeset: 0:9ab35a2d17cb
153 tag: tip
153 tag: tip
154 user: test
154 user: test
155 date: Thu Jan 01 00:00:00 1970 +0000
155 date: Thu Jan 01 00:00:00 1970 +0000
156 summary: a
156 summary: a
157
157
158 $ teststrip null 4
158 $ teststrip null 4
159 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
159 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
160 % before update null, strip 4
160 % before update null, strip 4
161 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
161 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
162 % after update null, strip 4
162 % after update null, strip 4
163
163
164 $ hg log
164 $ hg log
165 changeset: 4:264128213d29
165 changeset: 4:264128213d29
166 tag: tip
166 tag: tip
167 parent: 1:ef3a871183d7
167 parent: 1:ef3a871183d7
168 user: test
168 user: test
169 date: Thu Jan 01 00:00:00 1970 +0000
169 date: Thu Jan 01 00:00:00 1970 +0000
170 summary: c
170 summary: c
171
171
172 changeset: 3:443431ffac4f
172 changeset: 3:443431ffac4f
173 user: test
173 user: test
174 date: Thu Jan 01 00:00:00 1970 +0000
174 date: Thu Jan 01 00:00:00 1970 +0000
175 summary: e
175 summary: e
176
176
177 changeset: 2:65bd5f99a4a3
177 changeset: 2:65bd5f99a4a3
178 user: test
178 user: test
179 date: Thu Jan 01 00:00:00 1970 +0000
179 date: Thu Jan 01 00:00:00 1970 +0000
180 summary: d
180 summary: d
181
181
182 changeset: 1:ef3a871183d7
182 changeset: 1:ef3a871183d7
183 user: test
183 user: test
184 date: Thu Jan 01 00:00:00 1970 +0000
184 date: Thu Jan 01 00:00:00 1970 +0000
185 summary: b
185 summary: b
186
186
187 changeset: 0:9ab35a2d17cb
187 changeset: 0:9ab35a2d17cb
188 user: test
188 user: test
189 date: Thu Jan 01 00:00:00 1970 +0000
189 date: Thu Jan 01 00:00:00 1970 +0000
190 summary: a
190 summary: a
191
191
192 $ hg up -C 4
192 $ hg up -C 4
193 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
193 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
194 $ hg parents
194 $ hg parents
195 changeset: 4:264128213d29
195 changeset: 4:264128213d29
196 tag: tip
196 tag: tip
197 parent: 1:ef3a871183d7
197 parent: 1:ef3a871183d7
198 user: test
198 user: test
199 date: Thu Jan 01 00:00:00 1970 +0000
199 date: Thu Jan 01 00:00:00 1970 +0000
200 summary: c
200 summary: c
201
201
202
202
203 $ hg --traceback strip 4
203 $ hg --traceback strip 4
204 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
204 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
205 saved backup bundle to $TESTTMP/test/.hg/strip-backup/264128213d29-0b39d6bf-backup.hg (glob)
205 saved backup bundle to $TESTTMP/test/.hg/strip-backup/264128213d29-0b39d6bf-backup.hg (glob)
206 $ hg parents
206 $ hg parents
207 changeset: 1:ef3a871183d7
207 changeset: 1:ef3a871183d7
208 user: test
208 user: test
209 date: Thu Jan 01 00:00:00 1970 +0000
209 date: Thu Jan 01 00:00:00 1970 +0000
210 summary: b
210 summary: b
211
211
212 $ hg debugbundle .hg/strip-backup/*
212 $ hg debugbundle .hg/strip-backup/*
213 Stream params: {'Compression': 'BZ'}
213 Stream params: sortdict([('Compression', 'BZ')])
214 changegroup -- "{'version': '02'}"
214 changegroup -- "sortdict([('version', '02')])"
215 264128213d290d868c54642d13aeaa3675551a78
215 264128213d290d868c54642d13aeaa3675551a78
216 $ hg pull .hg/strip-backup/*
216 $ hg pull .hg/strip-backup/*
217 pulling from .hg/strip-backup/264128213d29-0b39d6bf-backup.hg
217 pulling from .hg/strip-backup/264128213d29-0b39d6bf-backup.hg
218 searching for changes
218 searching for changes
219 adding changesets
219 adding changesets
220 adding manifests
220 adding manifests
221 adding file changes
221 adding file changes
222 added 1 changesets with 0 changes to 0 files (+1 heads)
222 added 1 changesets with 0 changes to 0 files (+1 heads)
223 (run 'hg heads' to see heads, 'hg merge' to merge)
223 (run 'hg heads' to see heads, 'hg merge' to merge)
224 $ rm .hg/strip-backup/*
224 $ rm .hg/strip-backup/*
225 $ hg log --graph
225 $ hg log --graph
226 o changeset: 4:264128213d29
226 o changeset: 4:264128213d29
227 | tag: tip
227 | tag: tip
228 | parent: 1:ef3a871183d7
228 | parent: 1:ef3a871183d7
229 | user: test
229 | user: test
230 | date: Thu Jan 01 00:00:00 1970 +0000
230 | date: Thu Jan 01 00:00:00 1970 +0000
231 | summary: c
231 | summary: c
232 |
232 |
233 | o changeset: 3:443431ffac4f
233 | o changeset: 3:443431ffac4f
234 | | user: test
234 | | user: test
235 | | date: Thu Jan 01 00:00:00 1970 +0000
235 | | date: Thu Jan 01 00:00:00 1970 +0000
236 | | summary: e
236 | | summary: e
237 | |
237 | |
238 | o changeset: 2:65bd5f99a4a3
238 | o changeset: 2:65bd5f99a4a3
239 |/ user: test
239 |/ user: test
240 | date: Thu Jan 01 00:00:00 1970 +0000
240 | date: Thu Jan 01 00:00:00 1970 +0000
241 | summary: d
241 | summary: d
242 |
242 |
243 @ changeset: 1:ef3a871183d7
243 @ changeset: 1:ef3a871183d7
244 | user: test
244 | user: test
245 | date: Thu Jan 01 00:00:00 1970 +0000
245 | date: Thu Jan 01 00:00:00 1970 +0000
246 | summary: b
246 | summary: b
247 |
247 |
248 o changeset: 0:9ab35a2d17cb
248 o changeset: 0:9ab35a2d17cb
249 user: test
249 user: test
250 date: Thu Jan 01 00:00:00 1970 +0000
250 date: Thu Jan 01 00:00:00 1970 +0000
251 summary: a
251 summary: a
252
252
253 $ hg up -C 2
253 $ hg up -C 2
254 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
254 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
255 $ hg merge 4
255 $ hg merge 4
256 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
256 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
257 (branch merge, don't forget to commit)
257 (branch merge, don't forget to commit)
258
258
259 before strip of merge parent
259 before strip of merge parent
260
260
261 $ hg parents
261 $ hg parents
262 changeset: 2:65bd5f99a4a3
262 changeset: 2:65bd5f99a4a3
263 user: test
263 user: test
264 date: Thu Jan 01 00:00:00 1970 +0000
264 date: Thu Jan 01 00:00:00 1970 +0000
265 summary: d
265 summary: d
266
266
267 changeset: 4:264128213d29
267 changeset: 4:264128213d29
268 tag: tip
268 tag: tip
269 parent: 1:ef3a871183d7
269 parent: 1:ef3a871183d7
270 user: test
270 user: test
271 date: Thu Jan 01 00:00:00 1970 +0000
271 date: Thu Jan 01 00:00:00 1970 +0000
272 summary: c
272 summary: c
273
273
274 $ hg strip 4
274 $ hg strip 4
275 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
275 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
276 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
276 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
277
277
278 after strip of merge parent
278 after strip of merge parent
279
279
280 $ hg parents
280 $ hg parents
281 changeset: 1:ef3a871183d7
281 changeset: 1:ef3a871183d7
282 user: test
282 user: test
283 date: Thu Jan 01 00:00:00 1970 +0000
283 date: Thu Jan 01 00:00:00 1970 +0000
284 summary: b
284 summary: b
285
285
286 $ restore
286 $ restore
287
287
288 $ hg up
288 $ hg up
289 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
289 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
290 1 other heads for branch "default"
290 1 other heads for branch "default"
291 $ hg log -G
291 $ hg log -G
292 @ changeset: 4:264128213d29
292 @ changeset: 4:264128213d29
293 | tag: tip
293 | tag: tip
294 | parent: 1:ef3a871183d7
294 | parent: 1:ef3a871183d7
295 | user: test
295 | user: test
296 | date: Thu Jan 01 00:00:00 1970 +0000
296 | date: Thu Jan 01 00:00:00 1970 +0000
297 | summary: c
297 | summary: c
298 |
298 |
299 | o changeset: 3:443431ffac4f
299 | o changeset: 3:443431ffac4f
300 | | user: test
300 | | user: test
301 | | date: Thu Jan 01 00:00:00 1970 +0000
301 | | date: Thu Jan 01 00:00:00 1970 +0000
302 | | summary: e
302 | | summary: e
303 | |
303 | |
304 | o changeset: 2:65bd5f99a4a3
304 | o changeset: 2:65bd5f99a4a3
305 |/ user: test
305 |/ user: test
306 | date: Thu Jan 01 00:00:00 1970 +0000
306 | date: Thu Jan 01 00:00:00 1970 +0000
307 | summary: d
307 | summary: d
308 |
308 |
309 o changeset: 1:ef3a871183d7
309 o changeset: 1:ef3a871183d7
310 | user: test
310 | user: test
311 | date: Thu Jan 01 00:00:00 1970 +0000
311 | date: Thu Jan 01 00:00:00 1970 +0000
312 | summary: b
312 | summary: b
313 |
313 |
314 o changeset: 0:9ab35a2d17cb
314 o changeset: 0:9ab35a2d17cb
315 user: test
315 user: test
316 date: Thu Jan 01 00:00:00 1970 +0000
316 date: Thu Jan 01 00:00:00 1970 +0000
317 summary: a
317 summary: a
318
318
319
319
320 2 is parent of 3, only one strip should happen
320 2 is parent of 3, only one strip should happen
321
321
322 $ hg strip "roots(2)" 3
322 $ hg strip "roots(2)" 3
323 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
323 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
324 $ hg log -G
324 $ hg log -G
325 @ changeset: 2:264128213d29
325 @ changeset: 2:264128213d29
326 | tag: tip
326 | tag: tip
327 | user: test
327 | user: test
328 | date: Thu Jan 01 00:00:00 1970 +0000
328 | date: Thu Jan 01 00:00:00 1970 +0000
329 | summary: c
329 | summary: c
330 |
330 |
331 o changeset: 1:ef3a871183d7
331 o changeset: 1:ef3a871183d7
332 | user: test
332 | user: test
333 | date: Thu Jan 01 00:00:00 1970 +0000
333 | date: Thu Jan 01 00:00:00 1970 +0000
334 | summary: b
334 | summary: b
335 |
335 |
336 o changeset: 0:9ab35a2d17cb
336 o changeset: 0:9ab35a2d17cb
337 user: test
337 user: test
338 date: Thu Jan 01 00:00:00 1970 +0000
338 date: Thu Jan 01 00:00:00 1970 +0000
339 summary: a
339 summary: a
340
340
341 $ restore
341 $ restore
342 $ hg log -G
342 $ hg log -G
343 o changeset: 4:443431ffac4f
343 o changeset: 4:443431ffac4f
344 | tag: tip
344 | tag: tip
345 | user: test
345 | user: test
346 | date: Thu Jan 01 00:00:00 1970 +0000
346 | date: Thu Jan 01 00:00:00 1970 +0000
347 | summary: e
347 | summary: e
348 |
348 |
349 o changeset: 3:65bd5f99a4a3
349 o changeset: 3:65bd5f99a4a3
350 | parent: 1:ef3a871183d7
350 | parent: 1:ef3a871183d7
351 | user: test
351 | user: test
352 | date: Thu Jan 01 00:00:00 1970 +0000
352 | date: Thu Jan 01 00:00:00 1970 +0000
353 | summary: d
353 | summary: d
354 |
354 |
355 | @ changeset: 2:264128213d29
355 | @ changeset: 2:264128213d29
356 |/ user: test
356 |/ user: test
357 | date: Thu Jan 01 00:00:00 1970 +0000
357 | date: Thu Jan 01 00:00:00 1970 +0000
358 | summary: c
358 | summary: c
359 |
359 |
360 o changeset: 1:ef3a871183d7
360 o changeset: 1:ef3a871183d7
361 | user: test
361 | user: test
362 | date: Thu Jan 01 00:00:00 1970 +0000
362 | date: Thu Jan 01 00:00:00 1970 +0000
363 | summary: b
363 | summary: b
364 |
364 |
365 o changeset: 0:9ab35a2d17cb
365 o changeset: 0:9ab35a2d17cb
366 user: test
366 user: test
367 date: Thu Jan 01 00:00:00 1970 +0000
367 date: Thu Jan 01 00:00:00 1970 +0000
368 summary: a
368 summary: a
369
369
370
370
371 2 different branches: 2 strips
371 2 different branches: 2 strips
372
372
373 $ hg strip 2 4
373 $ hg strip 2 4
374 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
374 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
375 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
375 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
376 $ hg log -G
376 $ hg log -G
377 o changeset: 2:65bd5f99a4a3
377 o changeset: 2:65bd5f99a4a3
378 | tag: tip
378 | tag: tip
379 | user: test
379 | user: test
380 | date: Thu Jan 01 00:00:00 1970 +0000
380 | date: Thu Jan 01 00:00:00 1970 +0000
381 | summary: d
381 | summary: d
382 |
382 |
383 @ changeset: 1:ef3a871183d7
383 @ changeset: 1:ef3a871183d7
384 | user: test
384 | user: test
385 | date: Thu Jan 01 00:00:00 1970 +0000
385 | date: Thu Jan 01 00:00:00 1970 +0000
386 | summary: b
386 | summary: b
387 |
387 |
388 o changeset: 0:9ab35a2d17cb
388 o changeset: 0:9ab35a2d17cb
389 user: test
389 user: test
390 date: Thu Jan 01 00:00:00 1970 +0000
390 date: Thu Jan 01 00:00:00 1970 +0000
391 summary: a
391 summary: a
392
392
393 $ restore
393 $ restore
394
394
395 2 different branches and a common ancestor: 1 strip
395 2 different branches and a common ancestor: 1 strip
396
396
397 $ hg strip 1 "2|4"
397 $ hg strip 1 "2|4"
398 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
398 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
399 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
399 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
400 $ restore
400 $ restore
401
401
402 verify fncache is kept up-to-date
402 verify fncache is kept up-to-date
403
403
404 $ touch a
404 $ touch a
405 $ hg ci -qAm a
405 $ hg ci -qAm a
406 $ cat .hg/store/fncache | sort
406 $ cat .hg/store/fncache | sort
407 data/a.i
407 data/a.i
408 data/bar.i
408 data/bar.i
409 $ hg strip tip
409 $ hg strip tip
410 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
410 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
411 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
411 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
412 $ cat .hg/store/fncache
412 $ cat .hg/store/fncache
413 data/bar.i
413 data/bar.i
414
414
415 stripping an empty revset
415 stripping an empty revset
416
416
417 $ hg strip "1 and not 1"
417 $ hg strip "1 and not 1"
418 abort: empty revision set
418 abort: empty revision set
419 [255]
419 [255]
420
420
421 remove branchy history for qimport tests
421 remove branchy history for qimport tests
422
422
423 $ hg strip 3
423 $ hg strip 3
424 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
424 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
425
425
426
426
427 strip of applied mq should cleanup status file
427 strip of applied mq should cleanup status file
428
428
429 $ echo "mq=" >> $HGRCPATH
429 $ echo "mq=" >> $HGRCPATH
430 $ hg up -C 3
430 $ hg up -C 3
431 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
431 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
432 $ echo fooagain >> bar
432 $ echo fooagain >> bar
433 $ hg ci -mf
433 $ hg ci -mf
434 $ hg qimport -r tip:2
434 $ hg qimport -r tip:2
435
435
436 applied patches before strip
436 applied patches before strip
437
437
438 $ hg qapplied
438 $ hg qapplied
439 d
439 d
440 e
440 e
441 f
441 f
442
442
443 stripping revision in queue
443 stripping revision in queue
444
444
445 $ hg strip 3
445 $ hg strip 3
446 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
446 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
447 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
447 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
448
448
449 applied patches after stripping rev in queue
449 applied patches after stripping rev in queue
450
450
451 $ hg qapplied
451 $ hg qapplied
452 d
452 d
453
453
454 stripping ancestor of queue
454 stripping ancestor of queue
455
455
456 $ hg strip 1
456 $ hg strip 1
457 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
457 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
458 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
458 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
459
459
460 applied patches after stripping ancestor of queue
460 applied patches after stripping ancestor of queue
461
461
462 $ hg qapplied
462 $ hg qapplied
463
463
464 Verify strip protects against stripping wc parent when there are uncommitted mods
464 Verify strip protects against stripping wc parent when there are uncommitted mods
465
465
466 $ echo b > b
466 $ echo b > b
467 $ echo bb > bar
467 $ echo bb > bar
468 $ hg add b
468 $ hg add b
469 $ hg ci -m 'b'
469 $ hg ci -m 'b'
470 $ hg log --graph
470 $ hg log --graph
471 @ changeset: 1:76dcf9fab855
471 @ changeset: 1:76dcf9fab855
472 | tag: tip
472 | tag: tip
473 | user: test
473 | user: test
474 | date: Thu Jan 01 00:00:00 1970 +0000
474 | date: Thu Jan 01 00:00:00 1970 +0000
475 | summary: b
475 | summary: b
476 |
476 |
477 o changeset: 0:9ab35a2d17cb
477 o changeset: 0:9ab35a2d17cb
478 user: test
478 user: test
479 date: Thu Jan 01 00:00:00 1970 +0000
479 date: Thu Jan 01 00:00:00 1970 +0000
480 summary: a
480 summary: a
481
481
482 $ hg up 0
482 $ hg up 0
483 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
483 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
484 $ echo c > bar
484 $ echo c > bar
485 $ hg up -t false
485 $ hg up -t false
486 merging bar
486 merging bar
487 merging bar failed!
487 merging bar failed!
488 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
488 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
489 use 'hg resolve' to retry unresolved file merges
489 use 'hg resolve' to retry unresolved file merges
490 [1]
490 [1]
491 $ hg sum
491 $ hg sum
492 parent: 1:76dcf9fab855 tip
492 parent: 1:76dcf9fab855 tip
493 b
493 b
494 branch: default
494 branch: default
495 commit: 1 modified, 1 unknown, 1 unresolved
495 commit: 1 modified, 1 unknown, 1 unresolved
496 update: (current)
496 update: (current)
497 phases: 2 draft
497 phases: 2 draft
498 mq: 3 unapplied
498 mq: 3 unapplied
499
499
500 $ echo c > b
500 $ echo c > b
501 $ hg strip tip
501 $ hg strip tip
502 abort: local changes found
502 abort: local changes found
503 [255]
503 [255]
504 $ hg strip tip --keep
504 $ hg strip tip --keep
505 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
505 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
506 $ hg log --graph
506 $ hg log --graph
507 @ changeset: 0:9ab35a2d17cb
507 @ changeset: 0:9ab35a2d17cb
508 tag: tip
508 tag: tip
509 user: test
509 user: test
510 date: Thu Jan 01 00:00:00 1970 +0000
510 date: Thu Jan 01 00:00:00 1970 +0000
511 summary: a
511 summary: a
512
512
513 $ hg status
513 $ hg status
514 M bar
514 M bar
515 ? b
515 ? b
516 ? bar.orig
516 ? bar.orig
517
517
518 $ rm bar.orig
518 $ rm bar.orig
519 $ hg sum
519 $ hg sum
520 parent: 0:9ab35a2d17cb tip
520 parent: 0:9ab35a2d17cb tip
521 a
521 a
522 branch: default
522 branch: default
523 commit: 1 modified, 1 unknown
523 commit: 1 modified, 1 unknown
524 update: (current)
524 update: (current)
525 phases: 1 draft
525 phases: 1 draft
526 mq: 3 unapplied
526 mq: 3 unapplied
527
527
528 Strip adds, removes, modifies with --keep
528 Strip adds, removes, modifies with --keep
529
529
530 $ touch b
530 $ touch b
531 $ hg add b
531 $ hg add b
532 $ hg commit -mb
532 $ hg commit -mb
533 $ touch c
533 $ touch c
534
534
535 ... with a clean working dir
535 ... with a clean working dir
536
536
537 $ hg add c
537 $ hg add c
538 $ hg rm bar
538 $ hg rm bar
539 $ hg commit -mc
539 $ hg commit -mc
540 $ hg status
540 $ hg status
541 $ hg strip --keep tip
541 $ hg strip --keep tip
542 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
542 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
543 $ hg status
543 $ hg status
544 ! bar
544 ! bar
545 ? c
545 ? c
546
546
547 ... with a dirty working dir
547 ... with a dirty working dir
548
548
549 $ hg add c
549 $ hg add c
550 $ hg rm bar
550 $ hg rm bar
551 $ hg commit -mc
551 $ hg commit -mc
552 $ hg status
552 $ hg status
553 $ echo b > b
553 $ echo b > b
554 $ echo d > d
554 $ echo d > d
555 $ hg strip --keep tip
555 $ hg strip --keep tip
556 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
556 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
557 $ hg status
557 $ hg status
558 M b
558 M b
559 ! bar
559 ! bar
560 ? c
560 ? c
561 ? d
561 ? d
562
562
563 ... after updating the dirstate
563 ... after updating the dirstate
564 $ hg add c
564 $ hg add c
565 $ hg commit -mc
565 $ hg commit -mc
566 $ hg rm c
566 $ hg rm c
567 $ hg commit -mc
567 $ hg commit -mc
568 $ hg strip --keep '.^' -q
568 $ hg strip --keep '.^' -q
569 $ cd ..
569 $ cd ..
570
570
571 stripping many nodes on a complex graph (issue3299)
571 stripping many nodes on a complex graph (issue3299)
572
572
573 $ hg init issue3299
573 $ hg init issue3299
574 $ cd issue3299
574 $ cd issue3299
575 $ hg debugbuilddag '@a.:a@b.:b.:x<a@a.:a<b@b.:b<a@a.:a'
575 $ hg debugbuilddag '@a.:a@b.:b.:x<a@a.:a<b@b.:b<a@a.:a'
576 $ hg strip 'not ancestors(x)'
576 $ hg strip 'not ancestors(x)'
577 saved backup bundle to $TESTTMP/issue3299/.hg/strip-backup/*-backup.hg (glob)
577 saved backup bundle to $TESTTMP/issue3299/.hg/strip-backup/*-backup.hg (glob)
578
578
579 test hg strip -B bookmark
579 test hg strip -B bookmark
580
580
581 $ cd ..
581 $ cd ..
582 $ hg init bookmarks
582 $ hg init bookmarks
583 $ cd bookmarks
583 $ cd bookmarks
584 $ hg debugbuilddag '..<2.*1/2:m<2+3:c<m+3:a<2.:b<m+2:d<2.:e<m+1:f'
584 $ hg debugbuilddag '..<2.*1/2:m<2+3:c<m+3:a<2.:b<m+2:d<2.:e<m+1:f'
585 $ hg bookmark -r 'a' 'todelete'
585 $ hg bookmark -r 'a' 'todelete'
586 $ hg bookmark -r 'b' 'B'
586 $ hg bookmark -r 'b' 'B'
587 $ hg bookmark -r 'b' 'nostrip'
587 $ hg bookmark -r 'b' 'nostrip'
588 $ hg bookmark -r 'c' 'delete'
588 $ hg bookmark -r 'c' 'delete'
589 $ hg bookmark -r 'd' 'multipledelete1'
589 $ hg bookmark -r 'd' 'multipledelete1'
590 $ hg bookmark -r 'e' 'multipledelete2'
590 $ hg bookmark -r 'e' 'multipledelete2'
591 $ hg bookmark -r 'f' 'singlenode1'
591 $ hg bookmark -r 'f' 'singlenode1'
592 $ hg bookmark -r 'f' 'singlenode2'
592 $ hg bookmark -r 'f' 'singlenode2'
593 $ hg up -C todelete
593 $ hg up -C todelete
594 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
594 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
595 (activating bookmark todelete)
595 (activating bookmark todelete)
596 $ hg strip -B nostrip
596 $ hg strip -B nostrip
597 bookmark 'nostrip' deleted
597 bookmark 'nostrip' deleted
598 abort: empty revision set
598 abort: empty revision set
599 [255]
599 [255]
600 $ hg strip -B todelete
600 $ hg strip -B todelete
601 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
601 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
602 saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
602 saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
603 bookmark 'todelete' deleted
603 bookmark 'todelete' deleted
604 $ hg id -ir dcbb326fdec2
604 $ hg id -ir dcbb326fdec2
605 abort: unknown revision 'dcbb326fdec2'!
605 abort: unknown revision 'dcbb326fdec2'!
606 [255]
606 [255]
607 $ hg id -ir d62d843c9a01
607 $ hg id -ir d62d843c9a01
608 d62d843c9a01
608 d62d843c9a01
609 $ hg bookmarks
609 $ hg bookmarks
610 B 9:ff43616e5d0f
610 B 9:ff43616e5d0f
611 delete 6:2702dd0c91e7
611 delete 6:2702dd0c91e7
612 multipledelete1 11:e46a4836065c
612 multipledelete1 11:e46a4836065c
613 multipledelete2 12:b4594d867745
613 multipledelete2 12:b4594d867745
614 singlenode1 13:43227190fef8
614 singlenode1 13:43227190fef8
615 singlenode2 13:43227190fef8
615 singlenode2 13:43227190fef8
616 $ hg strip -B multipledelete1 -B multipledelete2
616 $ hg strip -B multipledelete1 -B multipledelete2
617 saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/e46a4836065c-89ec65c2-backup.hg (glob)
617 saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/e46a4836065c-89ec65c2-backup.hg (glob)
618 bookmark 'multipledelete1' deleted
618 bookmark 'multipledelete1' deleted
619 bookmark 'multipledelete2' deleted
619 bookmark 'multipledelete2' deleted
620 $ hg id -ir e46a4836065c
620 $ hg id -ir e46a4836065c
621 abort: unknown revision 'e46a4836065c'!
621 abort: unknown revision 'e46a4836065c'!
622 [255]
622 [255]
623 $ hg id -ir b4594d867745
623 $ hg id -ir b4594d867745
624 abort: unknown revision 'b4594d867745'!
624 abort: unknown revision 'b4594d867745'!
625 [255]
625 [255]
626 $ hg strip -B singlenode1 -B singlenode2
626 $ hg strip -B singlenode1 -B singlenode2
627 saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/43227190fef8-8da858f2-backup.hg (glob)
627 saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/43227190fef8-8da858f2-backup.hg (glob)
628 bookmark 'singlenode1' deleted
628 bookmark 'singlenode1' deleted
629 bookmark 'singlenode2' deleted
629 bookmark 'singlenode2' deleted
630 $ hg id -ir 43227190fef8
630 $ hg id -ir 43227190fef8
631 abort: unknown revision '43227190fef8'!
631 abort: unknown revision '43227190fef8'!
632 [255]
632 [255]
633 $ hg strip -B unknownbookmark
633 $ hg strip -B unknownbookmark
634 abort: bookmark 'unknownbookmark' not found
634 abort: bookmark 'unknownbookmark' not found
635 [255]
635 [255]
636 $ hg strip -B unknownbookmark1 -B unknownbookmark2
636 $ hg strip -B unknownbookmark1 -B unknownbookmark2
637 abort: bookmark 'unknownbookmark1,unknownbookmark2' not found
637 abort: bookmark 'unknownbookmark1,unknownbookmark2' not found
638 [255]
638 [255]
639 $ hg strip -B delete -B unknownbookmark
639 $ hg strip -B delete -B unknownbookmark
640 abort: bookmark 'unknownbookmark' not found
640 abort: bookmark 'unknownbookmark' not found
641 [255]
641 [255]
642 $ hg strip -B delete
642 $ hg strip -B delete
643 saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
643 saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
644 bookmark 'delete' deleted
644 bookmark 'delete' deleted
645 $ hg id -ir 6:2702dd0c91e7
645 $ hg id -ir 6:2702dd0c91e7
646 abort: unknown revision '2702dd0c91e7'!
646 abort: unknown revision '2702dd0c91e7'!
647 [255]
647 [255]
648 $ hg update B
648 $ hg update B
649 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
649 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
650 (activating bookmark B)
650 (activating bookmark B)
651 $ echo a > a
651 $ echo a > a
652 $ hg add a
652 $ hg add a
653 $ hg strip -B B
653 $ hg strip -B B
654 abort: local changes found
654 abort: local changes found
655 [255]
655 [255]
656 $ hg bookmarks
656 $ hg bookmarks
657 * B 6:ff43616e5d0f
657 * B 6:ff43616e5d0f
658
658
659 Make sure no one adds back a -b option:
659 Make sure no one adds back a -b option:
660
660
661 $ hg strip -b tip
661 $ hg strip -b tip
662 hg strip: option -b not recognized
662 hg strip: option -b not recognized
663 hg strip [-k] [-f] [-B bookmark] [-r] REV...
663 hg strip [-k] [-f] [-B bookmark] [-r] REV...
664
664
665 strip changesets and all their descendants from the repository
665 strip changesets and all their descendants from the repository
666
666
667 (use "hg help -e strip" to show help for the strip extension)
667 (use "hg help -e strip" to show help for the strip extension)
668
668
669 options ([+] can be repeated):
669 options ([+] can be repeated):
670
670
671 -r --rev REV [+] strip specified revision (optional, can specify
671 -r --rev REV [+] strip specified revision (optional, can specify
672 revisions without this option)
672 revisions without this option)
673 -f --force force removal of changesets, discard uncommitted
673 -f --force force removal of changesets, discard uncommitted
674 changes (no backup)
674 changes (no backup)
675 --no-backup no backups
675 --no-backup no backups
676 -k --keep do not modify working directory during strip
676 -k --keep do not modify working directory during strip
677 -B --bookmark VALUE [+] remove revs only reachable from given bookmark
677 -B --bookmark VALUE [+] remove revs only reachable from given bookmark
678 --mq operate on patch repository
678 --mq operate on patch repository
679
679
680 (use "hg strip -h" to show more help)
680 (use "hg strip -h" to show more help)
681 [255]
681 [255]
682
682
683 $ cd ..
683 $ cd ..
684
684
685 Verify bundles don't get overwritten:
685 Verify bundles don't get overwritten:
686
686
687 $ hg init doublebundle
687 $ hg init doublebundle
688 $ cd doublebundle
688 $ cd doublebundle
689 $ touch a
689 $ touch a
690 $ hg commit -Aqm a
690 $ hg commit -Aqm a
691 $ touch b
691 $ touch b
692 $ hg commit -Aqm b
692 $ hg commit -Aqm b
693 $ hg strip -r 0
693 $ hg strip -r 0
694 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
694 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
695 saved backup bundle to $TESTTMP/doublebundle/.hg/strip-backup/3903775176ed-e68910bd-backup.hg (glob)
695 saved backup bundle to $TESTTMP/doublebundle/.hg/strip-backup/3903775176ed-e68910bd-backup.hg (glob)
696 $ ls .hg/strip-backup
696 $ ls .hg/strip-backup
697 3903775176ed-e68910bd-backup.hg
697 3903775176ed-e68910bd-backup.hg
698 $ hg pull -q -r 3903775176ed .hg/strip-backup/3903775176ed-e68910bd-backup.hg
698 $ hg pull -q -r 3903775176ed .hg/strip-backup/3903775176ed-e68910bd-backup.hg
699 $ hg strip -r 0
699 $ hg strip -r 0
700 saved backup bundle to $TESTTMP/doublebundle/.hg/strip-backup/3903775176ed-54390173-backup.hg (glob)
700 saved backup bundle to $TESTTMP/doublebundle/.hg/strip-backup/3903775176ed-54390173-backup.hg (glob)
701 $ ls .hg/strip-backup
701 $ ls .hg/strip-backup
702 3903775176ed-54390173-backup.hg
702 3903775176ed-54390173-backup.hg
703 3903775176ed-e68910bd-backup.hg
703 3903775176ed-e68910bd-backup.hg
704 $ cd ..
704 $ cd ..
705
705
706 Test that we only bundle the stripped changesets (issue4736)
706 Test that we only bundle the stripped changesets (issue4736)
707 ------------------------------------------------------------
707 ------------------------------------------------------------
708
708
709 initialization (previous repo is empty anyway)
709 initialization (previous repo is empty anyway)
710
710
711 $ hg init issue4736
711 $ hg init issue4736
712 $ cd issue4736
712 $ cd issue4736
713 $ echo a > a
713 $ echo a > a
714 $ hg add a
714 $ hg add a
715 $ hg commit -m commitA
715 $ hg commit -m commitA
716 $ echo b > b
716 $ echo b > b
717 $ hg add b
717 $ hg add b
718 $ hg commit -m commitB
718 $ hg commit -m commitB
719 $ echo c > c
719 $ echo c > c
720 $ hg add c
720 $ hg add c
721 $ hg commit -m commitC
721 $ hg commit -m commitC
722 $ hg up 'desc(commitB)'
722 $ hg up 'desc(commitB)'
723 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
723 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
724 $ echo d > d
724 $ echo d > d
725 $ hg add d
725 $ hg add d
726 $ hg commit -m commitD
726 $ hg commit -m commitD
727 created new head
727 created new head
728 $ hg up 'desc(commitC)'
728 $ hg up 'desc(commitC)'
729 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
729 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
730 $ hg merge 'desc(commitD)'
730 $ hg merge 'desc(commitD)'
731 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
731 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
732 (branch merge, don't forget to commit)
732 (branch merge, don't forget to commit)
733 $ hg ci -m 'mergeCD'
733 $ hg ci -m 'mergeCD'
734 $ hg log -G
734 $ hg log -G
735 @ changeset: 4:d8db9d137221
735 @ changeset: 4:d8db9d137221
736 |\ tag: tip
736 |\ tag: tip
737 | | parent: 2:5c51d8d6557d
737 | | parent: 2:5c51d8d6557d
738 | | parent: 3:6625a5168474
738 | | parent: 3:6625a5168474
739 | | user: test
739 | | user: test
740 | | date: Thu Jan 01 00:00:00 1970 +0000
740 | | date: Thu Jan 01 00:00:00 1970 +0000
741 | | summary: mergeCD
741 | | summary: mergeCD
742 | |
742 | |
743 | o changeset: 3:6625a5168474
743 | o changeset: 3:6625a5168474
744 | | parent: 1:eca11cf91c71
744 | | parent: 1:eca11cf91c71
745 | | user: test
745 | | user: test
746 | | date: Thu Jan 01 00:00:00 1970 +0000
746 | | date: Thu Jan 01 00:00:00 1970 +0000
747 | | summary: commitD
747 | | summary: commitD
748 | |
748 | |
749 o | changeset: 2:5c51d8d6557d
749 o | changeset: 2:5c51d8d6557d
750 |/ user: test
750 |/ user: test
751 | date: Thu Jan 01 00:00:00 1970 +0000
751 | date: Thu Jan 01 00:00:00 1970 +0000
752 | summary: commitC
752 | summary: commitC
753 |
753 |
754 o changeset: 1:eca11cf91c71
754 o changeset: 1:eca11cf91c71
755 | user: test
755 | user: test
756 | date: Thu Jan 01 00:00:00 1970 +0000
756 | date: Thu Jan 01 00:00:00 1970 +0000
757 | summary: commitB
757 | summary: commitB
758 |
758 |
759 o changeset: 0:105141ef12d0
759 o changeset: 0:105141ef12d0
760 user: test
760 user: test
761 date: Thu Jan 01 00:00:00 1970 +0000
761 date: Thu Jan 01 00:00:00 1970 +0000
762 summary: commitA
762 summary: commitA
763
763
764
764
765 Check bundle behavior:
765 Check bundle behavior:
766
766
767 $ hg bundle -r 'desc(mergeCD)' --base 'desc(commitC)' ../issue4736.hg
767 $ hg bundle -r 'desc(mergeCD)' --base 'desc(commitC)' ../issue4736.hg
768 2 changesets found
768 2 changesets found
769 $ hg log -r 'bundle()' -R ../issue4736.hg
769 $ hg log -r 'bundle()' -R ../issue4736.hg
770 changeset: 3:6625a5168474
770 changeset: 3:6625a5168474
771 parent: 1:eca11cf91c71
771 parent: 1:eca11cf91c71
772 user: test
772 user: test
773 date: Thu Jan 01 00:00:00 1970 +0000
773 date: Thu Jan 01 00:00:00 1970 +0000
774 summary: commitD
774 summary: commitD
775
775
776 changeset: 4:d8db9d137221
776 changeset: 4:d8db9d137221
777 tag: tip
777 tag: tip
778 parent: 2:5c51d8d6557d
778 parent: 2:5c51d8d6557d
779 parent: 3:6625a5168474
779 parent: 3:6625a5168474
780 user: test
780 user: test
781 date: Thu Jan 01 00:00:00 1970 +0000
781 date: Thu Jan 01 00:00:00 1970 +0000
782 summary: mergeCD
782 summary: mergeCD
783
783
784
784
785 check strip behavior
785 check strip behavior
786
786
787 $ hg --config extensions.strip= strip 'desc(commitD)' --debug
787 $ hg --config extensions.strip= strip 'desc(commitD)' --debug
788 resolving manifests
788 resolving manifests
789 branchmerge: False, force: True, partial: False
789 branchmerge: False, force: True, partial: False
790 ancestor: d8db9d137221+, local: d8db9d137221+, remote: eca11cf91c71
790 ancestor: d8db9d137221+, local: d8db9d137221+, remote: eca11cf91c71
791 c: other deleted -> r
791 c: other deleted -> r
792 removing c
792 removing c
793 d: other deleted -> r
793 d: other deleted -> r
794 removing d
794 removing d
795 starting 4 threads for background file closing (?)
795 starting 4 threads for background file closing (?)
796 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
796 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
797 2 changesets found
797 2 changesets found
798 list of changesets:
798 list of changesets:
799 6625a516847449b6f0fa3737b9ba56e9f0f3032c
799 6625a516847449b6f0fa3737b9ba56e9f0f3032c
800 d8db9d1372214336d2b5570f20ee468d2c72fa8b
800 d8db9d1372214336d2b5570f20ee468d2c72fa8b
801 bundle2-output-bundle: "HG20", (1 params) 1 parts total
801 bundle2-output-bundle: "HG20", (1 params) 1 parts total
802 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
802 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
803 saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/6625a5168474-345bb43d-backup.hg (glob)
803 saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/6625a5168474-345bb43d-backup.hg (glob)
804 invalid branchheads cache (served): tip differs
804 invalid branchheads cache (served): tip differs
805 truncating cache/rbc-revs-v1 to 24
805 truncating cache/rbc-revs-v1 to 24
806 $ hg log -G
806 $ hg log -G
807 o changeset: 2:5c51d8d6557d
807 o changeset: 2:5c51d8d6557d
808 | tag: tip
808 | tag: tip
809 | user: test
809 | user: test
810 | date: Thu Jan 01 00:00:00 1970 +0000
810 | date: Thu Jan 01 00:00:00 1970 +0000
811 | summary: commitC
811 | summary: commitC
812 |
812 |
813 @ changeset: 1:eca11cf91c71
813 @ changeset: 1:eca11cf91c71
814 | user: test
814 | user: test
815 | date: Thu Jan 01 00:00:00 1970 +0000
815 | date: Thu Jan 01 00:00:00 1970 +0000
816 | summary: commitB
816 | summary: commitB
817 |
817 |
818 o changeset: 0:105141ef12d0
818 o changeset: 0:105141ef12d0
819 user: test
819 user: test
820 date: Thu Jan 01 00:00:00 1970 +0000
820 date: Thu Jan 01 00:00:00 1970 +0000
821 summary: commitA
821 summary: commitA
822
822
823
823
824 strip backup content
824 strip backup content
825
825
826 $ hg log -r 'bundle()' -R .hg/strip-backup/6625a5168474-*-backup.hg
826 $ hg log -r 'bundle()' -R .hg/strip-backup/6625a5168474-*-backup.hg
827 changeset: 3:6625a5168474
827 changeset: 3:6625a5168474
828 parent: 1:eca11cf91c71
828 parent: 1:eca11cf91c71
829 user: test
829 user: test
830 date: Thu Jan 01 00:00:00 1970 +0000
830 date: Thu Jan 01 00:00:00 1970 +0000
831 summary: commitD
831 summary: commitD
832
832
833 changeset: 4:d8db9d137221
833 changeset: 4:d8db9d137221
834 tag: tip
834 tag: tip
835 parent: 2:5c51d8d6557d
835 parent: 2:5c51d8d6557d
836 parent: 3:6625a5168474
836 parent: 3:6625a5168474
837 user: test
837 user: test
838 date: Thu Jan 01 00:00:00 1970 +0000
838 date: Thu Jan 01 00:00:00 1970 +0000
839 summary: mergeCD
839 summary: mergeCD
840
840
841 Check that the phase cache is properly invalidated after a strip with bookmark.
841 Check that the phase cache is properly invalidated after a strip with bookmark.
842
842
843 $ cat > ../stripstalephasecache.py << EOF
843 $ cat > ../stripstalephasecache.py << EOF
844 > from mercurial import extensions, localrepo
844 > from mercurial import extensions, localrepo
845 > def transactioncallback(orig, repo, desc, *args, **kwargs):
845 > def transactioncallback(orig, repo, desc, *args, **kwargs):
846 > def test(transaction):
846 > def test(transaction):
847 > # observe cache inconsistency
847 > # observe cache inconsistency
848 > try:
848 > try:
849 > [repo.changelog.node(r) for r in repo.revs("not public()")]
849 > [repo.changelog.node(r) for r in repo.revs("not public()")]
850 > except IndexError:
850 > except IndexError:
851 > repo.ui.status("Index error!\n")
851 > repo.ui.status("Index error!\n")
852 > transaction = orig(repo, desc, *args, **kwargs)
852 > transaction = orig(repo, desc, *args, **kwargs)
853 > # warm up the phase cache
853 > # warm up the phase cache
854 > list(repo.revs("not public()"))
854 > list(repo.revs("not public()"))
855 > if desc != 'strip':
855 > if desc != 'strip':
856 > transaction.addpostclose("phase invalidation test", test)
856 > transaction.addpostclose("phase invalidation test", test)
857 > return transaction
857 > return transaction
858 > def extsetup(ui):
858 > def extsetup(ui):
859 > extensions.wrapfunction(localrepo.localrepository, "transaction",
859 > extensions.wrapfunction(localrepo.localrepository, "transaction",
860 > transactioncallback)
860 > transactioncallback)
861 > EOF
861 > EOF
862 $ hg up -C 2
862 $ hg up -C 2
863 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
863 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
864 $ echo k > k
864 $ echo k > k
865 $ hg add k
865 $ hg add k
866 $ hg commit -m commitK
866 $ hg commit -m commitK
867 $ echo l > l
867 $ echo l > l
868 $ hg add l
868 $ hg add l
869 $ hg commit -m commitL
869 $ hg commit -m commitL
870 $ hg book -r tip blah
870 $ hg book -r tip blah
871 $ hg strip ".^" --config extensions.crash=$TESTTMP/stripstalephasecache.py
871 $ hg strip ".^" --config extensions.crash=$TESTTMP/stripstalephasecache.py
872 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
872 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
873 saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/8f0b4384875c-4fa10deb-backup.hg (glob)
873 saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/8f0b4384875c-4fa10deb-backup.hg (glob)
874 $ hg up -C 1
874 $ hg up -C 1
875 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
875 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
876
876
877 Error during post-close callback of the strip transaction
877 Error during post-close callback of the strip transaction
878 (They should be gracefully handled and reported)
878 (They should be gracefully handled and reported)
879
879
880 $ cat > ../crashstrip.py << EOF
880 $ cat > ../crashstrip.py << EOF
881 > from mercurial import error
881 > from mercurial import error
882 > def reposetup(ui, repo):
882 > def reposetup(ui, repo):
883 > class crashstriprepo(repo.__class__):
883 > class crashstriprepo(repo.__class__):
884 > def transaction(self, desc, *args, **kwargs):
884 > def transaction(self, desc, *args, **kwargs):
885 > tr = super(crashstriprepo, self).transaction(self, desc, *args, **kwargs)
885 > tr = super(crashstriprepo, self).transaction(self, desc, *args, **kwargs)
886 > if desc == 'strip':
886 > if desc == 'strip':
887 > def crash(tra): raise error.Abort('boom')
887 > def crash(tra): raise error.Abort('boom')
888 > tr.addpostclose('crash', crash)
888 > tr.addpostclose('crash', crash)
889 > return tr
889 > return tr
890 > repo.__class__ = crashstriprepo
890 > repo.__class__ = crashstriprepo
891 > EOF
891 > EOF
892 $ hg strip tip --config extensions.crash=$TESTTMP/crashstrip.py
892 $ hg strip tip --config extensions.crash=$TESTTMP/crashstrip.py
893 saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/5c51d8d6557d-70daef06-backup.hg (glob)
893 saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/5c51d8d6557d-70daef06-backup.hg (glob)
894 strip failed, full bundle stored in '$TESTTMP/issue4736/.hg/strip-backup/5c51d8d6557d-70daef06-backup.hg' (glob)
894 strip failed, full bundle stored in '$TESTTMP/issue4736/.hg/strip-backup/5c51d8d6557d-70daef06-backup.hg' (glob)
895 abort: boom
895 abort: boom
896 [255]
896 [255]
897
897
898
898
General Comments 0
You need to be logged in to leave comments. Login now