##// END OF EJS Templates
push: add "remote" to 'repository changed while pushing' messages (issue5971)...
Taapas Agrawal -
r40182:58ebf508 default
parent child Browse files
Show More
@@ -1,2302 +1,2302
1 # bundle2.py - generic container format to transmit arbitrary data.
1 # bundle2.py - generic container format to transmit arbitrary data.
2 #
2 #
3 # Copyright 2013 Facebook, Inc.
3 # Copyright 2013 Facebook, Inc.
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7 """Handling of the new bundle2 format
7 """Handling of the new bundle2 format
8
8
9 The goal of bundle2 is to act as an atomically packet to transmit a set of
9 The goal of bundle2 is to act as an atomically packet to transmit a set of
10 payloads in an application agnostic way. It consist in a sequence of "parts"
10 payloads in an application agnostic way. It consist in a sequence of "parts"
11 that will be handed to and processed by the application layer.
11 that will be handed to and processed by the application layer.
12
12
13
13
14 General format architecture
14 General format architecture
15 ===========================
15 ===========================
16
16
17 The format is architectured as follow
17 The format is architectured as follow
18
18
19 - magic string
19 - magic string
20 - stream level parameters
20 - stream level parameters
21 - payload parts (any number)
21 - payload parts (any number)
22 - end of stream marker.
22 - end of stream marker.
23
23
24 the Binary format
24 the Binary format
25 ============================
25 ============================
26
26
27 All numbers are unsigned and big-endian.
27 All numbers are unsigned and big-endian.
28
28
29 stream level parameters
29 stream level parameters
30 ------------------------
30 ------------------------
31
31
32 Binary format is as follow
32 Binary format is as follow
33
33
34 :params size: int32
34 :params size: int32
35
35
36 The total number of Bytes used by the parameters
36 The total number of Bytes used by the parameters
37
37
38 :params value: arbitrary number of Bytes
38 :params value: arbitrary number of Bytes
39
39
40 A blob of `params size` containing the serialized version of all stream level
40 A blob of `params size` containing the serialized version of all stream level
41 parameters.
41 parameters.
42
42
43 The blob contains a space separated list of parameters. Parameters with value
43 The blob contains a space separated list of parameters. Parameters with value
44 are stored in the form `<name>=<value>`. Both name and value are urlquoted.
44 are stored in the form `<name>=<value>`. Both name and value are urlquoted.
45
45
46 Empty name are obviously forbidden.
46 Empty name are obviously forbidden.
47
47
48 Name MUST start with a letter. If this first letter is lower case, the
48 Name MUST start with a letter. If this first letter is lower case, the
49 parameter is advisory and can be safely ignored. However when the first
49 parameter is advisory and can be safely ignored. However when the first
50 letter is capital, the parameter is mandatory and the bundling process MUST
50 letter is capital, the parameter is mandatory and the bundling process MUST
51 stop if he is not able to proceed it.
51 stop if he is not able to proceed it.
52
52
53 Stream parameters use a simple textual format for two main reasons:
53 Stream parameters use a simple textual format for two main reasons:
54
54
55 - Stream level parameters should remain simple and we want to discourage any
55 - Stream level parameters should remain simple and we want to discourage any
56 crazy usage.
56 crazy usage.
57 - Textual data allow easy human inspection of a bundle2 header in case of
57 - Textual data allow easy human inspection of a bundle2 header in case of
58 troubles.
58 troubles.
59
59
60 Any Applicative level options MUST go into a bundle2 part instead.
60 Any Applicative level options MUST go into a bundle2 part instead.
61
61
62 Payload part
62 Payload part
63 ------------------------
63 ------------------------
64
64
65 Binary format is as follow
65 Binary format is as follow
66
66
67 :header size: int32
67 :header size: int32
68
68
69 The total number of Bytes used by the part header. When the header is empty
69 The total number of Bytes used by the part header. When the header is empty
70 (size = 0) this is interpreted as the end of stream marker.
70 (size = 0) this is interpreted as the end of stream marker.
71
71
72 :header:
72 :header:
73
73
74 The header defines how to interpret the part. It contains two piece of
74 The header defines how to interpret the part. It contains two piece of
75 data: the part type, and the part parameters.
75 data: the part type, and the part parameters.
76
76
77 The part type is used to route an application level handler, that can
77 The part type is used to route an application level handler, that can
78 interpret payload.
78 interpret payload.
79
79
80 Part parameters are passed to the application level handler. They are
80 Part parameters are passed to the application level handler. They are
81 meant to convey information that will help the application level object to
81 meant to convey information that will help the application level object to
82 interpret the part payload.
82 interpret the part payload.
83
83
84 The binary format of the header is has follow
84 The binary format of the header is has follow
85
85
86 :typesize: (one byte)
86 :typesize: (one byte)
87
87
88 :parttype: alphanumerical part name (restricted to [a-zA-Z0-9_:-]*)
88 :parttype: alphanumerical part name (restricted to [a-zA-Z0-9_:-]*)
89
89
90 :partid: A 32bits integer (unique in the bundle) that can be used to refer
90 :partid: A 32bits integer (unique in the bundle) that can be used to refer
91 to this part.
91 to this part.
92
92
93 :parameters:
93 :parameters:
94
94
95 Part's parameter may have arbitrary content, the binary structure is::
95 Part's parameter may have arbitrary content, the binary structure is::
96
96
97 <mandatory-count><advisory-count><param-sizes><param-data>
97 <mandatory-count><advisory-count><param-sizes><param-data>
98
98
99 :mandatory-count: 1 byte, number of mandatory parameters
99 :mandatory-count: 1 byte, number of mandatory parameters
100
100
101 :advisory-count: 1 byte, number of advisory parameters
101 :advisory-count: 1 byte, number of advisory parameters
102
102
103 :param-sizes:
103 :param-sizes:
104
104
105 N couple of bytes, where N is the total number of parameters. Each
105 N couple of bytes, where N is the total number of parameters. Each
106 couple contains (<size-of-key>, <size-of-value) for one parameter.
106 couple contains (<size-of-key>, <size-of-value) for one parameter.
107
107
108 :param-data:
108 :param-data:
109
109
110 A blob of bytes from which each parameter key and value can be
110 A blob of bytes from which each parameter key and value can be
111 retrieved using the list of size couples stored in the previous
111 retrieved using the list of size couples stored in the previous
112 field.
112 field.
113
113
114 Mandatory parameters comes first, then the advisory ones.
114 Mandatory parameters comes first, then the advisory ones.
115
115
116 Each parameter's key MUST be unique within the part.
116 Each parameter's key MUST be unique within the part.
117
117
118 :payload:
118 :payload:
119
119
120 payload is a series of `<chunksize><chunkdata>`.
120 payload is a series of `<chunksize><chunkdata>`.
121
121
122 `chunksize` is an int32, `chunkdata` are plain bytes (as much as
122 `chunksize` is an int32, `chunkdata` are plain bytes (as much as
123 `chunksize` says)` The payload part is concluded by a zero size chunk.
123 `chunksize` says)` The payload part is concluded by a zero size chunk.
124
124
125 The current implementation always produces either zero or one chunk.
125 The current implementation always produces either zero or one chunk.
126 This is an implementation limitation that will ultimately be lifted.
126 This is an implementation limitation that will ultimately be lifted.
127
127
128 `chunksize` can be negative to trigger special case processing. No such
128 `chunksize` can be negative to trigger special case processing. No such
129 processing is in place yet.
129 processing is in place yet.
130
130
131 Bundle processing
131 Bundle processing
132 ============================
132 ============================
133
133
134 Each part is processed in order using a "part handler". Handler are registered
134 Each part is processed in order using a "part handler". Handler are registered
135 for a certain part type.
135 for a certain part type.
136
136
137 The matching of a part to its handler is case insensitive. The case of the
137 The matching of a part to its handler is case insensitive. The case of the
138 part type is used to know if a part is mandatory or advisory. If the Part type
138 part type is used to know if a part is mandatory or advisory. If the Part type
139 contains any uppercase char it is considered mandatory. When no handler is
139 contains any uppercase char it is considered mandatory. When no handler is
140 known for a Mandatory part, the process is aborted and an exception is raised.
140 known for a Mandatory part, the process is aborted and an exception is raised.
141 If the part is advisory and no handler is known, the part is ignored. When the
141 If the part is advisory and no handler is known, the part is ignored. When the
142 process is aborted, the full bundle is still read from the stream to keep the
142 process is aborted, the full bundle is still read from the stream to keep the
143 channel usable. But none of the part read from an abort are processed. In the
143 channel usable. But none of the part read from an abort are processed. In the
144 future, dropping the stream may become an option for channel we do not care to
144 future, dropping the stream may become an option for channel we do not care to
145 preserve.
145 preserve.
146 """
146 """
147
147
148 from __future__ import absolute_import, division
148 from __future__ import absolute_import, division
149
149
150 import collections
150 import collections
151 import errno
151 import errno
152 import os
152 import os
153 import re
153 import re
154 import string
154 import string
155 import struct
155 import struct
156 import sys
156 import sys
157
157
158 from .i18n import _
158 from .i18n import _
159 from . import (
159 from . import (
160 bookmarks,
160 bookmarks,
161 changegroup,
161 changegroup,
162 encoding,
162 encoding,
163 error,
163 error,
164 node as nodemod,
164 node as nodemod,
165 obsolete,
165 obsolete,
166 phases,
166 phases,
167 pushkey,
167 pushkey,
168 pycompat,
168 pycompat,
169 streamclone,
169 streamclone,
170 tags,
170 tags,
171 url,
171 url,
172 util,
172 util,
173 )
173 )
174 from .utils import (
174 from .utils import (
175 stringutil,
175 stringutil,
176 )
176 )
177
177
178 urlerr = util.urlerr
178 urlerr = util.urlerr
179 urlreq = util.urlreq
179 urlreq = util.urlreq
180
180
181 _pack = struct.pack
181 _pack = struct.pack
182 _unpack = struct.unpack
182 _unpack = struct.unpack
183
183
184 _fstreamparamsize = '>i'
184 _fstreamparamsize = '>i'
185 _fpartheadersize = '>i'
185 _fpartheadersize = '>i'
186 _fparttypesize = '>B'
186 _fparttypesize = '>B'
187 _fpartid = '>I'
187 _fpartid = '>I'
188 _fpayloadsize = '>i'
188 _fpayloadsize = '>i'
189 _fpartparamcount = '>BB'
189 _fpartparamcount = '>BB'
190
190
191 preferedchunksize = 32768
191 preferedchunksize = 32768
192
192
193 _parttypeforbidden = re.compile('[^a-zA-Z0-9_:-]')
193 _parttypeforbidden = re.compile('[^a-zA-Z0-9_:-]')
194
194
195 def outdebug(ui, message):
195 def outdebug(ui, message):
196 """debug regarding output stream (bundling)"""
196 """debug regarding output stream (bundling)"""
197 if ui.configbool('devel', 'bundle2.debug'):
197 if ui.configbool('devel', 'bundle2.debug'):
198 ui.debug('bundle2-output: %s\n' % message)
198 ui.debug('bundle2-output: %s\n' % message)
199
199
200 def indebug(ui, message):
200 def indebug(ui, message):
201 """debug on input stream (unbundling)"""
201 """debug on input stream (unbundling)"""
202 if ui.configbool('devel', 'bundle2.debug'):
202 if ui.configbool('devel', 'bundle2.debug'):
203 ui.debug('bundle2-input: %s\n' % message)
203 ui.debug('bundle2-input: %s\n' % message)
204
204
205 def validateparttype(parttype):
205 def validateparttype(parttype):
206 """raise ValueError if a parttype contains invalid character"""
206 """raise ValueError if a parttype contains invalid character"""
207 if _parttypeforbidden.search(parttype):
207 if _parttypeforbidden.search(parttype):
208 raise ValueError(parttype)
208 raise ValueError(parttype)
209
209
210 def _makefpartparamsizes(nbparams):
210 def _makefpartparamsizes(nbparams):
211 """return a struct format to read part parameter sizes
211 """return a struct format to read part parameter sizes
212
212
213 The number parameters is variable so we need to build that format
213 The number parameters is variable so we need to build that format
214 dynamically.
214 dynamically.
215 """
215 """
216 return '>'+('BB'*nbparams)
216 return '>'+('BB'*nbparams)
217
217
218 parthandlermapping = {}
218 parthandlermapping = {}
219
219
220 def parthandler(parttype, params=()):
220 def parthandler(parttype, params=()):
221 """decorator that register a function as a bundle2 part handler
221 """decorator that register a function as a bundle2 part handler
222
222
223 eg::
223 eg::
224
224
225 @parthandler('myparttype', ('mandatory', 'param', 'handled'))
225 @parthandler('myparttype', ('mandatory', 'param', 'handled'))
226 def myparttypehandler(...):
226 def myparttypehandler(...):
227 '''process a part of type "my part".'''
227 '''process a part of type "my part".'''
228 ...
228 ...
229 """
229 """
230 validateparttype(parttype)
230 validateparttype(parttype)
231 def _decorator(func):
231 def _decorator(func):
232 lparttype = parttype.lower() # enforce lower case matching.
232 lparttype = parttype.lower() # enforce lower case matching.
233 assert lparttype not in parthandlermapping
233 assert lparttype not in parthandlermapping
234 parthandlermapping[lparttype] = func
234 parthandlermapping[lparttype] = func
235 func.params = frozenset(params)
235 func.params = frozenset(params)
236 return func
236 return func
237 return _decorator
237 return _decorator
238
238
239 class unbundlerecords(object):
239 class unbundlerecords(object):
240 """keep record of what happens during and unbundle
240 """keep record of what happens during and unbundle
241
241
242 New records are added using `records.add('cat', obj)`. Where 'cat' is a
242 New records are added using `records.add('cat', obj)`. Where 'cat' is a
243 category of record and obj is an arbitrary object.
243 category of record and obj is an arbitrary object.
244
244
245 `records['cat']` will return all entries of this category 'cat'.
245 `records['cat']` will return all entries of this category 'cat'.
246
246
247 Iterating on the object itself will yield `('category', obj)` tuples
247 Iterating on the object itself will yield `('category', obj)` tuples
248 for all entries.
248 for all entries.
249
249
250 All iterations happens in chronological order.
250 All iterations happens in chronological order.
251 """
251 """
252
252
253 def __init__(self):
253 def __init__(self):
254 self._categories = {}
254 self._categories = {}
255 self._sequences = []
255 self._sequences = []
256 self._replies = {}
256 self._replies = {}
257
257
258 def add(self, category, entry, inreplyto=None):
258 def add(self, category, entry, inreplyto=None):
259 """add a new record of a given category.
259 """add a new record of a given category.
260
260
261 The entry can then be retrieved in the list returned by
261 The entry can then be retrieved in the list returned by
262 self['category']."""
262 self['category']."""
263 self._categories.setdefault(category, []).append(entry)
263 self._categories.setdefault(category, []).append(entry)
264 self._sequences.append((category, entry))
264 self._sequences.append((category, entry))
265 if inreplyto is not None:
265 if inreplyto is not None:
266 self.getreplies(inreplyto).add(category, entry)
266 self.getreplies(inreplyto).add(category, entry)
267
267
268 def getreplies(self, partid):
268 def getreplies(self, partid):
269 """get the records that are replies to a specific part"""
269 """get the records that are replies to a specific part"""
270 return self._replies.setdefault(partid, unbundlerecords())
270 return self._replies.setdefault(partid, unbundlerecords())
271
271
272 def __getitem__(self, cat):
272 def __getitem__(self, cat):
273 return tuple(self._categories.get(cat, ()))
273 return tuple(self._categories.get(cat, ()))
274
274
275 def __iter__(self):
275 def __iter__(self):
276 return iter(self._sequences)
276 return iter(self._sequences)
277
277
278 def __len__(self):
278 def __len__(self):
279 return len(self._sequences)
279 return len(self._sequences)
280
280
281 def __nonzero__(self):
281 def __nonzero__(self):
282 return bool(self._sequences)
282 return bool(self._sequences)
283
283
284 __bool__ = __nonzero__
284 __bool__ = __nonzero__
285
285
286 class bundleoperation(object):
286 class bundleoperation(object):
287 """an object that represents a single bundling process
287 """an object that represents a single bundling process
288
288
289 Its purpose is to carry unbundle-related objects and states.
289 Its purpose is to carry unbundle-related objects and states.
290
290
291 A new object should be created at the beginning of each bundle processing.
291 A new object should be created at the beginning of each bundle processing.
292 The object is to be returned by the processing function.
292 The object is to be returned by the processing function.
293
293
294 The object has very little content now it will ultimately contain:
294 The object has very little content now it will ultimately contain:
295 * an access to the repo the bundle is applied to,
295 * an access to the repo the bundle is applied to,
296 * a ui object,
296 * a ui object,
297 * a way to retrieve a transaction to add changes to the repo,
297 * a way to retrieve a transaction to add changes to the repo,
298 * a way to record the result of processing each part,
298 * a way to record the result of processing each part,
299 * a way to construct a bundle response when applicable.
299 * a way to construct a bundle response when applicable.
300 """
300 """
301
301
302 def __init__(self, repo, transactiongetter, captureoutput=True, source=''):
302 def __init__(self, repo, transactiongetter, captureoutput=True, source=''):
303 self.repo = repo
303 self.repo = repo
304 self.ui = repo.ui
304 self.ui = repo.ui
305 self.records = unbundlerecords()
305 self.records = unbundlerecords()
306 self.reply = None
306 self.reply = None
307 self.captureoutput = captureoutput
307 self.captureoutput = captureoutput
308 self.hookargs = {}
308 self.hookargs = {}
309 self._gettransaction = transactiongetter
309 self._gettransaction = transactiongetter
310 # carries value that can modify part behavior
310 # carries value that can modify part behavior
311 self.modes = {}
311 self.modes = {}
312 self.source = source
312 self.source = source
313
313
314 def gettransaction(self):
314 def gettransaction(self):
315 transaction = self._gettransaction()
315 transaction = self._gettransaction()
316
316
317 if self.hookargs:
317 if self.hookargs:
318 # the ones added to the transaction supercede those added
318 # the ones added to the transaction supercede those added
319 # to the operation.
319 # to the operation.
320 self.hookargs.update(transaction.hookargs)
320 self.hookargs.update(transaction.hookargs)
321 transaction.hookargs = self.hookargs
321 transaction.hookargs = self.hookargs
322
322
323 # mark the hookargs as flushed. further attempts to add to
323 # mark the hookargs as flushed. further attempts to add to
324 # hookargs will result in an abort.
324 # hookargs will result in an abort.
325 self.hookargs = None
325 self.hookargs = None
326
326
327 return transaction
327 return transaction
328
328
329 def addhookargs(self, hookargs):
329 def addhookargs(self, hookargs):
330 if self.hookargs is None:
330 if self.hookargs is None:
331 raise error.ProgrammingError('attempted to add hookargs to '
331 raise error.ProgrammingError('attempted to add hookargs to '
332 'operation after transaction started')
332 'operation after transaction started')
333 self.hookargs.update(hookargs)
333 self.hookargs.update(hookargs)
334
334
335 class TransactionUnavailable(RuntimeError):
335 class TransactionUnavailable(RuntimeError):
336 pass
336 pass
337
337
338 def _notransaction():
338 def _notransaction():
339 """default method to get a transaction while processing a bundle
339 """default method to get a transaction while processing a bundle
340
340
341 Raise an exception to highlight the fact that no transaction was expected
341 Raise an exception to highlight the fact that no transaction was expected
342 to be created"""
342 to be created"""
343 raise TransactionUnavailable()
343 raise TransactionUnavailable()
344
344
345 def applybundle(repo, unbundler, tr, source, url=None, **kwargs):
345 def applybundle(repo, unbundler, tr, source, url=None, **kwargs):
346 # transform me into unbundler.apply() as soon as the freeze is lifted
346 # transform me into unbundler.apply() as soon as the freeze is lifted
347 if isinstance(unbundler, unbundle20):
347 if isinstance(unbundler, unbundle20):
348 tr.hookargs['bundle2'] = '1'
348 tr.hookargs['bundle2'] = '1'
349 if source is not None and 'source' not in tr.hookargs:
349 if source is not None and 'source' not in tr.hookargs:
350 tr.hookargs['source'] = source
350 tr.hookargs['source'] = source
351 if url is not None and 'url' not in tr.hookargs:
351 if url is not None and 'url' not in tr.hookargs:
352 tr.hookargs['url'] = url
352 tr.hookargs['url'] = url
353 return processbundle(repo, unbundler, lambda: tr, source=source)
353 return processbundle(repo, unbundler, lambda: tr, source=source)
354 else:
354 else:
355 # the transactiongetter won't be used, but we might as well set it
355 # the transactiongetter won't be used, but we might as well set it
356 op = bundleoperation(repo, lambda: tr, source=source)
356 op = bundleoperation(repo, lambda: tr, source=source)
357 _processchangegroup(op, unbundler, tr, source, url, **kwargs)
357 _processchangegroup(op, unbundler, tr, source, url, **kwargs)
358 return op
358 return op
359
359
360 class partiterator(object):
360 class partiterator(object):
361 def __init__(self, repo, op, unbundler):
361 def __init__(self, repo, op, unbundler):
362 self.repo = repo
362 self.repo = repo
363 self.op = op
363 self.op = op
364 self.unbundler = unbundler
364 self.unbundler = unbundler
365 self.iterator = None
365 self.iterator = None
366 self.count = 0
366 self.count = 0
367 self.current = None
367 self.current = None
368
368
369 def __enter__(self):
369 def __enter__(self):
370 def func():
370 def func():
371 itr = enumerate(self.unbundler.iterparts())
371 itr = enumerate(self.unbundler.iterparts())
372 for count, p in itr:
372 for count, p in itr:
373 self.count = count
373 self.count = count
374 self.current = p
374 self.current = p
375 yield p
375 yield p
376 p.consume()
376 p.consume()
377 self.current = None
377 self.current = None
378 self.iterator = func()
378 self.iterator = func()
379 return self.iterator
379 return self.iterator
380
380
381 def __exit__(self, type, exc, tb):
381 def __exit__(self, type, exc, tb):
382 if not self.iterator:
382 if not self.iterator:
383 return
383 return
384
384
385 # Only gracefully abort in a normal exception situation. User aborts
385 # Only gracefully abort in a normal exception situation. User aborts
386 # like Ctrl+C throw a KeyboardInterrupt which is not a base Exception,
386 # like Ctrl+C throw a KeyboardInterrupt which is not a base Exception,
387 # and should not gracefully cleanup.
387 # and should not gracefully cleanup.
388 if isinstance(exc, Exception):
388 if isinstance(exc, Exception):
389 # Any exceptions seeking to the end of the bundle at this point are
389 # Any exceptions seeking to the end of the bundle at this point are
390 # almost certainly related to the underlying stream being bad.
390 # almost certainly related to the underlying stream being bad.
391 # And, chances are that the exception we're handling is related to
391 # And, chances are that the exception we're handling is related to
392 # getting in that bad state. So, we swallow the seeking error and
392 # getting in that bad state. So, we swallow the seeking error and
393 # re-raise the original error.
393 # re-raise the original error.
394 seekerror = False
394 seekerror = False
395 try:
395 try:
396 if self.current:
396 if self.current:
397 # consume the part content to not corrupt the stream.
397 # consume the part content to not corrupt the stream.
398 self.current.consume()
398 self.current.consume()
399
399
400 for part in self.iterator:
400 for part in self.iterator:
401 # consume the bundle content
401 # consume the bundle content
402 part.consume()
402 part.consume()
403 except Exception:
403 except Exception:
404 seekerror = True
404 seekerror = True
405
405
406 # Small hack to let caller code distinguish exceptions from bundle2
406 # Small hack to let caller code distinguish exceptions from bundle2
407 # processing from processing the old format. This is mostly needed
407 # processing from processing the old format. This is mostly needed
408 # to handle different return codes to unbundle according to the type
408 # to handle different return codes to unbundle according to the type
409 # of bundle. We should probably clean up or drop this return code
409 # of bundle. We should probably clean up or drop this return code
410 # craziness in a future version.
410 # craziness in a future version.
411 exc.duringunbundle2 = True
411 exc.duringunbundle2 = True
412 salvaged = []
412 salvaged = []
413 replycaps = None
413 replycaps = None
414 if self.op.reply is not None:
414 if self.op.reply is not None:
415 salvaged = self.op.reply.salvageoutput()
415 salvaged = self.op.reply.salvageoutput()
416 replycaps = self.op.reply.capabilities
416 replycaps = self.op.reply.capabilities
417 exc._replycaps = replycaps
417 exc._replycaps = replycaps
418 exc._bundle2salvagedoutput = salvaged
418 exc._bundle2salvagedoutput = salvaged
419
419
420 # Re-raising from a variable loses the original stack. So only use
420 # Re-raising from a variable loses the original stack. So only use
421 # that form if we need to.
421 # that form if we need to.
422 if seekerror:
422 if seekerror:
423 raise exc
423 raise exc
424
424
425 self.repo.ui.debug('bundle2-input-bundle: %i parts total\n' %
425 self.repo.ui.debug('bundle2-input-bundle: %i parts total\n' %
426 self.count)
426 self.count)
427
427
428 def processbundle(repo, unbundler, transactiongetter=None, op=None, source=''):
428 def processbundle(repo, unbundler, transactiongetter=None, op=None, source=''):
429 """This function process a bundle, apply effect to/from a repo
429 """This function process a bundle, apply effect to/from a repo
430
430
431 It iterates over each part then searches for and uses the proper handling
431 It iterates over each part then searches for and uses the proper handling
432 code to process the part. Parts are processed in order.
432 code to process the part. Parts are processed in order.
433
433
434 Unknown Mandatory part will abort the process.
434 Unknown Mandatory part will abort the process.
435
435
436 It is temporarily possible to provide a prebuilt bundleoperation to the
436 It is temporarily possible to provide a prebuilt bundleoperation to the
437 function. This is used to ensure output is properly propagated in case of
437 function. This is used to ensure output is properly propagated in case of
438 an error during the unbundling. This output capturing part will likely be
438 an error during the unbundling. This output capturing part will likely be
439 reworked and this ability will probably go away in the process.
439 reworked and this ability will probably go away in the process.
440 """
440 """
441 if op is None:
441 if op is None:
442 if transactiongetter is None:
442 if transactiongetter is None:
443 transactiongetter = _notransaction
443 transactiongetter = _notransaction
444 op = bundleoperation(repo, transactiongetter, source=source)
444 op = bundleoperation(repo, transactiongetter, source=source)
445 # todo:
445 # todo:
446 # - replace this is a init function soon.
446 # - replace this is a init function soon.
447 # - exception catching
447 # - exception catching
448 unbundler.params
448 unbundler.params
449 if repo.ui.debugflag:
449 if repo.ui.debugflag:
450 msg = ['bundle2-input-bundle:']
450 msg = ['bundle2-input-bundle:']
451 if unbundler.params:
451 if unbundler.params:
452 msg.append(' %i params' % len(unbundler.params))
452 msg.append(' %i params' % len(unbundler.params))
453 if op._gettransaction is None or op._gettransaction is _notransaction:
453 if op._gettransaction is None or op._gettransaction is _notransaction:
454 msg.append(' no-transaction')
454 msg.append(' no-transaction')
455 else:
455 else:
456 msg.append(' with-transaction')
456 msg.append(' with-transaction')
457 msg.append('\n')
457 msg.append('\n')
458 repo.ui.debug(''.join(msg))
458 repo.ui.debug(''.join(msg))
459
459
460 processparts(repo, op, unbundler)
460 processparts(repo, op, unbundler)
461
461
462 return op
462 return op
463
463
464 def processparts(repo, op, unbundler):
464 def processparts(repo, op, unbundler):
465 with partiterator(repo, op, unbundler) as parts:
465 with partiterator(repo, op, unbundler) as parts:
466 for part in parts:
466 for part in parts:
467 _processpart(op, part)
467 _processpart(op, part)
468
468
469 def _processchangegroup(op, cg, tr, source, url, **kwargs):
469 def _processchangegroup(op, cg, tr, source, url, **kwargs):
470 ret = cg.apply(op.repo, tr, source, url, **kwargs)
470 ret = cg.apply(op.repo, tr, source, url, **kwargs)
471 op.records.add('changegroup', {
471 op.records.add('changegroup', {
472 'return': ret,
472 'return': ret,
473 })
473 })
474 return ret
474 return ret
475
475
476 def _gethandler(op, part):
476 def _gethandler(op, part):
477 status = 'unknown' # used by debug output
477 status = 'unknown' # used by debug output
478 try:
478 try:
479 handler = parthandlermapping.get(part.type)
479 handler = parthandlermapping.get(part.type)
480 if handler is None:
480 if handler is None:
481 status = 'unsupported-type'
481 status = 'unsupported-type'
482 raise error.BundleUnknownFeatureError(parttype=part.type)
482 raise error.BundleUnknownFeatureError(parttype=part.type)
483 indebug(op.ui, 'found a handler for part %s' % part.type)
483 indebug(op.ui, 'found a handler for part %s' % part.type)
484 unknownparams = part.mandatorykeys - handler.params
484 unknownparams = part.mandatorykeys - handler.params
485 if unknownparams:
485 if unknownparams:
486 unknownparams = list(unknownparams)
486 unknownparams = list(unknownparams)
487 unknownparams.sort()
487 unknownparams.sort()
488 status = 'unsupported-params (%s)' % ', '.join(unknownparams)
488 status = 'unsupported-params (%s)' % ', '.join(unknownparams)
489 raise error.BundleUnknownFeatureError(parttype=part.type,
489 raise error.BundleUnknownFeatureError(parttype=part.type,
490 params=unknownparams)
490 params=unknownparams)
491 status = 'supported'
491 status = 'supported'
492 except error.BundleUnknownFeatureError as exc:
492 except error.BundleUnknownFeatureError as exc:
493 if part.mandatory: # mandatory parts
493 if part.mandatory: # mandatory parts
494 raise
494 raise
495 indebug(op.ui, 'ignoring unsupported advisory part %s' % exc)
495 indebug(op.ui, 'ignoring unsupported advisory part %s' % exc)
496 return # skip to part processing
496 return # skip to part processing
497 finally:
497 finally:
498 if op.ui.debugflag:
498 if op.ui.debugflag:
499 msg = ['bundle2-input-part: "%s"' % part.type]
499 msg = ['bundle2-input-part: "%s"' % part.type]
500 if not part.mandatory:
500 if not part.mandatory:
501 msg.append(' (advisory)')
501 msg.append(' (advisory)')
502 nbmp = len(part.mandatorykeys)
502 nbmp = len(part.mandatorykeys)
503 nbap = len(part.params) - nbmp
503 nbap = len(part.params) - nbmp
504 if nbmp or nbap:
504 if nbmp or nbap:
505 msg.append(' (params:')
505 msg.append(' (params:')
506 if nbmp:
506 if nbmp:
507 msg.append(' %i mandatory' % nbmp)
507 msg.append(' %i mandatory' % nbmp)
508 if nbap:
508 if nbap:
509 msg.append(' %i advisory' % nbmp)
509 msg.append(' %i advisory' % nbmp)
510 msg.append(')')
510 msg.append(')')
511 msg.append(' %s\n' % status)
511 msg.append(' %s\n' % status)
512 op.ui.debug(''.join(msg))
512 op.ui.debug(''.join(msg))
513
513
514 return handler
514 return handler
515
515
516 def _processpart(op, part):
516 def _processpart(op, part):
517 """process a single part from a bundle
517 """process a single part from a bundle
518
518
519 The part is guaranteed to have been fully consumed when the function exits
519 The part is guaranteed to have been fully consumed when the function exits
520 (even if an exception is raised)."""
520 (even if an exception is raised)."""
521 handler = _gethandler(op, part)
521 handler = _gethandler(op, part)
522 if handler is None:
522 if handler is None:
523 return
523 return
524
524
525 # handler is called outside the above try block so that we don't
525 # handler is called outside the above try block so that we don't
526 # risk catching KeyErrors from anything other than the
526 # risk catching KeyErrors from anything other than the
527 # parthandlermapping lookup (any KeyError raised by handler()
527 # parthandlermapping lookup (any KeyError raised by handler()
528 # itself represents a defect of a different variety).
528 # itself represents a defect of a different variety).
529 output = None
529 output = None
530 if op.captureoutput and op.reply is not None:
530 if op.captureoutput and op.reply is not None:
531 op.ui.pushbuffer(error=True, subproc=True)
531 op.ui.pushbuffer(error=True, subproc=True)
532 output = ''
532 output = ''
533 try:
533 try:
534 handler(op, part)
534 handler(op, part)
535 finally:
535 finally:
536 if output is not None:
536 if output is not None:
537 output = op.ui.popbuffer()
537 output = op.ui.popbuffer()
538 if output:
538 if output:
539 outpart = op.reply.newpart('output', data=output,
539 outpart = op.reply.newpart('output', data=output,
540 mandatory=False)
540 mandatory=False)
541 outpart.addparam(
541 outpart.addparam(
542 'in-reply-to', pycompat.bytestr(part.id), mandatory=False)
542 'in-reply-to', pycompat.bytestr(part.id), mandatory=False)
543
543
544 def decodecaps(blob):
544 def decodecaps(blob):
545 """decode a bundle2 caps bytes blob into a dictionary
545 """decode a bundle2 caps bytes blob into a dictionary
546
546
547 The blob is a list of capabilities (one per line)
547 The blob is a list of capabilities (one per line)
548 Capabilities may have values using a line of the form::
548 Capabilities may have values using a line of the form::
549
549
550 capability=value1,value2,value3
550 capability=value1,value2,value3
551
551
552 The values are always a list."""
552 The values are always a list."""
553 caps = {}
553 caps = {}
554 for line in blob.splitlines():
554 for line in blob.splitlines():
555 if not line:
555 if not line:
556 continue
556 continue
557 if '=' not in line:
557 if '=' not in line:
558 key, vals = line, ()
558 key, vals = line, ()
559 else:
559 else:
560 key, vals = line.split('=', 1)
560 key, vals = line.split('=', 1)
561 vals = vals.split(',')
561 vals = vals.split(',')
562 key = urlreq.unquote(key)
562 key = urlreq.unquote(key)
563 vals = [urlreq.unquote(v) for v in vals]
563 vals = [urlreq.unquote(v) for v in vals]
564 caps[key] = vals
564 caps[key] = vals
565 return caps
565 return caps
566
566
567 def encodecaps(caps):
567 def encodecaps(caps):
568 """encode a bundle2 caps dictionary into a bytes blob"""
568 """encode a bundle2 caps dictionary into a bytes blob"""
569 chunks = []
569 chunks = []
570 for ca in sorted(caps):
570 for ca in sorted(caps):
571 vals = caps[ca]
571 vals = caps[ca]
572 ca = urlreq.quote(ca)
572 ca = urlreq.quote(ca)
573 vals = [urlreq.quote(v) for v in vals]
573 vals = [urlreq.quote(v) for v in vals]
574 if vals:
574 if vals:
575 ca = "%s=%s" % (ca, ','.join(vals))
575 ca = "%s=%s" % (ca, ','.join(vals))
576 chunks.append(ca)
576 chunks.append(ca)
577 return '\n'.join(chunks)
577 return '\n'.join(chunks)
578
578
579 bundletypes = {
579 bundletypes = {
580 "": ("", 'UN'), # only when using unbundle on ssh and old http servers
580 "": ("", 'UN'), # only when using unbundle on ssh and old http servers
581 # since the unification ssh accepts a header but there
581 # since the unification ssh accepts a header but there
582 # is no capability signaling it.
582 # is no capability signaling it.
583 "HG20": (), # special-cased below
583 "HG20": (), # special-cased below
584 "HG10UN": ("HG10UN", 'UN'),
584 "HG10UN": ("HG10UN", 'UN'),
585 "HG10BZ": ("HG10", 'BZ'),
585 "HG10BZ": ("HG10", 'BZ'),
586 "HG10GZ": ("HG10GZ", 'GZ'),
586 "HG10GZ": ("HG10GZ", 'GZ'),
587 }
587 }
588
588
589 # hgweb uses this list to communicate its preferred type
589 # hgweb uses this list to communicate its preferred type
590 bundlepriority = ['HG10GZ', 'HG10BZ', 'HG10UN']
590 bundlepriority = ['HG10GZ', 'HG10BZ', 'HG10UN']
591
591
592 class bundle20(object):
592 class bundle20(object):
593 """represent an outgoing bundle2 container
593 """represent an outgoing bundle2 container
594
594
595 Use the `addparam` method to add stream level parameter. and `newpart` to
595 Use the `addparam` method to add stream level parameter. and `newpart` to
596 populate it. Then call `getchunks` to retrieve all the binary chunks of
596 populate it. Then call `getchunks` to retrieve all the binary chunks of
597 data that compose the bundle2 container."""
597 data that compose the bundle2 container."""
598
598
599 _magicstring = 'HG20'
599 _magicstring = 'HG20'
600
600
601 def __init__(self, ui, capabilities=()):
601 def __init__(self, ui, capabilities=()):
602 self.ui = ui
602 self.ui = ui
603 self._params = []
603 self._params = []
604 self._parts = []
604 self._parts = []
605 self.capabilities = dict(capabilities)
605 self.capabilities = dict(capabilities)
606 self._compengine = util.compengines.forbundletype('UN')
606 self._compengine = util.compengines.forbundletype('UN')
607 self._compopts = None
607 self._compopts = None
608 # If compression is being handled by a consumer of the raw
608 # If compression is being handled by a consumer of the raw
609 # data (e.g. the wire protocol), unsetting this flag tells
609 # data (e.g. the wire protocol), unsetting this flag tells
610 # consumers that the bundle is best left uncompressed.
610 # consumers that the bundle is best left uncompressed.
611 self.prefercompressed = True
611 self.prefercompressed = True
612
612
613 def setcompression(self, alg, compopts=None):
613 def setcompression(self, alg, compopts=None):
614 """setup core part compression to <alg>"""
614 """setup core part compression to <alg>"""
615 if alg in (None, 'UN'):
615 if alg in (None, 'UN'):
616 return
616 return
617 assert not any(n.lower() == 'compression' for n, v in self._params)
617 assert not any(n.lower() == 'compression' for n, v in self._params)
618 self.addparam('Compression', alg)
618 self.addparam('Compression', alg)
619 self._compengine = util.compengines.forbundletype(alg)
619 self._compengine = util.compengines.forbundletype(alg)
620 self._compopts = compopts
620 self._compopts = compopts
621
621
622 @property
622 @property
623 def nbparts(self):
623 def nbparts(self):
624 """total number of parts added to the bundler"""
624 """total number of parts added to the bundler"""
625 return len(self._parts)
625 return len(self._parts)
626
626
627 # methods used to defines the bundle2 content
627 # methods used to defines the bundle2 content
628 def addparam(self, name, value=None):
628 def addparam(self, name, value=None):
629 """add a stream level parameter"""
629 """add a stream level parameter"""
630 if not name:
630 if not name:
631 raise error.ProgrammingError(b'empty parameter name')
631 raise error.ProgrammingError(b'empty parameter name')
632 if name[0:1] not in pycompat.bytestr(string.ascii_letters):
632 if name[0:1] not in pycompat.bytestr(string.ascii_letters):
633 raise error.ProgrammingError(b'non letter first character: %s'
633 raise error.ProgrammingError(b'non letter first character: %s'
634 % name)
634 % name)
635 self._params.append((name, value))
635 self._params.append((name, value))
636
636
637 def addpart(self, part):
637 def addpart(self, part):
638 """add a new part to the bundle2 container
638 """add a new part to the bundle2 container
639
639
640 Parts contains the actual applicative payload."""
640 Parts contains the actual applicative payload."""
641 assert part.id is None
641 assert part.id is None
642 part.id = len(self._parts) # very cheap counter
642 part.id = len(self._parts) # very cheap counter
643 self._parts.append(part)
643 self._parts.append(part)
644
644
645 def newpart(self, typeid, *args, **kwargs):
645 def newpart(self, typeid, *args, **kwargs):
646 """create a new part and add it to the containers
646 """create a new part and add it to the containers
647
647
648 As the part is directly added to the containers. For now, this means
648 As the part is directly added to the containers. For now, this means
649 that any failure to properly initialize the part after calling
649 that any failure to properly initialize the part after calling
650 ``newpart`` should result in a failure of the whole bundling process.
650 ``newpart`` should result in a failure of the whole bundling process.
651
651
652 You can still fall back to manually create and add if you need better
652 You can still fall back to manually create and add if you need better
653 control."""
653 control."""
654 part = bundlepart(typeid, *args, **kwargs)
654 part = bundlepart(typeid, *args, **kwargs)
655 self.addpart(part)
655 self.addpart(part)
656 return part
656 return part
657
657
658 # methods used to generate the bundle2 stream
658 # methods used to generate the bundle2 stream
659 def getchunks(self):
659 def getchunks(self):
660 if self.ui.debugflag:
660 if self.ui.debugflag:
661 msg = ['bundle2-output-bundle: "%s",' % self._magicstring]
661 msg = ['bundle2-output-bundle: "%s",' % self._magicstring]
662 if self._params:
662 if self._params:
663 msg.append(' (%i params)' % len(self._params))
663 msg.append(' (%i params)' % len(self._params))
664 msg.append(' %i parts total\n' % len(self._parts))
664 msg.append(' %i parts total\n' % len(self._parts))
665 self.ui.debug(''.join(msg))
665 self.ui.debug(''.join(msg))
666 outdebug(self.ui, 'start emission of %s stream' % self._magicstring)
666 outdebug(self.ui, 'start emission of %s stream' % self._magicstring)
667 yield self._magicstring
667 yield self._magicstring
668 param = self._paramchunk()
668 param = self._paramchunk()
669 outdebug(self.ui, 'bundle parameter: %s' % param)
669 outdebug(self.ui, 'bundle parameter: %s' % param)
670 yield _pack(_fstreamparamsize, len(param))
670 yield _pack(_fstreamparamsize, len(param))
671 if param:
671 if param:
672 yield param
672 yield param
673 for chunk in self._compengine.compressstream(self._getcorechunk(),
673 for chunk in self._compengine.compressstream(self._getcorechunk(),
674 self._compopts):
674 self._compopts):
675 yield chunk
675 yield chunk
676
676
677 def _paramchunk(self):
677 def _paramchunk(self):
678 """return a encoded version of all stream parameters"""
678 """return a encoded version of all stream parameters"""
679 blocks = []
679 blocks = []
680 for par, value in self._params:
680 for par, value in self._params:
681 par = urlreq.quote(par)
681 par = urlreq.quote(par)
682 if value is not None:
682 if value is not None:
683 value = urlreq.quote(value)
683 value = urlreq.quote(value)
684 par = '%s=%s' % (par, value)
684 par = '%s=%s' % (par, value)
685 blocks.append(par)
685 blocks.append(par)
686 return ' '.join(blocks)
686 return ' '.join(blocks)
687
687
688 def _getcorechunk(self):
688 def _getcorechunk(self):
689 """yield chunk for the core part of the bundle
689 """yield chunk for the core part of the bundle
690
690
691 (all but headers and parameters)"""
691 (all but headers and parameters)"""
692 outdebug(self.ui, 'start of parts')
692 outdebug(self.ui, 'start of parts')
693 for part in self._parts:
693 for part in self._parts:
694 outdebug(self.ui, 'bundle part: "%s"' % part.type)
694 outdebug(self.ui, 'bundle part: "%s"' % part.type)
695 for chunk in part.getchunks(ui=self.ui):
695 for chunk in part.getchunks(ui=self.ui):
696 yield chunk
696 yield chunk
697 outdebug(self.ui, 'end of bundle')
697 outdebug(self.ui, 'end of bundle')
698 yield _pack(_fpartheadersize, 0)
698 yield _pack(_fpartheadersize, 0)
699
699
700
700
701 def salvageoutput(self):
701 def salvageoutput(self):
702 """return a list with a copy of all output parts in the bundle
702 """return a list with a copy of all output parts in the bundle
703
703
704 This is meant to be used during error handling to make sure we preserve
704 This is meant to be used during error handling to make sure we preserve
705 server output"""
705 server output"""
706 salvaged = []
706 salvaged = []
707 for part in self._parts:
707 for part in self._parts:
708 if part.type.startswith('output'):
708 if part.type.startswith('output'):
709 salvaged.append(part.copy())
709 salvaged.append(part.copy())
710 return salvaged
710 return salvaged
711
711
712
712
713 class unpackermixin(object):
713 class unpackermixin(object):
714 """A mixin to extract bytes and struct data from a stream"""
714 """A mixin to extract bytes and struct data from a stream"""
715
715
716 def __init__(self, fp):
716 def __init__(self, fp):
717 self._fp = fp
717 self._fp = fp
718
718
719 def _unpack(self, format):
719 def _unpack(self, format):
720 """unpack this struct format from the stream
720 """unpack this struct format from the stream
721
721
722 This method is meant for internal usage by the bundle2 protocol only.
722 This method is meant for internal usage by the bundle2 protocol only.
723 They directly manipulate the low level stream including bundle2 level
723 They directly manipulate the low level stream including bundle2 level
724 instruction.
724 instruction.
725
725
726 Do not use it to implement higher-level logic or methods."""
726 Do not use it to implement higher-level logic or methods."""
727 data = self._readexact(struct.calcsize(format))
727 data = self._readexact(struct.calcsize(format))
728 return _unpack(format, data)
728 return _unpack(format, data)
729
729
730 def _readexact(self, size):
730 def _readexact(self, size):
731 """read exactly <size> bytes from the stream
731 """read exactly <size> bytes from the stream
732
732
733 This method is meant for internal usage by the bundle2 protocol only.
733 This method is meant for internal usage by the bundle2 protocol only.
734 They directly manipulate the low level stream including bundle2 level
734 They directly manipulate the low level stream including bundle2 level
735 instruction.
735 instruction.
736
736
737 Do not use it to implement higher-level logic or methods."""
737 Do not use it to implement higher-level logic or methods."""
738 return changegroup.readexactly(self._fp, size)
738 return changegroup.readexactly(self._fp, size)
739
739
740 def getunbundler(ui, fp, magicstring=None):
740 def getunbundler(ui, fp, magicstring=None):
741 """return a valid unbundler object for a given magicstring"""
741 """return a valid unbundler object for a given magicstring"""
742 if magicstring is None:
742 if magicstring is None:
743 magicstring = changegroup.readexactly(fp, 4)
743 magicstring = changegroup.readexactly(fp, 4)
744 magic, version = magicstring[0:2], magicstring[2:4]
744 magic, version = magicstring[0:2], magicstring[2:4]
745 if magic != 'HG':
745 if magic != 'HG':
746 ui.debug(
746 ui.debug(
747 "error: invalid magic: %r (version %r), should be 'HG'\n"
747 "error: invalid magic: %r (version %r), should be 'HG'\n"
748 % (magic, version))
748 % (magic, version))
749 raise error.Abort(_('not a Mercurial bundle'))
749 raise error.Abort(_('not a Mercurial bundle'))
750 unbundlerclass = formatmap.get(version)
750 unbundlerclass = formatmap.get(version)
751 if unbundlerclass is None:
751 if unbundlerclass is None:
752 raise error.Abort(_('unknown bundle version %s') % version)
752 raise error.Abort(_('unknown bundle version %s') % version)
753 unbundler = unbundlerclass(ui, fp)
753 unbundler = unbundlerclass(ui, fp)
754 indebug(ui, 'start processing of %s stream' % magicstring)
754 indebug(ui, 'start processing of %s stream' % magicstring)
755 return unbundler
755 return unbundler
756
756
757 class unbundle20(unpackermixin):
757 class unbundle20(unpackermixin):
758 """interpret a bundle2 stream
758 """interpret a bundle2 stream
759
759
760 This class is fed with a binary stream and yields parts through its
760 This class is fed with a binary stream and yields parts through its
761 `iterparts` methods."""
761 `iterparts` methods."""
762
762
763 _magicstring = 'HG20'
763 _magicstring = 'HG20'
764
764
765 def __init__(self, ui, fp):
765 def __init__(self, ui, fp):
766 """If header is specified, we do not read it out of the stream."""
766 """If header is specified, we do not read it out of the stream."""
767 self.ui = ui
767 self.ui = ui
768 self._compengine = util.compengines.forbundletype('UN')
768 self._compengine = util.compengines.forbundletype('UN')
769 self._compressed = None
769 self._compressed = None
770 super(unbundle20, self).__init__(fp)
770 super(unbundle20, self).__init__(fp)
771
771
772 @util.propertycache
772 @util.propertycache
773 def params(self):
773 def params(self):
774 """dictionary of stream level parameters"""
774 """dictionary of stream level parameters"""
775 indebug(self.ui, 'reading bundle2 stream parameters')
775 indebug(self.ui, 'reading bundle2 stream parameters')
776 params = {}
776 params = {}
777 paramssize = self._unpack(_fstreamparamsize)[0]
777 paramssize = self._unpack(_fstreamparamsize)[0]
778 if paramssize < 0:
778 if paramssize < 0:
779 raise error.BundleValueError('negative bundle param size: %i'
779 raise error.BundleValueError('negative bundle param size: %i'
780 % paramssize)
780 % paramssize)
781 if paramssize:
781 if paramssize:
782 params = self._readexact(paramssize)
782 params = self._readexact(paramssize)
783 params = self._processallparams(params)
783 params = self._processallparams(params)
784 return params
784 return params
785
785
786 def _processallparams(self, paramsblock):
786 def _processallparams(self, paramsblock):
787 """"""
787 """"""
788 params = util.sortdict()
788 params = util.sortdict()
789 for p in paramsblock.split(' '):
789 for p in paramsblock.split(' '):
790 p = p.split('=', 1)
790 p = p.split('=', 1)
791 p = [urlreq.unquote(i) for i in p]
791 p = [urlreq.unquote(i) for i in p]
792 if len(p) < 2:
792 if len(p) < 2:
793 p.append(None)
793 p.append(None)
794 self._processparam(*p)
794 self._processparam(*p)
795 params[p[0]] = p[1]
795 params[p[0]] = p[1]
796 return params
796 return params
797
797
798
798
799 def _processparam(self, name, value):
799 def _processparam(self, name, value):
800 """process a parameter, applying its effect if needed
800 """process a parameter, applying its effect if needed
801
801
802 Parameter starting with a lower case letter are advisory and will be
802 Parameter starting with a lower case letter are advisory and will be
803 ignored when unknown. Those starting with an upper case letter are
803 ignored when unknown. Those starting with an upper case letter are
804 mandatory and will this function will raise a KeyError when unknown.
804 mandatory and will this function will raise a KeyError when unknown.
805
805
806 Note: no option are currently supported. Any input will be either
806 Note: no option are currently supported. Any input will be either
807 ignored or failing.
807 ignored or failing.
808 """
808 """
809 if not name:
809 if not name:
810 raise ValueError(r'empty parameter name')
810 raise ValueError(r'empty parameter name')
811 if name[0:1] not in pycompat.bytestr(string.ascii_letters):
811 if name[0:1] not in pycompat.bytestr(string.ascii_letters):
812 raise ValueError(r'non letter first character: %s' % name)
812 raise ValueError(r'non letter first character: %s' % name)
813 try:
813 try:
814 handler = b2streamparamsmap[name.lower()]
814 handler = b2streamparamsmap[name.lower()]
815 except KeyError:
815 except KeyError:
816 if name[0:1].islower():
816 if name[0:1].islower():
817 indebug(self.ui, "ignoring unknown parameter %s" % name)
817 indebug(self.ui, "ignoring unknown parameter %s" % name)
818 else:
818 else:
819 raise error.BundleUnknownFeatureError(params=(name,))
819 raise error.BundleUnknownFeatureError(params=(name,))
820 else:
820 else:
821 handler(self, name, value)
821 handler(self, name, value)
822
822
823 def _forwardchunks(self):
823 def _forwardchunks(self):
824 """utility to transfer a bundle2 as binary
824 """utility to transfer a bundle2 as binary
825
825
826 This is made necessary by the fact the 'getbundle' command over 'ssh'
826 This is made necessary by the fact the 'getbundle' command over 'ssh'
827 have no way to know then the reply end, relying on the bundle to be
827 have no way to know then the reply end, relying on the bundle to be
828 interpreted to know its end. This is terrible and we are sorry, but we
828 interpreted to know its end. This is terrible and we are sorry, but we
829 needed to move forward to get general delta enabled.
829 needed to move forward to get general delta enabled.
830 """
830 """
831 yield self._magicstring
831 yield self._magicstring
832 assert 'params' not in vars(self)
832 assert 'params' not in vars(self)
833 paramssize = self._unpack(_fstreamparamsize)[0]
833 paramssize = self._unpack(_fstreamparamsize)[0]
834 if paramssize < 0:
834 if paramssize < 0:
835 raise error.BundleValueError('negative bundle param size: %i'
835 raise error.BundleValueError('negative bundle param size: %i'
836 % paramssize)
836 % paramssize)
837 yield _pack(_fstreamparamsize, paramssize)
837 yield _pack(_fstreamparamsize, paramssize)
838 if paramssize:
838 if paramssize:
839 params = self._readexact(paramssize)
839 params = self._readexact(paramssize)
840 self._processallparams(params)
840 self._processallparams(params)
841 yield params
841 yield params
842 assert self._compengine.bundletype == 'UN'
842 assert self._compengine.bundletype == 'UN'
843 # From there, payload might need to be decompressed
843 # From there, payload might need to be decompressed
844 self._fp = self._compengine.decompressorreader(self._fp)
844 self._fp = self._compengine.decompressorreader(self._fp)
845 emptycount = 0
845 emptycount = 0
846 while emptycount < 2:
846 while emptycount < 2:
847 # so we can brainlessly loop
847 # so we can brainlessly loop
848 assert _fpartheadersize == _fpayloadsize
848 assert _fpartheadersize == _fpayloadsize
849 size = self._unpack(_fpartheadersize)[0]
849 size = self._unpack(_fpartheadersize)[0]
850 yield _pack(_fpartheadersize, size)
850 yield _pack(_fpartheadersize, size)
851 if size:
851 if size:
852 emptycount = 0
852 emptycount = 0
853 else:
853 else:
854 emptycount += 1
854 emptycount += 1
855 continue
855 continue
856 if size == flaginterrupt:
856 if size == flaginterrupt:
857 continue
857 continue
858 elif size < 0:
858 elif size < 0:
859 raise error.BundleValueError('negative chunk size: %i')
859 raise error.BundleValueError('negative chunk size: %i')
860 yield self._readexact(size)
860 yield self._readexact(size)
861
861
862
862
863 def iterparts(self, seekable=False):
863 def iterparts(self, seekable=False):
864 """yield all parts contained in the stream"""
864 """yield all parts contained in the stream"""
865 cls = seekableunbundlepart if seekable else unbundlepart
865 cls = seekableunbundlepart if seekable else unbundlepart
866 # make sure param have been loaded
866 # make sure param have been loaded
867 self.params
867 self.params
868 # From there, payload need to be decompressed
868 # From there, payload need to be decompressed
869 self._fp = self._compengine.decompressorreader(self._fp)
869 self._fp = self._compengine.decompressorreader(self._fp)
870 indebug(self.ui, 'start extraction of bundle2 parts')
870 indebug(self.ui, 'start extraction of bundle2 parts')
871 headerblock = self._readpartheader()
871 headerblock = self._readpartheader()
872 while headerblock is not None:
872 while headerblock is not None:
873 part = cls(self.ui, headerblock, self._fp)
873 part = cls(self.ui, headerblock, self._fp)
874 yield part
874 yield part
875 # Ensure part is fully consumed so we can start reading the next
875 # Ensure part is fully consumed so we can start reading the next
876 # part.
876 # part.
877 part.consume()
877 part.consume()
878
878
879 headerblock = self._readpartheader()
879 headerblock = self._readpartheader()
880 indebug(self.ui, 'end of bundle2 stream')
880 indebug(self.ui, 'end of bundle2 stream')
881
881
882 def _readpartheader(self):
882 def _readpartheader(self):
883 """reads a part header size and return the bytes blob
883 """reads a part header size and return the bytes blob
884
884
885 returns None if empty"""
885 returns None if empty"""
886 headersize = self._unpack(_fpartheadersize)[0]
886 headersize = self._unpack(_fpartheadersize)[0]
887 if headersize < 0:
887 if headersize < 0:
888 raise error.BundleValueError('negative part header size: %i'
888 raise error.BundleValueError('negative part header size: %i'
889 % headersize)
889 % headersize)
890 indebug(self.ui, 'part header size: %i' % headersize)
890 indebug(self.ui, 'part header size: %i' % headersize)
891 if headersize:
891 if headersize:
892 return self._readexact(headersize)
892 return self._readexact(headersize)
893 return None
893 return None
894
894
895 def compressed(self):
895 def compressed(self):
896 self.params # load params
896 self.params # load params
897 return self._compressed
897 return self._compressed
898
898
899 def close(self):
899 def close(self):
900 """close underlying file"""
900 """close underlying file"""
901 if util.safehasattr(self._fp, 'close'):
901 if util.safehasattr(self._fp, 'close'):
902 return self._fp.close()
902 return self._fp.close()
903
903
904 formatmap = {'20': unbundle20}
904 formatmap = {'20': unbundle20}
905
905
906 b2streamparamsmap = {}
906 b2streamparamsmap = {}
907
907
908 def b2streamparamhandler(name):
908 def b2streamparamhandler(name):
909 """register a handler for a stream level parameter"""
909 """register a handler for a stream level parameter"""
910 def decorator(func):
910 def decorator(func):
911 assert name not in formatmap
911 assert name not in formatmap
912 b2streamparamsmap[name] = func
912 b2streamparamsmap[name] = func
913 return func
913 return func
914 return decorator
914 return decorator
915
915
916 @b2streamparamhandler('compression')
916 @b2streamparamhandler('compression')
917 def processcompression(unbundler, param, value):
917 def processcompression(unbundler, param, value):
918 """read compression parameter and install payload decompression"""
918 """read compression parameter and install payload decompression"""
919 if value not in util.compengines.supportedbundletypes:
919 if value not in util.compengines.supportedbundletypes:
920 raise error.BundleUnknownFeatureError(params=(param,),
920 raise error.BundleUnknownFeatureError(params=(param,),
921 values=(value,))
921 values=(value,))
922 unbundler._compengine = util.compengines.forbundletype(value)
922 unbundler._compengine = util.compengines.forbundletype(value)
923 if value is not None:
923 if value is not None:
924 unbundler._compressed = True
924 unbundler._compressed = True
925
925
926 class bundlepart(object):
926 class bundlepart(object):
927 """A bundle2 part contains application level payload
927 """A bundle2 part contains application level payload
928
928
929 The part `type` is used to route the part to the application level
929 The part `type` is used to route the part to the application level
930 handler.
930 handler.
931
931
932 The part payload is contained in ``part.data``. It could be raw bytes or a
932 The part payload is contained in ``part.data``. It could be raw bytes or a
933 generator of byte chunks.
933 generator of byte chunks.
934
934
935 You can add parameters to the part using the ``addparam`` method.
935 You can add parameters to the part using the ``addparam`` method.
936 Parameters can be either mandatory (default) or advisory. Remote side
936 Parameters can be either mandatory (default) or advisory. Remote side
937 should be able to safely ignore the advisory ones.
937 should be able to safely ignore the advisory ones.
938
938
939 Both data and parameters cannot be modified after the generation has begun.
939 Both data and parameters cannot be modified after the generation has begun.
940 """
940 """
941
941
942 def __init__(self, parttype, mandatoryparams=(), advisoryparams=(),
942 def __init__(self, parttype, mandatoryparams=(), advisoryparams=(),
943 data='', mandatory=True):
943 data='', mandatory=True):
944 validateparttype(parttype)
944 validateparttype(parttype)
945 self.id = None
945 self.id = None
946 self.type = parttype
946 self.type = parttype
947 self._data = data
947 self._data = data
948 self._mandatoryparams = list(mandatoryparams)
948 self._mandatoryparams = list(mandatoryparams)
949 self._advisoryparams = list(advisoryparams)
949 self._advisoryparams = list(advisoryparams)
950 # checking for duplicated entries
950 # checking for duplicated entries
951 self._seenparams = set()
951 self._seenparams = set()
952 for pname, __ in self._mandatoryparams + self._advisoryparams:
952 for pname, __ in self._mandatoryparams + self._advisoryparams:
953 if pname in self._seenparams:
953 if pname in self._seenparams:
954 raise error.ProgrammingError('duplicated params: %s' % pname)
954 raise error.ProgrammingError('duplicated params: %s' % pname)
955 self._seenparams.add(pname)
955 self._seenparams.add(pname)
956 # status of the part's generation:
956 # status of the part's generation:
957 # - None: not started,
957 # - None: not started,
958 # - False: currently generated,
958 # - False: currently generated,
959 # - True: generation done.
959 # - True: generation done.
960 self._generated = None
960 self._generated = None
961 self.mandatory = mandatory
961 self.mandatory = mandatory
962
962
963 def __repr__(self):
963 def __repr__(self):
964 cls = "%s.%s" % (self.__class__.__module__, self.__class__.__name__)
964 cls = "%s.%s" % (self.__class__.__module__, self.__class__.__name__)
965 return ('<%s object at %x; id: %s; type: %s; mandatory: %s>'
965 return ('<%s object at %x; id: %s; type: %s; mandatory: %s>'
966 % (cls, id(self), self.id, self.type, self.mandatory))
966 % (cls, id(self), self.id, self.type, self.mandatory))
967
967
968 def copy(self):
968 def copy(self):
969 """return a copy of the part
969 """return a copy of the part
970
970
971 The new part have the very same content but no partid assigned yet.
971 The new part have the very same content but no partid assigned yet.
972 Parts with generated data cannot be copied."""
972 Parts with generated data cannot be copied."""
973 assert not util.safehasattr(self.data, 'next')
973 assert not util.safehasattr(self.data, 'next')
974 return self.__class__(self.type, self._mandatoryparams,
974 return self.__class__(self.type, self._mandatoryparams,
975 self._advisoryparams, self._data, self.mandatory)
975 self._advisoryparams, self._data, self.mandatory)
976
976
977 # methods used to defines the part content
977 # methods used to defines the part content
978 @property
978 @property
979 def data(self):
979 def data(self):
980 return self._data
980 return self._data
981
981
982 @data.setter
982 @data.setter
983 def data(self, data):
983 def data(self, data):
984 if self._generated is not None:
984 if self._generated is not None:
985 raise error.ReadOnlyPartError('part is being generated')
985 raise error.ReadOnlyPartError('part is being generated')
986 self._data = data
986 self._data = data
987
987
988 @property
988 @property
989 def mandatoryparams(self):
989 def mandatoryparams(self):
990 # make it an immutable tuple to force people through ``addparam``
990 # make it an immutable tuple to force people through ``addparam``
991 return tuple(self._mandatoryparams)
991 return tuple(self._mandatoryparams)
992
992
993 @property
993 @property
994 def advisoryparams(self):
994 def advisoryparams(self):
995 # make it an immutable tuple to force people through ``addparam``
995 # make it an immutable tuple to force people through ``addparam``
996 return tuple(self._advisoryparams)
996 return tuple(self._advisoryparams)
997
997
998 def addparam(self, name, value='', mandatory=True):
998 def addparam(self, name, value='', mandatory=True):
999 """add a parameter to the part
999 """add a parameter to the part
1000
1000
1001 If 'mandatory' is set to True, the remote handler must claim support
1001 If 'mandatory' is set to True, the remote handler must claim support
1002 for this parameter or the unbundling will be aborted.
1002 for this parameter or the unbundling will be aborted.
1003
1003
1004 The 'name' and 'value' cannot exceed 255 bytes each.
1004 The 'name' and 'value' cannot exceed 255 bytes each.
1005 """
1005 """
1006 if self._generated is not None:
1006 if self._generated is not None:
1007 raise error.ReadOnlyPartError('part is being generated')
1007 raise error.ReadOnlyPartError('part is being generated')
1008 if name in self._seenparams:
1008 if name in self._seenparams:
1009 raise ValueError('duplicated params: %s' % name)
1009 raise ValueError('duplicated params: %s' % name)
1010 self._seenparams.add(name)
1010 self._seenparams.add(name)
1011 params = self._advisoryparams
1011 params = self._advisoryparams
1012 if mandatory:
1012 if mandatory:
1013 params = self._mandatoryparams
1013 params = self._mandatoryparams
1014 params.append((name, value))
1014 params.append((name, value))
1015
1015
1016 # methods used to generates the bundle2 stream
1016 # methods used to generates the bundle2 stream
1017 def getchunks(self, ui):
1017 def getchunks(self, ui):
1018 if self._generated is not None:
1018 if self._generated is not None:
1019 raise error.ProgrammingError('part can only be consumed once')
1019 raise error.ProgrammingError('part can only be consumed once')
1020 self._generated = False
1020 self._generated = False
1021
1021
1022 if ui.debugflag:
1022 if ui.debugflag:
1023 msg = ['bundle2-output-part: "%s"' % self.type]
1023 msg = ['bundle2-output-part: "%s"' % self.type]
1024 if not self.mandatory:
1024 if not self.mandatory:
1025 msg.append(' (advisory)')
1025 msg.append(' (advisory)')
1026 nbmp = len(self.mandatoryparams)
1026 nbmp = len(self.mandatoryparams)
1027 nbap = len(self.advisoryparams)
1027 nbap = len(self.advisoryparams)
1028 if nbmp or nbap:
1028 if nbmp or nbap:
1029 msg.append(' (params:')
1029 msg.append(' (params:')
1030 if nbmp:
1030 if nbmp:
1031 msg.append(' %i mandatory' % nbmp)
1031 msg.append(' %i mandatory' % nbmp)
1032 if nbap:
1032 if nbap:
1033 msg.append(' %i advisory' % nbmp)
1033 msg.append(' %i advisory' % nbmp)
1034 msg.append(')')
1034 msg.append(')')
1035 if not self.data:
1035 if not self.data:
1036 msg.append(' empty payload')
1036 msg.append(' empty payload')
1037 elif (util.safehasattr(self.data, 'next')
1037 elif (util.safehasattr(self.data, 'next')
1038 or util.safehasattr(self.data, '__next__')):
1038 or util.safehasattr(self.data, '__next__')):
1039 msg.append(' streamed payload')
1039 msg.append(' streamed payload')
1040 else:
1040 else:
1041 msg.append(' %i bytes payload' % len(self.data))
1041 msg.append(' %i bytes payload' % len(self.data))
1042 msg.append('\n')
1042 msg.append('\n')
1043 ui.debug(''.join(msg))
1043 ui.debug(''.join(msg))
1044
1044
1045 #### header
1045 #### header
1046 if self.mandatory:
1046 if self.mandatory:
1047 parttype = self.type.upper()
1047 parttype = self.type.upper()
1048 else:
1048 else:
1049 parttype = self.type.lower()
1049 parttype = self.type.lower()
1050 outdebug(ui, 'part %s: "%s"' % (pycompat.bytestr(self.id), parttype))
1050 outdebug(ui, 'part %s: "%s"' % (pycompat.bytestr(self.id), parttype))
1051 ## parttype
1051 ## parttype
1052 header = [_pack(_fparttypesize, len(parttype)),
1052 header = [_pack(_fparttypesize, len(parttype)),
1053 parttype, _pack(_fpartid, self.id),
1053 parttype, _pack(_fpartid, self.id),
1054 ]
1054 ]
1055 ## parameters
1055 ## parameters
1056 # count
1056 # count
1057 manpar = self.mandatoryparams
1057 manpar = self.mandatoryparams
1058 advpar = self.advisoryparams
1058 advpar = self.advisoryparams
1059 header.append(_pack(_fpartparamcount, len(manpar), len(advpar)))
1059 header.append(_pack(_fpartparamcount, len(manpar), len(advpar)))
1060 # size
1060 # size
1061 parsizes = []
1061 parsizes = []
1062 for key, value in manpar:
1062 for key, value in manpar:
1063 parsizes.append(len(key))
1063 parsizes.append(len(key))
1064 parsizes.append(len(value))
1064 parsizes.append(len(value))
1065 for key, value in advpar:
1065 for key, value in advpar:
1066 parsizes.append(len(key))
1066 parsizes.append(len(key))
1067 parsizes.append(len(value))
1067 parsizes.append(len(value))
1068 paramsizes = _pack(_makefpartparamsizes(len(parsizes) // 2), *parsizes)
1068 paramsizes = _pack(_makefpartparamsizes(len(parsizes) // 2), *parsizes)
1069 header.append(paramsizes)
1069 header.append(paramsizes)
1070 # key, value
1070 # key, value
1071 for key, value in manpar:
1071 for key, value in manpar:
1072 header.append(key)
1072 header.append(key)
1073 header.append(value)
1073 header.append(value)
1074 for key, value in advpar:
1074 for key, value in advpar:
1075 header.append(key)
1075 header.append(key)
1076 header.append(value)
1076 header.append(value)
1077 ## finalize header
1077 ## finalize header
1078 try:
1078 try:
1079 headerchunk = ''.join(header)
1079 headerchunk = ''.join(header)
1080 except TypeError:
1080 except TypeError:
1081 raise TypeError(r'Found a non-bytes trying to '
1081 raise TypeError(r'Found a non-bytes trying to '
1082 r'build bundle part header: %r' % header)
1082 r'build bundle part header: %r' % header)
1083 outdebug(ui, 'header chunk size: %i' % len(headerchunk))
1083 outdebug(ui, 'header chunk size: %i' % len(headerchunk))
1084 yield _pack(_fpartheadersize, len(headerchunk))
1084 yield _pack(_fpartheadersize, len(headerchunk))
1085 yield headerchunk
1085 yield headerchunk
1086 ## payload
1086 ## payload
1087 try:
1087 try:
1088 for chunk in self._payloadchunks():
1088 for chunk in self._payloadchunks():
1089 outdebug(ui, 'payload chunk size: %i' % len(chunk))
1089 outdebug(ui, 'payload chunk size: %i' % len(chunk))
1090 yield _pack(_fpayloadsize, len(chunk))
1090 yield _pack(_fpayloadsize, len(chunk))
1091 yield chunk
1091 yield chunk
1092 except GeneratorExit:
1092 except GeneratorExit:
1093 # GeneratorExit means that nobody is listening for our
1093 # GeneratorExit means that nobody is listening for our
1094 # results anyway, so just bail quickly rather than trying
1094 # results anyway, so just bail quickly rather than trying
1095 # to produce an error part.
1095 # to produce an error part.
1096 ui.debug('bundle2-generatorexit\n')
1096 ui.debug('bundle2-generatorexit\n')
1097 raise
1097 raise
1098 except BaseException as exc:
1098 except BaseException as exc:
1099 bexc = stringutil.forcebytestr(exc)
1099 bexc = stringutil.forcebytestr(exc)
1100 # backup exception data for later
1100 # backup exception data for later
1101 ui.debug('bundle2-input-stream-interrupt: encoding exception %s'
1101 ui.debug('bundle2-input-stream-interrupt: encoding exception %s'
1102 % bexc)
1102 % bexc)
1103 tb = sys.exc_info()[2]
1103 tb = sys.exc_info()[2]
1104 msg = 'unexpected error: %s' % bexc
1104 msg = 'unexpected error: %s' % bexc
1105 interpart = bundlepart('error:abort', [('message', msg)],
1105 interpart = bundlepart('error:abort', [('message', msg)],
1106 mandatory=False)
1106 mandatory=False)
1107 interpart.id = 0
1107 interpart.id = 0
1108 yield _pack(_fpayloadsize, -1)
1108 yield _pack(_fpayloadsize, -1)
1109 for chunk in interpart.getchunks(ui=ui):
1109 for chunk in interpart.getchunks(ui=ui):
1110 yield chunk
1110 yield chunk
1111 outdebug(ui, 'closing payload chunk')
1111 outdebug(ui, 'closing payload chunk')
1112 # abort current part payload
1112 # abort current part payload
1113 yield _pack(_fpayloadsize, 0)
1113 yield _pack(_fpayloadsize, 0)
1114 pycompat.raisewithtb(exc, tb)
1114 pycompat.raisewithtb(exc, tb)
1115 # end of payload
1115 # end of payload
1116 outdebug(ui, 'closing payload chunk')
1116 outdebug(ui, 'closing payload chunk')
1117 yield _pack(_fpayloadsize, 0)
1117 yield _pack(_fpayloadsize, 0)
1118 self._generated = True
1118 self._generated = True
1119
1119
1120 def _payloadchunks(self):
1120 def _payloadchunks(self):
1121 """yield chunks of a the part payload
1121 """yield chunks of a the part payload
1122
1122
1123 Exists to handle the different methods to provide data to a part."""
1123 Exists to handle the different methods to provide data to a part."""
1124 # we only support fixed size data now.
1124 # we only support fixed size data now.
1125 # This will be improved in the future.
1125 # This will be improved in the future.
1126 if (util.safehasattr(self.data, 'next')
1126 if (util.safehasattr(self.data, 'next')
1127 or util.safehasattr(self.data, '__next__')):
1127 or util.safehasattr(self.data, '__next__')):
1128 buff = util.chunkbuffer(self.data)
1128 buff = util.chunkbuffer(self.data)
1129 chunk = buff.read(preferedchunksize)
1129 chunk = buff.read(preferedchunksize)
1130 while chunk:
1130 while chunk:
1131 yield chunk
1131 yield chunk
1132 chunk = buff.read(preferedchunksize)
1132 chunk = buff.read(preferedchunksize)
1133 elif len(self.data):
1133 elif len(self.data):
1134 yield self.data
1134 yield self.data
1135
1135
1136
1136
1137 flaginterrupt = -1
1137 flaginterrupt = -1
1138
1138
1139 class interrupthandler(unpackermixin):
1139 class interrupthandler(unpackermixin):
1140 """read one part and process it with restricted capability
1140 """read one part and process it with restricted capability
1141
1141
1142 This allows to transmit exception raised on the producer size during part
1142 This allows to transmit exception raised on the producer size during part
1143 iteration while the consumer is reading a part.
1143 iteration while the consumer is reading a part.
1144
1144
1145 Part processed in this manner only have access to a ui object,"""
1145 Part processed in this manner only have access to a ui object,"""
1146
1146
1147 def __init__(self, ui, fp):
1147 def __init__(self, ui, fp):
1148 super(interrupthandler, self).__init__(fp)
1148 super(interrupthandler, self).__init__(fp)
1149 self.ui = ui
1149 self.ui = ui
1150
1150
1151 def _readpartheader(self):
1151 def _readpartheader(self):
1152 """reads a part header size and return the bytes blob
1152 """reads a part header size and return the bytes blob
1153
1153
1154 returns None if empty"""
1154 returns None if empty"""
1155 headersize = self._unpack(_fpartheadersize)[0]
1155 headersize = self._unpack(_fpartheadersize)[0]
1156 if headersize < 0:
1156 if headersize < 0:
1157 raise error.BundleValueError('negative part header size: %i'
1157 raise error.BundleValueError('negative part header size: %i'
1158 % headersize)
1158 % headersize)
1159 indebug(self.ui, 'part header size: %i\n' % headersize)
1159 indebug(self.ui, 'part header size: %i\n' % headersize)
1160 if headersize:
1160 if headersize:
1161 return self._readexact(headersize)
1161 return self._readexact(headersize)
1162 return None
1162 return None
1163
1163
1164 def __call__(self):
1164 def __call__(self):
1165
1165
1166 self.ui.debug('bundle2-input-stream-interrupt:'
1166 self.ui.debug('bundle2-input-stream-interrupt:'
1167 ' opening out of band context\n')
1167 ' opening out of band context\n')
1168 indebug(self.ui, 'bundle2 stream interruption, looking for a part.')
1168 indebug(self.ui, 'bundle2 stream interruption, looking for a part.')
1169 headerblock = self._readpartheader()
1169 headerblock = self._readpartheader()
1170 if headerblock is None:
1170 if headerblock is None:
1171 indebug(self.ui, 'no part found during interruption.')
1171 indebug(self.ui, 'no part found during interruption.')
1172 return
1172 return
1173 part = unbundlepart(self.ui, headerblock, self._fp)
1173 part = unbundlepart(self.ui, headerblock, self._fp)
1174 op = interruptoperation(self.ui)
1174 op = interruptoperation(self.ui)
1175 hardabort = False
1175 hardabort = False
1176 try:
1176 try:
1177 _processpart(op, part)
1177 _processpart(op, part)
1178 except (SystemExit, KeyboardInterrupt):
1178 except (SystemExit, KeyboardInterrupt):
1179 hardabort = True
1179 hardabort = True
1180 raise
1180 raise
1181 finally:
1181 finally:
1182 if not hardabort:
1182 if not hardabort:
1183 part.consume()
1183 part.consume()
1184 self.ui.debug('bundle2-input-stream-interrupt:'
1184 self.ui.debug('bundle2-input-stream-interrupt:'
1185 ' closing out of band context\n')
1185 ' closing out of band context\n')
1186
1186
1187 class interruptoperation(object):
1187 class interruptoperation(object):
1188 """A limited operation to be use by part handler during interruption
1188 """A limited operation to be use by part handler during interruption
1189
1189
1190 It only have access to an ui object.
1190 It only have access to an ui object.
1191 """
1191 """
1192
1192
1193 def __init__(self, ui):
1193 def __init__(self, ui):
1194 self.ui = ui
1194 self.ui = ui
1195 self.reply = None
1195 self.reply = None
1196 self.captureoutput = False
1196 self.captureoutput = False
1197
1197
1198 @property
1198 @property
1199 def repo(self):
1199 def repo(self):
1200 raise error.ProgrammingError('no repo access from stream interruption')
1200 raise error.ProgrammingError('no repo access from stream interruption')
1201
1201
1202 def gettransaction(self):
1202 def gettransaction(self):
1203 raise TransactionUnavailable('no repo access from stream interruption')
1203 raise TransactionUnavailable('no repo access from stream interruption')
1204
1204
1205 def decodepayloadchunks(ui, fh):
1205 def decodepayloadchunks(ui, fh):
1206 """Reads bundle2 part payload data into chunks.
1206 """Reads bundle2 part payload data into chunks.
1207
1207
1208 Part payload data consists of framed chunks. This function takes
1208 Part payload data consists of framed chunks. This function takes
1209 a file handle and emits those chunks.
1209 a file handle and emits those chunks.
1210 """
1210 """
1211 dolog = ui.configbool('devel', 'bundle2.debug')
1211 dolog = ui.configbool('devel', 'bundle2.debug')
1212 debug = ui.debug
1212 debug = ui.debug
1213
1213
1214 headerstruct = struct.Struct(_fpayloadsize)
1214 headerstruct = struct.Struct(_fpayloadsize)
1215 headersize = headerstruct.size
1215 headersize = headerstruct.size
1216 unpack = headerstruct.unpack
1216 unpack = headerstruct.unpack
1217
1217
1218 readexactly = changegroup.readexactly
1218 readexactly = changegroup.readexactly
1219 read = fh.read
1219 read = fh.read
1220
1220
1221 chunksize = unpack(readexactly(fh, headersize))[0]
1221 chunksize = unpack(readexactly(fh, headersize))[0]
1222 indebug(ui, 'payload chunk size: %i' % chunksize)
1222 indebug(ui, 'payload chunk size: %i' % chunksize)
1223
1223
1224 # changegroup.readexactly() is inlined below for performance.
1224 # changegroup.readexactly() is inlined below for performance.
1225 while chunksize:
1225 while chunksize:
1226 if chunksize >= 0:
1226 if chunksize >= 0:
1227 s = read(chunksize)
1227 s = read(chunksize)
1228 if len(s) < chunksize:
1228 if len(s) < chunksize:
1229 raise error.Abort(_('stream ended unexpectedly '
1229 raise error.Abort(_('stream ended unexpectedly '
1230 ' (got %d bytes, expected %d)') %
1230 ' (got %d bytes, expected %d)') %
1231 (len(s), chunksize))
1231 (len(s), chunksize))
1232
1232
1233 yield s
1233 yield s
1234 elif chunksize == flaginterrupt:
1234 elif chunksize == flaginterrupt:
1235 # Interrupt "signal" detected. The regular stream is interrupted
1235 # Interrupt "signal" detected. The regular stream is interrupted
1236 # and a bundle2 part follows. Consume it.
1236 # and a bundle2 part follows. Consume it.
1237 interrupthandler(ui, fh)()
1237 interrupthandler(ui, fh)()
1238 else:
1238 else:
1239 raise error.BundleValueError(
1239 raise error.BundleValueError(
1240 'negative payload chunk size: %s' % chunksize)
1240 'negative payload chunk size: %s' % chunksize)
1241
1241
1242 s = read(headersize)
1242 s = read(headersize)
1243 if len(s) < headersize:
1243 if len(s) < headersize:
1244 raise error.Abort(_('stream ended unexpectedly '
1244 raise error.Abort(_('stream ended unexpectedly '
1245 ' (got %d bytes, expected %d)') %
1245 ' (got %d bytes, expected %d)') %
1246 (len(s), chunksize))
1246 (len(s), chunksize))
1247
1247
1248 chunksize = unpack(s)[0]
1248 chunksize = unpack(s)[0]
1249
1249
1250 # indebug() inlined for performance.
1250 # indebug() inlined for performance.
1251 if dolog:
1251 if dolog:
1252 debug('bundle2-input: payload chunk size: %i\n' % chunksize)
1252 debug('bundle2-input: payload chunk size: %i\n' % chunksize)
1253
1253
1254 class unbundlepart(unpackermixin):
1254 class unbundlepart(unpackermixin):
1255 """a bundle part read from a bundle"""
1255 """a bundle part read from a bundle"""
1256
1256
1257 def __init__(self, ui, header, fp):
1257 def __init__(self, ui, header, fp):
1258 super(unbundlepart, self).__init__(fp)
1258 super(unbundlepart, self).__init__(fp)
1259 self._seekable = (util.safehasattr(fp, 'seek') and
1259 self._seekable = (util.safehasattr(fp, 'seek') and
1260 util.safehasattr(fp, 'tell'))
1260 util.safehasattr(fp, 'tell'))
1261 self.ui = ui
1261 self.ui = ui
1262 # unbundle state attr
1262 # unbundle state attr
1263 self._headerdata = header
1263 self._headerdata = header
1264 self._headeroffset = 0
1264 self._headeroffset = 0
1265 self._initialized = False
1265 self._initialized = False
1266 self.consumed = False
1266 self.consumed = False
1267 # part data
1267 # part data
1268 self.id = None
1268 self.id = None
1269 self.type = None
1269 self.type = None
1270 self.mandatoryparams = None
1270 self.mandatoryparams = None
1271 self.advisoryparams = None
1271 self.advisoryparams = None
1272 self.params = None
1272 self.params = None
1273 self.mandatorykeys = ()
1273 self.mandatorykeys = ()
1274 self._readheader()
1274 self._readheader()
1275 self._mandatory = None
1275 self._mandatory = None
1276 self._pos = 0
1276 self._pos = 0
1277
1277
1278 def _fromheader(self, size):
1278 def _fromheader(self, size):
1279 """return the next <size> byte from the header"""
1279 """return the next <size> byte from the header"""
1280 offset = self._headeroffset
1280 offset = self._headeroffset
1281 data = self._headerdata[offset:(offset + size)]
1281 data = self._headerdata[offset:(offset + size)]
1282 self._headeroffset = offset + size
1282 self._headeroffset = offset + size
1283 return data
1283 return data
1284
1284
1285 def _unpackheader(self, format):
1285 def _unpackheader(self, format):
1286 """read given format from header
1286 """read given format from header
1287
1287
1288 This automatically compute the size of the format to read."""
1288 This automatically compute the size of the format to read."""
1289 data = self._fromheader(struct.calcsize(format))
1289 data = self._fromheader(struct.calcsize(format))
1290 return _unpack(format, data)
1290 return _unpack(format, data)
1291
1291
1292 def _initparams(self, mandatoryparams, advisoryparams):
1292 def _initparams(self, mandatoryparams, advisoryparams):
1293 """internal function to setup all logic related parameters"""
1293 """internal function to setup all logic related parameters"""
1294 # make it read only to prevent people touching it by mistake.
1294 # make it read only to prevent people touching it by mistake.
1295 self.mandatoryparams = tuple(mandatoryparams)
1295 self.mandatoryparams = tuple(mandatoryparams)
1296 self.advisoryparams = tuple(advisoryparams)
1296 self.advisoryparams = tuple(advisoryparams)
1297 # user friendly UI
1297 # user friendly UI
1298 self.params = util.sortdict(self.mandatoryparams)
1298 self.params = util.sortdict(self.mandatoryparams)
1299 self.params.update(self.advisoryparams)
1299 self.params.update(self.advisoryparams)
1300 self.mandatorykeys = frozenset(p[0] for p in mandatoryparams)
1300 self.mandatorykeys = frozenset(p[0] for p in mandatoryparams)
1301
1301
1302 def _readheader(self):
1302 def _readheader(self):
1303 """read the header and setup the object"""
1303 """read the header and setup the object"""
1304 typesize = self._unpackheader(_fparttypesize)[0]
1304 typesize = self._unpackheader(_fparttypesize)[0]
1305 self.type = self._fromheader(typesize)
1305 self.type = self._fromheader(typesize)
1306 indebug(self.ui, 'part type: "%s"' % self.type)
1306 indebug(self.ui, 'part type: "%s"' % self.type)
1307 self.id = self._unpackheader(_fpartid)[0]
1307 self.id = self._unpackheader(_fpartid)[0]
1308 indebug(self.ui, 'part id: "%s"' % pycompat.bytestr(self.id))
1308 indebug(self.ui, 'part id: "%s"' % pycompat.bytestr(self.id))
1309 # extract mandatory bit from type
1309 # extract mandatory bit from type
1310 self.mandatory = (self.type != self.type.lower())
1310 self.mandatory = (self.type != self.type.lower())
1311 self.type = self.type.lower()
1311 self.type = self.type.lower()
1312 ## reading parameters
1312 ## reading parameters
1313 # param count
1313 # param count
1314 mancount, advcount = self._unpackheader(_fpartparamcount)
1314 mancount, advcount = self._unpackheader(_fpartparamcount)
1315 indebug(self.ui, 'part parameters: %i' % (mancount + advcount))
1315 indebug(self.ui, 'part parameters: %i' % (mancount + advcount))
1316 # param size
1316 # param size
1317 fparamsizes = _makefpartparamsizes(mancount + advcount)
1317 fparamsizes = _makefpartparamsizes(mancount + advcount)
1318 paramsizes = self._unpackheader(fparamsizes)
1318 paramsizes = self._unpackheader(fparamsizes)
1319 # make it a list of couple again
1319 # make it a list of couple again
1320 paramsizes = list(zip(paramsizes[::2], paramsizes[1::2]))
1320 paramsizes = list(zip(paramsizes[::2], paramsizes[1::2]))
1321 # split mandatory from advisory
1321 # split mandatory from advisory
1322 mansizes = paramsizes[:mancount]
1322 mansizes = paramsizes[:mancount]
1323 advsizes = paramsizes[mancount:]
1323 advsizes = paramsizes[mancount:]
1324 # retrieve param value
1324 # retrieve param value
1325 manparams = []
1325 manparams = []
1326 for key, value in mansizes:
1326 for key, value in mansizes:
1327 manparams.append((self._fromheader(key), self._fromheader(value)))
1327 manparams.append((self._fromheader(key), self._fromheader(value)))
1328 advparams = []
1328 advparams = []
1329 for key, value in advsizes:
1329 for key, value in advsizes:
1330 advparams.append((self._fromheader(key), self._fromheader(value)))
1330 advparams.append((self._fromheader(key), self._fromheader(value)))
1331 self._initparams(manparams, advparams)
1331 self._initparams(manparams, advparams)
1332 ## part payload
1332 ## part payload
1333 self._payloadstream = util.chunkbuffer(self._payloadchunks())
1333 self._payloadstream = util.chunkbuffer(self._payloadchunks())
1334 # we read the data, tell it
1334 # we read the data, tell it
1335 self._initialized = True
1335 self._initialized = True
1336
1336
1337 def _payloadchunks(self):
1337 def _payloadchunks(self):
1338 """Generator of decoded chunks in the payload."""
1338 """Generator of decoded chunks in the payload."""
1339 return decodepayloadchunks(self.ui, self._fp)
1339 return decodepayloadchunks(self.ui, self._fp)
1340
1340
1341 def consume(self):
1341 def consume(self):
1342 """Read the part payload until completion.
1342 """Read the part payload until completion.
1343
1343
1344 By consuming the part data, the underlying stream read offset will
1344 By consuming the part data, the underlying stream read offset will
1345 be advanced to the next part (or end of stream).
1345 be advanced to the next part (or end of stream).
1346 """
1346 """
1347 if self.consumed:
1347 if self.consumed:
1348 return
1348 return
1349
1349
1350 chunk = self.read(32768)
1350 chunk = self.read(32768)
1351 while chunk:
1351 while chunk:
1352 self._pos += len(chunk)
1352 self._pos += len(chunk)
1353 chunk = self.read(32768)
1353 chunk = self.read(32768)
1354
1354
1355 def read(self, size=None):
1355 def read(self, size=None):
1356 """read payload data"""
1356 """read payload data"""
1357 if not self._initialized:
1357 if not self._initialized:
1358 self._readheader()
1358 self._readheader()
1359 if size is None:
1359 if size is None:
1360 data = self._payloadstream.read()
1360 data = self._payloadstream.read()
1361 else:
1361 else:
1362 data = self._payloadstream.read(size)
1362 data = self._payloadstream.read(size)
1363 self._pos += len(data)
1363 self._pos += len(data)
1364 if size is None or len(data) < size:
1364 if size is None or len(data) < size:
1365 if not self.consumed and self._pos:
1365 if not self.consumed and self._pos:
1366 self.ui.debug('bundle2-input-part: total payload size %i\n'
1366 self.ui.debug('bundle2-input-part: total payload size %i\n'
1367 % self._pos)
1367 % self._pos)
1368 self.consumed = True
1368 self.consumed = True
1369 return data
1369 return data
1370
1370
1371 class seekableunbundlepart(unbundlepart):
1371 class seekableunbundlepart(unbundlepart):
1372 """A bundle2 part in a bundle that is seekable.
1372 """A bundle2 part in a bundle that is seekable.
1373
1373
1374 Regular ``unbundlepart`` instances can only be read once. This class
1374 Regular ``unbundlepart`` instances can only be read once. This class
1375 extends ``unbundlepart`` to enable bi-directional seeking within the
1375 extends ``unbundlepart`` to enable bi-directional seeking within the
1376 part.
1376 part.
1377
1377
1378 Bundle2 part data consists of framed chunks. Offsets when seeking
1378 Bundle2 part data consists of framed chunks. Offsets when seeking
1379 refer to the decoded data, not the offsets in the underlying bundle2
1379 refer to the decoded data, not the offsets in the underlying bundle2
1380 stream.
1380 stream.
1381
1381
1382 To facilitate quickly seeking within the decoded data, instances of this
1382 To facilitate quickly seeking within the decoded data, instances of this
1383 class maintain a mapping between offsets in the underlying stream and
1383 class maintain a mapping between offsets in the underlying stream and
1384 the decoded payload. This mapping will consume memory in proportion
1384 the decoded payload. This mapping will consume memory in proportion
1385 to the number of chunks within the payload (which almost certainly
1385 to the number of chunks within the payload (which almost certainly
1386 increases in proportion with the size of the part).
1386 increases in proportion with the size of the part).
1387 """
1387 """
1388 def __init__(self, ui, header, fp):
1388 def __init__(self, ui, header, fp):
1389 # (payload, file) offsets for chunk starts.
1389 # (payload, file) offsets for chunk starts.
1390 self._chunkindex = []
1390 self._chunkindex = []
1391
1391
1392 super(seekableunbundlepart, self).__init__(ui, header, fp)
1392 super(seekableunbundlepart, self).__init__(ui, header, fp)
1393
1393
1394 def _payloadchunks(self, chunknum=0):
1394 def _payloadchunks(self, chunknum=0):
1395 '''seek to specified chunk and start yielding data'''
1395 '''seek to specified chunk and start yielding data'''
1396 if len(self._chunkindex) == 0:
1396 if len(self._chunkindex) == 0:
1397 assert chunknum == 0, 'Must start with chunk 0'
1397 assert chunknum == 0, 'Must start with chunk 0'
1398 self._chunkindex.append((0, self._tellfp()))
1398 self._chunkindex.append((0, self._tellfp()))
1399 else:
1399 else:
1400 assert chunknum < len(self._chunkindex), \
1400 assert chunknum < len(self._chunkindex), \
1401 'Unknown chunk %d' % chunknum
1401 'Unknown chunk %d' % chunknum
1402 self._seekfp(self._chunkindex[chunknum][1])
1402 self._seekfp(self._chunkindex[chunknum][1])
1403
1403
1404 pos = self._chunkindex[chunknum][0]
1404 pos = self._chunkindex[chunknum][0]
1405
1405
1406 for chunk in decodepayloadchunks(self.ui, self._fp):
1406 for chunk in decodepayloadchunks(self.ui, self._fp):
1407 chunknum += 1
1407 chunknum += 1
1408 pos += len(chunk)
1408 pos += len(chunk)
1409 if chunknum == len(self._chunkindex):
1409 if chunknum == len(self._chunkindex):
1410 self._chunkindex.append((pos, self._tellfp()))
1410 self._chunkindex.append((pos, self._tellfp()))
1411
1411
1412 yield chunk
1412 yield chunk
1413
1413
1414 def _findchunk(self, pos):
1414 def _findchunk(self, pos):
1415 '''for a given payload position, return a chunk number and offset'''
1415 '''for a given payload position, return a chunk number and offset'''
1416 for chunk, (ppos, fpos) in enumerate(self._chunkindex):
1416 for chunk, (ppos, fpos) in enumerate(self._chunkindex):
1417 if ppos == pos:
1417 if ppos == pos:
1418 return chunk, 0
1418 return chunk, 0
1419 elif ppos > pos:
1419 elif ppos > pos:
1420 return chunk - 1, pos - self._chunkindex[chunk - 1][0]
1420 return chunk - 1, pos - self._chunkindex[chunk - 1][0]
1421 raise ValueError('Unknown chunk')
1421 raise ValueError('Unknown chunk')
1422
1422
1423 def tell(self):
1423 def tell(self):
1424 return self._pos
1424 return self._pos
1425
1425
1426 def seek(self, offset, whence=os.SEEK_SET):
1426 def seek(self, offset, whence=os.SEEK_SET):
1427 if whence == os.SEEK_SET:
1427 if whence == os.SEEK_SET:
1428 newpos = offset
1428 newpos = offset
1429 elif whence == os.SEEK_CUR:
1429 elif whence == os.SEEK_CUR:
1430 newpos = self._pos + offset
1430 newpos = self._pos + offset
1431 elif whence == os.SEEK_END:
1431 elif whence == os.SEEK_END:
1432 if not self.consumed:
1432 if not self.consumed:
1433 # Can't use self.consume() here because it advances self._pos.
1433 # Can't use self.consume() here because it advances self._pos.
1434 chunk = self.read(32768)
1434 chunk = self.read(32768)
1435 while chunk:
1435 while chunk:
1436 chunk = self.read(32768)
1436 chunk = self.read(32768)
1437 newpos = self._chunkindex[-1][0] - offset
1437 newpos = self._chunkindex[-1][0] - offset
1438 else:
1438 else:
1439 raise ValueError('Unknown whence value: %r' % (whence,))
1439 raise ValueError('Unknown whence value: %r' % (whence,))
1440
1440
1441 if newpos > self._chunkindex[-1][0] and not self.consumed:
1441 if newpos > self._chunkindex[-1][0] and not self.consumed:
1442 # Can't use self.consume() here because it advances self._pos.
1442 # Can't use self.consume() here because it advances self._pos.
1443 chunk = self.read(32768)
1443 chunk = self.read(32768)
1444 while chunk:
1444 while chunk:
1445 chunk = self.read(32668)
1445 chunk = self.read(32668)
1446
1446
1447 if not 0 <= newpos <= self._chunkindex[-1][0]:
1447 if not 0 <= newpos <= self._chunkindex[-1][0]:
1448 raise ValueError('Offset out of range')
1448 raise ValueError('Offset out of range')
1449
1449
1450 if self._pos != newpos:
1450 if self._pos != newpos:
1451 chunk, internaloffset = self._findchunk(newpos)
1451 chunk, internaloffset = self._findchunk(newpos)
1452 self._payloadstream = util.chunkbuffer(self._payloadchunks(chunk))
1452 self._payloadstream = util.chunkbuffer(self._payloadchunks(chunk))
1453 adjust = self.read(internaloffset)
1453 adjust = self.read(internaloffset)
1454 if len(adjust) != internaloffset:
1454 if len(adjust) != internaloffset:
1455 raise error.Abort(_('Seek failed\n'))
1455 raise error.Abort(_('Seek failed\n'))
1456 self._pos = newpos
1456 self._pos = newpos
1457
1457
1458 def _seekfp(self, offset, whence=0):
1458 def _seekfp(self, offset, whence=0):
1459 """move the underlying file pointer
1459 """move the underlying file pointer
1460
1460
1461 This method is meant for internal usage by the bundle2 protocol only.
1461 This method is meant for internal usage by the bundle2 protocol only.
1462 They directly manipulate the low level stream including bundle2 level
1462 They directly manipulate the low level stream including bundle2 level
1463 instruction.
1463 instruction.
1464
1464
1465 Do not use it to implement higher-level logic or methods."""
1465 Do not use it to implement higher-level logic or methods."""
1466 if self._seekable:
1466 if self._seekable:
1467 return self._fp.seek(offset, whence)
1467 return self._fp.seek(offset, whence)
1468 else:
1468 else:
1469 raise NotImplementedError(_('File pointer is not seekable'))
1469 raise NotImplementedError(_('File pointer is not seekable'))
1470
1470
1471 def _tellfp(self):
1471 def _tellfp(self):
1472 """return the file offset, or None if file is not seekable
1472 """return the file offset, or None if file is not seekable
1473
1473
1474 This method is meant for internal usage by the bundle2 protocol only.
1474 This method is meant for internal usage by the bundle2 protocol only.
1475 They directly manipulate the low level stream including bundle2 level
1475 They directly manipulate the low level stream including bundle2 level
1476 instruction.
1476 instruction.
1477
1477
1478 Do not use it to implement higher-level logic or methods."""
1478 Do not use it to implement higher-level logic or methods."""
1479 if self._seekable:
1479 if self._seekable:
1480 try:
1480 try:
1481 return self._fp.tell()
1481 return self._fp.tell()
1482 except IOError as e:
1482 except IOError as e:
1483 if e.errno == errno.ESPIPE:
1483 if e.errno == errno.ESPIPE:
1484 self._seekable = False
1484 self._seekable = False
1485 else:
1485 else:
1486 raise
1486 raise
1487 return None
1487 return None
1488
1488
1489 # These are only the static capabilities.
1489 # These are only the static capabilities.
1490 # Check the 'getrepocaps' function for the rest.
1490 # Check the 'getrepocaps' function for the rest.
1491 capabilities = {'HG20': (),
1491 capabilities = {'HG20': (),
1492 'bookmarks': (),
1492 'bookmarks': (),
1493 'error': ('abort', 'unsupportedcontent', 'pushraced',
1493 'error': ('abort', 'unsupportedcontent', 'pushraced',
1494 'pushkey'),
1494 'pushkey'),
1495 'listkeys': (),
1495 'listkeys': (),
1496 'pushkey': (),
1496 'pushkey': (),
1497 'digests': tuple(sorted(util.DIGESTS.keys())),
1497 'digests': tuple(sorted(util.DIGESTS.keys())),
1498 'remote-changegroup': ('http', 'https'),
1498 'remote-changegroup': ('http', 'https'),
1499 'hgtagsfnodes': (),
1499 'hgtagsfnodes': (),
1500 'rev-branch-cache': (),
1500 'rev-branch-cache': (),
1501 'phases': ('heads',),
1501 'phases': ('heads',),
1502 'stream': ('v2',),
1502 'stream': ('v2',),
1503 }
1503 }
1504
1504
1505 def getrepocaps(repo, allowpushback=False, role=None):
1505 def getrepocaps(repo, allowpushback=False, role=None):
1506 """return the bundle2 capabilities for a given repo
1506 """return the bundle2 capabilities for a given repo
1507
1507
1508 Exists to allow extensions (like evolution) to mutate the capabilities.
1508 Exists to allow extensions (like evolution) to mutate the capabilities.
1509
1509
1510 The returned value is used for servers advertising their capabilities as
1510 The returned value is used for servers advertising their capabilities as
1511 well as clients advertising their capabilities to servers as part of
1511 well as clients advertising their capabilities to servers as part of
1512 bundle2 requests. The ``role`` argument specifies which is which.
1512 bundle2 requests. The ``role`` argument specifies which is which.
1513 """
1513 """
1514 if role not in ('client', 'server'):
1514 if role not in ('client', 'server'):
1515 raise error.ProgrammingError('role argument must be client or server')
1515 raise error.ProgrammingError('role argument must be client or server')
1516
1516
1517 caps = capabilities.copy()
1517 caps = capabilities.copy()
1518 caps['changegroup'] = tuple(sorted(
1518 caps['changegroup'] = tuple(sorted(
1519 changegroup.supportedincomingversions(repo)))
1519 changegroup.supportedincomingversions(repo)))
1520 if obsolete.isenabled(repo, obsolete.exchangeopt):
1520 if obsolete.isenabled(repo, obsolete.exchangeopt):
1521 supportedformat = tuple('V%i' % v for v in obsolete.formats)
1521 supportedformat = tuple('V%i' % v for v in obsolete.formats)
1522 caps['obsmarkers'] = supportedformat
1522 caps['obsmarkers'] = supportedformat
1523 if allowpushback:
1523 if allowpushback:
1524 caps['pushback'] = ()
1524 caps['pushback'] = ()
1525 cpmode = repo.ui.config('server', 'concurrent-push-mode')
1525 cpmode = repo.ui.config('server', 'concurrent-push-mode')
1526 if cpmode == 'check-related':
1526 if cpmode == 'check-related':
1527 caps['checkheads'] = ('related',)
1527 caps['checkheads'] = ('related',)
1528 if 'phases' in repo.ui.configlist('devel', 'legacy.exchange'):
1528 if 'phases' in repo.ui.configlist('devel', 'legacy.exchange'):
1529 caps.pop('phases')
1529 caps.pop('phases')
1530
1530
1531 # Don't advertise stream clone support in server mode if not configured.
1531 # Don't advertise stream clone support in server mode if not configured.
1532 if role == 'server':
1532 if role == 'server':
1533 streamsupported = repo.ui.configbool('server', 'uncompressed',
1533 streamsupported = repo.ui.configbool('server', 'uncompressed',
1534 untrusted=True)
1534 untrusted=True)
1535 featuresupported = repo.ui.configbool('server', 'bundle2.stream')
1535 featuresupported = repo.ui.configbool('server', 'bundle2.stream')
1536
1536
1537 if not streamsupported or not featuresupported:
1537 if not streamsupported or not featuresupported:
1538 caps.pop('stream')
1538 caps.pop('stream')
1539 # Else always advertise support on client, because payload support
1539 # Else always advertise support on client, because payload support
1540 # should always be advertised.
1540 # should always be advertised.
1541
1541
1542 return caps
1542 return caps
1543
1543
1544 def bundle2caps(remote):
1544 def bundle2caps(remote):
1545 """return the bundle capabilities of a peer as dict"""
1545 """return the bundle capabilities of a peer as dict"""
1546 raw = remote.capable('bundle2')
1546 raw = remote.capable('bundle2')
1547 if not raw and raw != '':
1547 if not raw and raw != '':
1548 return {}
1548 return {}
1549 capsblob = urlreq.unquote(remote.capable('bundle2'))
1549 capsblob = urlreq.unquote(remote.capable('bundle2'))
1550 return decodecaps(capsblob)
1550 return decodecaps(capsblob)
1551
1551
1552 def obsmarkersversion(caps):
1552 def obsmarkersversion(caps):
1553 """extract the list of supported obsmarkers versions from a bundle2caps dict
1553 """extract the list of supported obsmarkers versions from a bundle2caps dict
1554 """
1554 """
1555 obscaps = caps.get('obsmarkers', ())
1555 obscaps = caps.get('obsmarkers', ())
1556 return [int(c[1:]) for c in obscaps if c.startswith('V')]
1556 return [int(c[1:]) for c in obscaps if c.startswith('V')]
1557
1557
1558 def writenewbundle(ui, repo, source, filename, bundletype, outgoing, opts,
1558 def writenewbundle(ui, repo, source, filename, bundletype, outgoing, opts,
1559 vfs=None, compression=None, compopts=None):
1559 vfs=None, compression=None, compopts=None):
1560 if bundletype.startswith('HG10'):
1560 if bundletype.startswith('HG10'):
1561 cg = changegroup.makechangegroup(repo, outgoing, '01', source)
1561 cg = changegroup.makechangegroup(repo, outgoing, '01', source)
1562 return writebundle(ui, cg, filename, bundletype, vfs=vfs,
1562 return writebundle(ui, cg, filename, bundletype, vfs=vfs,
1563 compression=compression, compopts=compopts)
1563 compression=compression, compopts=compopts)
1564 elif not bundletype.startswith('HG20'):
1564 elif not bundletype.startswith('HG20'):
1565 raise error.ProgrammingError('unknown bundle type: %s' % bundletype)
1565 raise error.ProgrammingError('unknown bundle type: %s' % bundletype)
1566
1566
1567 caps = {}
1567 caps = {}
1568 if 'obsolescence' in opts:
1568 if 'obsolescence' in opts:
1569 caps['obsmarkers'] = ('V1',)
1569 caps['obsmarkers'] = ('V1',)
1570 bundle = bundle20(ui, caps)
1570 bundle = bundle20(ui, caps)
1571 bundle.setcompression(compression, compopts)
1571 bundle.setcompression(compression, compopts)
1572 _addpartsfromopts(ui, repo, bundle, source, outgoing, opts)
1572 _addpartsfromopts(ui, repo, bundle, source, outgoing, opts)
1573 chunkiter = bundle.getchunks()
1573 chunkiter = bundle.getchunks()
1574
1574
1575 return changegroup.writechunks(ui, chunkiter, filename, vfs=vfs)
1575 return changegroup.writechunks(ui, chunkiter, filename, vfs=vfs)
1576
1576
1577 def _addpartsfromopts(ui, repo, bundler, source, outgoing, opts):
1577 def _addpartsfromopts(ui, repo, bundler, source, outgoing, opts):
1578 # We should eventually reconcile this logic with the one behind
1578 # We should eventually reconcile this logic with the one behind
1579 # 'exchange.getbundle2partsgenerator'.
1579 # 'exchange.getbundle2partsgenerator'.
1580 #
1580 #
1581 # The type of input from 'getbundle' and 'writenewbundle' are a bit
1581 # The type of input from 'getbundle' and 'writenewbundle' are a bit
1582 # different right now. So we keep them separated for now for the sake of
1582 # different right now. So we keep them separated for now for the sake of
1583 # simplicity.
1583 # simplicity.
1584
1584
1585 # we might not always want a changegroup in such bundle, for example in
1585 # we might not always want a changegroup in such bundle, for example in
1586 # stream bundles
1586 # stream bundles
1587 if opts.get('changegroup', True):
1587 if opts.get('changegroup', True):
1588 cgversion = opts.get('cg.version')
1588 cgversion = opts.get('cg.version')
1589 if cgversion is None:
1589 if cgversion is None:
1590 cgversion = changegroup.safeversion(repo)
1590 cgversion = changegroup.safeversion(repo)
1591 cg = changegroup.makechangegroup(repo, outgoing, cgversion, source)
1591 cg = changegroup.makechangegroup(repo, outgoing, cgversion, source)
1592 part = bundler.newpart('changegroup', data=cg.getchunks())
1592 part = bundler.newpart('changegroup', data=cg.getchunks())
1593 part.addparam('version', cg.version)
1593 part.addparam('version', cg.version)
1594 if 'clcount' in cg.extras:
1594 if 'clcount' in cg.extras:
1595 part.addparam('nbchanges', '%d' % cg.extras['clcount'],
1595 part.addparam('nbchanges', '%d' % cg.extras['clcount'],
1596 mandatory=False)
1596 mandatory=False)
1597 if opts.get('phases') and repo.revs('%ln and secret()',
1597 if opts.get('phases') and repo.revs('%ln and secret()',
1598 outgoing.missingheads):
1598 outgoing.missingheads):
1599 part.addparam('targetphase', '%d' % phases.secret, mandatory=False)
1599 part.addparam('targetphase', '%d' % phases.secret, mandatory=False)
1600
1600
1601 if opts.get('streamv2', False):
1601 if opts.get('streamv2', False):
1602 addpartbundlestream2(bundler, repo, stream=True)
1602 addpartbundlestream2(bundler, repo, stream=True)
1603
1603
1604 if opts.get('tagsfnodescache', True):
1604 if opts.get('tagsfnodescache', True):
1605 addparttagsfnodescache(repo, bundler, outgoing)
1605 addparttagsfnodescache(repo, bundler, outgoing)
1606
1606
1607 if opts.get('revbranchcache', True):
1607 if opts.get('revbranchcache', True):
1608 addpartrevbranchcache(repo, bundler, outgoing)
1608 addpartrevbranchcache(repo, bundler, outgoing)
1609
1609
1610 if opts.get('obsolescence', False):
1610 if opts.get('obsolescence', False):
1611 obsmarkers = repo.obsstore.relevantmarkers(outgoing.missing)
1611 obsmarkers = repo.obsstore.relevantmarkers(outgoing.missing)
1612 buildobsmarkerspart(bundler, obsmarkers)
1612 buildobsmarkerspart(bundler, obsmarkers)
1613
1613
1614 if opts.get('phases', False):
1614 if opts.get('phases', False):
1615 headsbyphase = phases.subsetphaseheads(repo, outgoing.missing)
1615 headsbyphase = phases.subsetphaseheads(repo, outgoing.missing)
1616 phasedata = phases.binaryencode(headsbyphase)
1616 phasedata = phases.binaryencode(headsbyphase)
1617 bundler.newpart('phase-heads', data=phasedata)
1617 bundler.newpart('phase-heads', data=phasedata)
1618
1618
1619 def addparttagsfnodescache(repo, bundler, outgoing):
1619 def addparttagsfnodescache(repo, bundler, outgoing):
1620 # we include the tags fnode cache for the bundle changeset
1620 # we include the tags fnode cache for the bundle changeset
1621 # (as an optional parts)
1621 # (as an optional parts)
1622 cache = tags.hgtagsfnodescache(repo.unfiltered())
1622 cache = tags.hgtagsfnodescache(repo.unfiltered())
1623 chunks = []
1623 chunks = []
1624
1624
1625 # .hgtags fnodes are only relevant for head changesets. While we could
1625 # .hgtags fnodes are only relevant for head changesets. While we could
1626 # transfer values for all known nodes, there will likely be little to
1626 # transfer values for all known nodes, there will likely be little to
1627 # no benefit.
1627 # no benefit.
1628 #
1628 #
1629 # We don't bother using a generator to produce output data because
1629 # We don't bother using a generator to produce output data because
1630 # a) we only have 40 bytes per head and even esoteric numbers of heads
1630 # a) we only have 40 bytes per head and even esoteric numbers of heads
1631 # consume little memory (1M heads is 40MB) b) we don't want to send the
1631 # consume little memory (1M heads is 40MB) b) we don't want to send the
1632 # part if we don't have entries and knowing if we have entries requires
1632 # part if we don't have entries and knowing if we have entries requires
1633 # cache lookups.
1633 # cache lookups.
1634 for node in outgoing.missingheads:
1634 for node in outgoing.missingheads:
1635 # Don't compute missing, as this may slow down serving.
1635 # Don't compute missing, as this may slow down serving.
1636 fnode = cache.getfnode(node, computemissing=False)
1636 fnode = cache.getfnode(node, computemissing=False)
1637 if fnode is not None:
1637 if fnode is not None:
1638 chunks.extend([node, fnode])
1638 chunks.extend([node, fnode])
1639
1639
1640 if chunks:
1640 if chunks:
1641 bundler.newpart('hgtagsfnodes', data=''.join(chunks))
1641 bundler.newpart('hgtagsfnodes', data=''.join(chunks))
1642
1642
1643 def addpartrevbranchcache(repo, bundler, outgoing):
1643 def addpartrevbranchcache(repo, bundler, outgoing):
1644 # we include the rev branch cache for the bundle changeset
1644 # we include the rev branch cache for the bundle changeset
1645 # (as an optional parts)
1645 # (as an optional parts)
1646 cache = repo.revbranchcache()
1646 cache = repo.revbranchcache()
1647 cl = repo.unfiltered().changelog
1647 cl = repo.unfiltered().changelog
1648 branchesdata = collections.defaultdict(lambda: (set(), set()))
1648 branchesdata = collections.defaultdict(lambda: (set(), set()))
1649 for node in outgoing.missing:
1649 for node in outgoing.missing:
1650 branch, close = cache.branchinfo(cl.rev(node))
1650 branch, close = cache.branchinfo(cl.rev(node))
1651 branchesdata[branch][close].add(node)
1651 branchesdata[branch][close].add(node)
1652
1652
1653 def generate():
1653 def generate():
1654 for branch, (nodes, closed) in sorted(branchesdata.items()):
1654 for branch, (nodes, closed) in sorted(branchesdata.items()):
1655 utf8branch = encoding.fromlocal(branch)
1655 utf8branch = encoding.fromlocal(branch)
1656 yield rbcstruct.pack(len(utf8branch), len(nodes), len(closed))
1656 yield rbcstruct.pack(len(utf8branch), len(nodes), len(closed))
1657 yield utf8branch
1657 yield utf8branch
1658 for n in sorted(nodes):
1658 for n in sorted(nodes):
1659 yield n
1659 yield n
1660 for n in sorted(closed):
1660 for n in sorted(closed):
1661 yield n
1661 yield n
1662
1662
1663 bundler.newpart('cache:rev-branch-cache', data=generate(),
1663 bundler.newpart('cache:rev-branch-cache', data=generate(),
1664 mandatory=False)
1664 mandatory=False)
1665
1665
1666 def _formatrequirementsspec(requirements):
1666 def _formatrequirementsspec(requirements):
1667 return urlreq.quote(','.join(sorted(requirements)))
1667 return urlreq.quote(','.join(sorted(requirements)))
1668
1668
1669 def _formatrequirementsparams(requirements):
1669 def _formatrequirementsparams(requirements):
1670 requirements = _formatrequirementsspec(requirements)
1670 requirements = _formatrequirementsspec(requirements)
1671 params = "%s%s" % (urlreq.quote("requirements="), requirements)
1671 params = "%s%s" % (urlreq.quote("requirements="), requirements)
1672 return params
1672 return params
1673
1673
1674 def addpartbundlestream2(bundler, repo, **kwargs):
1674 def addpartbundlestream2(bundler, repo, **kwargs):
1675 if not kwargs.get(r'stream', False):
1675 if not kwargs.get(r'stream', False):
1676 return
1676 return
1677
1677
1678 if not streamclone.allowservergeneration(repo):
1678 if not streamclone.allowservergeneration(repo):
1679 raise error.Abort(_('stream data requested but server does not allow '
1679 raise error.Abort(_('stream data requested but server does not allow '
1680 'this feature'),
1680 'this feature'),
1681 hint=_('well-behaved clients should not be '
1681 hint=_('well-behaved clients should not be '
1682 'requesting stream data from servers not '
1682 'requesting stream data from servers not '
1683 'advertising it; the client may be buggy'))
1683 'advertising it; the client may be buggy'))
1684
1684
1685 # Stream clones don't compress well. And compression undermines a
1685 # Stream clones don't compress well. And compression undermines a
1686 # goal of stream clones, which is to be fast. Communicate the desire
1686 # goal of stream clones, which is to be fast. Communicate the desire
1687 # to avoid compression to consumers of the bundle.
1687 # to avoid compression to consumers of the bundle.
1688 bundler.prefercompressed = False
1688 bundler.prefercompressed = False
1689
1689
1690 filecount, bytecount, it = streamclone.generatev2(repo)
1690 filecount, bytecount, it = streamclone.generatev2(repo)
1691 requirements = _formatrequirementsspec(repo.requirements)
1691 requirements = _formatrequirementsspec(repo.requirements)
1692 part = bundler.newpart('stream2', data=it)
1692 part = bundler.newpart('stream2', data=it)
1693 part.addparam('bytecount', '%d' % bytecount, mandatory=True)
1693 part.addparam('bytecount', '%d' % bytecount, mandatory=True)
1694 part.addparam('filecount', '%d' % filecount, mandatory=True)
1694 part.addparam('filecount', '%d' % filecount, mandatory=True)
1695 part.addparam('requirements', requirements, mandatory=True)
1695 part.addparam('requirements', requirements, mandatory=True)
1696
1696
1697 def buildobsmarkerspart(bundler, markers):
1697 def buildobsmarkerspart(bundler, markers):
1698 """add an obsmarker part to the bundler with <markers>
1698 """add an obsmarker part to the bundler with <markers>
1699
1699
1700 No part is created if markers is empty.
1700 No part is created if markers is empty.
1701 Raises ValueError if the bundler doesn't support any known obsmarker format.
1701 Raises ValueError if the bundler doesn't support any known obsmarker format.
1702 """
1702 """
1703 if not markers:
1703 if not markers:
1704 return None
1704 return None
1705
1705
1706 remoteversions = obsmarkersversion(bundler.capabilities)
1706 remoteversions = obsmarkersversion(bundler.capabilities)
1707 version = obsolete.commonversion(remoteversions)
1707 version = obsolete.commonversion(remoteversions)
1708 if version is None:
1708 if version is None:
1709 raise ValueError('bundler does not support common obsmarker format')
1709 raise ValueError('bundler does not support common obsmarker format')
1710 stream = obsolete.encodemarkers(markers, True, version=version)
1710 stream = obsolete.encodemarkers(markers, True, version=version)
1711 return bundler.newpart('obsmarkers', data=stream)
1711 return bundler.newpart('obsmarkers', data=stream)
1712
1712
1713 def writebundle(ui, cg, filename, bundletype, vfs=None, compression=None,
1713 def writebundle(ui, cg, filename, bundletype, vfs=None, compression=None,
1714 compopts=None):
1714 compopts=None):
1715 """Write a bundle file and return its filename.
1715 """Write a bundle file and return its filename.
1716
1716
1717 Existing files will not be overwritten.
1717 Existing files will not be overwritten.
1718 If no filename is specified, a temporary file is created.
1718 If no filename is specified, a temporary file is created.
1719 bz2 compression can be turned off.
1719 bz2 compression can be turned off.
1720 The bundle file will be deleted in case of errors.
1720 The bundle file will be deleted in case of errors.
1721 """
1721 """
1722
1722
1723 if bundletype == "HG20":
1723 if bundletype == "HG20":
1724 bundle = bundle20(ui)
1724 bundle = bundle20(ui)
1725 bundle.setcompression(compression, compopts)
1725 bundle.setcompression(compression, compopts)
1726 part = bundle.newpart('changegroup', data=cg.getchunks())
1726 part = bundle.newpart('changegroup', data=cg.getchunks())
1727 part.addparam('version', cg.version)
1727 part.addparam('version', cg.version)
1728 if 'clcount' in cg.extras:
1728 if 'clcount' in cg.extras:
1729 part.addparam('nbchanges', '%d' % cg.extras['clcount'],
1729 part.addparam('nbchanges', '%d' % cg.extras['clcount'],
1730 mandatory=False)
1730 mandatory=False)
1731 chunkiter = bundle.getchunks()
1731 chunkiter = bundle.getchunks()
1732 else:
1732 else:
1733 # compression argument is only for the bundle2 case
1733 # compression argument is only for the bundle2 case
1734 assert compression is None
1734 assert compression is None
1735 if cg.version != '01':
1735 if cg.version != '01':
1736 raise error.Abort(_('old bundle types only supports v1 '
1736 raise error.Abort(_('old bundle types only supports v1 '
1737 'changegroups'))
1737 'changegroups'))
1738 header, comp = bundletypes[bundletype]
1738 header, comp = bundletypes[bundletype]
1739 if comp not in util.compengines.supportedbundletypes:
1739 if comp not in util.compengines.supportedbundletypes:
1740 raise error.Abort(_('unknown stream compression type: %s')
1740 raise error.Abort(_('unknown stream compression type: %s')
1741 % comp)
1741 % comp)
1742 compengine = util.compengines.forbundletype(comp)
1742 compengine = util.compengines.forbundletype(comp)
1743 def chunkiter():
1743 def chunkiter():
1744 yield header
1744 yield header
1745 for chunk in compengine.compressstream(cg.getchunks(), compopts):
1745 for chunk in compengine.compressstream(cg.getchunks(), compopts):
1746 yield chunk
1746 yield chunk
1747 chunkiter = chunkiter()
1747 chunkiter = chunkiter()
1748
1748
1749 # parse the changegroup data, otherwise we will block
1749 # parse the changegroup data, otherwise we will block
1750 # in case of sshrepo because we don't know the end of the stream
1750 # in case of sshrepo because we don't know the end of the stream
1751 return changegroup.writechunks(ui, chunkiter, filename, vfs=vfs)
1751 return changegroup.writechunks(ui, chunkiter, filename, vfs=vfs)
1752
1752
1753 def combinechangegroupresults(op):
1753 def combinechangegroupresults(op):
1754 """logic to combine 0 or more addchangegroup results into one"""
1754 """logic to combine 0 or more addchangegroup results into one"""
1755 results = [r.get('return', 0)
1755 results = [r.get('return', 0)
1756 for r in op.records['changegroup']]
1756 for r in op.records['changegroup']]
1757 changedheads = 0
1757 changedheads = 0
1758 result = 1
1758 result = 1
1759 for ret in results:
1759 for ret in results:
1760 # If any changegroup result is 0, return 0
1760 # If any changegroup result is 0, return 0
1761 if ret == 0:
1761 if ret == 0:
1762 result = 0
1762 result = 0
1763 break
1763 break
1764 if ret < -1:
1764 if ret < -1:
1765 changedheads += ret + 1
1765 changedheads += ret + 1
1766 elif ret > 1:
1766 elif ret > 1:
1767 changedheads += ret - 1
1767 changedheads += ret - 1
1768 if changedheads > 0:
1768 if changedheads > 0:
1769 result = 1 + changedheads
1769 result = 1 + changedheads
1770 elif changedheads < 0:
1770 elif changedheads < 0:
1771 result = -1 + changedheads
1771 result = -1 + changedheads
1772 return result
1772 return result
1773
1773
1774 @parthandler('changegroup', ('version', 'nbchanges', 'treemanifest',
1774 @parthandler('changegroup', ('version', 'nbchanges', 'treemanifest',
1775 'targetphase'))
1775 'targetphase'))
1776 def handlechangegroup(op, inpart):
1776 def handlechangegroup(op, inpart):
1777 """apply a changegroup part on the repo
1777 """apply a changegroup part on the repo
1778
1778
1779 This is a very early implementation that will massive rework before being
1779 This is a very early implementation that will massive rework before being
1780 inflicted to any end-user.
1780 inflicted to any end-user.
1781 """
1781 """
1782 from . import localrepo
1782 from . import localrepo
1783
1783
1784 tr = op.gettransaction()
1784 tr = op.gettransaction()
1785 unpackerversion = inpart.params.get('version', '01')
1785 unpackerversion = inpart.params.get('version', '01')
1786 # We should raise an appropriate exception here
1786 # We should raise an appropriate exception here
1787 cg = changegroup.getunbundler(unpackerversion, inpart, None)
1787 cg = changegroup.getunbundler(unpackerversion, inpart, None)
1788 # the source and url passed here are overwritten by the one contained in
1788 # the source and url passed here are overwritten by the one contained in
1789 # the transaction.hookargs argument. So 'bundle2' is a placeholder
1789 # the transaction.hookargs argument. So 'bundle2' is a placeholder
1790 nbchangesets = None
1790 nbchangesets = None
1791 if 'nbchanges' in inpart.params:
1791 if 'nbchanges' in inpart.params:
1792 nbchangesets = int(inpart.params.get('nbchanges'))
1792 nbchangesets = int(inpart.params.get('nbchanges'))
1793 if ('treemanifest' in inpart.params and
1793 if ('treemanifest' in inpart.params and
1794 'treemanifest' not in op.repo.requirements):
1794 'treemanifest' not in op.repo.requirements):
1795 if len(op.repo.changelog) != 0:
1795 if len(op.repo.changelog) != 0:
1796 raise error.Abort(_(
1796 raise error.Abort(_(
1797 "bundle contains tree manifests, but local repo is "
1797 "bundle contains tree manifests, but local repo is "
1798 "non-empty and does not use tree manifests"))
1798 "non-empty and does not use tree manifests"))
1799 op.repo.requirements.add('treemanifest')
1799 op.repo.requirements.add('treemanifest')
1800 op.repo.svfs.options = localrepo.resolvestorevfsoptions(
1800 op.repo.svfs.options = localrepo.resolvestorevfsoptions(
1801 op.repo.ui, op.repo.requirements, op.repo.features)
1801 op.repo.ui, op.repo.requirements, op.repo.features)
1802 op.repo._writerequirements()
1802 op.repo._writerequirements()
1803 extrakwargs = {}
1803 extrakwargs = {}
1804 targetphase = inpart.params.get('targetphase')
1804 targetphase = inpart.params.get('targetphase')
1805 if targetphase is not None:
1805 if targetphase is not None:
1806 extrakwargs[r'targetphase'] = int(targetphase)
1806 extrakwargs[r'targetphase'] = int(targetphase)
1807 ret = _processchangegroup(op, cg, tr, 'bundle2', 'bundle2',
1807 ret = _processchangegroup(op, cg, tr, 'bundle2', 'bundle2',
1808 expectedtotal=nbchangesets, **extrakwargs)
1808 expectedtotal=nbchangesets, **extrakwargs)
1809 if op.reply is not None:
1809 if op.reply is not None:
1810 # This is definitely not the final form of this
1810 # This is definitely not the final form of this
1811 # return. But one need to start somewhere.
1811 # return. But one need to start somewhere.
1812 part = op.reply.newpart('reply:changegroup', mandatory=False)
1812 part = op.reply.newpart('reply:changegroup', mandatory=False)
1813 part.addparam(
1813 part.addparam(
1814 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
1814 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
1815 part.addparam('return', '%i' % ret, mandatory=False)
1815 part.addparam('return', '%i' % ret, mandatory=False)
1816 assert not inpart.read()
1816 assert not inpart.read()
1817
1817
1818 _remotechangegroupparams = tuple(['url', 'size', 'digests'] +
1818 _remotechangegroupparams = tuple(['url', 'size', 'digests'] +
1819 ['digest:%s' % k for k in util.DIGESTS.keys()])
1819 ['digest:%s' % k for k in util.DIGESTS.keys()])
1820 @parthandler('remote-changegroup', _remotechangegroupparams)
1820 @parthandler('remote-changegroup', _remotechangegroupparams)
1821 def handleremotechangegroup(op, inpart):
1821 def handleremotechangegroup(op, inpart):
1822 """apply a bundle10 on the repo, given an url and validation information
1822 """apply a bundle10 on the repo, given an url and validation information
1823
1823
1824 All the information about the remote bundle to import are given as
1824 All the information about the remote bundle to import are given as
1825 parameters. The parameters include:
1825 parameters. The parameters include:
1826 - url: the url to the bundle10.
1826 - url: the url to the bundle10.
1827 - size: the bundle10 file size. It is used to validate what was
1827 - size: the bundle10 file size. It is used to validate what was
1828 retrieved by the client matches the server knowledge about the bundle.
1828 retrieved by the client matches the server knowledge about the bundle.
1829 - digests: a space separated list of the digest types provided as
1829 - digests: a space separated list of the digest types provided as
1830 parameters.
1830 parameters.
1831 - digest:<digest-type>: the hexadecimal representation of the digest with
1831 - digest:<digest-type>: the hexadecimal representation of the digest with
1832 that name. Like the size, it is used to validate what was retrieved by
1832 that name. Like the size, it is used to validate what was retrieved by
1833 the client matches what the server knows about the bundle.
1833 the client matches what the server knows about the bundle.
1834
1834
1835 When multiple digest types are given, all of them are checked.
1835 When multiple digest types are given, all of them are checked.
1836 """
1836 """
1837 try:
1837 try:
1838 raw_url = inpart.params['url']
1838 raw_url = inpart.params['url']
1839 except KeyError:
1839 except KeyError:
1840 raise error.Abort(_('remote-changegroup: missing "%s" param') % 'url')
1840 raise error.Abort(_('remote-changegroup: missing "%s" param') % 'url')
1841 parsed_url = util.url(raw_url)
1841 parsed_url = util.url(raw_url)
1842 if parsed_url.scheme not in capabilities['remote-changegroup']:
1842 if parsed_url.scheme not in capabilities['remote-changegroup']:
1843 raise error.Abort(_('remote-changegroup does not support %s urls') %
1843 raise error.Abort(_('remote-changegroup does not support %s urls') %
1844 parsed_url.scheme)
1844 parsed_url.scheme)
1845
1845
1846 try:
1846 try:
1847 size = int(inpart.params['size'])
1847 size = int(inpart.params['size'])
1848 except ValueError:
1848 except ValueError:
1849 raise error.Abort(_('remote-changegroup: invalid value for param "%s"')
1849 raise error.Abort(_('remote-changegroup: invalid value for param "%s"')
1850 % 'size')
1850 % 'size')
1851 except KeyError:
1851 except KeyError:
1852 raise error.Abort(_('remote-changegroup: missing "%s" param') % 'size')
1852 raise error.Abort(_('remote-changegroup: missing "%s" param') % 'size')
1853
1853
1854 digests = {}
1854 digests = {}
1855 for typ in inpart.params.get('digests', '').split():
1855 for typ in inpart.params.get('digests', '').split():
1856 param = 'digest:%s' % typ
1856 param = 'digest:%s' % typ
1857 try:
1857 try:
1858 value = inpart.params[param]
1858 value = inpart.params[param]
1859 except KeyError:
1859 except KeyError:
1860 raise error.Abort(_('remote-changegroup: missing "%s" param') %
1860 raise error.Abort(_('remote-changegroup: missing "%s" param') %
1861 param)
1861 param)
1862 digests[typ] = value
1862 digests[typ] = value
1863
1863
1864 real_part = util.digestchecker(url.open(op.ui, raw_url), size, digests)
1864 real_part = util.digestchecker(url.open(op.ui, raw_url), size, digests)
1865
1865
1866 tr = op.gettransaction()
1866 tr = op.gettransaction()
1867 from . import exchange
1867 from . import exchange
1868 cg = exchange.readbundle(op.repo.ui, real_part, raw_url)
1868 cg = exchange.readbundle(op.repo.ui, real_part, raw_url)
1869 if not isinstance(cg, changegroup.cg1unpacker):
1869 if not isinstance(cg, changegroup.cg1unpacker):
1870 raise error.Abort(_('%s: not a bundle version 1.0') %
1870 raise error.Abort(_('%s: not a bundle version 1.0') %
1871 util.hidepassword(raw_url))
1871 util.hidepassword(raw_url))
1872 ret = _processchangegroup(op, cg, tr, 'bundle2', 'bundle2')
1872 ret = _processchangegroup(op, cg, tr, 'bundle2', 'bundle2')
1873 if op.reply is not None:
1873 if op.reply is not None:
1874 # This is definitely not the final form of this
1874 # This is definitely not the final form of this
1875 # return. But one need to start somewhere.
1875 # return. But one need to start somewhere.
1876 part = op.reply.newpart('reply:changegroup')
1876 part = op.reply.newpart('reply:changegroup')
1877 part.addparam(
1877 part.addparam(
1878 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
1878 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
1879 part.addparam('return', '%i' % ret, mandatory=False)
1879 part.addparam('return', '%i' % ret, mandatory=False)
1880 try:
1880 try:
1881 real_part.validate()
1881 real_part.validate()
1882 except error.Abort as e:
1882 except error.Abort as e:
1883 raise error.Abort(_('bundle at %s is corrupted:\n%s') %
1883 raise error.Abort(_('bundle at %s is corrupted:\n%s') %
1884 (util.hidepassword(raw_url), bytes(e)))
1884 (util.hidepassword(raw_url), bytes(e)))
1885 assert not inpart.read()
1885 assert not inpart.read()
1886
1886
1887 @parthandler('reply:changegroup', ('return', 'in-reply-to'))
1887 @parthandler('reply:changegroup', ('return', 'in-reply-to'))
1888 def handlereplychangegroup(op, inpart):
1888 def handlereplychangegroup(op, inpart):
1889 ret = int(inpart.params['return'])
1889 ret = int(inpart.params['return'])
1890 replyto = int(inpart.params['in-reply-to'])
1890 replyto = int(inpart.params['in-reply-to'])
1891 op.records.add('changegroup', {'return': ret}, replyto)
1891 op.records.add('changegroup', {'return': ret}, replyto)
1892
1892
1893 @parthandler('check:bookmarks')
1893 @parthandler('check:bookmarks')
1894 def handlecheckbookmarks(op, inpart):
1894 def handlecheckbookmarks(op, inpart):
1895 """check location of bookmarks
1895 """check location of bookmarks
1896
1896
1897 This part is to be used to detect push race regarding bookmark, it
1897 This part is to be used to detect push race regarding bookmark, it
1898 contains binary encoded (bookmark, node) tuple. If the local state does
1898 contains binary encoded (bookmark, node) tuple. If the local state does
1899 not marks the one in the part, a PushRaced exception is raised
1899 not marks the one in the part, a PushRaced exception is raised
1900 """
1900 """
1901 bookdata = bookmarks.binarydecode(inpart)
1901 bookdata = bookmarks.binarydecode(inpart)
1902
1902
1903 msgstandard = ('repository changed while pushing - please try again '
1903 msgstandard = ('remote repository changed while pushing - please try again '
1904 '(bookmark "%s" move from %s to %s)')
1904 '(bookmark "%s" move from %s to %s)')
1905 msgmissing = ('repository changed while pushing - please try again '
1905 msgmissing = ('remote repository changed while pushing - please try again '
1906 '(bookmark "%s" is missing, expected %s)')
1906 '(bookmark "%s" is missing, expected %s)')
1907 msgexist = ('repository changed while pushing - please try again '
1907 msgexist = ('remote repository changed while pushing - please try again '
1908 '(bookmark "%s" set on %s, expected missing)')
1908 '(bookmark "%s" set on %s, expected missing)')
1909 for book, node in bookdata:
1909 for book, node in bookdata:
1910 currentnode = op.repo._bookmarks.get(book)
1910 currentnode = op.repo._bookmarks.get(book)
1911 if currentnode != node:
1911 if currentnode != node:
1912 if node is None:
1912 if node is None:
1913 finalmsg = msgexist % (book, nodemod.short(currentnode))
1913 finalmsg = msgexist % (book, nodemod.short(currentnode))
1914 elif currentnode is None:
1914 elif currentnode is None:
1915 finalmsg = msgmissing % (book, nodemod.short(node))
1915 finalmsg = msgmissing % (book, nodemod.short(node))
1916 else:
1916 else:
1917 finalmsg = msgstandard % (book, nodemod.short(node),
1917 finalmsg = msgstandard % (book, nodemod.short(node),
1918 nodemod.short(currentnode))
1918 nodemod.short(currentnode))
1919 raise error.PushRaced(finalmsg)
1919 raise error.PushRaced(finalmsg)
1920
1920
1921 @parthandler('check:heads')
1921 @parthandler('check:heads')
1922 def handlecheckheads(op, inpart):
1922 def handlecheckheads(op, inpart):
1923 """check that head of the repo did not change
1923 """check that head of the repo did not change
1924
1924
1925 This is used to detect a push race when using unbundle.
1925 This is used to detect a push race when using unbundle.
1926 This replaces the "heads" argument of unbundle."""
1926 This replaces the "heads" argument of unbundle."""
1927 h = inpart.read(20)
1927 h = inpart.read(20)
1928 heads = []
1928 heads = []
1929 while len(h) == 20:
1929 while len(h) == 20:
1930 heads.append(h)
1930 heads.append(h)
1931 h = inpart.read(20)
1931 h = inpart.read(20)
1932 assert not h
1932 assert not h
1933 # Trigger a transaction so that we are guaranteed to have the lock now.
1933 # Trigger a transaction so that we are guaranteed to have the lock now.
1934 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1934 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1935 op.gettransaction()
1935 op.gettransaction()
1936 if sorted(heads) != sorted(op.repo.heads()):
1936 if sorted(heads) != sorted(op.repo.heads()):
1937 raise error.PushRaced('repository changed while pushing - '
1937 raise error.PushRaced('remote repository changed while pushing - '
1938 'please try again')
1938 'please try again')
1939
1939
1940 @parthandler('check:updated-heads')
1940 @parthandler('check:updated-heads')
1941 def handlecheckupdatedheads(op, inpart):
1941 def handlecheckupdatedheads(op, inpart):
1942 """check for race on the heads touched by a push
1942 """check for race on the heads touched by a push
1943
1943
1944 This is similar to 'check:heads' but focus on the heads actually updated
1944 This is similar to 'check:heads' but focus on the heads actually updated
1945 during the push. If other activities happen on unrelated heads, it is
1945 during the push. If other activities happen on unrelated heads, it is
1946 ignored.
1946 ignored.
1947
1947
1948 This allow server with high traffic to avoid push contention as long as
1948 This allow server with high traffic to avoid push contention as long as
1949 unrelated parts of the graph are involved."""
1949 unrelated parts of the graph are involved."""
1950 h = inpart.read(20)
1950 h = inpart.read(20)
1951 heads = []
1951 heads = []
1952 while len(h) == 20:
1952 while len(h) == 20:
1953 heads.append(h)
1953 heads.append(h)
1954 h = inpart.read(20)
1954 h = inpart.read(20)
1955 assert not h
1955 assert not h
1956 # trigger a transaction so that we are guaranteed to have the lock now.
1956 # trigger a transaction so that we are guaranteed to have the lock now.
1957 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1957 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1958 op.gettransaction()
1958 op.gettransaction()
1959
1959
1960 currentheads = set()
1960 currentheads = set()
1961 for ls in op.repo.branchmap().itervalues():
1961 for ls in op.repo.branchmap().itervalues():
1962 currentheads.update(ls)
1962 currentheads.update(ls)
1963
1963
1964 for h in heads:
1964 for h in heads:
1965 if h not in currentheads:
1965 if h not in currentheads:
1966 raise error.PushRaced('repository changed while pushing - '
1966 raise error.PushRaced('remote repository changed while pushing - '
1967 'please try again')
1967 'please try again')
1968
1968
1969 @parthandler('check:phases')
1969 @parthandler('check:phases')
1970 def handlecheckphases(op, inpart):
1970 def handlecheckphases(op, inpart):
1971 """check that phase boundaries of the repository did not change
1971 """check that phase boundaries of the repository did not change
1972
1972
1973 This is used to detect a push race.
1973 This is used to detect a push race.
1974 """
1974 """
1975 phasetonodes = phases.binarydecode(inpart)
1975 phasetonodes = phases.binarydecode(inpart)
1976 unfi = op.repo.unfiltered()
1976 unfi = op.repo.unfiltered()
1977 cl = unfi.changelog
1977 cl = unfi.changelog
1978 phasecache = unfi._phasecache
1978 phasecache = unfi._phasecache
1979 msg = ('repository changed while pushing - please try again '
1979 msg = ('remote repository changed while pushing - please try again '
1980 '(%s is %s expected %s)')
1980 '(%s is %s expected %s)')
1981 for expectedphase, nodes in enumerate(phasetonodes):
1981 for expectedphase, nodes in enumerate(phasetonodes):
1982 for n in nodes:
1982 for n in nodes:
1983 actualphase = phasecache.phase(unfi, cl.rev(n))
1983 actualphase = phasecache.phase(unfi, cl.rev(n))
1984 if actualphase != expectedphase:
1984 if actualphase != expectedphase:
1985 finalmsg = msg % (nodemod.short(n),
1985 finalmsg = msg % (nodemod.short(n),
1986 phases.phasenames[actualphase],
1986 phases.phasenames[actualphase],
1987 phases.phasenames[expectedphase])
1987 phases.phasenames[expectedphase])
1988 raise error.PushRaced(finalmsg)
1988 raise error.PushRaced(finalmsg)
1989
1989
1990 @parthandler('output')
1990 @parthandler('output')
1991 def handleoutput(op, inpart):
1991 def handleoutput(op, inpart):
1992 """forward output captured on the server to the client"""
1992 """forward output captured on the server to the client"""
1993 for line in inpart.read().splitlines():
1993 for line in inpart.read().splitlines():
1994 op.ui.status(_('remote: %s\n') % line)
1994 op.ui.status(_('remote: %s\n') % line)
1995
1995
1996 @parthandler('replycaps')
1996 @parthandler('replycaps')
1997 def handlereplycaps(op, inpart):
1997 def handlereplycaps(op, inpart):
1998 """Notify that a reply bundle should be created
1998 """Notify that a reply bundle should be created
1999
1999
2000 The payload contains the capabilities information for the reply"""
2000 The payload contains the capabilities information for the reply"""
2001 caps = decodecaps(inpart.read())
2001 caps = decodecaps(inpart.read())
2002 if op.reply is None:
2002 if op.reply is None:
2003 op.reply = bundle20(op.ui, caps)
2003 op.reply = bundle20(op.ui, caps)
2004
2004
2005 class AbortFromPart(error.Abort):
2005 class AbortFromPart(error.Abort):
2006 """Sub-class of Abort that denotes an error from a bundle2 part."""
2006 """Sub-class of Abort that denotes an error from a bundle2 part."""
2007
2007
2008 @parthandler('error:abort', ('message', 'hint'))
2008 @parthandler('error:abort', ('message', 'hint'))
2009 def handleerrorabort(op, inpart):
2009 def handleerrorabort(op, inpart):
2010 """Used to transmit abort error over the wire"""
2010 """Used to transmit abort error over the wire"""
2011 raise AbortFromPart(inpart.params['message'],
2011 raise AbortFromPart(inpart.params['message'],
2012 hint=inpart.params.get('hint'))
2012 hint=inpart.params.get('hint'))
2013
2013
2014 @parthandler('error:pushkey', ('namespace', 'key', 'new', 'old', 'ret',
2014 @parthandler('error:pushkey', ('namespace', 'key', 'new', 'old', 'ret',
2015 'in-reply-to'))
2015 'in-reply-to'))
2016 def handleerrorpushkey(op, inpart):
2016 def handleerrorpushkey(op, inpart):
2017 """Used to transmit failure of a mandatory pushkey over the wire"""
2017 """Used to transmit failure of a mandatory pushkey over the wire"""
2018 kwargs = {}
2018 kwargs = {}
2019 for name in ('namespace', 'key', 'new', 'old', 'ret'):
2019 for name in ('namespace', 'key', 'new', 'old', 'ret'):
2020 value = inpart.params.get(name)
2020 value = inpart.params.get(name)
2021 if value is not None:
2021 if value is not None:
2022 kwargs[name] = value
2022 kwargs[name] = value
2023 raise error.PushkeyFailed(inpart.params['in-reply-to'],
2023 raise error.PushkeyFailed(inpart.params['in-reply-to'],
2024 **pycompat.strkwargs(kwargs))
2024 **pycompat.strkwargs(kwargs))
2025
2025
2026 @parthandler('error:unsupportedcontent', ('parttype', 'params'))
2026 @parthandler('error:unsupportedcontent', ('parttype', 'params'))
2027 def handleerrorunsupportedcontent(op, inpart):
2027 def handleerrorunsupportedcontent(op, inpart):
2028 """Used to transmit unknown content error over the wire"""
2028 """Used to transmit unknown content error over the wire"""
2029 kwargs = {}
2029 kwargs = {}
2030 parttype = inpart.params.get('parttype')
2030 parttype = inpart.params.get('parttype')
2031 if parttype is not None:
2031 if parttype is not None:
2032 kwargs['parttype'] = parttype
2032 kwargs['parttype'] = parttype
2033 params = inpart.params.get('params')
2033 params = inpart.params.get('params')
2034 if params is not None:
2034 if params is not None:
2035 kwargs['params'] = params.split('\0')
2035 kwargs['params'] = params.split('\0')
2036
2036
2037 raise error.BundleUnknownFeatureError(**pycompat.strkwargs(kwargs))
2037 raise error.BundleUnknownFeatureError(**pycompat.strkwargs(kwargs))
2038
2038
2039 @parthandler('error:pushraced', ('message',))
2039 @parthandler('error:pushraced', ('message',))
2040 def handleerrorpushraced(op, inpart):
2040 def handleerrorpushraced(op, inpart):
2041 """Used to transmit push race error over the wire"""
2041 """Used to transmit push race error over the wire"""
2042 raise error.ResponseError(_('push failed:'), inpart.params['message'])
2042 raise error.ResponseError(_('push failed:'), inpart.params['message'])
2043
2043
2044 @parthandler('listkeys', ('namespace',))
2044 @parthandler('listkeys', ('namespace',))
2045 def handlelistkeys(op, inpart):
2045 def handlelistkeys(op, inpart):
2046 """retrieve pushkey namespace content stored in a bundle2"""
2046 """retrieve pushkey namespace content stored in a bundle2"""
2047 namespace = inpart.params['namespace']
2047 namespace = inpart.params['namespace']
2048 r = pushkey.decodekeys(inpart.read())
2048 r = pushkey.decodekeys(inpart.read())
2049 op.records.add('listkeys', (namespace, r))
2049 op.records.add('listkeys', (namespace, r))
2050
2050
2051 @parthandler('pushkey', ('namespace', 'key', 'old', 'new'))
2051 @parthandler('pushkey', ('namespace', 'key', 'old', 'new'))
2052 def handlepushkey(op, inpart):
2052 def handlepushkey(op, inpart):
2053 """process a pushkey request"""
2053 """process a pushkey request"""
2054 dec = pushkey.decode
2054 dec = pushkey.decode
2055 namespace = dec(inpart.params['namespace'])
2055 namespace = dec(inpart.params['namespace'])
2056 key = dec(inpart.params['key'])
2056 key = dec(inpart.params['key'])
2057 old = dec(inpart.params['old'])
2057 old = dec(inpart.params['old'])
2058 new = dec(inpart.params['new'])
2058 new = dec(inpart.params['new'])
2059 # Grab the transaction to ensure that we have the lock before performing the
2059 # Grab the transaction to ensure that we have the lock before performing the
2060 # pushkey.
2060 # pushkey.
2061 if op.ui.configbool('experimental', 'bundle2lazylocking'):
2061 if op.ui.configbool('experimental', 'bundle2lazylocking'):
2062 op.gettransaction()
2062 op.gettransaction()
2063 ret = op.repo.pushkey(namespace, key, old, new)
2063 ret = op.repo.pushkey(namespace, key, old, new)
2064 record = {'namespace': namespace,
2064 record = {'namespace': namespace,
2065 'key': key,
2065 'key': key,
2066 'old': old,
2066 'old': old,
2067 'new': new}
2067 'new': new}
2068 op.records.add('pushkey', record)
2068 op.records.add('pushkey', record)
2069 if op.reply is not None:
2069 if op.reply is not None:
2070 rpart = op.reply.newpart('reply:pushkey')
2070 rpart = op.reply.newpart('reply:pushkey')
2071 rpart.addparam(
2071 rpart.addparam(
2072 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
2072 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
2073 rpart.addparam('return', '%i' % ret, mandatory=False)
2073 rpart.addparam('return', '%i' % ret, mandatory=False)
2074 if inpart.mandatory and not ret:
2074 if inpart.mandatory and not ret:
2075 kwargs = {}
2075 kwargs = {}
2076 for key in ('namespace', 'key', 'new', 'old', 'ret'):
2076 for key in ('namespace', 'key', 'new', 'old', 'ret'):
2077 if key in inpart.params:
2077 if key in inpart.params:
2078 kwargs[key] = inpart.params[key]
2078 kwargs[key] = inpart.params[key]
2079 raise error.PushkeyFailed(partid='%d' % inpart.id,
2079 raise error.PushkeyFailed(partid='%d' % inpart.id,
2080 **pycompat.strkwargs(kwargs))
2080 **pycompat.strkwargs(kwargs))
2081
2081
2082 @parthandler('bookmarks')
2082 @parthandler('bookmarks')
2083 def handlebookmark(op, inpart):
2083 def handlebookmark(op, inpart):
2084 """transmit bookmark information
2084 """transmit bookmark information
2085
2085
2086 The part contains binary encoded bookmark information.
2086 The part contains binary encoded bookmark information.
2087
2087
2088 The exact behavior of this part can be controlled by the 'bookmarks' mode
2088 The exact behavior of this part can be controlled by the 'bookmarks' mode
2089 on the bundle operation.
2089 on the bundle operation.
2090
2090
2091 When mode is 'apply' (the default) the bookmark information is applied as
2091 When mode is 'apply' (the default) the bookmark information is applied as
2092 is to the unbundling repository. Make sure a 'check:bookmarks' part is
2092 is to the unbundling repository. Make sure a 'check:bookmarks' part is
2093 issued earlier to check for push races in such update. This behavior is
2093 issued earlier to check for push races in such update. This behavior is
2094 suitable for pushing.
2094 suitable for pushing.
2095
2095
2096 When mode is 'records', the information is recorded into the 'bookmarks'
2096 When mode is 'records', the information is recorded into the 'bookmarks'
2097 records of the bundle operation. This behavior is suitable for pulling.
2097 records of the bundle operation. This behavior is suitable for pulling.
2098 """
2098 """
2099 changes = bookmarks.binarydecode(inpart)
2099 changes = bookmarks.binarydecode(inpart)
2100
2100
2101 pushkeycompat = op.repo.ui.configbool('server', 'bookmarks-pushkey-compat')
2101 pushkeycompat = op.repo.ui.configbool('server', 'bookmarks-pushkey-compat')
2102 bookmarksmode = op.modes.get('bookmarks', 'apply')
2102 bookmarksmode = op.modes.get('bookmarks', 'apply')
2103
2103
2104 if bookmarksmode == 'apply':
2104 if bookmarksmode == 'apply':
2105 tr = op.gettransaction()
2105 tr = op.gettransaction()
2106 bookstore = op.repo._bookmarks
2106 bookstore = op.repo._bookmarks
2107 if pushkeycompat:
2107 if pushkeycompat:
2108 allhooks = []
2108 allhooks = []
2109 for book, node in changes:
2109 for book, node in changes:
2110 hookargs = tr.hookargs.copy()
2110 hookargs = tr.hookargs.copy()
2111 hookargs['pushkeycompat'] = '1'
2111 hookargs['pushkeycompat'] = '1'
2112 hookargs['namespace'] = 'bookmarks'
2112 hookargs['namespace'] = 'bookmarks'
2113 hookargs['key'] = book
2113 hookargs['key'] = book
2114 hookargs['old'] = nodemod.hex(bookstore.get(book, ''))
2114 hookargs['old'] = nodemod.hex(bookstore.get(book, ''))
2115 hookargs['new'] = nodemod.hex(node if node is not None else '')
2115 hookargs['new'] = nodemod.hex(node if node is not None else '')
2116 allhooks.append(hookargs)
2116 allhooks.append(hookargs)
2117
2117
2118 for hookargs in allhooks:
2118 for hookargs in allhooks:
2119 op.repo.hook('prepushkey', throw=True,
2119 op.repo.hook('prepushkey', throw=True,
2120 **pycompat.strkwargs(hookargs))
2120 **pycompat.strkwargs(hookargs))
2121
2121
2122 bookstore.applychanges(op.repo, op.gettransaction(), changes)
2122 bookstore.applychanges(op.repo, op.gettransaction(), changes)
2123
2123
2124 if pushkeycompat:
2124 if pushkeycompat:
2125 def runhook():
2125 def runhook():
2126 for hookargs in allhooks:
2126 for hookargs in allhooks:
2127 op.repo.hook('pushkey', **pycompat.strkwargs(hookargs))
2127 op.repo.hook('pushkey', **pycompat.strkwargs(hookargs))
2128 op.repo._afterlock(runhook)
2128 op.repo._afterlock(runhook)
2129
2129
2130 elif bookmarksmode == 'records':
2130 elif bookmarksmode == 'records':
2131 for book, node in changes:
2131 for book, node in changes:
2132 record = {'bookmark': book, 'node': node}
2132 record = {'bookmark': book, 'node': node}
2133 op.records.add('bookmarks', record)
2133 op.records.add('bookmarks', record)
2134 else:
2134 else:
2135 raise error.ProgrammingError('unkown bookmark mode: %s' % bookmarksmode)
2135 raise error.ProgrammingError('unkown bookmark mode: %s' % bookmarksmode)
2136
2136
2137 @parthandler('phase-heads')
2137 @parthandler('phase-heads')
2138 def handlephases(op, inpart):
2138 def handlephases(op, inpart):
2139 """apply phases from bundle part to repo"""
2139 """apply phases from bundle part to repo"""
2140 headsbyphase = phases.binarydecode(inpart)
2140 headsbyphase = phases.binarydecode(inpart)
2141 phases.updatephases(op.repo.unfiltered(), op.gettransaction, headsbyphase)
2141 phases.updatephases(op.repo.unfiltered(), op.gettransaction, headsbyphase)
2142
2142
2143 @parthandler('reply:pushkey', ('return', 'in-reply-to'))
2143 @parthandler('reply:pushkey', ('return', 'in-reply-to'))
2144 def handlepushkeyreply(op, inpart):
2144 def handlepushkeyreply(op, inpart):
2145 """retrieve the result of a pushkey request"""
2145 """retrieve the result of a pushkey request"""
2146 ret = int(inpart.params['return'])
2146 ret = int(inpart.params['return'])
2147 partid = int(inpart.params['in-reply-to'])
2147 partid = int(inpart.params['in-reply-to'])
2148 op.records.add('pushkey', {'return': ret}, partid)
2148 op.records.add('pushkey', {'return': ret}, partid)
2149
2149
2150 @parthandler('obsmarkers')
2150 @parthandler('obsmarkers')
2151 def handleobsmarker(op, inpart):
2151 def handleobsmarker(op, inpart):
2152 """add a stream of obsmarkers to the repo"""
2152 """add a stream of obsmarkers to the repo"""
2153 tr = op.gettransaction()
2153 tr = op.gettransaction()
2154 markerdata = inpart.read()
2154 markerdata = inpart.read()
2155 if op.ui.config('experimental', 'obsmarkers-exchange-debug'):
2155 if op.ui.config('experimental', 'obsmarkers-exchange-debug'):
2156 op.ui.write(('obsmarker-exchange: %i bytes received\n')
2156 op.ui.write(('obsmarker-exchange: %i bytes received\n')
2157 % len(markerdata))
2157 % len(markerdata))
2158 # The mergemarkers call will crash if marker creation is not enabled.
2158 # The mergemarkers call will crash if marker creation is not enabled.
2159 # we want to avoid this if the part is advisory.
2159 # we want to avoid this if the part is advisory.
2160 if not inpart.mandatory and op.repo.obsstore.readonly:
2160 if not inpart.mandatory and op.repo.obsstore.readonly:
2161 op.repo.ui.debug('ignoring obsolescence markers, feature not enabled\n')
2161 op.repo.ui.debug('ignoring obsolescence markers, feature not enabled\n')
2162 return
2162 return
2163 new = op.repo.obsstore.mergemarkers(tr, markerdata)
2163 new = op.repo.obsstore.mergemarkers(tr, markerdata)
2164 op.repo.invalidatevolatilesets()
2164 op.repo.invalidatevolatilesets()
2165 if new:
2165 if new:
2166 op.repo.ui.status(_('%i new obsolescence markers\n') % new)
2166 op.repo.ui.status(_('%i new obsolescence markers\n') % new)
2167 op.records.add('obsmarkers', {'new': new})
2167 op.records.add('obsmarkers', {'new': new})
2168 if op.reply is not None:
2168 if op.reply is not None:
2169 rpart = op.reply.newpart('reply:obsmarkers')
2169 rpart = op.reply.newpart('reply:obsmarkers')
2170 rpart.addparam(
2170 rpart.addparam(
2171 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
2171 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
2172 rpart.addparam('new', '%i' % new, mandatory=False)
2172 rpart.addparam('new', '%i' % new, mandatory=False)
2173
2173
2174
2174
2175 @parthandler('reply:obsmarkers', ('new', 'in-reply-to'))
2175 @parthandler('reply:obsmarkers', ('new', 'in-reply-to'))
2176 def handleobsmarkerreply(op, inpart):
2176 def handleobsmarkerreply(op, inpart):
2177 """retrieve the result of a pushkey request"""
2177 """retrieve the result of a pushkey request"""
2178 ret = int(inpart.params['new'])
2178 ret = int(inpart.params['new'])
2179 partid = int(inpart.params['in-reply-to'])
2179 partid = int(inpart.params['in-reply-to'])
2180 op.records.add('obsmarkers', {'new': ret}, partid)
2180 op.records.add('obsmarkers', {'new': ret}, partid)
2181
2181
2182 @parthandler('hgtagsfnodes')
2182 @parthandler('hgtagsfnodes')
2183 def handlehgtagsfnodes(op, inpart):
2183 def handlehgtagsfnodes(op, inpart):
2184 """Applies .hgtags fnodes cache entries to the local repo.
2184 """Applies .hgtags fnodes cache entries to the local repo.
2185
2185
2186 Payload is pairs of 20 byte changeset nodes and filenodes.
2186 Payload is pairs of 20 byte changeset nodes and filenodes.
2187 """
2187 """
2188 # Grab the transaction so we ensure that we have the lock at this point.
2188 # Grab the transaction so we ensure that we have the lock at this point.
2189 if op.ui.configbool('experimental', 'bundle2lazylocking'):
2189 if op.ui.configbool('experimental', 'bundle2lazylocking'):
2190 op.gettransaction()
2190 op.gettransaction()
2191 cache = tags.hgtagsfnodescache(op.repo.unfiltered())
2191 cache = tags.hgtagsfnodescache(op.repo.unfiltered())
2192
2192
2193 count = 0
2193 count = 0
2194 while True:
2194 while True:
2195 node = inpart.read(20)
2195 node = inpart.read(20)
2196 fnode = inpart.read(20)
2196 fnode = inpart.read(20)
2197 if len(node) < 20 or len(fnode) < 20:
2197 if len(node) < 20 or len(fnode) < 20:
2198 op.ui.debug('ignoring incomplete received .hgtags fnodes data\n')
2198 op.ui.debug('ignoring incomplete received .hgtags fnodes data\n')
2199 break
2199 break
2200 cache.setfnode(node, fnode)
2200 cache.setfnode(node, fnode)
2201 count += 1
2201 count += 1
2202
2202
2203 cache.write()
2203 cache.write()
2204 op.ui.debug('applied %i hgtags fnodes cache entries\n' % count)
2204 op.ui.debug('applied %i hgtags fnodes cache entries\n' % count)
2205
2205
2206 rbcstruct = struct.Struct('>III')
2206 rbcstruct = struct.Struct('>III')
2207
2207
2208 @parthandler('cache:rev-branch-cache')
2208 @parthandler('cache:rev-branch-cache')
2209 def handlerbc(op, inpart):
2209 def handlerbc(op, inpart):
2210 """receive a rev-branch-cache payload and update the local cache
2210 """receive a rev-branch-cache payload and update the local cache
2211
2211
2212 The payload is a series of data related to each branch
2212 The payload is a series of data related to each branch
2213
2213
2214 1) branch name length
2214 1) branch name length
2215 2) number of open heads
2215 2) number of open heads
2216 3) number of closed heads
2216 3) number of closed heads
2217 4) open heads nodes
2217 4) open heads nodes
2218 5) closed heads nodes
2218 5) closed heads nodes
2219 """
2219 """
2220 total = 0
2220 total = 0
2221 rawheader = inpart.read(rbcstruct.size)
2221 rawheader = inpart.read(rbcstruct.size)
2222 cache = op.repo.revbranchcache()
2222 cache = op.repo.revbranchcache()
2223 cl = op.repo.unfiltered().changelog
2223 cl = op.repo.unfiltered().changelog
2224 while rawheader:
2224 while rawheader:
2225 header = rbcstruct.unpack(rawheader)
2225 header = rbcstruct.unpack(rawheader)
2226 total += header[1] + header[2]
2226 total += header[1] + header[2]
2227 utf8branch = inpart.read(header[0])
2227 utf8branch = inpart.read(header[0])
2228 branch = encoding.tolocal(utf8branch)
2228 branch = encoding.tolocal(utf8branch)
2229 for x in pycompat.xrange(header[1]):
2229 for x in pycompat.xrange(header[1]):
2230 node = inpart.read(20)
2230 node = inpart.read(20)
2231 rev = cl.rev(node)
2231 rev = cl.rev(node)
2232 cache.setdata(branch, rev, node, False)
2232 cache.setdata(branch, rev, node, False)
2233 for x in pycompat.xrange(header[2]):
2233 for x in pycompat.xrange(header[2]):
2234 node = inpart.read(20)
2234 node = inpart.read(20)
2235 rev = cl.rev(node)
2235 rev = cl.rev(node)
2236 cache.setdata(branch, rev, node, True)
2236 cache.setdata(branch, rev, node, True)
2237 rawheader = inpart.read(rbcstruct.size)
2237 rawheader = inpart.read(rbcstruct.size)
2238 cache.write()
2238 cache.write()
2239
2239
2240 @parthandler('pushvars')
2240 @parthandler('pushvars')
2241 def bundle2getvars(op, part):
2241 def bundle2getvars(op, part):
2242 '''unbundle a bundle2 containing shellvars on the server'''
2242 '''unbundle a bundle2 containing shellvars on the server'''
2243 # An option to disable unbundling on server-side for security reasons
2243 # An option to disable unbundling on server-side for security reasons
2244 if op.ui.configbool('push', 'pushvars.server'):
2244 if op.ui.configbool('push', 'pushvars.server'):
2245 hookargs = {}
2245 hookargs = {}
2246 for key, value in part.advisoryparams:
2246 for key, value in part.advisoryparams:
2247 key = key.upper()
2247 key = key.upper()
2248 # We want pushed variables to have USERVAR_ prepended so we know
2248 # We want pushed variables to have USERVAR_ prepended so we know
2249 # they came from the --pushvar flag.
2249 # they came from the --pushvar flag.
2250 key = "USERVAR_" + key
2250 key = "USERVAR_" + key
2251 hookargs[key] = value
2251 hookargs[key] = value
2252 op.addhookargs(hookargs)
2252 op.addhookargs(hookargs)
2253
2253
2254 @parthandler('stream2', ('requirements', 'filecount', 'bytecount'))
2254 @parthandler('stream2', ('requirements', 'filecount', 'bytecount'))
2255 def handlestreamv2bundle(op, part):
2255 def handlestreamv2bundle(op, part):
2256
2256
2257 requirements = urlreq.unquote(part.params['requirements']).split(',')
2257 requirements = urlreq.unquote(part.params['requirements']).split(',')
2258 filecount = int(part.params['filecount'])
2258 filecount = int(part.params['filecount'])
2259 bytecount = int(part.params['bytecount'])
2259 bytecount = int(part.params['bytecount'])
2260
2260
2261 repo = op.repo
2261 repo = op.repo
2262 if len(repo):
2262 if len(repo):
2263 msg = _('cannot apply stream clone to non empty repository')
2263 msg = _('cannot apply stream clone to non empty repository')
2264 raise error.Abort(msg)
2264 raise error.Abort(msg)
2265
2265
2266 repo.ui.debug('applying stream bundle\n')
2266 repo.ui.debug('applying stream bundle\n')
2267 streamclone.applybundlev2(repo, part, filecount, bytecount,
2267 streamclone.applybundlev2(repo, part, filecount, bytecount,
2268 requirements)
2268 requirements)
2269
2269
2270 def widen_bundle(repo, diffmatcher, common, known, cgversion, ellipses):
2270 def widen_bundle(repo, diffmatcher, common, known, cgversion, ellipses):
2271 """generates bundle2 for widening a narrow clone
2271 """generates bundle2 for widening a narrow clone
2272
2272
2273 repo is the localrepository instance
2273 repo is the localrepository instance
2274 diffmatcher is a differencemacther of '(newincludes, newexcludes) -
2274 diffmatcher is a differencemacther of '(newincludes, newexcludes) -
2275 (oldincludes, oldexcludes)'
2275 (oldincludes, oldexcludes)'
2276 common is set of common heads between server and client
2276 common is set of common heads between server and client
2277 known is a set of revs known on the client side (used in ellipses)
2277 known is a set of revs known on the client side (used in ellipses)
2278 cgversion is the changegroup version to send
2278 cgversion is the changegroup version to send
2279 ellipses is boolean value telling whether to send ellipses data or not
2279 ellipses is boolean value telling whether to send ellipses data or not
2280
2280
2281 returns bundle2 of the data required for extending
2281 returns bundle2 of the data required for extending
2282 """
2282 """
2283 bundler = bundle20(repo.ui)
2283 bundler = bundle20(repo.ui)
2284 commonnodes = set()
2284 commonnodes = set()
2285 cl = repo.changelog
2285 cl = repo.changelog
2286 for r in repo.revs("::%ln", common):
2286 for r in repo.revs("::%ln", common):
2287 commonnodes.add(cl.node(r))
2287 commonnodes.add(cl.node(r))
2288 if commonnodes:
2288 if commonnodes:
2289 # XXX: we should only send the filelogs (and treemanifest). user
2289 # XXX: we should only send the filelogs (and treemanifest). user
2290 # already has the changelog and manifest
2290 # already has the changelog and manifest
2291 packer = changegroup.getbundler(cgversion, repo,
2291 packer = changegroup.getbundler(cgversion, repo,
2292 filematcher=diffmatcher,
2292 filematcher=diffmatcher,
2293 fullnodes=commonnodes)
2293 fullnodes=commonnodes)
2294 cgdata = packer.generate(set([nodemod.nullid]), list(commonnodes),
2294 cgdata = packer.generate(set([nodemod.nullid]), list(commonnodes),
2295 False, 'narrow_widen', changelog=False)
2295 False, 'narrow_widen', changelog=False)
2296
2296
2297 part = bundler.newpart('changegroup', data=cgdata)
2297 part = bundler.newpart('changegroup', data=cgdata)
2298 part.addparam('version', cgversion)
2298 part.addparam('version', cgversion)
2299 if 'treemanifest' in repo.requirements:
2299 if 'treemanifest' in repo.requirements:
2300 part.addparam('treemanifest', '1')
2300 part.addparam('treemanifest', '1')
2301
2301
2302 return bundler
2302 return bundler
@@ -1,1159 +1,1159
1 #testcases sshv1 sshv2
1 #testcases sshv1 sshv2
2
2
3 #if sshv2
3 #if sshv2
4 $ cat >> $HGRCPATH << EOF
4 $ cat >> $HGRCPATH << EOF
5 > [experimental]
5 > [experimental]
6 > sshpeer.advertise-v2 = true
6 > sshpeer.advertise-v2 = true
7 > sshserver.support-v2 = true
7 > sshserver.support-v2 = true
8 > EOF
8 > EOF
9 #endif
9 #endif
10
10
11 Test exchange of common information using bundle2
11 Test exchange of common information using bundle2
12
12
13
13
14 $ getmainid() {
14 $ getmainid() {
15 > hg -R main log --template '{node}\n' --rev "$1"
15 > hg -R main log --template '{node}\n' --rev "$1"
16 > }
16 > }
17
17
18 enable obsolescence
18 enable obsolescence
19
19
20 $ cp $HGRCPATH $TESTTMP/hgrc.orig
20 $ cp $HGRCPATH $TESTTMP/hgrc.orig
21 $ cat > $TESTTMP/bundle2-pushkey-hook.sh << EOF
21 $ cat > $TESTTMP/bundle2-pushkey-hook.sh << EOF
22 > echo pushkey: lock state after \"\$HG_NAMESPACE\"
22 > echo pushkey: lock state after \"\$HG_NAMESPACE\"
23 > hg debuglock
23 > hg debuglock
24 > EOF
24 > EOF
25
25
26 $ cat >> $HGRCPATH << EOF
26 $ cat >> $HGRCPATH << EOF
27 > [experimental]
27 > [experimental]
28 > evolution.createmarkers=True
28 > evolution.createmarkers=True
29 > evolution.exchange=True
29 > evolution.exchange=True
30 > bundle2-output-capture=True
30 > bundle2-output-capture=True
31 > [ui]
31 > [ui]
32 > ssh="$PYTHON" "$TESTDIR/dummyssh"
32 > ssh="$PYTHON" "$TESTDIR/dummyssh"
33 > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
33 > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
34 > [web]
34 > [web]
35 > push_ssl = false
35 > push_ssl = false
36 > allow_push = *
36 > allow_push = *
37 > [phases]
37 > [phases]
38 > publish=False
38 > publish=False
39 > [hooks]
39 > [hooks]
40 > pretxnclose.tip = hg log -r tip -T "pre-close-tip:{node|short} {phase} {bookmarks}\n"
40 > pretxnclose.tip = hg log -r tip -T "pre-close-tip:{node|short} {phase} {bookmarks}\n"
41 > txnclose.tip = hg log -r tip -T "postclose-tip:{node|short} {phase} {bookmarks}\n"
41 > txnclose.tip = hg log -r tip -T "postclose-tip:{node|short} {phase} {bookmarks}\n"
42 > txnclose.env = sh -c "HG_LOCAL= printenv.py txnclose"
42 > txnclose.env = sh -c "HG_LOCAL= printenv.py txnclose"
43 > pushkey= sh "$TESTTMP/bundle2-pushkey-hook.sh"
43 > pushkey= sh "$TESTTMP/bundle2-pushkey-hook.sh"
44 > EOF
44 > EOF
45
45
46 The extension requires a repo (currently unused)
46 The extension requires a repo (currently unused)
47
47
48 $ hg init main
48 $ hg init main
49 $ cd main
49 $ cd main
50 $ touch a
50 $ touch a
51 $ hg add a
51 $ hg add a
52 $ hg commit -m 'a'
52 $ hg commit -m 'a'
53 pre-close-tip:3903775176ed draft
53 pre-close-tip:3903775176ed draft
54 postclose-tip:3903775176ed draft
54 postclose-tip:3903775176ed draft
55 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
55 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
56
56
57 $ hg unbundle $TESTDIR/bundles/rebase.hg
57 $ hg unbundle $TESTDIR/bundles/rebase.hg
58 adding changesets
58 adding changesets
59 adding manifests
59 adding manifests
60 adding file changes
60 adding file changes
61 added 8 changesets with 7 changes to 7 files (+3 heads)
61 added 8 changesets with 7 changes to 7 files (+3 heads)
62 pre-close-tip:02de42196ebe draft
62 pre-close-tip:02de42196ebe draft
63 new changesets cd010b8cd998:02de42196ebe (8 drafts)
63 new changesets cd010b8cd998:02de42196ebe (8 drafts)
64 postclose-tip:02de42196ebe draft
64 postclose-tip:02de42196ebe draft
65 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=unbundle HG_TXNID=TXN:$ID$ HG_TXNNAME=unbundle
65 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=unbundle HG_TXNID=TXN:$ID$ HG_TXNNAME=unbundle
66 bundle:*/tests/bundles/rebase.hg HG_URL=bundle:*/tests/bundles/rebase.hg (glob)
66 bundle:*/tests/bundles/rebase.hg HG_URL=bundle:*/tests/bundles/rebase.hg (glob)
67 (run 'hg heads' to see heads, 'hg merge' to merge)
67 (run 'hg heads' to see heads, 'hg merge' to merge)
68
68
69 $ cd ..
69 $ cd ..
70
70
71 Real world exchange
71 Real world exchange
72 =====================
72 =====================
73
73
74 Add more obsolescence information
74 Add more obsolescence information
75
75
76 $ hg -R main debugobsolete -d '0 0' 1111111111111111111111111111111111111111 `getmainid 9520eea781bc`
76 $ hg -R main debugobsolete -d '0 0' 1111111111111111111111111111111111111111 `getmainid 9520eea781bc`
77 pre-close-tip:02de42196ebe draft
77 pre-close-tip:02de42196ebe draft
78 postclose-tip:02de42196ebe draft
78 postclose-tip:02de42196ebe draft
79 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
79 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
80 $ hg -R main debugobsolete -d '0 0' 2222222222222222222222222222222222222222 `getmainid 24b6387c8c8c`
80 $ hg -R main debugobsolete -d '0 0' 2222222222222222222222222222222222222222 `getmainid 24b6387c8c8c`
81 pre-close-tip:02de42196ebe draft
81 pre-close-tip:02de42196ebe draft
82 postclose-tip:02de42196ebe draft
82 postclose-tip:02de42196ebe draft
83 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
83 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
84
84
85 clone --pull
85 clone --pull
86
86
87 $ hg -R main phase --public cd010b8cd998
87 $ hg -R main phase --public cd010b8cd998
88 pre-close-tip:02de42196ebe draft
88 pre-close-tip:02de42196ebe draft
89 postclose-tip:02de42196ebe draft
89 postclose-tip:02de42196ebe draft
90 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
90 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
91 $ hg clone main other --pull --rev 9520eea781bc
91 $ hg clone main other --pull --rev 9520eea781bc
92 adding changesets
92 adding changesets
93 adding manifests
93 adding manifests
94 adding file changes
94 adding file changes
95 added 2 changesets with 2 changes to 2 files
95 added 2 changesets with 2 changes to 2 files
96 1 new obsolescence markers
96 1 new obsolescence markers
97 pre-close-tip:9520eea781bc draft
97 pre-close-tip:9520eea781bc draft
98 new changesets cd010b8cd998:9520eea781bc (1 drafts)
98 new changesets cd010b8cd998:9520eea781bc (1 drafts)
99 postclose-tip:9520eea781bc draft
99 postclose-tip:9520eea781bc draft
100 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_NODE_LAST=9520eea781bcca16c1e15acc0ba14335a0e8e5ba HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
100 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_NODE_LAST=9520eea781bcca16c1e15acc0ba14335a0e8e5ba HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
101 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
101 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
102 updating to branch default
102 updating to branch default
103 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
103 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
104 $ hg -R other log -G
104 $ hg -R other log -G
105 @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
105 @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
106 |
106 |
107 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
107 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
108
108
109 $ hg -R other debugobsolete
109 $ hg -R other debugobsolete
110 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
110 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
111
111
112 pull
112 pull
113
113
114 $ hg -R main phase --public 9520eea781bc
114 $ hg -R main phase --public 9520eea781bc
115 pre-close-tip:02de42196ebe draft
115 pre-close-tip:02de42196ebe draft
116 postclose-tip:02de42196ebe draft
116 postclose-tip:02de42196ebe draft
117 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
117 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
118 $ hg -R other pull -r 24b6387c8c8c
118 $ hg -R other pull -r 24b6387c8c8c
119 pulling from $TESTTMP/main
119 pulling from $TESTTMP/main
120 searching for changes
120 searching for changes
121 adding changesets
121 adding changesets
122 adding manifests
122 adding manifests
123 adding file changes
123 adding file changes
124 added 1 changesets with 1 changes to 1 files (+1 heads)
124 added 1 changesets with 1 changes to 1 files (+1 heads)
125 1 new obsolescence markers
125 1 new obsolescence markers
126 pre-close-tip:24b6387c8c8c draft
126 pre-close-tip:24b6387c8c8c draft
127 new changesets 24b6387c8c8c (1 drafts)
127 new changesets 24b6387c8c8c (1 drafts)
128 postclose-tip:24b6387c8c8c draft
128 postclose-tip:24b6387c8c8c draft
129 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_NODE_LAST=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
129 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_NODE_LAST=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
130 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
130 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
131 (run 'hg heads' to see heads, 'hg merge' to merge)
131 (run 'hg heads' to see heads, 'hg merge' to merge)
132 $ hg -R other log -G
132 $ hg -R other log -G
133 o 2:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F
133 o 2:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F
134 |
134 |
135 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
135 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
136 |/
136 |/
137 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
137 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
138
138
139 $ hg -R other debugobsolete
139 $ hg -R other debugobsolete
140 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
140 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
141 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
141 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
142
142
143 pull empty (with phase movement)
143 pull empty (with phase movement)
144
144
145 $ hg -R main phase --public 24b6387c8c8c
145 $ hg -R main phase --public 24b6387c8c8c
146 pre-close-tip:02de42196ebe draft
146 pre-close-tip:02de42196ebe draft
147 postclose-tip:02de42196ebe draft
147 postclose-tip:02de42196ebe draft
148 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
148 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
149 $ hg -R other pull -r 24b6387c8c8c
149 $ hg -R other pull -r 24b6387c8c8c
150 pulling from $TESTTMP/main
150 pulling from $TESTTMP/main
151 no changes found
151 no changes found
152 pre-close-tip:24b6387c8c8c public
152 pre-close-tip:24b6387c8c8c public
153 1 local changesets published
153 1 local changesets published
154 postclose-tip:24b6387c8c8c public
154 postclose-tip:24b6387c8c8c public
155 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=0 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
155 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=0 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
156 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
156 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
157 $ hg -R other log -G
157 $ hg -R other log -G
158 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
158 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
159 |
159 |
160 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
160 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
161 |/
161 |/
162 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
162 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
163
163
164 $ hg -R other debugobsolete
164 $ hg -R other debugobsolete
165 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
165 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
166 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
166 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
167
167
168 pull empty
168 pull empty
169
169
170 $ hg -R other pull -r 24b6387c8c8c
170 $ hg -R other pull -r 24b6387c8c8c
171 pulling from $TESTTMP/main
171 pulling from $TESTTMP/main
172 no changes found
172 no changes found
173 pre-close-tip:24b6387c8c8c public
173 pre-close-tip:24b6387c8c8c public
174 postclose-tip:24b6387c8c8c public
174 postclose-tip:24b6387c8c8c public
175 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=0 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
175 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=0 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
176 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
176 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
177 $ hg -R other log -G
177 $ hg -R other log -G
178 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
178 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
179 |
179 |
180 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
180 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
181 |/
181 |/
182 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
182 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
183
183
184 $ hg -R other debugobsolete
184 $ hg -R other debugobsolete
185 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
185 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
186 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
186 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
187
187
188 add extra data to test their exchange during push
188 add extra data to test their exchange during push
189
189
190 $ hg -R main bookmark --rev eea13746799a book_eea1
190 $ hg -R main bookmark --rev eea13746799a book_eea1
191 pre-close-tip:02de42196ebe draft
191 pre-close-tip:02de42196ebe draft
192 postclose-tip:02de42196ebe draft
192 postclose-tip:02de42196ebe draft
193 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
193 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
194 $ hg -R main debugobsolete -d '0 0' 3333333333333333333333333333333333333333 `getmainid eea13746799a`
194 $ hg -R main debugobsolete -d '0 0' 3333333333333333333333333333333333333333 `getmainid eea13746799a`
195 pre-close-tip:02de42196ebe draft
195 pre-close-tip:02de42196ebe draft
196 postclose-tip:02de42196ebe draft
196 postclose-tip:02de42196ebe draft
197 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
197 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
198 $ hg -R main bookmark --rev 02de42196ebe book_02de
198 $ hg -R main bookmark --rev 02de42196ebe book_02de
199 pre-close-tip:02de42196ebe draft book_02de
199 pre-close-tip:02de42196ebe draft book_02de
200 postclose-tip:02de42196ebe draft book_02de
200 postclose-tip:02de42196ebe draft book_02de
201 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
201 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
202 $ hg -R main debugobsolete -d '0 0' 4444444444444444444444444444444444444444 `getmainid 02de42196ebe`
202 $ hg -R main debugobsolete -d '0 0' 4444444444444444444444444444444444444444 `getmainid 02de42196ebe`
203 pre-close-tip:02de42196ebe draft book_02de
203 pre-close-tip:02de42196ebe draft book_02de
204 postclose-tip:02de42196ebe draft book_02de
204 postclose-tip:02de42196ebe draft book_02de
205 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
205 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
206 $ hg -R main bookmark --rev 42ccdea3bb16 book_42cc
206 $ hg -R main bookmark --rev 42ccdea3bb16 book_42cc
207 pre-close-tip:02de42196ebe draft book_02de
207 pre-close-tip:02de42196ebe draft book_02de
208 postclose-tip:02de42196ebe draft book_02de
208 postclose-tip:02de42196ebe draft book_02de
209 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
209 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
210 $ hg -R main debugobsolete -d '0 0' 5555555555555555555555555555555555555555 `getmainid 42ccdea3bb16`
210 $ hg -R main debugobsolete -d '0 0' 5555555555555555555555555555555555555555 `getmainid 42ccdea3bb16`
211 pre-close-tip:02de42196ebe draft book_02de
211 pre-close-tip:02de42196ebe draft book_02de
212 postclose-tip:02de42196ebe draft book_02de
212 postclose-tip:02de42196ebe draft book_02de
213 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
213 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
214 $ hg -R main bookmark --rev 5fddd98957c8 book_5fdd
214 $ hg -R main bookmark --rev 5fddd98957c8 book_5fdd
215 pre-close-tip:02de42196ebe draft book_02de
215 pre-close-tip:02de42196ebe draft book_02de
216 postclose-tip:02de42196ebe draft book_02de
216 postclose-tip:02de42196ebe draft book_02de
217 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
217 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
218 $ hg -R main debugobsolete -d '0 0' 6666666666666666666666666666666666666666 `getmainid 5fddd98957c8`
218 $ hg -R main debugobsolete -d '0 0' 6666666666666666666666666666666666666666 `getmainid 5fddd98957c8`
219 pre-close-tip:02de42196ebe draft book_02de
219 pre-close-tip:02de42196ebe draft book_02de
220 postclose-tip:02de42196ebe draft book_02de
220 postclose-tip:02de42196ebe draft book_02de
221 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
221 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
222 $ hg -R main bookmark --rev 32af7686d403 book_32af
222 $ hg -R main bookmark --rev 32af7686d403 book_32af
223 pre-close-tip:02de42196ebe draft book_02de
223 pre-close-tip:02de42196ebe draft book_02de
224 postclose-tip:02de42196ebe draft book_02de
224 postclose-tip:02de42196ebe draft book_02de
225 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
225 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
226 $ hg -R main debugobsolete -d '0 0' 7777777777777777777777777777777777777777 `getmainid 32af7686d403`
226 $ hg -R main debugobsolete -d '0 0' 7777777777777777777777777777777777777777 `getmainid 32af7686d403`
227 pre-close-tip:02de42196ebe draft book_02de
227 pre-close-tip:02de42196ebe draft book_02de
228 postclose-tip:02de42196ebe draft book_02de
228 postclose-tip:02de42196ebe draft book_02de
229 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
229 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
230
230
231 $ hg -R other bookmark --rev cd010b8cd998 book_eea1
231 $ hg -R other bookmark --rev cd010b8cd998 book_eea1
232 pre-close-tip:24b6387c8c8c public
232 pre-close-tip:24b6387c8c8c public
233 postclose-tip:24b6387c8c8c public
233 postclose-tip:24b6387c8c8c public
234 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
234 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
235 $ hg -R other bookmark --rev cd010b8cd998 book_02de
235 $ hg -R other bookmark --rev cd010b8cd998 book_02de
236 pre-close-tip:24b6387c8c8c public
236 pre-close-tip:24b6387c8c8c public
237 postclose-tip:24b6387c8c8c public
237 postclose-tip:24b6387c8c8c public
238 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
238 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
239 $ hg -R other bookmark --rev cd010b8cd998 book_42cc
239 $ hg -R other bookmark --rev cd010b8cd998 book_42cc
240 pre-close-tip:24b6387c8c8c public
240 pre-close-tip:24b6387c8c8c public
241 postclose-tip:24b6387c8c8c public
241 postclose-tip:24b6387c8c8c public
242 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
242 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
243 $ hg -R other bookmark --rev cd010b8cd998 book_5fdd
243 $ hg -R other bookmark --rev cd010b8cd998 book_5fdd
244 pre-close-tip:24b6387c8c8c public
244 pre-close-tip:24b6387c8c8c public
245 postclose-tip:24b6387c8c8c public
245 postclose-tip:24b6387c8c8c public
246 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
246 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
247 $ hg -R other bookmark --rev cd010b8cd998 book_32af
247 $ hg -R other bookmark --rev cd010b8cd998 book_32af
248 pre-close-tip:24b6387c8c8c public
248 pre-close-tip:24b6387c8c8c public
249 postclose-tip:24b6387c8c8c public
249 postclose-tip:24b6387c8c8c public
250 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
250 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
251
251
252 $ hg -R main phase --public eea13746799a
252 $ hg -R main phase --public eea13746799a
253 pre-close-tip:02de42196ebe draft book_02de
253 pre-close-tip:02de42196ebe draft book_02de
254 postclose-tip:02de42196ebe draft book_02de
254 postclose-tip:02de42196ebe draft book_02de
255 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
255 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
256
256
257 push
257 push
258 $ hg -R main push other --rev eea13746799a --bookmark book_eea1
258 $ hg -R main push other --rev eea13746799a --bookmark book_eea1
259 pushing to other
259 pushing to other
260 searching for changes
260 searching for changes
261 remote: adding changesets
261 remote: adding changesets
262 remote: adding manifests
262 remote: adding manifests
263 remote: adding file changes
263 remote: adding file changes
264 remote: added 1 changesets with 0 changes to 0 files (-1 heads)
264 remote: added 1 changesets with 0 changes to 0 files (-1 heads)
265 remote: 1 new obsolescence markers
265 remote: 1 new obsolescence markers
266 remote: pre-close-tip:eea13746799a public book_eea1
266 remote: pre-close-tip:eea13746799a public book_eea1
267 remote: pushkey: lock state after "bookmarks"
267 remote: pushkey: lock state after "bookmarks"
268 remote: lock: free
268 remote: lock: free
269 remote: wlock: free
269 remote: wlock: free
270 remote: postclose-tip:eea13746799a public book_eea1
270 remote: postclose-tip:eea13746799a public book_eea1
271 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_NODE_LAST=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_PHASES_MOVED=1 HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/other
271 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_NODE_LAST=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_PHASES_MOVED=1 HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/other
272 updating bookmark book_eea1
272 updating bookmark book_eea1
273 pre-close-tip:02de42196ebe draft book_02de
273 pre-close-tip:02de42196ebe draft book_02de
274 postclose-tip:02de42196ebe draft book_02de
274 postclose-tip:02de42196ebe draft book_02de
275 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
275 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
276 file:/*/$TESTTMP/other HG_URL=file:$TESTTMP/other (glob)
276 file:/*/$TESTTMP/other HG_URL=file:$TESTTMP/other (glob)
277 $ hg -R other log -G
277 $ hg -R other log -G
278 o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
278 o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
279 |\
279 |\
280 | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
280 | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
281 | |
281 | |
282 @ | 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
282 @ | 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
283 |/
283 |/
284 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de book_32af book_42cc book_5fdd A
284 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de book_32af book_42cc book_5fdd A
285
285
286 $ hg -R other debugobsolete
286 $ hg -R other debugobsolete
287 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
287 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
288 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
288 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
289 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
289 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
290
290
291 pull over ssh
291 pull over ssh
292
292
293 $ hg -R other pull ssh://user@dummy/main -r 02de42196ebe --bookmark book_02de
293 $ hg -R other pull ssh://user@dummy/main -r 02de42196ebe --bookmark book_02de
294 pulling from ssh://user@dummy/main
294 pulling from ssh://user@dummy/main
295 searching for changes
295 searching for changes
296 adding changesets
296 adding changesets
297 adding manifests
297 adding manifests
298 adding file changes
298 adding file changes
299 added 1 changesets with 1 changes to 1 files (+1 heads)
299 added 1 changesets with 1 changes to 1 files (+1 heads)
300 1 new obsolescence markers
300 1 new obsolescence markers
301 updating bookmark book_02de
301 updating bookmark book_02de
302 pre-close-tip:02de42196ebe draft book_02de
302 pre-close-tip:02de42196ebe draft book_02de
303 new changesets 02de42196ebe (1 drafts)
303 new changesets 02de42196ebe (1 drafts)
304 postclose-tip:02de42196ebe draft book_02de
304 postclose-tip:02de42196ebe draft book_02de
305 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
305 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
306 ssh://user@dummy/main HG_URL=ssh://user@dummy/main
306 ssh://user@dummy/main HG_URL=ssh://user@dummy/main
307 (run 'hg heads' to see heads, 'hg merge' to merge)
307 (run 'hg heads' to see heads, 'hg merge' to merge)
308 $ hg -R other debugobsolete
308 $ hg -R other debugobsolete
309 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
309 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
310 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
310 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
311 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
311 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
312 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
312 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
313
313
314 pull over http
314 pull over http
315
315
316 $ hg serve -R main -p $HGPORT -d --pid-file=main.pid -E main-error.log
316 $ hg serve -R main -p $HGPORT -d --pid-file=main.pid -E main-error.log
317 $ cat main.pid >> $DAEMON_PIDS
317 $ cat main.pid >> $DAEMON_PIDS
318
318
319 $ hg -R other pull http://localhost:$HGPORT/ -r 42ccdea3bb16 --bookmark book_42cc
319 $ hg -R other pull http://localhost:$HGPORT/ -r 42ccdea3bb16 --bookmark book_42cc
320 pulling from http://localhost:$HGPORT/
320 pulling from http://localhost:$HGPORT/
321 searching for changes
321 searching for changes
322 adding changesets
322 adding changesets
323 adding manifests
323 adding manifests
324 adding file changes
324 adding file changes
325 added 1 changesets with 1 changes to 1 files (+1 heads)
325 added 1 changesets with 1 changes to 1 files (+1 heads)
326 1 new obsolescence markers
326 1 new obsolescence markers
327 updating bookmark book_42cc
327 updating bookmark book_42cc
328 pre-close-tip:42ccdea3bb16 draft book_42cc
328 pre-close-tip:42ccdea3bb16 draft book_42cc
329 new changesets 42ccdea3bb16 (1 drafts)
329 new changesets 42ccdea3bb16 (1 drafts)
330 postclose-tip:42ccdea3bb16 draft book_42cc
330 postclose-tip:42ccdea3bb16 draft book_42cc
331 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_NODE_LAST=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
331 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_NODE_LAST=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
332 http://localhost:$HGPORT/ HG_URL=http://localhost:$HGPORT/
332 http://localhost:$HGPORT/ HG_URL=http://localhost:$HGPORT/
333 (run 'hg heads .' to see heads, 'hg merge' to merge)
333 (run 'hg heads .' to see heads, 'hg merge' to merge)
334 $ cat main-error.log
334 $ cat main-error.log
335 $ hg -R other debugobsolete
335 $ hg -R other debugobsolete
336 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
336 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
337 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
337 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
338 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
338 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
339 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
339 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
340 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
340 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
341
341
342 push over ssh
342 push over ssh
343
343
344 $ hg -R main push ssh://user@dummy/other -r 5fddd98957c8 --bookmark book_5fdd
344 $ hg -R main push ssh://user@dummy/other -r 5fddd98957c8 --bookmark book_5fdd
345 pushing to ssh://user@dummy/other
345 pushing to ssh://user@dummy/other
346 searching for changes
346 searching for changes
347 remote: adding changesets
347 remote: adding changesets
348 remote: adding manifests
348 remote: adding manifests
349 remote: adding file changes
349 remote: adding file changes
350 remote: added 1 changesets with 1 changes to 1 files
350 remote: added 1 changesets with 1 changes to 1 files
351 remote: 1 new obsolescence markers
351 remote: 1 new obsolescence markers
352 remote: pre-close-tip:5fddd98957c8 draft book_5fdd
352 remote: pre-close-tip:5fddd98957c8 draft book_5fdd
353 remote: pushkey: lock state after "bookmarks"
353 remote: pushkey: lock state after "bookmarks"
354 remote: lock: free
354 remote: lock: free
355 remote: wlock: free
355 remote: wlock: free
356 remote: postclose-tip:5fddd98957c8 draft book_5fdd
356 remote: postclose-tip:5fddd98957c8 draft book_5fdd
357 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_NODE_LAST=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_TXNNAME=serve HG_URL=remote:ssh:$LOCALIP
357 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_NODE_LAST=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_TXNNAME=serve HG_URL=remote:ssh:$LOCALIP
358 updating bookmark book_5fdd
358 updating bookmark book_5fdd
359 pre-close-tip:02de42196ebe draft book_02de
359 pre-close-tip:02de42196ebe draft book_02de
360 postclose-tip:02de42196ebe draft book_02de
360 postclose-tip:02de42196ebe draft book_02de
361 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
361 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
362 ssh://user@dummy/other HG_URL=ssh://user@dummy/other
362 ssh://user@dummy/other HG_URL=ssh://user@dummy/other
363 $ hg -R other log -G
363 $ hg -R other log -G
364 o 6:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
364 o 6:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
365 |
365 |
366 o 5:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
366 o 5:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
367 |
367 |
368 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
368 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
369 | |
369 | |
370 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
370 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
371 | |/|
371 | |/|
372 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
372 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
373 |/ /
373 |/ /
374 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
374 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
375 |/
375 |/
376 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af A
376 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af A
377
377
378 $ hg -R other debugobsolete
378 $ hg -R other debugobsolete
379 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
379 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
380 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
380 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
381 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
381 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
382 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
382 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
383 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
383 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
384 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
384 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
385
385
386 push over http
386 push over http
387
387
388 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
388 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
389 $ cat other.pid >> $DAEMON_PIDS
389 $ cat other.pid >> $DAEMON_PIDS
390
390
391 $ hg -R main phase --public 32af7686d403
391 $ hg -R main phase --public 32af7686d403
392 pre-close-tip:02de42196ebe draft book_02de
392 pre-close-tip:02de42196ebe draft book_02de
393 postclose-tip:02de42196ebe draft book_02de
393 postclose-tip:02de42196ebe draft book_02de
394 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
394 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
395 $ hg -R main push http://localhost:$HGPORT2/ -r 32af7686d403 --bookmark book_32af
395 $ hg -R main push http://localhost:$HGPORT2/ -r 32af7686d403 --bookmark book_32af
396 pushing to http://localhost:$HGPORT2/
396 pushing to http://localhost:$HGPORT2/
397 searching for changes
397 searching for changes
398 remote: adding changesets
398 remote: adding changesets
399 remote: adding manifests
399 remote: adding manifests
400 remote: adding file changes
400 remote: adding file changes
401 remote: added 1 changesets with 1 changes to 1 files
401 remote: added 1 changesets with 1 changes to 1 files
402 remote: 1 new obsolescence markers
402 remote: 1 new obsolescence markers
403 remote: pre-close-tip:32af7686d403 public book_32af
403 remote: pre-close-tip:32af7686d403 public book_32af
404 remote: pushkey: lock state after "bookmarks"
404 remote: pushkey: lock state after "bookmarks"
405 remote: lock: free
405 remote: lock: free
406 remote: wlock: free
406 remote: wlock: free
407 remote: postclose-tip:32af7686d403 public book_32af
407 remote: postclose-tip:32af7686d403 public book_32af
408 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=32af7686d403cf45b5d95f2d70cebea587ac806a HG_NODE_LAST=32af7686d403cf45b5d95f2d70cebea587ac806a HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_TXNNAME=serve HG_URL=remote:http:$LOCALIP: (glob)
408 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=32af7686d403cf45b5d95f2d70cebea587ac806a HG_NODE_LAST=32af7686d403cf45b5d95f2d70cebea587ac806a HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_TXNNAME=serve HG_URL=remote:http:$LOCALIP: (glob)
409 updating bookmark book_32af
409 updating bookmark book_32af
410 pre-close-tip:02de42196ebe draft book_02de
410 pre-close-tip:02de42196ebe draft book_02de
411 postclose-tip:02de42196ebe draft book_02de
411 postclose-tip:02de42196ebe draft book_02de
412 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
412 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
413 http://localhost:$HGPORT2/ HG_URL=http://localhost:$HGPORT2/
413 http://localhost:$HGPORT2/ HG_URL=http://localhost:$HGPORT2/
414 $ cat other-error.log
414 $ cat other-error.log
415
415
416 Check final content.
416 Check final content.
417
417
418 $ hg -R other log -G
418 $ hg -R other log -G
419 o 7:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af D
419 o 7:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af D
420 |
420 |
421 o 6:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
421 o 6:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
422 |
422 |
423 o 5:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
423 o 5:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
424 |
424 |
425 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
425 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
426 | |
426 | |
427 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
427 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
428 | |/|
428 | |/|
429 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
429 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
430 |/ /
430 |/ /
431 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
431 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
432 |/
432 |/
433 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
433 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
434
434
435 $ hg -R other debugobsolete
435 $ hg -R other debugobsolete
436 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
436 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
437 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
437 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
438 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
438 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
439 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
439 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
440 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
440 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
441 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
441 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
442 7777777777777777777777777777777777777777 32af7686d403cf45b5d95f2d70cebea587ac806a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
442 7777777777777777777777777777777777777777 32af7686d403cf45b5d95f2d70cebea587ac806a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
443
443
444 (check that no 'pending' files remain)
444 (check that no 'pending' files remain)
445
445
446 $ ls -1 other/.hg/bookmarks*
446 $ ls -1 other/.hg/bookmarks*
447 other/.hg/bookmarks
447 other/.hg/bookmarks
448 $ ls -1 other/.hg/store/phaseroots*
448 $ ls -1 other/.hg/store/phaseroots*
449 other/.hg/store/phaseroots
449 other/.hg/store/phaseroots
450 $ ls -1 other/.hg/store/00changelog.i*
450 $ ls -1 other/.hg/store/00changelog.i*
451 other/.hg/store/00changelog.i
451 other/.hg/store/00changelog.i
452
452
453 Error Handling
453 Error Handling
454 ==============
454 ==============
455
455
456 Check that errors are properly returned to the client during push.
456 Check that errors are properly returned to the client during push.
457
457
458 Setting up
458 Setting up
459
459
460 $ cat > failpush.py << EOF
460 $ cat > failpush.py << EOF
461 > """A small extension that makes push fails when using bundle2
461 > """A small extension that makes push fails when using bundle2
462 >
462 >
463 > used to test error handling in bundle2
463 > used to test error handling in bundle2
464 > """
464 > """
465 >
465 >
466 > from mercurial import error
466 > from mercurial import error
467 > from mercurial import bundle2
467 > from mercurial import bundle2
468 > from mercurial import exchange
468 > from mercurial import exchange
469 > from mercurial import extensions
469 > from mercurial import extensions
470 > from mercurial import registrar
470 > from mercurial import registrar
471 > cmdtable = {}
471 > cmdtable = {}
472 > command = registrar.command(cmdtable)
472 > command = registrar.command(cmdtable)
473 >
473 >
474 > configtable = {}
474 > configtable = {}
475 > configitem = registrar.configitem(configtable)
475 > configitem = registrar.configitem(configtable)
476 > configitem(b'failpush', b'reason',
476 > configitem(b'failpush', b'reason',
477 > default=None,
477 > default=None,
478 > )
478 > )
479 >
479 >
480 > def _pushbundle2failpart(pushop, bundler):
480 > def _pushbundle2failpart(pushop, bundler):
481 > reason = pushop.ui.config(b'failpush', b'reason')
481 > reason = pushop.ui.config(b'failpush', b'reason')
482 > part = None
482 > part = None
483 > if reason == b'abort':
483 > if reason == b'abort':
484 > bundler.newpart(b'test:abort')
484 > bundler.newpart(b'test:abort')
485 > if reason == b'unknown':
485 > if reason == b'unknown':
486 > bundler.newpart(b'test:unknown')
486 > bundler.newpart(b'test:unknown')
487 > if reason == b'race':
487 > if reason == b'race':
488 > # 20 Bytes of crap
488 > # 20 Bytes of crap
489 > bundler.newpart(b'check:heads', data=b'01234567890123456789')
489 > bundler.newpart(b'check:heads', data=b'01234567890123456789')
490 >
490 >
491 > @bundle2.parthandler(b"test:abort")
491 > @bundle2.parthandler(b"test:abort")
492 > def handleabort(op, part):
492 > def handleabort(op, part):
493 > raise error.Abort(b'Abandon ship!', hint=b"don't panic")
493 > raise error.Abort(b'Abandon ship!', hint=b"don't panic")
494 >
494 >
495 > def uisetup(ui):
495 > def uisetup(ui):
496 > exchange.b2partsgenmapping[b'failpart'] = _pushbundle2failpart
496 > exchange.b2partsgenmapping[b'failpart'] = _pushbundle2failpart
497 > exchange.b2partsgenorder.insert(0, b'failpart')
497 > exchange.b2partsgenorder.insert(0, b'failpart')
498 >
498 >
499 > EOF
499 > EOF
500
500
501 $ cd main
501 $ cd main
502 $ hg up tip
502 $ hg up tip
503 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
503 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
504 $ echo 'I' > I
504 $ echo 'I' > I
505 $ hg add I
505 $ hg add I
506 $ hg ci -m 'I'
506 $ hg ci -m 'I'
507 pre-close-tip:e7ec4e813ba6 draft
507 pre-close-tip:e7ec4e813ba6 draft
508 postclose-tip:e7ec4e813ba6 draft
508 postclose-tip:e7ec4e813ba6 draft
509 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
509 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
510 $ hg id
510 $ hg id
511 e7ec4e813ba6 tip
511 e7ec4e813ba6 tip
512 $ cd ..
512 $ cd ..
513
513
514 $ cat << EOF >> $HGRCPATH
514 $ cat << EOF >> $HGRCPATH
515 > [extensions]
515 > [extensions]
516 > failpush=$TESTTMP/failpush.py
516 > failpush=$TESTTMP/failpush.py
517 > EOF
517 > EOF
518
518
519 $ killdaemons.py
519 $ killdaemons.py
520 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
520 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
521 $ cat other.pid >> $DAEMON_PIDS
521 $ cat other.pid >> $DAEMON_PIDS
522
522
523 Doing the actual push: Abort error
523 Doing the actual push: Abort error
524
524
525 $ cat << EOF >> $HGRCPATH
525 $ cat << EOF >> $HGRCPATH
526 > [failpush]
526 > [failpush]
527 > reason = abort
527 > reason = abort
528 > EOF
528 > EOF
529
529
530 $ hg -R main push other -r e7ec4e813ba6
530 $ hg -R main push other -r e7ec4e813ba6
531 pushing to other
531 pushing to other
532 searching for changes
532 searching for changes
533 abort: Abandon ship!
533 abort: Abandon ship!
534 (don't panic)
534 (don't panic)
535 [255]
535 [255]
536
536
537 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
537 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
538 pushing to ssh://user@dummy/other
538 pushing to ssh://user@dummy/other
539 searching for changes
539 searching for changes
540 remote: Abandon ship!
540 remote: Abandon ship!
541 remote: (don't panic)
541 remote: (don't panic)
542 abort: push failed on remote
542 abort: push failed on remote
543 [255]
543 [255]
544
544
545 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
545 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
546 pushing to http://localhost:$HGPORT2/
546 pushing to http://localhost:$HGPORT2/
547 searching for changes
547 searching for changes
548 remote: Abandon ship!
548 remote: Abandon ship!
549 remote: (don't panic)
549 remote: (don't panic)
550 abort: push failed on remote
550 abort: push failed on remote
551 [255]
551 [255]
552
552
553
553
554 Doing the actual push: unknown mandatory parts
554 Doing the actual push: unknown mandatory parts
555
555
556 $ cat << EOF >> $HGRCPATH
556 $ cat << EOF >> $HGRCPATH
557 > [failpush]
557 > [failpush]
558 > reason = unknown
558 > reason = unknown
559 > EOF
559 > EOF
560
560
561 $ hg -R main push other -r e7ec4e813ba6
561 $ hg -R main push other -r e7ec4e813ba6
562 pushing to other
562 pushing to other
563 searching for changes
563 searching for changes
564 abort: missing support for test:unknown
564 abort: missing support for test:unknown
565 [255]
565 [255]
566
566
567 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
567 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
568 pushing to ssh://user@dummy/other
568 pushing to ssh://user@dummy/other
569 searching for changes
569 searching for changes
570 abort: missing support for test:unknown
570 abort: missing support for test:unknown
571 [255]
571 [255]
572
572
573 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
573 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
574 pushing to http://localhost:$HGPORT2/
574 pushing to http://localhost:$HGPORT2/
575 searching for changes
575 searching for changes
576 abort: missing support for test:unknown
576 abort: missing support for test:unknown
577 [255]
577 [255]
578
578
579 Doing the actual push: race
579 Doing the actual push: race
580
580
581 $ cat << EOF >> $HGRCPATH
581 $ cat << EOF >> $HGRCPATH
582 > [failpush]
582 > [failpush]
583 > reason = race
583 > reason = race
584 > EOF
584 > EOF
585
585
586 $ hg -R main push other -r e7ec4e813ba6
586 $ hg -R main push other -r e7ec4e813ba6
587 pushing to other
587 pushing to other
588 searching for changes
588 searching for changes
589 abort: push failed:
589 abort: push failed:
590 'repository changed while pushing - please try again'
590 'remote repository changed while pushing - please try again'
591 [255]
591 [255]
592
592
593 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
593 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
594 pushing to ssh://user@dummy/other
594 pushing to ssh://user@dummy/other
595 searching for changes
595 searching for changes
596 abort: push failed:
596 abort: push failed:
597 'repository changed while pushing - please try again'
597 'remote repository changed while pushing - please try again'
598 [255]
598 [255]
599
599
600 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
600 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
601 pushing to http://localhost:$HGPORT2/
601 pushing to http://localhost:$HGPORT2/
602 searching for changes
602 searching for changes
603 abort: push failed:
603 abort: push failed:
604 'repository changed while pushing - please try again'
604 'remote repository changed while pushing - please try again'
605 [255]
605 [255]
606
606
607 Doing the actual push: hook abort
607 Doing the actual push: hook abort
608
608
609 $ cat << EOF >> $HGRCPATH
609 $ cat << EOF >> $HGRCPATH
610 > [failpush]
610 > [failpush]
611 > reason =
611 > reason =
612 > [hooks]
612 > [hooks]
613 > pretxnclose.failpush = sh -c "echo 'You shall not pass!'; false"
613 > pretxnclose.failpush = sh -c "echo 'You shall not pass!'; false"
614 > txnabort.failpush = sh -c "echo 'Cleaning up the mess...'"
614 > txnabort.failpush = sh -c "echo 'Cleaning up the mess...'"
615 > EOF
615 > EOF
616
616
617 $ killdaemons.py
617 $ killdaemons.py
618 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
618 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
619 $ cat other.pid >> $DAEMON_PIDS
619 $ cat other.pid >> $DAEMON_PIDS
620
620
621 $ hg -R main push other -r e7ec4e813ba6
621 $ hg -R main push other -r e7ec4e813ba6
622 pushing to other
622 pushing to other
623 searching for changes
623 searching for changes
624 remote: adding changesets
624 remote: adding changesets
625 remote: adding manifests
625 remote: adding manifests
626 remote: adding file changes
626 remote: adding file changes
627 remote: added 1 changesets with 1 changes to 1 files
627 remote: added 1 changesets with 1 changes to 1 files
628 remote: pre-close-tip:e7ec4e813ba6 draft
628 remote: pre-close-tip:e7ec4e813ba6 draft
629 remote: You shall not pass!
629 remote: You shall not pass!
630 remote: transaction abort!
630 remote: transaction abort!
631 remote: Cleaning up the mess...
631 remote: Cleaning up the mess...
632 remote: rollback completed
632 remote: rollback completed
633 abort: pretxnclose.failpush hook exited with status 1
633 abort: pretxnclose.failpush hook exited with status 1
634 [255]
634 [255]
635
635
636 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
636 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
637 pushing to ssh://user@dummy/other
637 pushing to ssh://user@dummy/other
638 searching for changes
638 searching for changes
639 remote: adding changesets
639 remote: adding changesets
640 remote: adding manifests
640 remote: adding manifests
641 remote: adding file changes
641 remote: adding file changes
642 remote: added 1 changesets with 1 changes to 1 files
642 remote: added 1 changesets with 1 changes to 1 files
643 remote: pre-close-tip:e7ec4e813ba6 draft
643 remote: pre-close-tip:e7ec4e813ba6 draft
644 remote: You shall not pass!
644 remote: You shall not pass!
645 remote: transaction abort!
645 remote: transaction abort!
646 remote: Cleaning up the mess...
646 remote: Cleaning up the mess...
647 remote: rollback completed
647 remote: rollback completed
648 remote: pretxnclose.failpush hook exited with status 1
648 remote: pretxnclose.failpush hook exited with status 1
649 abort: push failed on remote
649 abort: push failed on remote
650 [255]
650 [255]
651
651
652 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
652 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
653 pushing to http://localhost:$HGPORT2/
653 pushing to http://localhost:$HGPORT2/
654 searching for changes
654 searching for changes
655 remote: adding changesets
655 remote: adding changesets
656 remote: adding manifests
656 remote: adding manifests
657 remote: adding file changes
657 remote: adding file changes
658 remote: added 1 changesets with 1 changes to 1 files
658 remote: added 1 changesets with 1 changes to 1 files
659 remote: pre-close-tip:e7ec4e813ba6 draft
659 remote: pre-close-tip:e7ec4e813ba6 draft
660 remote: You shall not pass!
660 remote: You shall not pass!
661 remote: transaction abort!
661 remote: transaction abort!
662 remote: Cleaning up the mess...
662 remote: Cleaning up the mess...
663 remote: rollback completed
663 remote: rollback completed
664 remote: pretxnclose.failpush hook exited with status 1
664 remote: pretxnclose.failpush hook exited with status 1
665 abort: push failed on remote
665 abort: push failed on remote
666 [255]
666 [255]
667
667
668 (check that no 'pending' files remain)
668 (check that no 'pending' files remain)
669
669
670 $ ls -1 other/.hg/bookmarks*
670 $ ls -1 other/.hg/bookmarks*
671 other/.hg/bookmarks
671 other/.hg/bookmarks
672 $ ls -1 other/.hg/store/phaseroots*
672 $ ls -1 other/.hg/store/phaseroots*
673 other/.hg/store/phaseroots
673 other/.hg/store/phaseroots
674 $ ls -1 other/.hg/store/00changelog.i*
674 $ ls -1 other/.hg/store/00changelog.i*
675 other/.hg/store/00changelog.i
675 other/.hg/store/00changelog.i
676
676
677 Check error from hook during the unbundling process itself
677 Check error from hook during the unbundling process itself
678
678
679 $ cat << EOF >> $HGRCPATH
679 $ cat << EOF >> $HGRCPATH
680 > pretxnchangegroup = sh -c "echo 'Fail early!'; false"
680 > pretxnchangegroup = sh -c "echo 'Fail early!'; false"
681 > EOF
681 > EOF
682 $ killdaemons.py # reload http config
682 $ killdaemons.py # reload http config
683 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
683 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
684 $ cat other.pid >> $DAEMON_PIDS
684 $ cat other.pid >> $DAEMON_PIDS
685
685
686 $ hg -R main push other -r e7ec4e813ba6
686 $ hg -R main push other -r e7ec4e813ba6
687 pushing to other
687 pushing to other
688 searching for changes
688 searching for changes
689 remote: adding changesets
689 remote: adding changesets
690 remote: adding manifests
690 remote: adding manifests
691 remote: adding file changes
691 remote: adding file changes
692 remote: added 1 changesets with 1 changes to 1 files
692 remote: added 1 changesets with 1 changes to 1 files
693 remote: Fail early!
693 remote: Fail early!
694 remote: transaction abort!
694 remote: transaction abort!
695 remote: Cleaning up the mess...
695 remote: Cleaning up the mess...
696 remote: rollback completed
696 remote: rollback completed
697 abort: pretxnchangegroup hook exited with status 1
697 abort: pretxnchangegroup hook exited with status 1
698 [255]
698 [255]
699 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
699 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
700 pushing to ssh://user@dummy/other
700 pushing to ssh://user@dummy/other
701 searching for changes
701 searching for changes
702 remote: adding changesets
702 remote: adding changesets
703 remote: adding manifests
703 remote: adding manifests
704 remote: adding file changes
704 remote: adding file changes
705 remote: added 1 changesets with 1 changes to 1 files
705 remote: added 1 changesets with 1 changes to 1 files
706 remote: Fail early!
706 remote: Fail early!
707 remote: transaction abort!
707 remote: transaction abort!
708 remote: Cleaning up the mess...
708 remote: Cleaning up the mess...
709 remote: rollback completed
709 remote: rollback completed
710 remote: pretxnchangegroup hook exited with status 1
710 remote: pretxnchangegroup hook exited with status 1
711 abort: push failed on remote
711 abort: push failed on remote
712 [255]
712 [255]
713 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
713 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
714 pushing to http://localhost:$HGPORT2/
714 pushing to http://localhost:$HGPORT2/
715 searching for changes
715 searching for changes
716 remote: adding changesets
716 remote: adding changesets
717 remote: adding manifests
717 remote: adding manifests
718 remote: adding file changes
718 remote: adding file changes
719 remote: added 1 changesets with 1 changes to 1 files
719 remote: added 1 changesets with 1 changes to 1 files
720 remote: Fail early!
720 remote: Fail early!
721 remote: transaction abort!
721 remote: transaction abort!
722 remote: Cleaning up the mess...
722 remote: Cleaning up the mess...
723 remote: rollback completed
723 remote: rollback completed
724 remote: pretxnchangegroup hook exited with status 1
724 remote: pretxnchangegroup hook exited with status 1
725 abort: push failed on remote
725 abort: push failed on remote
726 [255]
726 [255]
727
727
728 Check output capture control.
728 Check output capture control.
729
729
730 (should be still forced for http, disabled for local and ssh)
730 (should be still forced for http, disabled for local and ssh)
731
731
732 $ cat >> $HGRCPATH << EOF
732 $ cat >> $HGRCPATH << EOF
733 > [experimental]
733 > [experimental]
734 > bundle2-output-capture=False
734 > bundle2-output-capture=False
735 > EOF
735 > EOF
736
736
737 $ hg -R main push other -r e7ec4e813ba6
737 $ hg -R main push other -r e7ec4e813ba6
738 pushing to other
738 pushing to other
739 searching for changes
739 searching for changes
740 adding changesets
740 adding changesets
741 adding manifests
741 adding manifests
742 adding file changes
742 adding file changes
743 added 1 changesets with 1 changes to 1 files
743 added 1 changesets with 1 changes to 1 files
744 Fail early!
744 Fail early!
745 transaction abort!
745 transaction abort!
746 Cleaning up the mess...
746 Cleaning up the mess...
747 rollback completed
747 rollback completed
748 abort: pretxnchangegroup hook exited with status 1
748 abort: pretxnchangegroup hook exited with status 1
749 [255]
749 [255]
750 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
750 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
751 pushing to ssh://user@dummy/other
751 pushing to ssh://user@dummy/other
752 searching for changes
752 searching for changes
753 remote: adding changesets
753 remote: adding changesets
754 remote: adding manifests
754 remote: adding manifests
755 remote: adding file changes
755 remote: adding file changes
756 remote: added 1 changesets with 1 changes to 1 files
756 remote: added 1 changesets with 1 changes to 1 files
757 remote: Fail early!
757 remote: Fail early!
758 remote: transaction abort!
758 remote: transaction abort!
759 remote: Cleaning up the mess...
759 remote: Cleaning up the mess...
760 remote: rollback completed
760 remote: rollback completed
761 remote: pretxnchangegroup hook exited with status 1
761 remote: pretxnchangegroup hook exited with status 1
762 abort: push failed on remote
762 abort: push failed on remote
763 [255]
763 [255]
764 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
764 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
765 pushing to http://localhost:$HGPORT2/
765 pushing to http://localhost:$HGPORT2/
766 searching for changes
766 searching for changes
767 remote: adding changesets
767 remote: adding changesets
768 remote: adding manifests
768 remote: adding manifests
769 remote: adding file changes
769 remote: adding file changes
770 remote: added 1 changesets with 1 changes to 1 files
770 remote: added 1 changesets with 1 changes to 1 files
771 remote: Fail early!
771 remote: Fail early!
772 remote: transaction abort!
772 remote: transaction abort!
773 remote: Cleaning up the mess...
773 remote: Cleaning up the mess...
774 remote: rollback completed
774 remote: rollback completed
775 remote: pretxnchangegroup hook exited with status 1
775 remote: pretxnchangegroup hook exited with status 1
776 abort: push failed on remote
776 abort: push failed on remote
777 [255]
777 [255]
778
778
779 Check abort from mandatory pushkey
779 Check abort from mandatory pushkey
780
780
781 $ cat > mandatorypart.py << EOF
781 $ cat > mandatorypart.py << EOF
782 > from mercurial import exchange
782 > from mercurial import exchange
783 > from mercurial import pushkey
783 > from mercurial import pushkey
784 > from mercurial import node
784 > from mercurial import node
785 > from mercurial import error
785 > from mercurial import error
786 > @exchange.b2partsgenerator(b'failingpuskey')
786 > @exchange.b2partsgenerator(b'failingpuskey')
787 > def addfailingpushey(pushop, bundler):
787 > def addfailingpushey(pushop, bundler):
788 > enc = pushkey.encode
788 > enc = pushkey.encode
789 > part = bundler.newpart(b'pushkey')
789 > part = bundler.newpart(b'pushkey')
790 > part.addparam(b'namespace', enc(b'phases'))
790 > part.addparam(b'namespace', enc(b'phases'))
791 > part.addparam(b'key', enc(b'cd010b8cd998f3981a5a8115f94f8da4ab506089'))
791 > part.addparam(b'key', enc(b'cd010b8cd998f3981a5a8115f94f8da4ab506089'))
792 > part.addparam(b'old', enc(b'0')) # successful update
792 > part.addparam(b'old', enc(b'0')) # successful update
793 > part.addparam(b'new', enc(b'0'))
793 > part.addparam(b'new', enc(b'0'))
794 > def fail(pushop, exc):
794 > def fail(pushop, exc):
795 > raise error.Abort(b'Correct phase push failed (because hooks)')
795 > raise error.Abort(b'Correct phase push failed (because hooks)')
796 > pushop.pkfailcb[part.id] = fail
796 > pushop.pkfailcb[part.id] = fail
797 > EOF
797 > EOF
798 $ cat >> $HGRCPATH << EOF
798 $ cat >> $HGRCPATH << EOF
799 > [hooks]
799 > [hooks]
800 > pretxnchangegroup=
800 > pretxnchangegroup=
801 > pretxnclose.failpush=
801 > pretxnclose.failpush=
802 > prepushkey.failpush = sh -c "echo 'do not push the key !'; false"
802 > prepushkey.failpush = sh -c "echo 'do not push the key !'; false"
803 > [extensions]
803 > [extensions]
804 > mandatorypart=$TESTTMP/mandatorypart.py
804 > mandatorypart=$TESTTMP/mandatorypart.py
805 > EOF
805 > EOF
806 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config
806 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config
807 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
807 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
808 $ cat other.pid >> $DAEMON_PIDS
808 $ cat other.pid >> $DAEMON_PIDS
809
809
810 (Failure from a hook)
810 (Failure from a hook)
811
811
812 $ hg -R main push other -r e7ec4e813ba6
812 $ hg -R main push other -r e7ec4e813ba6
813 pushing to other
813 pushing to other
814 searching for changes
814 searching for changes
815 adding changesets
815 adding changesets
816 adding manifests
816 adding manifests
817 adding file changes
817 adding file changes
818 added 1 changesets with 1 changes to 1 files
818 added 1 changesets with 1 changes to 1 files
819 do not push the key !
819 do not push the key !
820 pushkey-abort: prepushkey.failpush hook exited with status 1
820 pushkey-abort: prepushkey.failpush hook exited with status 1
821 transaction abort!
821 transaction abort!
822 Cleaning up the mess...
822 Cleaning up the mess...
823 rollback completed
823 rollback completed
824 abort: Correct phase push failed (because hooks)
824 abort: Correct phase push failed (because hooks)
825 [255]
825 [255]
826 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
826 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
827 pushing to ssh://user@dummy/other
827 pushing to ssh://user@dummy/other
828 searching for changes
828 searching for changes
829 remote: adding changesets
829 remote: adding changesets
830 remote: adding manifests
830 remote: adding manifests
831 remote: adding file changes
831 remote: adding file changes
832 remote: added 1 changesets with 1 changes to 1 files
832 remote: added 1 changesets with 1 changes to 1 files
833 remote: do not push the key !
833 remote: do not push the key !
834 remote: pushkey-abort: prepushkey.failpush hook exited with status 1
834 remote: pushkey-abort: prepushkey.failpush hook exited with status 1
835 remote: transaction abort!
835 remote: transaction abort!
836 remote: Cleaning up the mess...
836 remote: Cleaning up the mess...
837 remote: rollback completed
837 remote: rollback completed
838 abort: Correct phase push failed (because hooks)
838 abort: Correct phase push failed (because hooks)
839 [255]
839 [255]
840 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
840 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
841 pushing to http://localhost:$HGPORT2/
841 pushing to http://localhost:$HGPORT2/
842 searching for changes
842 searching for changes
843 remote: adding changesets
843 remote: adding changesets
844 remote: adding manifests
844 remote: adding manifests
845 remote: adding file changes
845 remote: adding file changes
846 remote: added 1 changesets with 1 changes to 1 files
846 remote: added 1 changesets with 1 changes to 1 files
847 remote: do not push the key !
847 remote: do not push the key !
848 remote: pushkey-abort: prepushkey.failpush hook exited with status 1
848 remote: pushkey-abort: prepushkey.failpush hook exited with status 1
849 remote: transaction abort!
849 remote: transaction abort!
850 remote: Cleaning up the mess...
850 remote: Cleaning up the mess...
851 remote: rollback completed
851 remote: rollback completed
852 abort: Correct phase push failed (because hooks)
852 abort: Correct phase push failed (because hooks)
853 [255]
853 [255]
854
854
855 (Failure from a the pushkey)
855 (Failure from a the pushkey)
856
856
857 $ cat > mandatorypart.py << EOF
857 $ cat > mandatorypart.py << EOF
858 > from mercurial import exchange
858 > from mercurial import exchange
859 > from mercurial import pushkey
859 > from mercurial import pushkey
860 > from mercurial import node
860 > from mercurial import node
861 > from mercurial import error
861 > from mercurial import error
862 > @exchange.b2partsgenerator(b'failingpuskey')
862 > @exchange.b2partsgenerator(b'failingpuskey')
863 > def addfailingpushey(pushop, bundler):
863 > def addfailingpushey(pushop, bundler):
864 > enc = pushkey.encode
864 > enc = pushkey.encode
865 > part = bundler.newpart(b'pushkey')
865 > part = bundler.newpart(b'pushkey')
866 > part.addparam(b'namespace', enc(b'phases'))
866 > part.addparam(b'namespace', enc(b'phases'))
867 > part.addparam(b'key', enc(b'cd010b8cd998f3981a5a8115f94f8da4ab506089'))
867 > part.addparam(b'key', enc(b'cd010b8cd998f3981a5a8115f94f8da4ab506089'))
868 > part.addparam(b'old', enc(b'4')) # will fail
868 > part.addparam(b'old', enc(b'4')) # will fail
869 > part.addparam(b'new', enc(b'3'))
869 > part.addparam(b'new', enc(b'3'))
870 > def fail(pushop, exc):
870 > def fail(pushop, exc):
871 > raise error.Abort(b'Clown phase push failed')
871 > raise error.Abort(b'Clown phase push failed')
872 > pushop.pkfailcb[part.id] = fail
872 > pushop.pkfailcb[part.id] = fail
873 > EOF
873 > EOF
874 $ cat >> $HGRCPATH << EOF
874 $ cat >> $HGRCPATH << EOF
875 > [hooks]
875 > [hooks]
876 > prepushkey.failpush =
876 > prepushkey.failpush =
877 > EOF
877 > EOF
878 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config
878 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config
879 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
879 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
880 $ cat other.pid >> $DAEMON_PIDS
880 $ cat other.pid >> $DAEMON_PIDS
881
881
882 $ hg -R main push other -r e7ec4e813ba6
882 $ hg -R main push other -r e7ec4e813ba6
883 pushing to other
883 pushing to other
884 searching for changes
884 searching for changes
885 adding changesets
885 adding changesets
886 adding manifests
886 adding manifests
887 adding file changes
887 adding file changes
888 added 1 changesets with 1 changes to 1 files
888 added 1 changesets with 1 changes to 1 files
889 transaction abort!
889 transaction abort!
890 Cleaning up the mess...
890 Cleaning up the mess...
891 rollback completed
891 rollback completed
892 pushkey: lock state after "phases"
892 pushkey: lock state after "phases"
893 lock: free
893 lock: free
894 wlock: free
894 wlock: free
895 abort: Clown phase push failed
895 abort: Clown phase push failed
896 [255]
896 [255]
897 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
897 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
898 pushing to ssh://user@dummy/other
898 pushing to ssh://user@dummy/other
899 searching for changes
899 searching for changes
900 remote: adding changesets
900 remote: adding changesets
901 remote: adding manifests
901 remote: adding manifests
902 remote: adding file changes
902 remote: adding file changes
903 remote: added 1 changesets with 1 changes to 1 files
903 remote: added 1 changesets with 1 changes to 1 files
904 remote: transaction abort!
904 remote: transaction abort!
905 remote: Cleaning up the mess...
905 remote: Cleaning up the mess...
906 remote: rollback completed
906 remote: rollback completed
907 remote: pushkey: lock state after "phases"
907 remote: pushkey: lock state after "phases"
908 remote: lock: free
908 remote: lock: free
909 remote: wlock: free
909 remote: wlock: free
910 abort: Clown phase push failed
910 abort: Clown phase push failed
911 [255]
911 [255]
912 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
912 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
913 pushing to http://localhost:$HGPORT2/
913 pushing to http://localhost:$HGPORT2/
914 searching for changes
914 searching for changes
915 remote: adding changesets
915 remote: adding changesets
916 remote: adding manifests
916 remote: adding manifests
917 remote: adding file changes
917 remote: adding file changes
918 remote: added 1 changesets with 1 changes to 1 files
918 remote: added 1 changesets with 1 changes to 1 files
919 remote: transaction abort!
919 remote: transaction abort!
920 remote: Cleaning up the mess...
920 remote: Cleaning up the mess...
921 remote: rollback completed
921 remote: rollback completed
922 remote: pushkey: lock state after "phases"
922 remote: pushkey: lock state after "phases"
923 remote: lock: free
923 remote: lock: free
924 remote: wlock: free
924 remote: wlock: free
925 abort: Clown phase push failed
925 abort: Clown phase push failed
926 [255]
926 [255]
927
927
928 Test lazily acquiring the lock during unbundle
928 Test lazily acquiring the lock during unbundle
929 $ cp $TESTTMP/hgrc.orig $HGRCPATH
929 $ cp $TESTTMP/hgrc.orig $HGRCPATH
930 $ cat >> $HGRCPATH <<EOF
930 $ cat >> $HGRCPATH <<EOF
931 > [ui]
931 > [ui]
932 > ssh="$PYTHON" "$TESTDIR/dummyssh"
932 > ssh="$PYTHON" "$TESTDIR/dummyssh"
933 > EOF
933 > EOF
934
934
935 $ cat >> $TESTTMP/locktester.py <<EOF
935 $ cat >> $TESTTMP/locktester.py <<EOF
936 > import os
936 > import os
937 > from mercurial import extensions, bundle2, error
937 > from mercurial import extensions, bundle2, error
938 > def checklock(orig, repo, *args, **kwargs):
938 > def checklock(orig, repo, *args, **kwargs):
939 > if repo.svfs.lexists(b"lock"):
939 > if repo.svfs.lexists(b"lock"):
940 > raise error.Abort(b"Lock should not be taken")
940 > raise error.Abort(b"Lock should not be taken")
941 > return orig(repo, *args, **kwargs)
941 > return orig(repo, *args, **kwargs)
942 > def extsetup(ui):
942 > def extsetup(ui):
943 > extensions.wrapfunction(bundle2, b'processbundle', checklock)
943 > extensions.wrapfunction(bundle2, b'processbundle', checklock)
944 > EOF
944 > EOF
945
945
946 $ hg init lazylock
946 $ hg init lazylock
947 $ cat >> lazylock/.hg/hgrc <<EOF
947 $ cat >> lazylock/.hg/hgrc <<EOF
948 > [extensions]
948 > [extensions]
949 > locktester=$TESTTMP/locktester.py
949 > locktester=$TESTTMP/locktester.py
950 > EOF
950 > EOF
951
951
952 $ hg clone -q ssh://user@dummy/lazylock lazylockclient
952 $ hg clone -q ssh://user@dummy/lazylock lazylockclient
953 $ cd lazylockclient
953 $ cd lazylockclient
954 $ touch a && hg ci -Aqm a
954 $ touch a && hg ci -Aqm a
955 $ hg push
955 $ hg push
956 pushing to ssh://user@dummy/lazylock
956 pushing to ssh://user@dummy/lazylock
957 searching for changes
957 searching for changes
958 remote: Lock should not be taken
958 remote: Lock should not be taken
959 abort: push failed on remote
959 abort: push failed on remote
960 [255]
960 [255]
961
961
962 $ cat >> ../lazylock/.hg/hgrc <<EOF
962 $ cat >> ../lazylock/.hg/hgrc <<EOF
963 > [experimental]
963 > [experimental]
964 > bundle2lazylocking=True
964 > bundle2lazylocking=True
965 > EOF
965 > EOF
966 $ hg push
966 $ hg push
967 pushing to ssh://user@dummy/lazylock
967 pushing to ssh://user@dummy/lazylock
968 searching for changes
968 searching for changes
969 remote: adding changesets
969 remote: adding changesets
970 remote: adding manifests
970 remote: adding manifests
971 remote: adding file changes
971 remote: adding file changes
972 remote: added 1 changesets with 1 changes to 1 files
972 remote: added 1 changesets with 1 changes to 1 files
973
973
974 $ cd ..
974 $ cd ..
975
975
976 Servers can disable bundle1 for clone/pull operations
976 Servers can disable bundle1 for clone/pull operations
977
977
978 $ killdaemons.py
978 $ killdaemons.py
979 $ hg init bundle2onlyserver
979 $ hg init bundle2onlyserver
980 $ cd bundle2onlyserver
980 $ cd bundle2onlyserver
981 $ cat > .hg/hgrc << EOF
981 $ cat > .hg/hgrc << EOF
982 > [server]
982 > [server]
983 > bundle1.pull = false
983 > bundle1.pull = false
984 > EOF
984 > EOF
985
985
986 $ touch foo
986 $ touch foo
987 $ hg -q commit -A -m initial
987 $ hg -q commit -A -m initial
988
988
989 $ hg serve -p $HGPORT -d --pid-file=hg.pid
989 $ hg serve -p $HGPORT -d --pid-file=hg.pid
990 $ cat hg.pid >> $DAEMON_PIDS
990 $ cat hg.pid >> $DAEMON_PIDS
991
991
992 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2
992 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2
993 requesting all changes
993 requesting all changes
994 abort: remote error:
994 abort: remote error:
995 incompatible Mercurial client; bundle2 required
995 incompatible Mercurial client; bundle2 required
996 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
996 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
997 [255]
997 [255]
998 $ killdaemons.py
998 $ killdaemons.py
999 $ cd ..
999 $ cd ..
1000
1000
1001 bundle1 can still pull non-generaldelta repos when generaldelta bundle1 disabled
1001 bundle1 can still pull non-generaldelta repos when generaldelta bundle1 disabled
1002
1002
1003 $ hg --config format.usegeneraldelta=false init notgdserver
1003 $ hg --config format.usegeneraldelta=false init notgdserver
1004 $ cd notgdserver
1004 $ cd notgdserver
1005 $ cat > .hg/hgrc << EOF
1005 $ cat > .hg/hgrc << EOF
1006 > [server]
1006 > [server]
1007 > bundle1gd.pull = false
1007 > bundle1gd.pull = false
1008 > EOF
1008 > EOF
1009
1009
1010 $ touch foo
1010 $ touch foo
1011 $ hg -q commit -A -m initial
1011 $ hg -q commit -A -m initial
1012 $ hg serve -p $HGPORT -d --pid-file=hg.pid
1012 $ hg serve -p $HGPORT -d --pid-file=hg.pid
1013 $ cat hg.pid >> $DAEMON_PIDS
1013 $ cat hg.pid >> $DAEMON_PIDS
1014
1014
1015 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2-1
1015 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2-1
1016 requesting all changes
1016 requesting all changes
1017 adding changesets
1017 adding changesets
1018 adding manifests
1018 adding manifests
1019 adding file changes
1019 adding file changes
1020 added 1 changesets with 1 changes to 1 files
1020 added 1 changesets with 1 changes to 1 files
1021 new changesets 96ee1d7354c4
1021 new changesets 96ee1d7354c4
1022 updating to branch default
1022 updating to branch default
1023 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1023 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1024
1024
1025 $ killdaemons.py
1025 $ killdaemons.py
1026 $ cd ../bundle2onlyserver
1026 $ cd ../bundle2onlyserver
1027
1027
1028 bundle1 pull can be disabled for generaldelta repos only
1028 bundle1 pull can be disabled for generaldelta repos only
1029
1029
1030 $ cat > .hg/hgrc << EOF
1030 $ cat > .hg/hgrc << EOF
1031 > [server]
1031 > [server]
1032 > bundle1gd.pull = false
1032 > bundle1gd.pull = false
1033 > EOF
1033 > EOF
1034
1034
1035 $ hg serve -p $HGPORT -d --pid-file=hg.pid
1035 $ hg serve -p $HGPORT -d --pid-file=hg.pid
1036 $ cat hg.pid >> $DAEMON_PIDS
1036 $ cat hg.pid >> $DAEMON_PIDS
1037 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2
1037 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2
1038 requesting all changes
1038 requesting all changes
1039 abort: remote error:
1039 abort: remote error:
1040 incompatible Mercurial client; bundle2 required
1040 incompatible Mercurial client; bundle2 required
1041 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1041 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1042 [255]
1042 [255]
1043
1043
1044 $ killdaemons.py
1044 $ killdaemons.py
1045
1045
1046 Verify the global server.bundle1 option works
1046 Verify the global server.bundle1 option works
1047
1047
1048 $ cd ..
1048 $ cd ..
1049 $ cat > bundle2onlyserver/.hg/hgrc << EOF
1049 $ cat > bundle2onlyserver/.hg/hgrc << EOF
1050 > [server]
1050 > [server]
1051 > bundle1 = false
1051 > bundle1 = false
1052 > EOF
1052 > EOF
1053 $ hg serve -R bundle2onlyserver -p $HGPORT -d --pid-file=hg.pid
1053 $ hg serve -R bundle2onlyserver -p $HGPORT -d --pid-file=hg.pid
1054 $ cat hg.pid >> $DAEMON_PIDS
1054 $ cat hg.pid >> $DAEMON_PIDS
1055 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT not-bundle2
1055 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT not-bundle2
1056 requesting all changes
1056 requesting all changes
1057 abort: remote error:
1057 abort: remote error:
1058 incompatible Mercurial client; bundle2 required
1058 incompatible Mercurial client; bundle2 required
1059 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1059 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1060 [255]
1060 [255]
1061 $ killdaemons.py
1061 $ killdaemons.py
1062
1062
1063 $ hg --config devel.legacy.exchange=bundle1 clone ssh://user@dummy/bundle2onlyserver not-bundle2-ssh
1063 $ hg --config devel.legacy.exchange=bundle1 clone ssh://user@dummy/bundle2onlyserver not-bundle2-ssh
1064 requesting all changes
1064 requesting all changes
1065 adding changesets
1065 adding changesets
1066 remote: abort: incompatible Mercurial client; bundle2 required
1066 remote: abort: incompatible Mercurial client; bundle2 required
1067 remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1067 remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1068 transaction abort!
1068 transaction abort!
1069 rollback completed
1069 rollback completed
1070 abort: stream ended unexpectedly (got 0 bytes, expected 4)
1070 abort: stream ended unexpectedly (got 0 bytes, expected 4)
1071 [255]
1071 [255]
1072
1072
1073 $ cat > bundle2onlyserver/.hg/hgrc << EOF
1073 $ cat > bundle2onlyserver/.hg/hgrc << EOF
1074 > [server]
1074 > [server]
1075 > bundle1gd = false
1075 > bundle1gd = false
1076 > EOF
1076 > EOF
1077 $ hg serve -R bundle2onlyserver -p $HGPORT -d --pid-file=hg.pid
1077 $ hg serve -R bundle2onlyserver -p $HGPORT -d --pid-file=hg.pid
1078 $ cat hg.pid >> $DAEMON_PIDS
1078 $ cat hg.pid >> $DAEMON_PIDS
1079
1079
1080 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2
1080 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2
1081 requesting all changes
1081 requesting all changes
1082 abort: remote error:
1082 abort: remote error:
1083 incompatible Mercurial client; bundle2 required
1083 incompatible Mercurial client; bundle2 required
1084 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1084 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1085 [255]
1085 [255]
1086
1086
1087 $ killdaemons.py
1087 $ killdaemons.py
1088
1088
1089 $ cd notgdserver
1089 $ cd notgdserver
1090 $ cat > .hg/hgrc << EOF
1090 $ cat > .hg/hgrc << EOF
1091 > [server]
1091 > [server]
1092 > bundle1gd = false
1092 > bundle1gd = false
1093 > EOF
1093 > EOF
1094 $ hg serve -p $HGPORT -d --pid-file=hg.pid
1094 $ hg serve -p $HGPORT -d --pid-file=hg.pid
1095 $ cat hg.pid >> $DAEMON_PIDS
1095 $ cat hg.pid >> $DAEMON_PIDS
1096
1096
1097 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2-2
1097 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2-2
1098 requesting all changes
1098 requesting all changes
1099 adding changesets
1099 adding changesets
1100 adding manifests
1100 adding manifests
1101 adding file changes
1101 adding file changes
1102 added 1 changesets with 1 changes to 1 files
1102 added 1 changesets with 1 changes to 1 files
1103 new changesets 96ee1d7354c4
1103 new changesets 96ee1d7354c4
1104 updating to branch default
1104 updating to branch default
1105 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1105 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1106
1106
1107 $ killdaemons.py
1107 $ killdaemons.py
1108 $ cd ../bundle2onlyserver
1108 $ cd ../bundle2onlyserver
1109
1109
1110 Verify bundle1 pushes can be disabled
1110 Verify bundle1 pushes can be disabled
1111
1111
1112 $ cat > .hg/hgrc << EOF
1112 $ cat > .hg/hgrc << EOF
1113 > [server]
1113 > [server]
1114 > bundle1.push = false
1114 > bundle1.push = false
1115 > [web]
1115 > [web]
1116 > allow_push = *
1116 > allow_push = *
1117 > push_ssl = false
1117 > push_ssl = false
1118 > EOF
1118 > EOF
1119
1119
1120 $ hg serve -p $HGPORT -d --pid-file=hg.pid -E error.log
1120 $ hg serve -p $HGPORT -d --pid-file=hg.pid -E error.log
1121 $ cat hg.pid >> $DAEMON_PIDS
1121 $ cat hg.pid >> $DAEMON_PIDS
1122 $ cd ..
1122 $ cd ..
1123
1123
1124 $ hg clone http://localhost:$HGPORT bundle2-only
1124 $ hg clone http://localhost:$HGPORT bundle2-only
1125 requesting all changes
1125 requesting all changes
1126 adding changesets
1126 adding changesets
1127 adding manifests
1127 adding manifests
1128 adding file changes
1128 adding file changes
1129 added 1 changesets with 1 changes to 1 files
1129 added 1 changesets with 1 changes to 1 files
1130 new changesets 96ee1d7354c4
1130 new changesets 96ee1d7354c4
1131 updating to branch default
1131 updating to branch default
1132 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1132 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1133 $ cd bundle2-only
1133 $ cd bundle2-only
1134 $ echo commit > foo
1134 $ echo commit > foo
1135 $ hg commit -m commit
1135 $ hg commit -m commit
1136 $ hg --config devel.legacy.exchange=bundle1 push
1136 $ hg --config devel.legacy.exchange=bundle1 push
1137 pushing to http://localhost:$HGPORT/
1137 pushing to http://localhost:$HGPORT/
1138 searching for changes
1138 searching for changes
1139 abort: remote error:
1139 abort: remote error:
1140 incompatible Mercurial client; bundle2 required
1140 incompatible Mercurial client; bundle2 required
1141 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1141 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1142 [255]
1142 [255]
1143
1143
1144 (also check with ssh)
1144 (also check with ssh)
1145
1145
1146 $ hg --config devel.legacy.exchange=bundle1 push ssh://user@dummy/bundle2onlyserver
1146 $ hg --config devel.legacy.exchange=bundle1 push ssh://user@dummy/bundle2onlyserver
1147 pushing to ssh://user@dummy/bundle2onlyserver
1147 pushing to ssh://user@dummy/bundle2onlyserver
1148 searching for changes
1148 searching for changes
1149 remote: abort: incompatible Mercurial client; bundle2 required
1149 remote: abort: incompatible Mercurial client; bundle2 required
1150 remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1150 remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1151 [1]
1151 [1]
1152
1152
1153 $ hg push
1153 $ hg push
1154 pushing to http://localhost:$HGPORT/
1154 pushing to http://localhost:$HGPORT/
1155 searching for changes
1155 searching for changes
1156 remote: adding changesets
1156 remote: adding changesets
1157 remote: adding manifests
1157 remote: adding manifests
1158 remote: adding file changes
1158 remote: adding file changes
1159 remote: added 1 changesets with 1 changes to 1 files
1159 remote: added 1 changesets with 1 changes to 1 files
@@ -1,1236 +1,1236
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 > import gc
15 > import gc
16 > import os
16 > import os
17 > import sys
17 > import sys
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 > from mercurial import pycompat
25 > from mercurial import pycompat
26 > from mercurial import registrar
26 > from mercurial import registrar
27 >
27 >
28 >
28 >
29 > try:
29 > try:
30 > import msvcrt
30 > import msvcrt
31 > msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
31 > msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
32 > msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
32 > msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
33 > msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
33 > msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
34 > except ImportError:
34 > except ImportError:
35 > pass
35 > pass
36 >
36 >
37 > cmdtable = {}
37 > cmdtable = {}
38 > command = registrar.command(cmdtable)
38 > command = registrar.command(cmdtable)
39 >
39 >
40 > ELEPHANTSSONG = b"""Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
40 > ELEPHANTSSONG = b"""Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
41 > Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
41 > Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
42 > Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko."""
42 > Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko."""
43 > assert len(ELEPHANTSSONG) == 178 # future test say 178 bytes, trust it.
43 > assert len(ELEPHANTSSONG) == 178 # future test say 178 bytes, trust it.
44 >
44 >
45 > @bundle2.parthandler(b'test:song')
45 > @bundle2.parthandler(b'test:song')
46 > def songhandler(op, part):
46 > def songhandler(op, part):
47 > """handle a "test:song" bundle2 part, printing the lyrics on stdin"""
47 > """handle a "test:song" bundle2 part, printing the lyrics on stdin"""
48 > op.ui.write(b'The choir starts singing:\n')
48 > op.ui.write(b'The choir starts singing:\n')
49 > verses = 0
49 > verses = 0
50 > for line in part.read().split(b'\n'):
50 > for line in part.read().split(b'\n'):
51 > op.ui.write(b' %s\n' % line)
51 > op.ui.write(b' %s\n' % line)
52 > verses += 1
52 > verses += 1
53 > op.records.add(b'song', {b'verses': verses})
53 > op.records.add(b'song', {b'verses': verses})
54 >
54 >
55 > @bundle2.parthandler(b'test:ping')
55 > @bundle2.parthandler(b'test:ping')
56 > def pinghandler(op, part):
56 > def pinghandler(op, part):
57 > op.ui.write(b'received ping request (id %i)\n' % part.id)
57 > op.ui.write(b'received ping request (id %i)\n' % part.id)
58 > if op.reply is not None and b'ping-pong' in op.reply.capabilities:
58 > if op.reply is not None and b'ping-pong' in op.reply.capabilities:
59 > op.ui.write_err(b'replying to ping request (id %i)\n' % part.id)
59 > op.ui.write_err(b'replying to ping request (id %i)\n' % part.id)
60 > op.reply.newpart(b'test:pong', [(b'in-reply-to', b'%d' % part.id)],
60 > op.reply.newpart(b'test:pong', [(b'in-reply-to', b'%d' % part.id)],
61 > mandatory=False)
61 > mandatory=False)
62 >
62 >
63 > @bundle2.parthandler(b'test:debugreply')
63 > @bundle2.parthandler(b'test:debugreply')
64 > def debugreply(op, part):
64 > def debugreply(op, part):
65 > """print data about the capacity of the bundle reply"""
65 > """print data about the capacity of the bundle reply"""
66 > if op.reply is None:
66 > if op.reply is None:
67 > op.ui.write(b'debugreply: no reply\n')
67 > op.ui.write(b'debugreply: no reply\n')
68 > else:
68 > else:
69 > op.ui.write(b'debugreply: capabilities:\n')
69 > op.ui.write(b'debugreply: capabilities:\n')
70 > for cap in sorted(op.reply.capabilities):
70 > for cap in sorted(op.reply.capabilities):
71 > op.ui.write(b"debugreply: '%s'\n" % cap)
71 > op.ui.write(b"debugreply: '%s'\n" % cap)
72 > for val in op.reply.capabilities[cap]:
72 > for val in op.reply.capabilities[cap]:
73 > op.ui.write(b"debugreply: '%s'\n" % val)
73 > op.ui.write(b"debugreply: '%s'\n" % val)
74 >
74 >
75 > @command(b'bundle2',
75 > @command(b'bundle2',
76 > [(b'', b'param', [], b'stream level parameter'),
76 > [(b'', b'param', [], b'stream level parameter'),
77 > (b'', b'unknown', False, b'include an unknown mandatory part in the bundle'),
77 > (b'', b'unknown', False, b'include an unknown mandatory part in the bundle'),
78 > (b'', b'unknownparams', False, b'include an unknown part parameters in the bundle'),
78 > (b'', b'unknownparams', False, b'include an unknown part parameters in the bundle'),
79 > (b'', b'parts', False, b'include some arbitrary parts to the bundle'),
79 > (b'', b'parts', False, b'include some arbitrary parts to the bundle'),
80 > (b'', b'reply', False, b'produce a reply bundle'),
80 > (b'', b'reply', False, b'produce a reply bundle'),
81 > (b'', b'pushrace', False, b'includes a check:head part with unknown nodes'),
81 > (b'', b'pushrace', False, b'includes a check:head part with unknown nodes'),
82 > (b'', b'genraise', False, b'includes a part that raise an exception during generation'),
82 > (b'', b'genraise', False, b'includes a part that raise an exception during generation'),
83 > (b'', b'timeout', False, b'emulate a timeout during bundle generation'),
83 > (b'', b'timeout', False, b'emulate a timeout during bundle generation'),
84 > (b'r', b'rev', [], b'includes those changeset in the bundle'),
84 > (b'r', b'rev', [], b'includes those changeset in the bundle'),
85 > (b'', b'compress', b'', b'compress the stream'),],
85 > (b'', b'compress', b'', b'compress the stream'),],
86 > b'[OUTPUTFILE]')
86 > b'[OUTPUTFILE]')
87 > def cmdbundle2(ui, repo, path=None, **opts):
87 > def cmdbundle2(ui, repo, path=None, **opts):
88 > """write a bundle2 container on standard output"""
88 > """write a bundle2 container on standard output"""
89 > bundler = bundle2.bundle20(ui)
89 > bundler = bundle2.bundle20(ui)
90 > for p in opts['param']:
90 > for p in opts['param']:
91 > p = p.split(b'=', 1)
91 > p = p.split(b'=', 1)
92 > try:
92 > try:
93 > bundler.addparam(*p)
93 > bundler.addparam(*p)
94 > except error.ProgrammingError as exc:
94 > except error.ProgrammingError as exc:
95 > raise error.Abort(b'%s' % exc)
95 > raise error.Abort(b'%s' % exc)
96 >
96 >
97 > if opts['compress']:
97 > if opts['compress']:
98 > bundler.setcompression(opts['compress'])
98 > bundler.setcompression(opts['compress'])
99 >
99 >
100 > if opts['reply']:
100 > if opts['reply']:
101 > capsstring = b'ping-pong\nelephants=babar,celeste\ncity%3D%21=celeste%2Cville'
101 > capsstring = b'ping-pong\nelephants=babar,celeste\ncity%3D%21=celeste%2Cville'
102 > bundler.newpart(b'replycaps', data=capsstring)
102 > bundler.newpart(b'replycaps', data=capsstring)
103 >
103 >
104 > if opts['pushrace']:
104 > if opts['pushrace']:
105 > # also serve to test the assignement of data outside of init
105 > # also serve to test the assignement of data outside of init
106 > part = bundler.newpart(b'check:heads')
106 > part = bundler.newpart(b'check:heads')
107 > part.data = b'01234567890123456789'
107 > part.data = b'01234567890123456789'
108 >
108 >
109 > revs = opts['rev']
109 > revs = opts['rev']
110 > if 'rev' in opts:
110 > if 'rev' in opts:
111 > revs = scmutil.revrange(repo, opts['rev'])
111 > revs = scmutil.revrange(repo, opts['rev'])
112 > if revs:
112 > if revs:
113 > # very crude version of a changegroup part creation
113 > # very crude version of a changegroup part creation
114 > bundled = repo.revs('%ld::%ld', revs, revs)
114 > bundled = repo.revs('%ld::%ld', revs, revs)
115 > headmissing = [c.node() for c in repo.set('heads(%ld)', revs)]
115 > headmissing = [c.node() for c in repo.set('heads(%ld)', revs)]
116 > headcommon = [c.node() for c in repo.set('parents(%ld) - %ld', revs, revs)]
116 > headcommon = [c.node() for c in repo.set('parents(%ld) - %ld', revs, revs)]
117 > outgoing = discovery.outgoing(repo, headcommon, headmissing)
117 > outgoing = discovery.outgoing(repo, headcommon, headmissing)
118 > cg = changegroup.makechangegroup(repo, outgoing, b'01',
118 > cg = changegroup.makechangegroup(repo, outgoing, b'01',
119 > b'test:bundle2')
119 > b'test:bundle2')
120 > bundler.newpart(b'changegroup', data=cg.getchunks(),
120 > bundler.newpart(b'changegroup', data=cg.getchunks(),
121 > mandatory=False)
121 > mandatory=False)
122 >
122 >
123 > if opts['parts']:
123 > if opts['parts']:
124 > bundler.newpart(b'test:empty', mandatory=False)
124 > bundler.newpart(b'test:empty', mandatory=False)
125 > # add a second one to make sure we handle multiple parts
125 > # add a second one to make sure we handle multiple parts
126 > bundler.newpart(b'test:empty', mandatory=False)
126 > bundler.newpart(b'test:empty', mandatory=False)
127 > bundler.newpart(b'test:song', data=ELEPHANTSSONG, mandatory=False)
127 > bundler.newpart(b'test:song', data=ELEPHANTSSONG, mandatory=False)
128 > bundler.newpart(b'test:debugreply', mandatory=False)
128 > bundler.newpart(b'test:debugreply', mandatory=False)
129 > mathpart = bundler.newpart(b'test:math')
129 > mathpart = bundler.newpart(b'test:math')
130 > mathpart.addparam(b'pi', b'3.14')
130 > mathpart.addparam(b'pi', b'3.14')
131 > mathpart.addparam(b'e', b'2.72')
131 > mathpart.addparam(b'e', b'2.72')
132 > mathpart.addparam(b'cooking', b'raw', mandatory=False)
132 > mathpart.addparam(b'cooking', b'raw', mandatory=False)
133 > mathpart.data = b'42'
133 > mathpart.data = b'42'
134 > mathpart.mandatory = False
134 > mathpart.mandatory = False
135 > # advisory known part with unknown mandatory param
135 > # advisory known part with unknown mandatory param
136 > bundler.newpart(b'test:song', [(b'randomparam', b'')], mandatory=False)
136 > bundler.newpart(b'test:song', [(b'randomparam', b'')], mandatory=False)
137 > if opts['unknown']:
137 > if opts['unknown']:
138 > bundler.newpart(b'test:unknown', data=b'some random content')
138 > bundler.newpart(b'test:unknown', data=b'some random content')
139 > if opts['unknownparams']:
139 > if opts['unknownparams']:
140 > bundler.newpart(b'test:song', [(b'randomparams', b'')])
140 > bundler.newpart(b'test:song', [(b'randomparams', b'')])
141 > if opts['parts']:
141 > if opts['parts']:
142 > bundler.newpart(b'test:ping', mandatory=False)
142 > bundler.newpart(b'test:ping', mandatory=False)
143 > if opts['genraise']:
143 > if opts['genraise']:
144 > def genraise():
144 > def genraise():
145 > yield b'first line\n'
145 > yield b'first line\n'
146 > raise RuntimeError('Someone set up us the bomb!')
146 > raise RuntimeError('Someone set up us the bomb!')
147 > bundler.newpart(b'output', data=genraise(), mandatory=False)
147 > bundler.newpart(b'output', data=genraise(), mandatory=False)
148 >
148 >
149 > if path is None:
149 > if path is None:
150 > file = pycompat.stdout
150 > file = pycompat.stdout
151 > else:
151 > else:
152 > file = open(path, 'wb')
152 > file = open(path, 'wb')
153 >
153 >
154 > if opts['timeout']:
154 > if opts['timeout']:
155 > bundler.newpart(b'test:song', data=ELEPHANTSSONG, mandatory=False)
155 > bundler.newpart(b'test:song', data=ELEPHANTSSONG, mandatory=False)
156 > for idx, junk in enumerate(bundler.getchunks()):
156 > for idx, junk in enumerate(bundler.getchunks()):
157 > ui.write(b'%d chunk\n' % idx)
157 > ui.write(b'%d chunk\n' % idx)
158 > if idx > 4:
158 > if idx > 4:
159 > # This throws a GeneratorExit inside the generator, which
159 > # This throws a GeneratorExit inside the generator, which
160 > # can cause problems if the exception-recovery code is
160 > # can cause problems if the exception-recovery code is
161 > # too zealous. It's important for this test that the break
161 > # too zealous. It's important for this test that the break
162 > # occur while we're in the middle of a part.
162 > # occur while we're in the middle of a part.
163 > break
163 > break
164 > gc.collect()
164 > gc.collect()
165 > ui.write(b'fake timeout complete.\n')
165 > ui.write(b'fake timeout complete.\n')
166 > return
166 > return
167 > try:
167 > try:
168 > for chunk in bundler.getchunks():
168 > for chunk in bundler.getchunks():
169 > file.write(chunk)
169 > file.write(chunk)
170 > except RuntimeError as exc:
170 > except RuntimeError as exc:
171 > raise error.Abort(exc)
171 > raise error.Abort(exc)
172 > finally:
172 > finally:
173 > file.flush()
173 > file.flush()
174 >
174 >
175 > @command(b'unbundle2', [], b'')
175 > @command(b'unbundle2', [], b'')
176 > def cmdunbundle2(ui, repo, replypath=None):
176 > def cmdunbundle2(ui, repo, replypath=None):
177 > """process a bundle2 stream from stdin on the current repo"""
177 > """process a bundle2 stream from stdin on the current repo"""
178 > try:
178 > try:
179 > tr = None
179 > tr = None
180 > lock = repo.lock()
180 > lock = repo.lock()
181 > tr = repo.transaction(b'processbundle')
181 > tr = repo.transaction(b'processbundle')
182 > try:
182 > try:
183 > unbundler = bundle2.getunbundler(ui, pycompat.stdin)
183 > unbundler = bundle2.getunbundler(ui, pycompat.stdin)
184 > op = bundle2.processbundle(repo, unbundler, lambda: tr)
184 > op = bundle2.processbundle(repo, unbundler, lambda: tr)
185 > tr.close()
185 > tr.close()
186 > except error.BundleValueError as exc:
186 > except error.BundleValueError as exc:
187 > raise error.Abort(b'missing support for %s' % exc)
187 > raise error.Abort(b'missing support for %s' % exc)
188 > except error.PushRaced as exc:
188 > except error.PushRaced as exc:
189 > raise error.Abort(b'push race: %s' % exc)
189 > raise error.Abort(b'push race: %s' % exc)
190 > finally:
190 > finally:
191 > if tr is not None:
191 > if tr is not None:
192 > tr.release()
192 > tr.release()
193 > lock.release()
193 > lock.release()
194 > remains = pycompat.stdin.read()
194 > remains = pycompat.stdin.read()
195 > ui.write(b'%i unread bytes\n' % len(remains))
195 > ui.write(b'%i unread bytes\n' % len(remains))
196 > if op.records[b'song']:
196 > if op.records[b'song']:
197 > totalverses = sum(r[b'verses'] for r in op.records[b'song'])
197 > totalverses = sum(r[b'verses'] for r in op.records[b'song'])
198 > ui.write(b'%i total verses sung\n' % totalverses)
198 > ui.write(b'%i total verses sung\n' % totalverses)
199 > for rec in op.records[b'changegroup']:
199 > for rec in op.records[b'changegroup']:
200 > ui.write(b'addchangegroup return: %i\n' % rec[b'return'])
200 > ui.write(b'addchangegroup return: %i\n' % rec[b'return'])
201 > if op.reply is not None and replypath is not None:
201 > if op.reply is not None and replypath is not None:
202 > with open(replypath, 'wb') as file:
202 > with open(replypath, 'wb') as file:
203 > for chunk in op.reply.getchunks():
203 > for chunk in op.reply.getchunks():
204 > file.write(chunk)
204 > file.write(chunk)
205 >
205 >
206 > @command(b'statbundle2', [], b'')
206 > @command(b'statbundle2', [], b'')
207 > def cmdstatbundle2(ui, repo):
207 > def cmdstatbundle2(ui, repo):
208 > """print statistic on the bundle2 container read from stdin"""
208 > """print statistic on the bundle2 container read from stdin"""
209 > unbundler = bundle2.getunbundler(ui, pycompat.stdin)
209 > unbundler = bundle2.getunbundler(ui, pycompat.stdin)
210 > try:
210 > try:
211 > params = unbundler.params
211 > params = unbundler.params
212 > except error.BundleValueError as exc:
212 > except error.BundleValueError as exc:
213 > raise error.Abort(b'unknown parameters: %s' % exc)
213 > raise error.Abort(b'unknown parameters: %s' % exc)
214 > ui.write(b'options count: %i\n' % len(params))
214 > ui.write(b'options count: %i\n' % len(params))
215 > for key in sorted(params):
215 > for key in sorted(params):
216 > ui.write(b'- %s\n' % key)
216 > ui.write(b'- %s\n' % key)
217 > value = params[key]
217 > value = params[key]
218 > if value is not None:
218 > if value is not None:
219 > ui.write(b' %s\n' % value)
219 > ui.write(b' %s\n' % value)
220 > count = 0
220 > count = 0
221 > for p in unbundler.iterparts():
221 > for p in unbundler.iterparts():
222 > count += 1
222 > count += 1
223 > ui.write(b' :%s:\n' % p.type)
223 > ui.write(b' :%s:\n' % p.type)
224 > ui.write(b' mandatory: %i\n' % len(p.mandatoryparams))
224 > ui.write(b' mandatory: %i\n' % len(p.mandatoryparams))
225 > ui.write(b' advisory: %i\n' % len(p.advisoryparams))
225 > ui.write(b' advisory: %i\n' % len(p.advisoryparams))
226 > ui.write(b' payload: %i bytes\n' % len(p.read()))
226 > ui.write(b' payload: %i bytes\n' % len(p.read()))
227 > ui.write(b'parts count: %i\n' % count)
227 > ui.write(b'parts count: %i\n' % count)
228 > EOF
228 > EOF
229 $ cat >> $HGRCPATH << EOF
229 $ cat >> $HGRCPATH << EOF
230 > [extensions]
230 > [extensions]
231 > bundle2=$TESTTMP/bundle2.py
231 > bundle2=$TESTTMP/bundle2.py
232 > [experimental]
232 > [experimental]
233 > evolution.createmarkers=True
233 > evolution.createmarkers=True
234 > [ui]
234 > [ui]
235 > ssh="$PYTHON" "$TESTDIR/dummyssh"
235 > ssh="$PYTHON" "$TESTDIR/dummyssh"
236 > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
236 > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
237 > [web]
237 > [web]
238 > push_ssl = false
238 > push_ssl = false
239 > allow_push = *
239 > allow_push = *
240 > [phases]
240 > [phases]
241 > publish=False
241 > publish=False
242 > EOF
242 > EOF
243
243
244 The extension requires a repo (currently unused)
244 The extension requires a repo (currently unused)
245
245
246 $ hg init main
246 $ hg init main
247 $ cd main
247 $ cd main
248 $ touch a
248 $ touch a
249 $ hg add a
249 $ hg add a
250 $ hg commit -m 'a'
250 $ hg commit -m 'a'
251
251
252
252
253 Empty bundle
253 Empty bundle
254 =================
254 =================
255
255
256 - no option
256 - no option
257 - no parts
257 - no parts
258
258
259 Test bundling
259 Test bundling
260
260
261 $ hg bundle2 | f --hexdump
261 $ hg bundle2 | f --hexdump
262
262
263 0000: 48 47 32 30 00 00 00 00 00 00 00 00 |HG20........|
263 0000: 48 47 32 30 00 00 00 00 00 00 00 00 |HG20........|
264
264
265 Test timeouts during bundling
265 Test timeouts during bundling
266 $ hg bundle2 --timeout --debug --config devel.bundle2.debug=yes
266 $ hg bundle2 --timeout --debug --config devel.bundle2.debug=yes
267 bundle2-output-bundle: "HG20", 1 parts total
267 bundle2-output-bundle: "HG20", 1 parts total
268 bundle2-output: start emission of HG20 stream
268 bundle2-output: start emission of HG20 stream
269 0 chunk
269 0 chunk
270 bundle2-output: bundle parameter:
270 bundle2-output: bundle parameter:
271 1 chunk
271 1 chunk
272 bundle2-output: start of parts
272 bundle2-output: start of parts
273 bundle2-output: bundle part: "test:song"
273 bundle2-output: bundle part: "test:song"
274 bundle2-output-part: "test:song" (advisory) 178 bytes payload
274 bundle2-output-part: "test:song" (advisory) 178 bytes payload
275 bundle2-output: part 0: "test:song"
275 bundle2-output: part 0: "test:song"
276 bundle2-output: header chunk size: 16
276 bundle2-output: header chunk size: 16
277 2 chunk
277 2 chunk
278 3 chunk
278 3 chunk
279 bundle2-output: payload chunk size: 178
279 bundle2-output: payload chunk size: 178
280 4 chunk
280 4 chunk
281 5 chunk
281 5 chunk
282 bundle2-generatorexit
282 bundle2-generatorexit
283 fake timeout complete.
283 fake timeout complete.
284
284
285 Test unbundling
285 Test unbundling
286
286
287 $ hg bundle2 | hg statbundle2
287 $ hg bundle2 | hg statbundle2
288 options count: 0
288 options count: 0
289 parts count: 0
289 parts count: 0
290
290
291 Test old style bundle are detected and refused
291 Test old style bundle are detected and refused
292
292
293 $ hg bundle --all --type v1 ../bundle.hg
293 $ hg bundle --all --type v1 ../bundle.hg
294 1 changesets found
294 1 changesets found
295 $ hg statbundle2 < ../bundle.hg
295 $ hg statbundle2 < ../bundle.hg
296 abort: unknown bundle version 10
296 abort: unknown bundle version 10
297 [255]
297 [255]
298
298
299 Test parameters
299 Test parameters
300 =================
300 =================
301
301
302 - some options
302 - some options
303 - no parts
303 - no parts
304
304
305 advisory parameters, no value
305 advisory parameters, no value
306 -------------------------------
306 -------------------------------
307
307
308 Simplest possible parameters form
308 Simplest possible parameters form
309
309
310 Test generation simple option
310 Test generation simple option
311
311
312 $ hg bundle2 --param 'caution' | f --hexdump
312 $ hg bundle2 --param 'caution' | f --hexdump
313
313
314 0000: 48 47 32 30 00 00 00 07 63 61 75 74 69 6f 6e 00 |HG20....caution.|
314 0000: 48 47 32 30 00 00 00 07 63 61 75 74 69 6f 6e 00 |HG20....caution.|
315 0010: 00 00 00 |...|
315 0010: 00 00 00 |...|
316
316
317 Test unbundling
317 Test unbundling
318
318
319 $ hg bundle2 --param 'caution' | hg statbundle2
319 $ hg bundle2 --param 'caution' | hg statbundle2
320 options count: 1
320 options count: 1
321 - caution
321 - caution
322 parts count: 0
322 parts count: 0
323
323
324 Test generation multiple option
324 Test generation multiple option
325
325
326 $ hg bundle2 --param 'caution' --param 'meal' | f --hexdump
326 $ hg bundle2 --param 'caution' --param 'meal' | f --hexdump
327
327
328 0000: 48 47 32 30 00 00 00 0c 63 61 75 74 69 6f 6e 20 |HG20....caution |
328 0000: 48 47 32 30 00 00 00 0c 63 61 75 74 69 6f 6e 20 |HG20....caution |
329 0010: 6d 65 61 6c 00 00 00 00 |meal....|
329 0010: 6d 65 61 6c 00 00 00 00 |meal....|
330
330
331 Test unbundling
331 Test unbundling
332
332
333 $ hg bundle2 --param 'caution' --param 'meal' | hg statbundle2
333 $ hg bundle2 --param 'caution' --param 'meal' | hg statbundle2
334 options count: 2
334 options count: 2
335 - caution
335 - caution
336 - meal
336 - meal
337 parts count: 0
337 parts count: 0
338
338
339 advisory parameters, with value
339 advisory parameters, with value
340 -------------------------------
340 -------------------------------
341
341
342 Test generation
342 Test generation
343
343
344 $ hg bundle2 --param 'caution' --param 'meal=vegan' --param 'elephants' | f --hexdump
344 $ hg bundle2 --param 'caution' --param 'meal=vegan' --param 'elephants' | f --hexdump
345
345
346 0000: 48 47 32 30 00 00 00 1c 63 61 75 74 69 6f 6e 20 |HG20....caution |
346 0000: 48 47 32 30 00 00 00 1c 63 61 75 74 69 6f 6e 20 |HG20....caution |
347 0010: 6d 65 61 6c 3d 76 65 67 61 6e 20 65 6c 65 70 68 |meal=vegan eleph|
347 0010: 6d 65 61 6c 3d 76 65 67 61 6e 20 65 6c 65 70 68 |meal=vegan eleph|
348 0020: 61 6e 74 73 00 00 00 00 |ants....|
348 0020: 61 6e 74 73 00 00 00 00 |ants....|
349
349
350 Test unbundling
350 Test unbundling
351
351
352 $ hg bundle2 --param 'caution' --param 'meal=vegan' --param 'elephants' | hg statbundle2
352 $ hg bundle2 --param 'caution' --param 'meal=vegan' --param 'elephants' | hg statbundle2
353 options count: 3
353 options count: 3
354 - caution
354 - caution
355 - elephants
355 - elephants
356 - meal
356 - meal
357 vegan
357 vegan
358 parts count: 0
358 parts count: 0
359
359
360 parameter with special char in value
360 parameter with special char in value
361 ---------------------------------------------------
361 ---------------------------------------------------
362
362
363 Test generation
363 Test generation
364
364
365 $ hg bundle2 --param 'e|! 7/=babar%#==tutu' --param simple | f --hexdump
365 $ hg bundle2 --param 'e|! 7/=babar%#==tutu' --param simple | f --hexdump
366
366
367 0000: 48 47 32 30 00 00 00 29 65 25 37 43 25 32 31 25 |HG20...)e%7C%21%|
367 0000: 48 47 32 30 00 00 00 29 65 25 37 43 25 32 31 25 |HG20...)e%7C%21%|
368 0010: 32 30 37 2f 3d 62 61 62 61 72 25 32 35 25 32 33 |207/=babar%25%23|
368 0010: 32 30 37 2f 3d 62 61 62 61 72 25 32 35 25 32 33 |207/=babar%25%23|
369 0020: 25 33 44 25 33 44 74 75 74 75 20 73 69 6d 70 6c |%3D%3Dtutu simpl|
369 0020: 25 33 44 25 33 44 74 75 74 75 20 73 69 6d 70 6c |%3D%3Dtutu simpl|
370 0030: 65 00 00 00 00 |e....|
370 0030: 65 00 00 00 00 |e....|
371
371
372 Test unbundling
372 Test unbundling
373
373
374 $ hg bundle2 --param 'e|! 7/=babar%#==tutu' --param simple | hg statbundle2
374 $ hg bundle2 --param 'e|! 7/=babar%#==tutu' --param simple | hg statbundle2
375 options count: 2
375 options count: 2
376 - e|! 7/
376 - e|! 7/
377 babar%#==tutu
377 babar%#==tutu
378 - simple
378 - simple
379 parts count: 0
379 parts count: 0
380
380
381 Test unknown mandatory option
381 Test unknown mandatory option
382 ---------------------------------------------------
382 ---------------------------------------------------
383
383
384 $ hg bundle2 --param 'Gravity' | hg statbundle2
384 $ hg bundle2 --param 'Gravity' | hg statbundle2
385 abort: unknown parameters: Stream Parameter - Gravity
385 abort: unknown parameters: Stream Parameter - Gravity
386 [255]
386 [255]
387
387
388 Test debug output
388 Test debug output
389 ---------------------------------------------------
389 ---------------------------------------------------
390
390
391 bundling debug
391 bundling debug
392
392
393 $ hg bundle2 --debug --param 'e|! 7/=babar%#==tutu' --param simple ../out.hg2 --config progress.debug=true --config devel.bundle2.debug=true
393 $ hg bundle2 --debug --param 'e|! 7/=babar%#==tutu' --param simple ../out.hg2 --config progress.debug=true --config devel.bundle2.debug=true
394 bundle2-output-bundle: "HG20", (2 params) 0 parts total
394 bundle2-output-bundle: "HG20", (2 params) 0 parts total
395 bundle2-output: start emission of HG20 stream
395 bundle2-output: start emission of HG20 stream
396 bundle2-output: bundle parameter: e%7C%21%207/=babar%25%23%3D%3Dtutu simple
396 bundle2-output: bundle parameter: e%7C%21%207/=babar%25%23%3D%3Dtutu simple
397 bundle2-output: start of parts
397 bundle2-output: start of parts
398 bundle2-output: end of bundle
398 bundle2-output: end of bundle
399
399
400 file content is ok
400 file content is ok
401
401
402 $ f --hexdump ../out.hg2
402 $ f --hexdump ../out.hg2
403 ../out.hg2:
403 ../out.hg2:
404 0000: 48 47 32 30 00 00 00 29 65 25 37 43 25 32 31 25 |HG20...)e%7C%21%|
404 0000: 48 47 32 30 00 00 00 29 65 25 37 43 25 32 31 25 |HG20...)e%7C%21%|
405 0010: 32 30 37 2f 3d 62 61 62 61 72 25 32 35 25 32 33 |207/=babar%25%23|
405 0010: 32 30 37 2f 3d 62 61 62 61 72 25 32 35 25 32 33 |207/=babar%25%23|
406 0020: 25 33 44 25 33 44 74 75 74 75 20 73 69 6d 70 6c |%3D%3Dtutu simpl|
406 0020: 25 33 44 25 33 44 74 75 74 75 20 73 69 6d 70 6c |%3D%3Dtutu simpl|
407 0030: 65 00 00 00 00 |e....|
407 0030: 65 00 00 00 00 |e....|
408
408
409 unbundling debug
409 unbundling debug
410
410
411 $ hg statbundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true < ../out.hg2
411 $ hg statbundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true < ../out.hg2
412 bundle2-input: start processing of HG20 stream
412 bundle2-input: start processing of HG20 stream
413 bundle2-input: reading bundle2 stream parameters
413 bundle2-input: reading bundle2 stream parameters
414 bundle2-input: ignoring unknown parameter e|! 7/
414 bundle2-input: ignoring unknown parameter e|! 7/
415 bundle2-input: ignoring unknown parameter simple
415 bundle2-input: ignoring unknown parameter simple
416 options count: 2
416 options count: 2
417 - e|! 7/
417 - e|! 7/
418 babar%#==tutu
418 babar%#==tutu
419 - simple
419 - simple
420 bundle2-input: start extraction of bundle2 parts
420 bundle2-input: start extraction of bundle2 parts
421 bundle2-input: part header size: 0
421 bundle2-input: part header size: 0
422 bundle2-input: end of bundle2 stream
422 bundle2-input: end of bundle2 stream
423 parts count: 0
423 parts count: 0
424
424
425
425
426 Test buggy input
426 Test buggy input
427 ---------------------------------------------------
427 ---------------------------------------------------
428
428
429 empty parameter name
429 empty parameter name
430
430
431 $ hg bundle2 --param '' --quiet
431 $ hg bundle2 --param '' --quiet
432 abort: empty parameter name
432 abort: empty parameter name
433 [255]
433 [255]
434
434
435 bad parameter name
435 bad parameter name
436
436
437 $ hg bundle2 --param 42babar
437 $ hg bundle2 --param 42babar
438 abort: non letter first character: 42babar
438 abort: non letter first character: 42babar
439 [255]
439 [255]
440
440
441
441
442 Test part
442 Test part
443 =================
443 =================
444
444
445 $ hg bundle2 --parts ../parts.hg2 --debug --config progress.debug=true --config devel.bundle2.debug=true
445 $ hg bundle2 --parts ../parts.hg2 --debug --config progress.debug=true --config devel.bundle2.debug=true
446 bundle2-output-bundle: "HG20", 7 parts total
446 bundle2-output-bundle: "HG20", 7 parts total
447 bundle2-output: start emission of HG20 stream
447 bundle2-output: start emission of HG20 stream
448 bundle2-output: bundle parameter:
448 bundle2-output: bundle parameter:
449 bundle2-output: start of parts
449 bundle2-output: start of parts
450 bundle2-output: bundle part: "test:empty"
450 bundle2-output: bundle part: "test:empty"
451 bundle2-output-part: "test:empty" (advisory) empty payload
451 bundle2-output-part: "test:empty" (advisory) empty payload
452 bundle2-output: part 0: "test:empty"
452 bundle2-output: part 0: "test:empty"
453 bundle2-output: header chunk size: 17
453 bundle2-output: header chunk size: 17
454 bundle2-output: closing payload chunk
454 bundle2-output: closing payload chunk
455 bundle2-output: bundle part: "test:empty"
455 bundle2-output: bundle part: "test:empty"
456 bundle2-output-part: "test:empty" (advisory) empty payload
456 bundle2-output-part: "test:empty" (advisory) empty payload
457 bundle2-output: part 1: "test:empty"
457 bundle2-output: part 1: "test:empty"
458 bundle2-output: header chunk size: 17
458 bundle2-output: header chunk size: 17
459 bundle2-output: closing payload chunk
459 bundle2-output: closing payload chunk
460 bundle2-output: bundle part: "test:song"
460 bundle2-output: bundle part: "test:song"
461 bundle2-output-part: "test:song" (advisory) 178 bytes payload
461 bundle2-output-part: "test:song" (advisory) 178 bytes payload
462 bundle2-output: part 2: "test:song"
462 bundle2-output: part 2: "test:song"
463 bundle2-output: header chunk size: 16
463 bundle2-output: header chunk size: 16
464 bundle2-output: payload chunk size: 178
464 bundle2-output: payload chunk size: 178
465 bundle2-output: closing payload chunk
465 bundle2-output: closing payload chunk
466 bundle2-output: bundle part: "test:debugreply"
466 bundle2-output: bundle part: "test:debugreply"
467 bundle2-output-part: "test:debugreply" (advisory) empty payload
467 bundle2-output-part: "test:debugreply" (advisory) empty payload
468 bundle2-output: part 3: "test:debugreply"
468 bundle2-output: part 3: "test:debugreply"
469 bundle2-output: header chunk size: 22
469 bundle2-output: header chunk size: 22
470 bundle2-output: closing payload chunk
470 bundle2-output: closing payload chunk
471 bundle2-output: bundle part: "test:math"
471 bundle2-output: bundle part: "test:math"
472 bundle2-output-part: "test:math" (advisory) (params: 2 mandatory 2 advisory) 2 bytes payload
472 bundle2-output-part: "test:math" (advisory) (params: 2 mandatory 2 advisory) 2 bytes payload
473 bundle2-output: part 4: "test:math"
473 bundle2-output: part 4: "test:math"
474 bundle2-output: header chunk size: 43
474 bundle2-output: header chunk size: 43
475 bundle2-output: payload chunk size: 2
475 bundle2-output: payload chunk size: 2
476 bundle2-output: closing payload chunk
476 bundle2-output: closing payload chunk
477 bundle2-output: bundle part: "test:song"
477 bundle2-output: bundle part: "test:song"
478 bundle2-output-part: "test:song" (advisory) (params: 1 mandatory) empty payload
478 bundle2-output-part: "test:song" (advisory) (params: 1 mandatory) empty payload
479 bundle2-output: part 5: "test:song"
479 bundle2-output: part 5: "test:song"
480 bundle2-output: header chunk size: 29
480 bundle2-output: header chunk size: 29
481 bundle2-output: closing payload chunk
481 bundle2-output: closing payload chunk
482 bundle2-output: bundle part: "test:ping"
482 bundle2-output: bundle part: "test:ping"
483 bundle2-output-part: "test:ping" (advisory) empty payload
483 bundle2-output-part: "test:ping" (advisory) empty payload
484 bundle2-output: part 6: "test:ping"
484 bundle2-output: part 6: "test:ping"
485 bundle2-output: header chunk size: 16
485 bundle2-output: header chunk size: 16
486 bundle2-output: closing payload chunk
486 bundle2-output: closing payload chunk
487 bundle2-output: end of bundle
487 bundle2-output: end of bundle
488
488
489 $ f --hexdump ../parts.hg2
489 $ f --hexdump ../parts.hg2
490 ../parts.hg2:
490 ../parts.hg2:
491 0000: 48 47 32 30 00 00 00 00 00 00 00 11 0a 74 65 73 |HG20.........tes|
491 0000: 48 47 32 30 00 00 00 00 00 00 00 11 0a 74 65 73 |HG20.........tes|
492 0010: 74 3a 65 6d 70 74 79 00 00 00 00 00 00 00 00 00 |t:empty.........|
492 0010: 74 3a 65 6d 70 74 79 00 00 00 00 00 00 00 00 00 |t:empty.........|
493 0020: 00 00 00 00 11 0a 74 65 73 74 3a 65 6d 70 74 79 |......test:empty|
493 0020: 00 00 00 00 11 0a 74 65 73 74 3a 65 6d 70 74 79 |......test:empty|
494 0030: 00 00 00 01 00 00 00 00 00 00 00 00 00 10 09 74 |...............t|
494 0030: 00 00 00 01 00 00 00 00 00 00 00 00 00 10 09 74 |...............t|
495 0040: 65 73 74 3a 73 6f 6e 67 00 00 00 02 00 00 00 00 |est:song........|
495 0040: 65 73 74 3a 73 6f 6e 67 00 00 00 02 00 00 00 00 |est:song........|
496 0050: 00 b2 50 61 74 61 6c 69 20 44 69 72 61 70 61 74 |..Patali Dirapat|
496 0050: 00 b2 50 61 74 61 6c 69 20 44 69 72 61 70 61 74 |..Patali Dirapat|
497 0060: 61 2c 20 43 72 6f 6d 64 61 20 43 72 6f 6d 64 61 |a, Cromda Cromda|
497 0060: 61 2c 20 43 72 6f 6d 64 61 20 43 72 6f 6d 64 61 |a, Cromda Cromda|
498 0070: 20 52 69 70 61 6c 6f 2c 20 50 61 74 61 20 50 61 | Ripalo, Pata Pa|
498 0070: 20 52 69 70 61 6c 6f 2c 20 50 61 74 61 20 50 61 | Ripalo, Pata Pa|
499 0080: 74 61 2c 20 4b 6f 20 4b 6f 20 4b 6f 0a 42 6f 6b |ta, Ko Ko Ko.Bok|
499 0080: 74 61 2c 20 4b 6f 20 4b 6f 20 4b 6f 0a 42 6f 6b |ta, Ko Ko Ko.Bok|
500 0090: 6f 72 6f 20 44 69 70 6f 75 6c 69 74 6f 2c 20 52 |oro Dipoulito, R|
500 0090: 6f 72 6f 20 44 69 70 6f 75 6c 69 74 6f 2c 20 52 |oro Dipoulito, R|
501 00a0: 6f 6e 64 69 20 52 6f 6e 64 69 20 50 65 70 69 6e |ondi Rondi Pepin|
501 00a0: 6f 6e 64 69 20 52 6f 6e 64 69 20 50 65 70 69 6e |ondi Rondi Pepin|
502 00b0: 6f 2c 20 50 61 74 61 20 50 61 74 61 2c 20 4b 6f |o, Pata Pata, Ko|
502 00b0: 6f 2c 20 50 61 74 61 20 50 61 74 61 2c 20 4b 6f |o, Pata Pata, Ko|
503 00c0: 20 4b 6f 20 4b 6f 0a 45 6d 61 6e 61 20 4b 61 72 | Ko Ko.Emana Kar|
503 00c0: 20 4b 6f 20 4b 6f 0a 45 6d 61 6e 61 20 4b 61 72 | Ko Ko.Emana Kar|
504 00d0: 61 73 73 6f 6c 69 2c 20 4c 6f 75 63 72 61 20 4c |assoli, Loucra L|
504 00d0: 61 73 73 6f 6c 69 2c 20 4c 6f 75 63 72 61 20 4c |assoli, Loucra L|
505 00e0: 6f 75 63 72 61 20 50 6f 6e 70 6f 6e 74 6f 2c 20 |oucra Ponponto, |
505 00e0: 6f 75 63 72 61 20 50 6f 6e 70 6f 6e 74 6f 2c 20 |oucra Ponponto, |
506 00f0: 50 61 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f |Pata Pata, Ko Ko|
506 00f0: 50 61 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f |Pata Pata, Ko Ko|
507 0100: 20 4b 6f 2e 00 00 00 00 00 00 00 16 0f 74 65 73 | Ko..........tes|
507 0100: 20 4b 6f 2e 00 00 00 00 00 00 00 16 0f 74 65 73 | Ko..........tes|
508 0110: 74 3a 64 65 62 75 67 72 65 70 6c 79 00 00 00 03 |t:debugreply....|
508 0110: 74 3a 64 65 62 75 67 72 65 70 6c 79 00 00 00 03 |t:debugreply....|
509 0120: 00 00 00 00 00 00 00 00 00 2b 09 74 65 73 74 3a |.........+.test:|
509 0120: 00 00 00 00 00 00 00 00 00 2b 09 74 65 73 74 3a |.........+.test:|
510 0130: 6d 61 74 68 00 00 00 04 02 01 02 04 01 04 07 03 |math............|
510 0130: 6d 61 74 68 00 00 00 04 02 01 02 04 01 04 07 03 |math............|
511 0140: 70 69 33 2e 31 34 65 32 2e 37 32 63 6f 6f 6b 69 |pi3.14e2.72cooki|
511 0140: 70 69 33 2e 31 34 65 32 2e 37 32 63 6f 6f 6b 69 |pi3.14e2.72cooki|
512 0150: 6e 67 72 61 77 00 00 00 02 34 32 00 00 00 00 00 |ngraw....42.....|
512 0150: 6e 67 72 61 77 00 00 00 02 34 32 00 00 00 00 00 |ngraw....42.....|
513 0160: 00 00 1d 09 74 65 73 74 3a 73 6f 6e 67 00 00 00 |....test:song...|
513 0160: 00 00 1d 09 74 65 73 74 3a 73 6f 6e 67 00 00 00 |....test:song...|
514 0170: 05 01 00 0b 00 72 61 6e 64 6f 6d 70 61 72 61 6d |.....randomparam|
514 0170: 05 01 00 0b 00 72 61 6e 64 6f 6d 70 61 72 61 6d |.....randomparam|
515 0180: 00 00 00 00 00 00 00 10 09 74 65 73 74 3a 70 69 |.........test:pi|
515 0180: 00 00 00 00 00 00 00 10 09 74 65 73 74 3a 70 69 |.........test:pi|
516 0190: 6e 67 00 00 00 06 00 00 00 00 00 00 00 00 00 00 |ng..............|
516 0190: 6e 67 00 00 00 06 00 00 00 00 00 00 00 00 00 00 |ng..............|
517
517
518
518
519 $ hg statbundle2 < ../parts.hg2
519 $ hg statbundle2 < ../parts.hg2
520 options count: 0
520 options count: 0
521 :test:empty:
521 :test:empty:
522 mandatory: 0
522 mandatory: 0
523 advisory: 0
523 advisory: 0
524 payload: 0 bytes
524 payload: 0 bytes
525 :test:empty:
525 :test:empty:
526 mandatory: 0
526 mandatory: 0
527 advisory: 0
527 advisory: 0
528 payload: 0 bytes
528 payload: 0 bytes
529 :test:song:
529 :test:song:
530 mandatory: 0
530 mandatory: 0
531 advisory: 0
531 advisory: 0
532 payload: 178 bytes
532 payload: 178 bytes
533 :test:debugreply:
533 :test:debugreply:
534 mandatory: 0
534 mandatory: 0
535 advisory: 0
535 advisory: 0
536 payload: 0 bytes
536 payload: 0 bytes
537 :test:math:
537 :test:math:
538 mandatory: 2
538 mandatory: 2
539 advisory: 1
539 advisory: 1
540 payload: 2 bytes
540 payload: 2 bytes
541 :test:song:
541 :test:song:
542 mandatory: 1
542 mandatory: 1
543 advisory: 0
543 advisory: 0
544 payload: 0 bytes
544 payload: 0 bytes
545 :test:ping:
545 :test:ping:
546 mandatory: 0
546 mandatory: 0
547 advisory: 0
547 advisory: 0
548 payload: 0 bytes
548 payload: 0 bytes
549 parts count: 7
549 parts count: 7
550
550
551 $ hg statbundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true < ../parts.hg2
551 $ hg statbundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true < ../parts.hg2
552 bundle2-input: start processing of HG20 stream
552 bundle2-input: start processing of HG20 stream
553 bundle2-input: reading bundle2 stream parameters
553 bundle2-input: reading bundle2 stream parameters
554 options count: 0
554 options count: 0
555 bundle2-input: start extraction of bundle2 parts
555 bundle2-input: start extraction of bundle2 parts
556 bundle2-input: part header size: 17
556 bundle2-input: part header size: 17
557 bundle2-input: part type: "test:empty"
557 bundle2-input: part type: "test:empty"
558 bundle2-input: part id: "0"
558 bundle2-input: part id: "0"
559 bundle2-input: part parameters: 0
559 bundle2-input: part parameters: 0
560 :test:empty:
560 :test:empty:
561 mandatory: 0
561 mandatory: 0
562 advisory: 0
562 advisory: 0
563 bundle2-input: payload chunk size: 0
563 bundle2-input: payload chunk size: 0
564 payload: 0 bytes
564 payload: 0 bytes
565 bundle2-input: part header size: 17
565 bundle2-input: part header size: 17
566 bundle2-input: part type: "test:empty"
566 bundle2-input: part type: "test:empty"
567 bundle2-input: part id: "1"
567 bundle2-input: part id: "1"
568 bundle2-input: part parameters: 0
568 bundle2-input: part parameters: 0
569 :test:empty:
569 :test:empty:
570 mandatory: 0
570 mandatory: 0
571 advisory: 0
571 advisory: 0
572 bundle2-input: payload chunk size: 0
572 bundle2-input: payload chunk size: 0
573 payload: 0 bytes
573 payload: 0 bytes
574 bundle2-input: part header size: 16
574 bundle2-input: part header size: 16
575 bundle2-input: part type: "test:song"
575 bundle2-input: part type: "test:song"
576 bundle2-input: part id: "2"
576 bundle2-input: part id: "2"
577 bundle2-input: part parameters: 0
577 bundle2-input: part parameters: 0
578 :test:song:
578 :test:song:
579 mandatory: 0
579 mandatory: 0
580 advisory: 0
580 advisory: 0
581 bundle2-input: payload chunk size: 178
581 bundle2-input: payload chunk size: 178
582 bundle2-input: payload chunk size: 0
582 bundle2-input: payload chunk size: 0
583 bundle2-input-part: total payload size 178
583 bundle2-input-part: total payload size 178
584 payload: 178 bytes
584 payload: 178 bytes
585 bundle2-input: part header size: 22
585 bundle2-input: part header size: 22
586 bundle2-input: part type: "test:debugreply"
586 bundle2-input: part type: "test:debugreply"
587 bundle2-input: part id: "3"
587 bundle2-input: part id: "3"
588 bundle2-input: part parameters: 0
588 bundle2-input: part parameters: 0
589 :test:debugreply:
589 :test:debugreply:
590 mandatory: 0
590 mandatory: 0
591 advisory: 0
591 advisory: 0
592 bundle2-input: payload chunk size: 0
592 bundle2-input: payload chunk size: 0
593 payload: 0 bytes
593 payload: 0 bytes
594 bundle2-input: part header size: 43
594 bundle2-input: part header size: 43
595 bundle2-input: part type: "test:math"
595 bundle2-input: part type: "test:math"
596 bundle2-input: part id: "4"
596 bundle2-input: part id: "4"
597 bundle2-input: part parameters: 3
597 bundle2-input: part parameters: 3
598 :test:math:
598 :test:math:
599 mandatory: 2
599 mandatory: 2
600 advisory: 1
600 advisory: 1
601 bundle2-input: payload chunk size: 2
601 bundle2-input: payload chunk size: 2
602 bundle2-input: payload chunk size: 0
602 bundle2-input: payload chunk size: 0
603 bundle2-input-part: total payload size 2
603 bundle2-input-part: total payload size 2
604 payload: 2 bytes
604 payload: 2 bytes
605 bundle2-input: part header size: 29
605 bundle2-input: part header size: 29
606 bundle2-input: part type: "test:song"
606 bundle2-input: part type: "test:song"
607 bundle2-input: part id: "5"
607 bundle2-input: part id: "5"
608 bundle2-input: part parameters: 1
608 bundle2-input: part parameters: 1
609 :test:song:
609 :test:song:
610 mandatory: 1
610 mandatory: 1
611 advisory: 0
611 advisory: 0
612 bundle2-input: payload chunk size: 0
612 bundle2-input: payload chunk size: 0
613 payload: 0 bytes
613 payload: 0 bytes
614 bundle2-input: part header size: 16
614 bundle2-input: part header size: 16
615 bundle2-input: part type: "test:ping"
615 bundle2-input: part type: "test:ping"
616 bundle2-input: part id: "6"
616 bundle2-input: part id: "6"
617 bundle2-input: part parameters: 0
617 bundle2-input: part parameters: 0
618 :test:ping:
618 :test:ping:
619 mandatory: 0
619 mandatory: 0
620 advisory: 0
620 advisory: 0
621 bundle2-input: payload chunk size: 0
621 bundle2-input: payload chunk size: 0
622 payload: 0 bytes
622 payload: 0 bytes
623 bundle2-input: part header size: 0
623 bundle2-input: part header size: 0
624 bundle2-input: end of bundle2 stream
624 bundle2-input: end of bundle2 stream
625 parts count: 7
625 parts count: 7
626
626
627 Test actual unbundling of test part
627 Test actual unbundling of test part
628 =======================================
628 =======================================
629
629
630 Process the bundle
630 Process the bundle
631
631
632 $ hg unbundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true < ../parts.hg2
632 $ hg unbundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true < ../parts.hg2
633 bundle2-input: start processing of HG20 stream
633 bundle2-input: start processing of HG20 stream
634 bundle2-input: reading bundle2 stream parameters
634 bundle2-input: reading bundle2 stream parameters
635 bundle2-input-bundle: with-transaction
635 bundle2-input-bundle: with-transaction
636 bundle2-input: start extraction of bundle2 parts
636 bundle2-input: start extraction of bundle2 parts
637 bundle2-input: part header size: 17
637 bundle2-input: part header size: 17
638 bundle2-input: part type: "test:empty"
638 bundle2-input: part type: "test:empty"
639 bundle2-input: part id: "0"
639 bundle2-input: part id: "0"
640 bundle2-input: part parameters: 0
640 bundle2-input: part parameters: 0
641 bundle2-input: ignoring unsupported advisory part test:empty
641 bundle2-input: ignoring unsupported advisory part test:empty
642 bundle2-input-part: "test:empty" (advisory) unsupported-type
642 bundle2-input-part: "test:empty" (advisory) unsupported-type
643 bundle2-input: payload chunk size: 0
643 bundle2-input: payload chunk size: 0
644 bundle2-input: part header size: 17
644 bundle2-input: part header size: 17
645 bundle2-input: part type: "test:empty"
645 bundle2-input: part type: "test:empty"
646 bundle2-input: part id: "1"
646 bundle2-input: part id: "1"
647 bundle2-input: part parameters: 0
647 bundle2-input: part parameters: 0
648 bundle2-input: ignoring unsupported advisory part test:empty
648 bundle2-input: ignoring unsupported advisory part test:empty
649 bundle2-input-part: "test:empty" (advisory) unsupported-type
649 bundle2-input-part: "test:empty" (advisory) unsupported-type
650 bundle2-input: payload chunk size: 0
650 bundle2-input: payload chunk size: 0
651 bundle2-input: part header size: 16
651 bundle2-input: part header size: 16
652 bundle2-input: part type: "test:song"
652 bundle2-input: part type: "test:song"
653 bundle2-input: part id: "2"
653 bundle2-input: part id: "2"
654 bundle2-input: part parameters: 0
654 bundle2-input: part parameters: 0
655 bundle2-input: found a handler for part test:song
655 bundle2-input: found a handler for part test:song
656 bundle2-input-part: "test:song" (advisory) supported
656 bundle2-input-part: "test:song" (advisory) supported
657 The choir starts singing:
657 The choir starts singing:
658 bundle2-input: payload chunk size: 178
658 bundle2-input: payload chunk size: 178
659 bundle2-input: payload chunk size: 0
659 bundle2-input: payload chunk size: 0
660 bundle2-input-part: total payload size 178
660 bundle2-input-part: total payload size 178
661 Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
661 Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
662 Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
662 Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
663 Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.
663 Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.
664 bundle2-input: part header size: 22
664 bundle2-input: part header size: 22
665 bundle2-input: part type: "test:debugreply"
665 bundle2-input: part type: "test:debugreply"
666 bundle2-input: part id: "3"
666 bundle2-input: part id: "3"
667 bundle2-input: part parameters: 0
667 bundle2-input: part parameters: 0
668 bundle2-input: found a handler for part test:debugreply
668 bundle2-input: found a handler for part test:debugreply
669 bundle2-input-part: "test:debugreply" (advisory) supported
669 bundle2-input-part: "test:debugreply" (advisory) supported
670 debugreply: no reply
670 debugreply: no reply
671 bundle2-input: payload chunk size: 0
671 bundle2-input: payload chunk size: 0
672 bundle2-input: part header size: 43
672 bundle2-input: part header size: 43
673 bundle2-input: part type: "test:math"
673 bundle2-input: part type: "test:math"
674 bundle2-input: part id: "4"
674 bundle2-input: part id: "4"
675 bundle2-input: part parameters: 3
675 bundle2-input: part parameters: 3
676 bundle2-input: ignoring unsupported advisory part test:math
676 bundle2-input: ignoring unsupported advisory part test:math
677 bundle2-input-part: "test:math" (advisory) (params: 2 mandatory 2 advisory) unsupported-type
677 bundle2-input-part: "test:math" (advisory) (params: 2 mandatory 2 advisory) unsupported-type
678 bundle2-input: payload chunk size: 2
678 bundle2-input: payload chunk size: 2
679 bundle2-input: payload chunk size: 0
679 bundle2-input: payload chunk size: 0
680 bundle2-input-part: total payload size 2
680 bundle2-input-part: total payload size 2
681 bundle2-input: part header size: 29
681 bundle2-input: part header size: 29
682 bundle2-input: part type: "test:song"
682 bundle2-input: part type: "test:song"
683 bundle2-input: part id: "5"
683 bundle2-input: part id: "5"
684 bundle2-input: part parameters: 1
684 bundle2-input: part parameters: 1
685 bundle2-input: found a handler for part test:song
685 bundle2-input: found a handler for part test:song
686 bundle2-input: ignoring unsupported advisory part test:song - randomparam
686 bundle2-input: ignoring unsupported advisory part test:song - randomparam
687 bundle2-input-part: "test:song" (advisory) (params: 1 mandatory) unsupported-params (randomparam)
687 bundle2-input-part: "test:song" (advisory) (params: 1 mandatory) unsupported-params (randomparam)
688 bundle2-input: payload chunk size: 0
688 bundle2-input: payload chunk size: 0
689 bundle2-input: part header size: 16
689 bundle2-input: part header size: 16
690 bundle2-input: part type: "test:ping"
690 bundle2-input: part type: "test:ping"
691 bundle2-input: part id: "6"
691 bundle2-input: part id: "6"
692 bundle2-input: part parameters: 0
692 bundle2-input: part parameters: 0
693 bundle2-input: found a handler for part test:ping
693 bundle2-input: found a handler for part test:ping
694 bundle2-input-part: "test:ping" (advisory) supported
694 bundle2-input-part: "test:ping" (advisory) supported
695 received ping request (id 6)
695 received ping request (id 6)
696 bundle2-input: payload chunk size: 0
696 bundle2-input: payload chunk size: 0
697 bundle2-input: part header size: 0
697 bundle2-input: part header size: 0
698 bundle2-input: end of bundle2 stream
698 bundle2-input: end of bundle2 stream
699 bundle2-input-bundle: 6 parts total
699 bundle2-input-bundle: 6 parts total
700 0 unread bytes
700 0 unread bytes
701 3 total verses sung
701 3 total verses sung
702
702
703 Unbundle with an unknown mandatory part
703 Unbundle with an unknown mandatory part
704 (should abort)
704 (should abort)
705
705
706 $ hg bundle2 --parts --unknown ../unknown.hg2
706 $ hg bundle2 --parts --unknown ../unknown.hg2
707
707
708 $ hg unbundle2 < ../unknown.hg2
708 $ hg unbundle2 < ../unknown.hg2
709 The choir starts singing:
709 The choir starts singing:
710 Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
710 Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
711 Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
711 Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
712 Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.
712 Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.
713 debugreply: no reply
713 debugreply: no reply
714 0 unread bytes
714 0 unread bytes
715 abort: missing support for test:unknown
715 abort: missing support for test:unknown
716 [255]
716 [255]
717
717
718 Unbundle with an unknown mandatory part parameters
718 Unbundle with an unknown mandatory part parameters
719 (should abort)
719 (should abort)
720
720
721 $ hg bundle2 --unknownparams ../unknown.hg2
721 $ hg bundle2 --unknownparams ../unknown.hg2
722
722
723 $ hg unbundle2 < ../unknown.hg2
723 $ hg unbundle2 < ../unknown.hg2
724 0 unread bytes
724 0 unread bytes
725 abort: missing support for test:song - randomparams
725 abort: missing support for test:song - randomparams
726 [255]
726 [255]
727
727
728 unbundle with a reply
728 unbundle with a reply
729
729
730 $ hg bundle2 --parts --reply ../parts-reply.hg2
730 $ hg bundle2 --parts --reply ../parts-reply.hg2
731 $ hg unbundle2 ../reply.hg2 < ../parts-reply.hg2
731 $ hg unbundle2 ../reply.hg2 < ../parts-reply.hg2
732 0 unread bytes
732 0 unread bytes
733 3 total verses sung
733 3 total verses sung
734
734
735 The reply is a bundle
735 The reply is a bundle
736
736
737 $ f --hexdump ../reply.hg2
737 $ f --hexdump ../reply.hg2
738 ../reply.hg2:
738 ../reply.hg2:
739 0000: 48 47 32 30 00 00 00 00 00 00 00 1b 06 6f 75 74 |HG20.........out|
739 0000: 48 47 32 30 00 00 00 00 00 00 00 1b 06 6f 75 74 |HG20.........out|
740 0010: 70 75 74 00 00 00 00 00 01 0b 01 69 6e 2d 72 65 |put........in-re|
740 0010: 70 75 74 00 00 00 00 00 01 0b 01 69 6e 2d 72 65 |put........in-re|
741 0020: 70 6c 79 2d 74 6f 33 00 00 00 d9 54 68 65 20 63 |ply-to3....The c|
741 0020: 70 6c 79 2d 74 6f 33 00 00 00 d9 54 68 65 20 63 |ply-to3....The c|
742 0030: 68 6f 69 72 20 73 74 61 72 74 73 20 73 69 6e 67 |hoir starts sing|
742 0030: 68 6f 69 72 20 73 74 61 72 74 73 20 73 69 6e 67 |hoir starts sing|
743 0040: 69 6e 67 3a 0a 20 20 20 20 50 61 74 61 6c 69 20 |ing:. Patali |
743 0040: 69 6e 67 3a 0a 20 20 20 20 50 61 74 61 6c 69 20 |ing:. Patali |
744 0050: 44 69 72 61 70 61 74 61 2c 20 43 72 6f 6d 64 61 |Dirapata, Cromda|
744 0050: 44 69 72 61 70 61 74 61 2c 20 43 72 6f 6d 64 61 |Dirapata, Cromda|
745 0060: 20 43 72 6f 6d 64 61 20 52 69 70 61 6c 6f 2c 20 | Cromda Ripalo, |
745 0060: 20 43 72 6f 6d 64 61 20 52 69 70 61 6c 6f 2c 20 | Cromda Ripalo, |
746 0070: 50 61 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f |Pata Pata, Ko Ko|
746 0070: 50 61 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f |Pata Pata, Ko Ko|
747 0080: 20 4b 6f 0a 20 20 20 20 42 6f 6b 6f 72 6f 20 44 | Ko. Bokoro D|
747 0080: 20 4b 6f 0a 20 20 20 20 42 6f 6b 6f 72 6f 20 44 | Ko. Bokoro D|
748 0090: 69 70 6f 75 6c 69 74 6f 2c 20 52 6f 6e 64 69 20 |ipoulito, Rondi |
748 0090: 69 70 6f 75 6c 69 74 6f 2c 20 52 6f 6e 64 69 20 |ipoulito, Rondi |
749 00a0: 52 6f 6e 64 69 20 50 65 70 69 6e 6f 2c 20 50 61 |Rondi Pepino, Pa|
749 00a0: 52 6f 6e 64 69 20 50 65 70 69 6e 6f 2c 20 50 61 |Rondi Pepino, Pa|
750 00b0: 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f 20 4b |ta Pata, Ko Ko K|
750 00b0: 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f 20 4b |ta Pata, Ko Ko K|
751 00c0: 6f 0a 20 20 20 20 45 6d 61 6e 61 20 4b 61 72 61 |o. Emana Kara|
751 00c0: 6f 0a 20 20 20 20 45 6d 61 6e 61 20 4b 61 72 61 |o. Emana Kara|
752 00d0: 73 73 6f 6c 69 2c 20 4c 6f 75 63 72 61 20 4c 6f |ssoli, Loucra Lo|
752 00d0: 73 73 6f 6c 69 2c 20 4c 6f 75 63 72 61 20 4c 6f |ssoli, Loucra Lo|
753 00e0: 75 63 72 61 20 50 6f 6e 70 6f 6e 74 6f 2c 20 50 |ucra Ponponto, P|
753 00e0: 75 63 72 61 20 50 6f 6e 70 6f 6e 74 6f 2c 20 50 |ucra Ponponto, P|
754 00f0: 61 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f 20 |ata Pata, Ko Ko |
754 00f0: 61 74 61 20 50 61 74 61 2c 20 4b 6f 20 4b 6f 20 |ata Pata, Ko Ko |
755 0100: 4b 6f 2e 0a 00 00 00 00 00 00 00 1b 06 6f 75 74 |Ko...........out|
755 0100: 4b 6f 2e 0a 00 00 00 00 00 00 00 1b 06 6f 75 74 |Ko...........out|
756 0110: 70 75 74 00 00 00 01 00 01 0b 01 69 6e 2d 72 65 |put........in-re|
756 0110: 70 75 74 00 00 00 01 00 01 0b 01 69 6e 2d 72 65 |put........in-re|
757 0120: 70 6c 79 2d 74 6f 34 00 00 00 c9 64 65 62 75 67 |ply-to4....debug|
757 0120: 70 6c 79 2d 74 6f 34 00 00 00 c9 64 65 62 75 67 |ply-to4....debug|
758 0130: 72 65 70 6c 79 3a 20 63 61 70 61 62 69 6c 69 74 |reply: capabilit|
758 0130: 72 65 70 6c 79 3a 20 63 61 70 61 62 69 6c 69 74 |reply: capabilit|
759 0140: 69 65 73 3a 0a 64 65 62 75 67 72 65 70 6c 79 3a |ies:.debugreply:|
759 0140: 69 65 73 3a 0a 64 65 62 75 67 72 65 70 6c 79 3a |ies:.debugreply:|
760 0150: 20 20 20 20 20 27 63 69 74 79 3d 21 27 0a 64 65 | 'city=!'.de|
760 0150: 20 20 20 20 20 27 63 69 74 79 3d 21 27 0a 64 65 | 'city=!'.de|
761 0160: 62 75 67 72 65 70 6c 79 3a 20 20 20 20 20 20 20 |bugreply: |
761 0160: 62 75 67 72 65 70 6c 79 3a 20 20 20 20 20 20 20 |bugreply: |
762 0170: 20 20 27 63 65 6c 65 73 74 65 2c 76 69 6c 6c 65 | 'celeste,ville|
762 0170: 20 20 27 63 65 6c 65 73 74 65 2c 76 69 6c 6c 65 | 'celeste,ville|
763 0180: 27 0a 64 65 62 75 67 72 65 70 6c 79 3a 20 20 20 |'.debugreply: |
763 0180: 27 0a 64 65 62 75 67 72 65 70 6c 79 3a 20 20 20 |'.debugreply: |
764 0190: 20 20 27 65 6c 65 70 68 61 6e 74 73 27 0a 64 65 | 'elephants'.de|
764 0190: 20 20 27 65 6c 65 70 68 61 6e 74 73 27 0a 64 65 | 'elephants'.de|
765 01a0: 62 75 67 72 65 70 6c 79 3a 20 20 20 20 20 20 20 |bugreply: |
765 01a0: 62 75 67 72 65 70 6c 79 3a 20 20 20 20 20 20 20 |bugreply: |
766 01b0: 20 20 27 62 61 62 61 72 27 0a 64 65 62 75 67 72 | 'babar'.debugr|
766 01b0: 20 20 27 62 61 62 61 72 27 0a 64 65 62 75 67 72 | 'babar'.debugr|
767 01c0: 65 70 6c 79 3a 20 20 20 20 20 20 20 20 20 27 63 |eply: 'c|
767 01c0: 65 70 6c 79 3a 20 20 20 20 20 20 20 20 20 27 63 |eply: 'c|
768 01d0: 65 6c 65 73 74 65 27 0a 64 65 62 75 67 72 65 70 |eleste'.debugrep|
768 01d0: 65 6c 65 73 74 65 27 0a 64 65 62 75 67 72 65 70 |eleste'.debugrep|
769 01e0: 6c 79 3a 20 20 20 20 20 27 70 69 6e 67 2d 70 6f |ly: 'ping-po|
769 01e0: 6c 79 3a 20 20 20 20 20 27 70 69 6e 67 2d 70 6f |ly: 'ping-po|
770 01f0: 6e 67 27 0a 00 00 00 00 00 00 00 1e 09 74 65 73 |ng'..........tes|
770 01f0: 6e 67 27 0a 00 00 00 00 00 00 00 1e 09 74 65 73 |ng'..........tes|
771 0200: 74 3a 70 6f 6e 67 00 00 00 02 01 00 0b 01 69 6e |t:pong........in|
771 0200: 74 3a 70 6f 6e 67 00 00 00 02 01 00 0b 01 69 6e |t:pong........in|
772 0210: 2d 72 65 70 6c 79 2d 74 6f 37 00 00 00 00 00 00 |-reply-to7......|
772 0210: 2d 72 65 70 6c 79 2d 74 6f 37 00 00 00 00 00 00 |-reply-to7......|
773 0220: 00 1b 06 6f 75 74 70 75 74 00 00 00 03 00 01 0b |...output.......|
773 0220: 00 1b 06 6f 75 74 70 75 74 00 00 00 03 00 01 0b |...output.......|
774 0230: 01 69 6e 2d 72 65 70 6c 79 2d 74 6f 37 00 00 00 |.in-reply-to7...|
774 0230: 01 69 6e 2d 72 65 70 6c 79 2d 74 6f 37 00 00 00 |.in-reply-to7...|
775 0240: 3d 72 65 63 65 69 76 65 64 20 70 69 6e 67 20 72 |=received ping r|
775 0240: 3d 72 65 63 65 69 76 65 64 20 70 69 6e 67 20 72 |=received ping r|
776 0250: 65 71 75 65 73 74 20 28 69 64 20 37 29 0a 72 65 |equest (id 7).re|
776 0250: 65 71 75 65 73 74 20 28 69 64 20 37 29 0a 72 65 |equest (id 7).re|
777 0260: 70 6c 79 69 6e 67 20 74 6f 20 70 69 6e 67 20 72 |plying to ping r|
777 0260: 70 6c 79 69 6e 67 20 74 6f 20 70 69 6e 67 20 72 |plying to ping r|
778 0270: 65 71 75 65 73 74 20 28 69 64 20 37 29 0a 00 00 |equest (id 7)...|
778 0270: 65 71 75 65 73 74 20 28 69 64 20 37 29 0a 00 00 |equest (id 7)...|
779 0280: 00 00 00 00 00 00 |......|
779 0280: 00 00 00 00 00 00 |......|
780
780
781 The reply is valid
781 The reply is valid
782
782
783 $ hg statbundle2 < ../reply.hg2
783 $ hg statbundle2 < ../reply.hg2
784 options count: 0
784 options count: 0
785 :output:
785 :output:
786 mandatory: 0
786 mandatory: 0
787 advisory: 1
787 advisory: 1
788 payload: 217 bytes
788 payload: 217 bytes
789 :output:
789 :output:
790 mandatory: 0
790 mandatory: 0
791 advisory: 1
791 advisory: 1
792 payload: 201 bytes
792 payload: 201 bytes
793 :test:pong:
793 :test:pong:
794 mandatory: 1
794 mandatory: 1
795 advisory: 0
795 advisory: 0
796 payload: 0 bytes
796 payload: 0 bytes
797 :output:
797 :output:
798 mandatory: 0
798 mandatory: 0
799 advisory: 1
799 advisory: 1
800 payload: 61 bytes
800 payload: 61 bytes
801 parts count: 4
801 parts count: 4
802
802
803 Unbundle the reply to get the output:
803 Unbundle the reply to get the output:
804
804
805 $ hg unbundle2 < ../reply.hg2
805 $ hg unbundle2 < ../reply.hg2
806 remote: The choir starts singing:
806 remote: The choir starts singing:
807 remote: Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
807 remote: Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
808 remote: Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
808 remote: Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
809 remote: Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.
809 remote: Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.
810 remote: debugreply: capabilities:
810 remote: debugreply: capabilities:
811 remote: debugreply: 'city=!'
811 remote: debugreply: 'city=!'
812 remote: debugreply: 'celeste,ville'
812 remote: debugreply: 'celeste,ville'
813 remote: debugreply: 'elephants'
813 remote: debugreply: 'elephants'
814 remote: debugreply: 'babar'
814 remote: debugreply: 'babar'
815 remote: debugreply: 'celeste'
815 remote: debugreply: 'celeste'
816 remote: debugreply: 'ping-pong'
816 remote: debugreply: 'ping-pong'
817 remote: received ping request (id 7)
817 remote: received ping request (id 7)
818 remote: replying to ping request (id 7)
818 remote: replying to ping request (id 7)
819 0 unread bytes
819 0 unread bytes
820
820
821 Test push race detection
821 Test push race detection
822
822
823 $ hg bundle2 --pushrace ../part-race.hg2
823 $ hg bundle2 --pushrace ../part-race.hg2
824
824
825 $ hg unbundle2 < ../part-race.hg2
825 $ hg unbundle2 < ../part-race.hg2
826 0 unread bytes
826 0 unread bytes
827 abort: push race: repository changed while pushing - please try again
827 abort: push race: remote repository changed while pushing - please try again
828 [255]
828 [255]
829
829
830 Support for changegroup
830 Support for changegroup
831 ===================================
831 ===================================
832
832
833 $ hg unbundle $TESTDIR/bundles/rebase.hg
833 $ hg unbundle $TESTDIR/bundles/rebase.hg
834 adding changesets
834 adding changesets
835 adding manifests
835 adding manifests
836 adding file changes
836 adding file changes
837 added 8 changesets with 7 changes to 7 files (+3 heads)
837 added 8 changesets with 7 changes to 7 files (+3 heads)
838 new changesets cd010b8cd998:02de42196ebe (8 drafts)
838 new changesets cd010b8cd998:02de42196ebe (8 drafts)
839 (run 'hg heads' to see heads, 'hg merge' to merge)
839 (run 'hg heads' to see heads, 'hg merge' to merge)
840
840
841 $ hg log -G
841 $ hg log -G
842 o 8:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> H
842 o 8:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> H
843 |
843 |
844 | o 7:eea13746799a draft Nicolas Dumazet <nicdumz.commits@gmail.com> G
844 | o 7:eea13746799a draft Nicolas Dumazet <nicdumz.commits@gmail.com> G
845 |/|
845 |/|
846 o | 6:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F
846 o | 6:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F
847 | |
847 | |
848 | o 5:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
848 | o 5:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
849 |/
849 |/
850 | o 4:32af7686d403 draft Nicolas Dumazet <nicdumz.commits@gmail.com> D
850 | o 4:32af7686d403 draft Nicolas Dumazet <nicdumz.commits@gmail.com> D
851 | |
851 | |
852 | o 3:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> C
852 | o 3:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> C
853 | |
853 | |
854 | o 2:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> B
854 | o 2:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> B
855 |/
855 |/
856 o 1:cd010b8cd998 draft Nicolas Dumazet <nicdumz.commits@gmail.com> A
856 o 1:cd010b8cd998 draft Nicolas Dumazet <nicdumz.commits@gmail.com> A
857
857
858 @ 0:3903775176ed draft test a
858 @ 0:3903775176ed draft test a
859
859
860
860
861 $ hg bundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true --rev '8+7+5+4' ../rev.hg2
861 $ hg bundle2 --debug --config progress.debug=true --config devel.bundle2.debug=true --rev '8+7+5+4' ../rev.hg2
862 4 changesets found
862 4 changesets found
863 list of changesets:
863 list of changesets:
864 32af7686d403cf45b5d95f2d70cebea587ac806a
864 32af7686d403cf45b5d95f2d70cebea587ac806a
865 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
865 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
866 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
866 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
867 02de42196ebee42ef284b6780a87cdc96e8eaab6
867 02de42196ebee42ef284b6780a87cdc96e8eaab6
868 bundle2-output-bundle: "HG20", 1 parts total
868 bundle2-output-bundle: "HG20", 1 parts total
869 bundle2-output: start emission of HG20 stream
869 bundle2-output: start emission of HG20 stream
870 bundle2-output: bundle parameter:
870 bundle2-output: bundle parameter:
871 bundle2-output: start of parts
871 bundle2-output: start of parts
872 bundle2-output: bundle part: "changegroup"
872 bundle2-output: bundle part: "changegroup"
873 bundle2-output-part: "changegroup" (advisory) streamed payload
873 bundle2-output-part: "changegroup" (advisory) streamed payload
874 bundle2-output: part 0: "changegroup"
874 bundle2-output: part 0: "changegroup"
875 bundle2-output: header chunk size: 18
875 bundle2-output: header chunk size: 18
876 changesets: 1/4 chunks (25.00%)
876 changesets: 1/4 chunks (25.00%)
877 changesets: 2/4 chunks (50.00%)
877 changesets: 2/4 chunks (50.00%)
878 changesets: 3/4 chunks (75.00%)
878 changesets: 3/4 chunks (75.00%)
879 changesets: 4/4 chunks (100.00%)
879 changesets: 4/4 chunks (100.00%)
880 manifests: 1/4 chunks (25.00%)
880 manifests: 1/4 chunks (25.00%)
881 manifests: 2/4 chunks (50.00%)
881 manifests: 2/4 chunks (50.00%)
882 manifests: 3/4 chunks (75.00%)
882 manifests: 3/4 chunks (75.00%)
883 manifests: 4/4 chunks (100.00%)
883 manifests: 4/4 chunks (100.00%)
884 files: D 1/3 files (33.33%)
884 files: D 1/3 files (33.33%)
885 files: E 2/3 files (66.67%)
885 files: E 2/3 files (66.67%)
886 files: H 3/3 files (100.00%)
886 files: H 3/3 files (100.00%)
887 bundle2-output: payload chunk size: 1555
887 bundle2-output: payload chunk size: 1555
888 bundle2-output: closing payload chunk
888 bundle2-output: closing payload chunk
889 bundle2-output: end of bundle
889 bundle2-output: end of bundle
890
890
891 $ f --hexdump ../rev.hg2
891 $ f --hexdump ../rev.hg2
892 ../rev.hg2:
892 ../rev.hg2:
893 0000: 48 47 32 30 00 00 00 00 00 00 00 12 0b 63 68 61 |HG20.........cha|
893 0000: 48 47 32 30 00 00 00 00 00 00 00 12 0b 63 68 61 |HG20.........cha|
894 0010: 6e 67 65 67 72 6f 75 70 00 00 00 00 00 00 00 00 |ngegroup........|
894 0010: 6e 67 65 67 72 6f 75 70 00 00 00 00 00 00 00 00 |ngegroup........|
895 0020: 06 13 00 00 00 a4 32 af 76 86 d4 03 cf 45 b5 d9 |......2.v....E..|
895 0020: 06 13 00 00 00 a4 32 af 76 86 d4 03 cf 45 b5 d9 |......2.v....E..|
896 0030: 5f 2d 70 ce be a5 87 ac 80 6a 5f dd d9 89 57 c8 |_-p......j_...W.|
896 0030: 5f 2d 70 ce be a5 87 ac 80 6a 5f dd d9 89 57 c8 |_-p......j_...W.|
897 0040: a5 4a 4d 43 6d fe 1d a9 d8 7f 21 a1 b9 7b 00 00 |.JMCm.....!..{..|
897 0040: a5 4a 4d 43 6d fe 1d a9 d8 7f 21 a1 b9 7b 00 00 |.JMCm.....!..{..|
898 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
898 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
899 0060: 00 00 32 af 76 86 d4 03 cf 45 b5 d9 5f 2d 70 ce |..2.v....E.._-p.|
899 0060: 00 00 32 af 76 86 d4 03 cf 45 b5 d9 5f 2d 70 ce |..2.v....E.._-p.|
900 0070: be a5 87 ac 80 6a 00 00 00 00 00 00 00 29 00 00 |.....j.......)..|
900 0070: be a5 87 ac 80 6a 00 00 00 00 00 00 00 29 00 00 |.....j.......)..|
901 0080: 00 29 36 65 31 66 34 63 34 37 65 63 62 35 33 33 |.)6e1f4c47ecb533|
901 0080: 00 29 36 65 31 66 34 63 34 37 65 63 62 35 33 33 |.)6e1f4c47ecb533|
902 0090: 66 66 64 30 63 38 65 35 32 63 64 63 38 38 61 66 |ffd0c8e52cdc88af|
902 0090: 66 66 64 30 63 38 65 35 32 63 64 63 38 38 61 66 |ffd0c8e52cdc88af|
903 00a0: 62 36 63 64 33 39 65 32 30 63 0a 00 00 00 66 00 |b6cd39e20c....f.|
903 00a0: 62 36 63 64 33 39 65 32 30 63 0a 00 00 00 66 00 |b6cd39e20c....f.|
904 00b0: 00 00 68 00 00 00 02 44 0a 00 00 00 69 00 00 00 |..h....D....i...|
904 00b0: 00 00 68 00 00 00 02 44 0a 00 00 00 69 00 00 00 |..h....D....i...|
905 00c0: 6a 00 00 00 01 44 00 00 00 a4 95 20 ee a7 81 bc |j....D..... ....|
905 00c0: 6a 00 00 00 01 44 00 00 00 a4 95 20 ee a7 81 bc |j....D..... ....|
906 00d0: ca 16 c1 e1 5a cc 0b a1 43 35 a0 e8 e5 ba cd 01 |....Z...C5......|
906 00d0: ca 16 c1 e1 5a cc 0b a1 43 35 a0 e8 e5 ba cd 01 |....Z...C5......|
907 00e0: 0b 8c d9 98 f3 98 1a 5a 81 15 f9 4f 8d a4 ab 50 |.......Z...O...P|
907 00e0: 0b 8c d9 98 f3 98 1a 5a 81 15 f9 4f 8d a4 ab 50 |.......Z...O...P|
908 00f0: 60 89 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |`...............|
908 00f0: 60 89 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |`...............|
909 0100: 00 00 00 00 00 00 95 20 ee a7 81 bc ca 16 c1 e1 |....... ........|
909 0100: 00 00 00 00 00 00 95 20 ee a7 81 bc ca 16 c1 e1 |....... ........|
910 0110: 5a cc 0b a1 43 35 a0 e8 e5 ba 00 00 00 00 00 00 |Z...C5..........|
910 0110: 5a cc 0b a1 43 35 a0 e8 e5 ba 00 00 00 00 00 00 |Z...C5..........|
911 0120: 00 29 00 00 00 29 34 64 65 63 65 39 63 38 32 36 |.)...)4dece9c826|
911 0120: 00 29 00 00 00 29 34 64 65 63 65 39 63 38 32 36 |.)...)4dece9c826|
912 0130: 66 36 39 34 39 30 35 30 37 62 39 38 63 36 33 38 |f69490507b98c638|
912 0130: 66 36 39 34 39 30 35 30 37 62 39 38 63 36 33 38 |f69490507b98c638|
913 0140: 33 61 33 30 30 39 62 32 39 35 38 33 37 64 0a 00 |3a3009b295837d..|
913 0140: 33 61 33 30 30 39 62 32 39 35 38 33 37 64 0a 00 |3a3009b295837d..|
914 0150: 00 00 66 00 00 00 68 00 00 00 02 45 0a 00 00 00 |..f...h....E....|
914 0150: 00 00 66 00 00 00 68 00 00 00 02 45 0a 00 00 00 |..f...h....E....|
915 0160: 69 00 00 00 6a 00 00 00 01 45 00 00 00 a2 ee a1 |i...j....E......|
915 0160: 69 00 00 00 6a 00 00 00 01 45 00 00 00 a2 ee a1 |i...j....E......|
916 0170: 37 46 79 9a 9e 0b fd 88 f2 9d 3c 2e 9d c9 38 9f |7Fy.......<...8.|
916 0170: 37 46 79 9a 9e 0b fd 88 f2 9d 3c 2e 9d c9 38 9f |7Fy.......<...8.|
917 0180: 52 4f 24 b6 38 7c 8c 8c ae 37 17 88 80 f3 fa 95 |RO$.8|...7......|
917 0180: 52 4f 24 b6 38 7c 8c 8c ae 37 17 88 80 f3 fa 95 |RO$.8|...7......|
918 0190: de d3 cb 1c f7 85 95 20 ee a7 81 bc ca 16 c1 e1 |....... ........|
918 0190: de d3 cb 1c f7 85 95 20 ee a7 81 bc ca 16 c1 e1 |....... ........|
919 01a0: 5a cc 0b a1 43 35 a0 e8 e5 ba ee a1 37 46 79 9a |Z...C5......7Fy.|
919 01a0: 5a cc 0b a1 43 35 a0 e8 e5 ba ee a1 37 46 79 9a |Z...C5......7Fy.|
920 01b0: 9e 0b fd 88 f2 9d 3c 2e 9d c9 38 9f 52 4f 00 00 |......<...8.RO..|
920 01b0: 9e 0b fd 88 f2 9d 3c 2e 9d c9 38 9f 52 4f 00 00 |......<...8.RO..|
921 01c0: 00 00 00 00 00 29 00 00 00 29 33 36 35 62 39 33 |.....)...)365b93|
921 01c0: 00 00 00 00 00 29 00 00 00 29 33 36 35 62 39 33 |.....)...)365b93|
922 01d0: 64 35 37 66 64 66 34 38 31 34 65 32 62 35 39 31 |d57fdf4814e2b591|
922 01d0: 64 35 37 66 64 66 34 38 31 34 65 32 62 35 39 31 |d57fdf4814e2b591|
923 01e0: 31 64 36 62 61 63 66 66 32 62 31 32 30 31 34 34 |1d6bacff2b120144|
923 01e0: 31 64 36 62 61 63 66 66 32 62 31 32 30 31 34 34 |1d6bacff2b120144|
924 01f0: 34 31 0a 00 00 00 66 00 00 00 68 00 00 00 00 00 |41....f...h.....|
924 01f0: 34 31 0a 00 00 00 66 00 00 00 68 00 00 00 00 00 |41....f...h.....|
925 0200: 00 00 69 00 00 00 6a 00 00 00 01 47 00 00 00 a4 |..i...j....G....|
925 0200: 00 00 69 00 00 00 6a 00 00 00 01 47 00 00 00 a4 |..i...j....G....|
926 0210: 02 de 42 19 6e be e4 2e f2 84 b6 78 0a 87 cd c9 |..B.n......x....|
926 0210: 02 de 42 19 6e be e4 2e f2 84 b6 78 0a 87 cd c9 |..B.n......x....|
927 0220: 6e 8e aa b6 24 b6 38 7c 8c 8c ae 37 17 88 80 f3 |n...$.8|...7....|
927 0220: 6e 8e aa b6 24 b6 38 7c 8c 8c ae 37 17 88 80 f3 |n...$.8|...7....|
928 0230: fa 95 de d3 cb 1c f7 85 00 00 00 00 00 00 00 00 |................|
928 0230: fa 95 de d3 cb 1c f7 85 00 00 00 00 00 00 00 00 |................|
929 0240: 00 00 00 00 00 00 00 00 00 00 00 00 02 de 42 19 |..............B.|
929 0240: 00 00 00 00 00 00 00 00 00 00 00 00 02 de 42 19 |..............B.|
930 0250: 6e be e4 2e f2 84 b6 78 0a 87 cd c9 6e 8e aa b6 |n......x....n...|
930 0250: 6e be e4 2e f2 84 b6 78 0a 87 cd c9 6e 8e aa b6 |n......x....n...|
931 0260: 00 00 00 00 00 00 00 29 00 00 00 29 38 62 65 65 |.......)...)8bee|
931 0260: 00 00 00 00 00 00 00 29 00 00 00 29 38 62 65 65 |.......)...)8bee|
932 0270: 34 38 65 64 63 37 33 31 38 35 34 31 66 63 30 30 |48edc7318541fc00|
932 0270: 34 38 65 64 63 37 33 31 38 35 34 31 66 63 30 30 |48edc7318541fc00|
933 0280: 31 33 65 65 34 31 62 30 38 39 32 37 36 61 38 63 |13ee41b089276a8c|
933 0280: 31 33 65 65 34 31 62 30 38 39 32 37 36 61 38 63 |13ee41b089276a8c|
934 0290: 32 34 62 66 0a 00 00 00 66 00 00 00 66 00 00 00 |24bf....f...f...|
934 0290: 32 34 62 66 0a 00 00 00 66 00 00 00 66 00 00 00 |24bf....f...f...|
935 02a0: 02 48 0a 00 00 00 67 00 00 00 68 00 00 00 01 48 |.H....g...h....H|
935 02a0: 02 48 0a 00 00 00 67 00 00 00 68 00 00 00 01 48 |.H....g...h....H|
936 02b0: 00 00 00 00 00 00 00 8b 6e 1f 4c 47 ec b5 33 ff |........n.LG..3.|
936 02b0: 00 00 00 00 00 00 00 8b 6e 1f 4c 47 ec b5 33 ff |........n.LG..3.|
937 02c0: d0 c8 e5 2c dc 88 af b6 cd 39 e2 0c 66 a5 a0 18 |...,.....9..f...|
937 02c0: d0 c8 e5 2c dc 88 af b6 cd 39 e2 0c 66 a5 a0 18 |...,.....9..f...|
938 02d0: 17 fd f5 23 9c 27 38 02 b5 b7 61 8d 05 1c 89 e4 |...#.'8...a.....|
938 02d0: 17 fd f5 23 9c 27 38 02 b5 b7 61 8d 05 1c 89 e4 |...#.'8...a.....|
939 02e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
939 02e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
940 02f0: 00 00 00 00 32 af 76 86 d4 03 cf 45 b5 d9 5f 2d |....2.v....E.._-|
940 02f0: 00 00 00 00 32 af 76 86 d4 03 cf 45 b5 d9 5f 2d |....2.v....E.._-|
941 0300: 70 ce be a5 87 ac 80 6a 00 00 00 81 00 00 00 81 |p......j........|
941 0300: 70 ce be a5 87 ac 80 6a 00 00 00 81 00 00 00 81 |p......j........|
942 0310: 00 00 00 2b 44 00 63 33 66 31 63 61 32 39 32 34 |...+D.c3f1ca2924|
942 0310: 00 00 00 2b 44 00 63 33 66 31 63 61 32 39 32 34 |...+D.c3f1ca2924|
943 0320: 63 31 36 61 31 39 62 30 36 35 36 61 38 34 39 30 |c16a19b0656a8490|
943 0320: 63 31 36 61 31 39 62 30 36 35 36 61 38 34 39 30 |c16a19b0656a8490|
944 0330: 30 65 35 30 34 65 35 62 30 61 65 63 32 64 0a 00 |0e504e5b0aec2d..|
944 0330: 30 65 35 30 34 65 35 62 30 61 65 63 32 64 0a 00 |0e504e5b0aec2d..|
945 0340: 00 00 8b 4d ec e9 c8 26 f6 94 90 50 7b 98 c6 38 |...M...&...P{..8|
945 0340: 00 00 8b 4d ec e9 c8 26 f6 94 90 50 7b 98 c6 38 |...M...&...P{..8|
946 0350: 3a 30 09 b2 95 83 7d 00 7d 8c 9d 88 84 13 25 f5 |:0....}.}.....%.|
946 0350: 3a 30 09 b2 95 83 7d 00 7d 8c 9d 88 84 13 25 f5 |:0....}.}.....%.|
947 0360: c6 b0 63 71 b3 5b 4e 8a 2b 1a 83 00 00 00 00 00 |..cq.[N.+.......|
947 0360: c6 b0 63 71 b3 5b 4e 8a 2b 1a 83 00 00 00 00 00 |..cq.[N.+.......|
948 0370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 95 |................|
948 0370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 95 |................|
949 0380: 20 ee a7 81 bc ca 16 c1 e1 5a cc 0b a1 43 35 a0 | ........Z...C5.|
949 0380: 20 ee a7 81 bc ca 16 c1 e1 5a cc 0b a1 43 35 a0 | ........Z...C5.|
950 0390: e8 e5 ba 00 00 00 2b 00 00 00 ac 00 00 00 2b 45 |......+.......+E|
950 0390: e8 e5 ba 00 00 00 2b 00 00 00 ac 00 00 00 2b 45 |......+.......+E|
951 03a0: 00 39 63 36 66 64 30 33 35 30 61 36 63 30 64 30 |.9c6fd0350a6c0d0|
951 03a0: 00 39 63 36 66 64 30 33 35 30 61 36 63 30 64 30 |.9c6fd0350a6c0d0|
952 03b0: 63 34 39 64 34 61 39 63 35 30 31 37 63 66 30 37 |c49d4a9c5017cf07|
952 03b0: 63 34 39 64 34 61 39 63 35 30 31 37 63 66 30 37 |c49d4a9c5017cf07|
953 03c0: 30 34 33 66 35 34 65 35 38 0a 00 00 00 8b 36 5b |043f54e58.....6[|
953 03c0: 30 34 33 66 35 34 65 35 38 0a 00 00 00 8b 36 5b |043f54e58.....6[|
954 03d0: 93 d5 7f df 48 14 e2 b5 91 1d 6b ac ff 2b 12 01 |....H.....k..+..|
954 03d0: 93 d5 7f df 48 14 e2 b5 91 1d 6b ac ff 2b 12 01 |....H.....k..+..|
955 03e0: 44 41 28 a5 84 c6 5e f1 21 f8 9e b6 6a b7 d0 bc |DA(...^.!...j...|
955 03e0: 44 41 28 a5 84 c6 5e f1 21 f8 9e b6 6a b7 d0 bc |DA(...^.!...j...|
956 03f0: 15 3d 80 99 e7 ce 4d ec e9 c8 26 f6 94 90 50 7b |.=....M...&...P{|
956 03f0: 15 3d 80 99 e7 ce 4d ec e9 c8 26 f6 94 90 50 7b |.=....M...&...P{|
957 0400: 98 c6 38 3a 30 09 b2 95 83 7d ee a1 37 46 79 9a |..8:0....}..7Fy.|
957 0400: 98 c6 38 3a 30 09 b2 95 83 7d ee a1 37 46 79 9a |..8:0....}..7Fy.|
958 0410: 9e 0b fd 88 f2 9d 3c 2e 9d c9 38 9f 52 4f 00 00 |......<...8.RO..|
958 0410: 9e 0b fd 88 f2 9d 3c 2e 9d c9 38 9f 52 4f 00 00 |......<...8.RO..|
959 0420: 00 56 00 00 00 56 00 00 00 2b 46 00 32 32 62 66 |.V...V...+F.22bf|
959 0420: 00 56 00 00 00 56 00 00 00 2b 46 00 32 32 62 66 |.V...V...+F.22bf|
960 0430: 63 66 64 36 32 61 32 31 61 33 32 38 37 65 64 62 |cfd62a21a3287edb|
960 0430: 63 66 64 36 32 61 32 31 61 33 32 38 37 65 64 62 |cfd62a21a3287edb|
961 0440: 64 34 64 36 35 36 32 31 38 64 30 66 35 32 35 65 |d4d656218d0f525e|
961 0440: 64 34 64 36 35 36 32 31 38 64 30 66 35 32 35 65 |d4d656218d0f525e|
962 0450: 64 37 36 61 0a 00 00 00 97 8b ee 48 ed c7 31 85 |d76a.......H..1.|
962 0450: 64 37 36 61 0a 00 00 00 97 8b ee 48 ed c7 31 85 |d76a.......H..1.|
963 0460: 41 fc 00 13 ee 41 b0 89 27 6a 8c 24 bf 28 a5 84 |A....A..'j.$.(..|
963 0460: 41 fc 00 13 ee 41 b0 89 27 6a 8c 24 bf 28 a5 84 |A....A..'j.$.(..|
964 0470: c6 5e f1 21 f8 9e b6 6a b7 d0 bc 15 3d 80 99 e7 |.^.!...j....=...|
964 0470: c6 5e f1 21 f8 9e b6 6a b7 d0 bc 15 3d 80 99 e7 |.^.!...j....=...|
965 0480: ce 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
965 0480: ce 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
966 0490: 00 00 00 00 00 02 de 42 19 6e be e4 2e f2 84 b6 |.......B.n......|
966 0490: 00 00 00 00 00 02 de 42 19 6e be e4 2e f2 84 b6 |.......B.n......|
967 04a0: 78 0a 87 cd c9 6e 8e aa b6 00 00 00 2b 00 00 00 |x....n......+...|
967 04a0: 78 0a 87 cd c9 6e 8e aa b6 00 00 00 2b 00 00 00 |x....n......+...|
968 04b0: 56 00 00 00 00 00 00 00 81 00 00 00 81 00 00 00 |V...............|
968 04b0: 56 00 00 00 00 00 00 00 81 00 00 00 81 00 00 00 |V...............|
969 04c0: 2b 48 00 38 35 30 30 31 38 39 65 37 34 61 39 65 |+H.8500189e74a9e|
969 04c0: 2b 48 00 38 35 30 30 31 38 39 65 37 34 61 39 65 |+H.8500189e74a9e|
970 04d0: 30 34 37 35 65 38 32 32 30 39 33 62 63 37 64 62 |0475e822093bc7db|
970 04d0: 30 34 37 35 65 38 32 32 30 39 33 62 63 37 64 62 |0475e822093bc7db|
971 04e0: 30 64 36 33 31 61 65 62 30 62 34 0a 00 00 00 00 |0d631aeb0b4.....|
971 04e0: 30 64 36 33 31 61 65 62 30 62 34 0a 00 00 00 00 |0d631aeb0b4.....|
972 04f0: 00 00 00 05 44 00 00 00 62 c3 f1 ca 29 24 c1 6a |....D...b...)$.j|
972 04f0: 00 00 00 05 44 00 00 00 62 c3 f1 ca 29 24 c1 6a |....D...b...)$.j|
973 0500: 19 b0 65 6a 84 90 0e 50 4e 5b 0a ec 2d 00 00 00 |..ej...PN[..-...|
973 0500: 19 b0 65 6a 84 90 0e 50 4e 5b 0a ec 2d 00 00 00 |..ej...PN[..-...|
974 0510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
974 0510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
975 0520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
975 0520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
976 0530: 00 00 00 00 00 32 af 76 86 d4 03 cf 45 b5 d9 5f |.....2.v....E.._|
976 0530: 00 00 00 00 00 32 af 76 86 d4 03 cf 45 b5 d9 5f |.....2.v....E.._|
977 0540: 2d 70 ce be a5 87 ac 80 6a 00 00 00 00 00 00 00 |-p......j.......|
977 0540: 2d 70 ce be a5 87 ac 80 6a 00 00 00 00 00 00 00 |-p......j.......|
978 0550: 00 00 00 00 02 44 0a 00 00 00 00 00 00 00 05 45 |.....D.........E|
978 0550: 00 00 00 00 02 44 0a 00 00 00 00 00 00 00 05 45 |.....D.........E|
979 0560: 00 00 00 62 9c 6f d0 35 0a 6c 0d 0c 49 d4 a9 c5 |...b.o.5.l..I...|
979 0560: 00 00 00 62 9c 6f d0 35 0a 6c 0d 0c 49 d4 a9 c5 |...b.o.5.l..I...|
980 0570: 01 7c f0 70 43 f5 4e 58 00 00 00 00 00 00 00 00 |.|.pC.NX........|
980 0570: 01 7c f0 70 43 f5 4e 58 00 00 00 00 00 00 00 00 |.|.pC.NX........|
981 0580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
981 0580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
982 0590: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
982 0590: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
983 05a0: 95 20 ee a7 81 bc ca 16 c1 e1 5a cc 0b a1 43 35 |. ........Z...C5|
983 05a0: 95 20 ee a7 81 bc ca 16 c1 e1 5a cc 0b a1 43 35 |. ........Z...C5|
984 05b0: a0 e8 e5 ba 00 00 00 00 00 00 00 00 00 00 00 02 |................|
984 05b0: a0 e8 e5 ba 00 00 00 00 00 00 00 00 00 00 00 02 |................|
985 05c0: 45 0a 00 00 00 00 00 00 00 05 48 00 00 00 62 85 |E.........H...b.|
985 05c0: 45 0a 00 00 00 00 00 00 00 05 48 00 00 00 62 85 |E.........H...b.|
986 05d0: 00 18 9e 74 a9 e0 47 5e 82 20 93 bc 7d b0 d6 31 |...t..G^. ..}..1|
986 05d0: 00 18 9e 74 a9 e0 47 5e 82 20 93 bc 7d b0 d6 31 |...t..G^. ..}..1|
987 05e0: ae b0 b4 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
987 05e0: ae b0 b4 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
988 05f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
988 05f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
989 0600: 00 00 00 00 00 00 00 00 00 00 00 02 de 42 19 6e |.............B.n|
989 0600: 00 00 00 00 00 00 00 00 00 00 00 02 de 42 19 6e |.............B.n|
990 0610: be e4 2e f2 84 b6 78 0a 87 cd c9 6e 8e aa b6 00 |......x....n....|
990 0610: be e4 2e f2 84 b6 78 0a 87 cd c9 6e 8e aa b6 00 |......x....n....|
991 0620: 00 00 00 00 00 00 00 00 00 00 02 48 0a 00 00 00 |...........H....|
991 0620: 00 00 00 00 00 00 00 00 00 00 02 48 0a 00 00 00 |...........H....|
992 0630: 00 00 00 00 00 00 00 00 00 00 00 00 00 |.............|
992 0630: 00 00 00 00 00 00 00 00 00 00 00 00 00 |.............|
993
993
994 $ hg debugbundle ../rev.hg2
994 $ hg debugbundle ../rev.hg2
995 Stream params: {}
995 Stream params: {}
996 changegroup -- {} (mandatory: False)
996 changegroup -- {} (mandatory: False)
997 32af7686d403cf45b5d95f2d70cebea587ac806a
997 32af7686d403cf45b5d95f2d70cebea587ac806a
998 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
998 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
999 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
999 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
1000 02de42196ebee42ef284b6780a87cdc96e8eaab6
1000 02de42196ebee42ef284b6780a87cdc96e8eaab6
1001 $ hg unbundle ../rev.hg2
1001 $ hg unbundle ../rev.hg2
1002 adding changesets
1002 adding changesets
1003 adding manifests
1003 adding manifests
1004 adding file changes
1004 adding file changes
1005 added 0 changesets with 0 changes to 3 files
1005 added 0 changesets with 0 changes to 3 files
1006 (run 'hg update' to get a working copy)
1006 (run 'hg update' to get a working copy)
1007
1007
1008 with reply
1008 with reply
1009
1009
1010 $ hg bundle2 --rev '8+7+5+4' --reply ../rev-rr.hg2
1010 $ hg bundle2 --rev '8+7+5+4' --reply ../rev-rr.hg2
1011 $ hg unbundle2 ../rev-reply.hg2 < ../rev-rr.hg2
1011 $ hg unbundle2 ../rev-reply.hg2 < ../rev-rr.hg2
1012 0 unread bytes
1012 0 unread bytes
1013 addchangegroup return: 1
1013 addchangegroup return: 1
1014
1014
1015 $ f --hexdump ../rev-reply.hg2
1015 $ f --hexdump ../rev-reply.hg2
1016 ../rev-reply.hg2:
1016 ../rev-reply.hg2:
1017 0000: 48 47 32 30 00 00 00 00 00 00 00 2f 11 72 65 70 |HG20......./.rep|
1017 0000: 48 47 32 30 00 00 00 00 00 00 00 2f 11 72 65 70 |HG20......./.rep|
1018 0010: 6c 79 3a 63 68 61 6e 67 65 67 72 6f 75 70 00 00 |ly:changegroup..|
1018 0010: 6c 79 3a 63 68 61 6e 67 65 67 72 6f 75 70 00 00 |ly:changegroup..|
1019 0020: 00 00 00 02 0b 01 06 01 69 6e 2d 72 65 70 6c 79 |........in-reply|
1019 0020: 00 00 00 02 0b 01 06 01 69 6e 2d 72 65 70 6c 79 |........in-reply|
1020 0030: 2d 74 6f 31 72 65 74 75 72 6e 31 00 00 00 00 00 |-to1return1.....|
1020 0030: 2d 74 6f 31 72 65 74 75 72 6e 31 00 00 00 00 00 |-to1return1.....|
1021 0040: 00 00 1b 06 6f 75 74 70 75 74 00 00 00 01 00 01 |....output......|
1021 0040: 00 00 1b 06 6f 75 74 70 75 74 00 00 00 01 00 01 |....output......|
1022 0050: 0b 01 69 6e 2d 72 65 70 6c 79 2d 74 6f 31 00 00 |..in-reply-to1..|
1022 0050: 0b 01 69 6e 2d 72 65 70 6c 79 2d 74 6f 31 00 00 |..in-reply-to1..|
1023 0060: 00 64 61 64 64 69 6e 67 20 63 68 61 6e 67 65 73 |.dadding changes|
1023 0060: 00 64 61 64 64 69 6e 67 20 63 68 61 6e 67 65 73 |.dadding changes|
1024 0070: 65 74 73 0a 61 64 64 69 6e 67 20 6d 61 6e 69 66 |ets.adding manif|
1024 0070: 65 74 73 0a 61 64 64 69 6e 67 20 6d 61 6e 69 66 |ets.adding manif|
1025 0080: 65 73 74 73 0a 61 64 64 69 6e 67 20 66 69 6c 65 |ests.adding file|
1025 0080: 65 73 74 73 0a 61 64 64 69 6e 67 20 66 69 6c 65 |ests.adding file|
1026 0090: 20 63 68 61 6e 67 65 73 0a 61 64 64 65 64 20 30 | changes.added 0|
1026 0090: 20 63 68 61 6e 67 65 73 0a 61 64 64 65 64 20 30 | changes.added 0|
1027 00a0: 20 63 68 61 6e 67 65 73 65 74 73 20 77 69 74 68 | changesets with|
1027 00a0: 20 63 68 61 6e 67 65 73 65 74 73 20 77 69 74 68 | changesets with|
1028 00b0: 20 30 20 63 68 61 6e 67 65 73 20 74 6f 20 33 20 | 0 changes to 3 |
1028 00b0: 20 30 20 63 68 61 6e 67 65 73 20 74 6f 20 33 20 | 0 changes to 3 |
1029 00c0: 66 69 6c 65 73 0a 00 00 00 00 00 00 00 00 |files.........|
1029 00c0: 66 69 6c 65 73 0a 00 00 00 00 00 00 00 00 |files.........|
1030
1030
1031 Check handling of exception during generation.
1031 Check handling of exception during generation.
1032 ----------------------------------------------
1032 ----------------------------------------------
1033
1033
1034 $ hg bundle2 --genraise > ../genfailed.hg2
1034 $ hg bundle2 --genraise > ../genfailed.hg2
1035 abort: Someone set up us the bomb!
1035 abort: Someone set up us the bomb!
1036 [255]
1036 [255]
1037
1037
1038 Should still be a valid bundle
1038 Should still be a valid bundle
1039
1039
1040 $ f --hexdump ../genfailed.hg2
1040 $ f --hexdump ../genfailed.hg2
1041 ../genfailed.hg2:
1041 ../genfailed.hg2:
1042 0000: 48 47 32 30 00 00 00 00 00 00 00 0d 06 6f 75 74 |HG20.........out|
1042 0000: 48 47 32 30 00 00 00 00 00 00 00 0d 06 6f 75 74 |HG20.........out|
1043 0010: 70 75 74 00 00 00 00 00 00 ff ff ff ff 00 00 00 |put.............|
1043 0010: 70 75 74 00 00 00 00 00 00 ff ff ff ff 00 00 00 |put.............|
1044 0020: 48 0b 65 72 72 6f 72 3a 61 62 6f 72 74 00 00 00 |H.error:abort...|
1044 0020: 48 0b 65 72 72 6f 72 3a 61 62 6f 72 74 00 00 00 |H.error:abort...|
1045 0030: 00 01 00 07 2d 6d 65 73 73 61 67 65 75 6e 65 78 |....-messageunex|
1045 0030: 00 01 00 07 2d 6d 65 73 73 61 67 65 75 6e 65 78 |....-messageunex|
1046 0040: 70 65 63 74 65 64 20 65 72 72 6f 72 3a 20 53 6f |pected error: So|
1046 0040: 70 65 63 74 65 64 20 65 72 72 6f 72 3a 20 53 6f |pected error: So|
1047 0050: 6d 65 6f 6e 65 20 73 65 74 20 75 70 20 75 73 20 |meone set up us |
1047 0050: 6d 65 6f 6e 65 20 73 65 74 20 75 70 20 75 73 20 |meone set up us |
1048 0060: 74 68 65 20 62 6f 6d 62 21 00 00 00 00 00 00 00 |the bomb!.......|
1048 0060: 74 68 65 20 62 6f 6d 62 21 00 00 00 00 00 00 00 |the bomb!.......|
1049 0070: 00 |.|
1049 0070: 00 |.|
1050
1050
1051 And its handling on the other size raise a clean exception
1051 And its handling on the other size raise a clean exception
1052
1052
1053 $ cat ../genfailed.hg2 | hg unbundle2
1053 $ cat ../genfailed.hg2 | hg unbundle2
1054 0 unread bytes
1054 0 unread bytes
1055 abort: unexpected error: Someone set up us the bomb!
1055 abort: unexpected error: Someone set up us the bomb!
1056 [255]
1056 [255]
1057
1057
1058 Test compression
1058 Test compression
1059 ================
1059 ================
1060
1060
1061 Simple case where it just work: GZ
1061 Simple case where it just work: GZ
1062 ----------------------------------
1062 ----------------------------------
1063
1063
1064 $ hg bundle2 --compress GZ --rev '8+7+5+4' ../rev.hg2.bz
1064 $ hg bundle2 --compress GZ --rev '8+7+5+4' ../rev.hg2.bz
1065 $ f --hexdump ../rev.hg2.bz
1065 $ f --hexdump ../rev.hg2.bz
1066 ../rev.hg2.bz:
1066 ../rev.hg2.bz:
1067 0000: 48 47 32 30 00 00 00 0e 43 6f 6d 70 72 65 73 73 |HG20....Compress|
1067 0000: 48 47 32 30 00 00 00 0e 43 6f 6d 70 72 65 73 73 |HG20....Compress|
1068 0010: 69 6f 6e 3d 47 5a 78 9c 95 94 7d 68 95 55 1c c7 |ion=GZx...}h.U..|
1068 0010: 69 6f 6e 3d 47 5a 78 9c 95 94 7d 68 95 55 1c c7 |ion=GZx...}h.U..|
1069 0020: 9f 3b 31 e8 ce fa c3 65 be a0 a4 b4 52 b9 29 e7 |.;1....e....R.).|
1069 0020: 9f 3b 31 e8 ce fa c3 65 be a0 a4 b4 52 b9 29 e7 |.;1....e....R.).|
1070 0030: f5 79 ce 89 fa 63 ed 5e 77 8b 9c c3 3f 2a 1c 68 |.y...c.^w...?*.h|
1070 0030: f5 79 ce 89 fa 63 ed 5e 77 8b 9c c3 3f 2a 1c 68 |.y...c.^w...?*.h|
1071 0040: cf 79 9b dd 6a ae b0 28 74 b8 e5 96 5b bb 86 61 |.y..j..(t...[..a|
1071 0040: cf 79 9b dd 6a ae b0 28 74 b8 e5 96 5b bb 86 61 |.y..j..(t...[..a|
1072 0050: a3 15 6e 3a 71 c8 6a e8 a5 da 95 64 28 22 ce 69 |..n:q.j....d(".i|
1072 0050: a3 15 6e 3a 71 c8 6a e8 a5 da 95 64 28 22 ce 69 |..n:q.j....d(".i|
1073 0060: cd 06 59 34 28 2b 51 2a 58 c3 17 56 2a 9a 9d 67 |..Y4(+Q*X..V*..g|
1073 0060: cd 06 59 34 28 2b 51 2a 58 c3 17 56 2a 9a 9d 67 |..Y4(+Q*X..V*..g|
1074 0070: dc c6 35 9e c4 1d f8 9e 87 f3 9c f3 3b bf 0f bf |..5.........;...|
1074 0070: dc c6 35 9e c4 1d f8 9e 87 f3 9c f3 3b bf 0f bf |..5.........;...|
1075 0080: 97 e3 38 ce f4 42 b9 d6 af ae d2 55 af ae 7b ad |..8..B.....U..{.|
1075 0080: 97 e3 38 ce f4 42 b9 d6 af ae d2 55 af ae 7b ad |..8..B.....U..{.|
1076 0090: c6 c9 8d bb 8a ec b4 07 ed 7f fd ed d3 53 be 4e |.............S.N|
1076 0090: c6 c9 8d bb 8a ec b4 07 ed 7f fd ed d3 53 be 4e |.............S.N|
1077 00a0: f4 0e af 59 52 73 ea 50 d7 96 9e ba d4 9a 1f 87 |...YRs.P........|
1077 00a0: f4 0e af 59 52 73 ea 50 d7 96 9e ba d4 9a 1f 87 |...YRs.P........|
1078 00b0: 9b 9f 1d e8 7a 6a 79 e9 cb 7f cf eb fe 7e d3 82 |....zjy......~..|
1078 00b0: 9b 9f 1d e8 7a 6a 79 e9 cb 7f cf eb fe 7e d3 82 |....zjy......~..|
1079 00c0: ce 2f 36 38 21 23 cc 36 b7 b5 38 90 ab a1 21 92 |./68!#.6..8...!.|
1079 00c0: ce 2f 36 38 21 23 cc 36 b7 b5 38 90 ab a1 21 92 |./68!#.6..8...!.|
1080 00d0: 78 5a 0a 8a b1 31 0a 48 a6 29 92 4a 32 e6 1b e1 |xZ...1.H.).J2...|
1080 00d0: 78 5a 0a 8a b1 31 0a 48 a6 29 92 4a 32 e6 1b e1 |xZ...1.H.).J2...|
1081 00e0: 4a 85 b9 46 40 46 ed 61 63 b5 d6 aa 20 1e ac 5e |J..F@F.ac... ..^|
1081 00e0: 4a 85 b9 46 40 46 ed 61 63 b5 d6 aa 20 1e ac 5e |J..F@F.ac... ..^|
1082 00f0: b0 0a ae 8a c4 03 c6 d6 f9 a3 7b eb fb 4e de 7f |..........{..N..|
1082 00f0: b0 0a ae 8a c4 03 c6 d6 f9 a3 7b eb fb 4e de 7f |..........{..N..|
1083 0100: e4 97 55 5f 15 76 96 d2 5d bf 9d 3f 38 18 29 4c |..U_.v..]..?8.)L|
1083 0100: e4 97 55 5f 15 76 96 d2 5d bf 9d 3f 38 18 29 4c |..U_.v..]..?8.)L|
1084 0110: 0f b7 5d 6e 9b b3 aa 7e c6 d5 15 5b f7 7c 52 f1 |..]n...~...[.|R.|
1084 0110: 0f b7 5d 6e 9b b3 aa 7e c6 d5 15 5b f7 7c 52 f1 |..]n...~...[.|R.|
1085 0120: 7c 73 18 63 98 6d 3e 23 51 5a 6a 2e 19 72 8d cb ||s.c.m>#QZj..r..|
1085 0120: 7c 73 18 63 98 6d 3e 23 51 5a 6a 2e 19 72 8d cb ||s.c.m>#QZj..r..|
1086 0130: 09 07 14 78 82 33 e9 62 86 7d 0c 00 17 88 53 86 |...x.3.b.}....S.|
1086 0130: 09 07 14 78 82 33 e9 62 86 7d 0c 00 17 88 53 86 |...x.3.b.}....S.|
1087 0140: 3d 75 0b 63 e2 16 c6 84 9d 76 8f 76 7a cb de fc |=u.c.....v.vz...|
1087 0140: 3d 75 0b 63 e2 16 c6 84 9d 76 8f 76 7a cb de fc |=u.c.....v.vz...|
1088 0150: a8 a3 f0 46 d3 a5 f6 c7 96 b6 9f 60 3b 57 ae 28 |...F.......`;W.(|
1088 0150: a8 a3 f0 46 d3 a5 f6 c7 96 b6 9f 60 3b 57 ae 28 |...F.......`;W.(|
1089 0160: ce b2 8d e9 f4 3e 6f 66 53 dd e5 6b ad 67 be f9 |.....>ofS..k.g..|
1089 0160: ce b2 8d e9 f4 3e 6f 66 53 dd e5 6b ad 67 be f9 |.....>ofS..k.g..|
1090 0170: 72 ee 5f 8d 61 3c 61 b6 f9 8c d8 a5 82 63 45 3d |r._.a<a......cE=|
1090 0170: 72 ee 5f 8d 61 3c 61 b6 f9 8c d8 a5 82 63 45 3d |r._.a<a......cE=|
1091 0180: a3 0c 61 90 68 24 28 87 50 b9 c2 97 c6 20 01 11 |..a.h$(.P.... ..|
1091 0180: a3 0c 61 90 68 24 28 87 50 b9 c2 97 c6 20 01 11 |..a.h$(.P.... ..|
1092 0190: 80 84 10 98 cf e8 e4 13 96 05 51 2c 38 f3 c4 ec |..........Q,8...|
1092 0190: 80 84 10 98 cf e8 e4 13 96 05 51 2c 38 f3 c4 ec |..........Q,8...|
1093 01a0: ea 43 e7 96 5e 6a c8 be 11 dd 32 78 a2 fa dd 8f |.C..^j....2x....|
1093 01a0: ea 43 e7 96 5e 6a c8 be 11 dd 32 78 a2 fa dd 8f |.C..^j....2x....|
1094 01b0: b3 61 84 61 51 0c b3 cd 27 64 42 6b c2 b4 92 1e |.a.aQ...'dBk....|
1094 01b0: b3 61 84 61 51 0c b3 cd 27 64 42 6b c2 b4 92 1e |.a.aQ...'dBk....|
1095 01c0: 86 8c 12 68 24 00 10 db 7f 50 00 c6 91 e7 fa 4c |...h$....P.....L|
1095 01c0: 86 8c 12 68 24 00 10 db 7f 50 00 c6 91 e7 fa 4c |...h$....P.....L|
1096 01d0: 22 22 cc bf 84 81 0a 92 c1 aa 2a c7 1b 49 e6 ee |""........*..I..|
1096 01d0: 22 22 cc bf 84 81 0a 92 c1 aa 2a c7 1b 49 e6 ee |""........*..I..|
1097 01e0: 6b a9 7e e0 e9 b2 91 5e 7c 73 68 e0 fc 23 3f 34 |k.~....^|sh..#?4|
1097 01e0: 6b a9 7e e0 e9 b2 91 5e 7c 73 68 e0 fc 23 3f 34 |k.~....^|sh..#?4|
1098 01f0: ed cf 0e f2 b3 d3 4c d7 ae 59 33 6f 8c 3d b8 63 |......L..Y3o.=.c|
1098 01f0: ed cf 0e f2 b3 d3 4c d7 ae 59 33 6f 8c 3d b8 63 |......L..Y3o.=.c|
1099 0200: 21 2b e8 3d e0 6f 9d 3a b7 f9 dc 24 2a b2 3e a7 |!+.=.o.:...$*.>.|
1099 0200: 21 2b e8 3d e0 6f 9d 3a b7 f9 dc 24 2a b2 3e a7 |!+.=.o.:...$*.>.|
1100 0210: 58 dc 91 d8 40 e9 23 8e 88 84 ae 0f b9 00 2e b5 |X...@.#.........|
1100 0210: 58 dc 91 d8 40 e9 23 8e 88 84 ae 0f b9 00 2e b5 |X...@.#.........|
1101 0220: 74 36 f3 40 53 40 34 15 c0 d7 12 8d e7 bb 65 f9 |t6.@S@4.......e.|
1101 0220: 74 36 f3 40 53 40 34 15 c0 d7 12 8d e7 bb 65 f9 |t6.@S@4.......e.|
1102 0230: c8 ef 03 0f ff f9 fe b6 8a 0d 6d fd ec 51 70 f7 |..........m..Qp.|
1102 0230: c8 ef 03 0f ff f9 fe b6 8a 0d 6d fd ec 51 70 f7 |..........m..Qp.|
1103 0240: a7 ad 9b 6b 9d da 74 7b 53 43 d1 43 63 fd 19 f9 |...k..t{SC.Cc...|
1103 0240: a7 ad 9b 6b 9d da 74 7b 53 43 d1 43 63 fd 19 f9 |...k..t{SC.Cc...|
1104 0250: ca 67 95 e5 ef c4 e6 6c 9e 44 e1 c5 ac 7a 82 6f |.g.....l.D...z.o|
1104 0250: ca 67 95 e5 ef c4 e6 6c 9e 44 e1 c5 ac 7a 82 6f |.g.....l.D...z.o|
1105 0260: c2 e1 d2 b5 2d 81 29 f0 5d 09 6c 6f 10 ae 88 cf |....-.).].lo....|
1105 0260: c2 e1 d2 b5 2d 81 29 f0 5d 09 6c 6f 10 ae 88 cf |....-.).].lo....|
1106 0270: 25 05 d0 93 06 78 80 60 43 2d 10 1b 47 71 2b b7 |%....x.`C-..Gq+.|
1106 0270: 25 05 d0 93 06 78 80 60 43 2d 10 1b 47 71 2b b7 |%....x.`C-..Gq+.|
1107 0280: 7f bb e9 a7 e4 7d 67 7b df 9b f7 62 cf cd d8 f4 |.....}g{...b....|
1107 0280: 7f bb e9 a7 e4 7d 67 7b df 9b f7 62 cf cd d8 f4 |.....}g{...b....|
1108 0290: 48 bc 64 51 57 43 ff ea 8b 0b ae 74 64 53 07 86 |H.dQWC.....tdS..|
1108 0290: 48 bc 64 51 57 43 ff ea 8b 0b ae 74 64 53 07 86 |H.dQWC.....tdS..|
1109 02a0: fa 66 3c 5e f7 e1 af a7 c2 90 ff a7 be 9e c9 29 |.f<^...........)|
1109 02a0: fa 66 3c 5e f7 e1 af a7 c2 90 ff a7 be 9e c9 29 |.f<^...........)|
1110 02b0: b6 cc 41 48 18 69 94 8b 7c 04 7d 8c 98 a7 95 50 |..AH.i..|.}....P|
1110 02b0: b6 cc 41 48 18 69 94 8b 7c 04 7d 8c 98 a7 95 50 |..AH.i..|.}....P|
1111 02c0: 44 d9 d0 20 c8 14 30 14 51 ad 6c 16 03 94 0f 5a |D.. ..0.Q.l....Z|
1111 02c0: 44 d9 d0 20 c8 14 30 14 51 ad 6c 16 03 94 0f 5a |D.. ..0.Q.l....Z|
1112 02d0: 46 93 7f 1c 87 8d 25 d7 9d a2 d1 92 4c f3 c2 54 |F.....%.....L..T|
1112 02d0: 46 93 7f 1c 87 8d 25 d7 9d a2 d1 92 4c f3 c2 54 |F.....%.....L..T|
1113 02e0: ba f8 70 18 ca 24 0a 29 96 43 71 f2 93 95 74 18 |..p..$.).Cq...t.|
1113 02e0: ba f8 70 18 ca 24 0a 29 96 43 71 f2 93 95 74 18 |..p..$.).Cq...t.|
1114 02f0: b5 65 c4 b8 f6 6c 5c 34 20 1e d5 0c 21 c0 b1 90 |.e...l\4 ...!...|
1114 02f0: b5 65 c4 b8 f6 6c 5c 34 20 1e d5 0c 21 c0 b1 90 |.e...l\4 ...!...|
1115 0300: 9e 12 40 b9 18 fa 5a 00 41 a2 39 d3 a9 c1 73 21 |..@...Z.A.9...s!|
1115 0300: 9e 12 40 b9 18 fa 5a 00 41 a2 39 d3 a9 c1 73 21 |..@...Z.A.9...s!|
1116 0310: 8e 5e 3c b9 b8 f8 48 6a 76 46 a7 1a b6 dd 5b 51 |.^<...HjvF....[Q|
1116 0310: 8e 5e 3c b9 b8 f8 48 6a 76 46 a7 1a b6 dd 5b 51 |.^<...HjvF....[Q|
1117 0320: 5e 19 1d 59 12 c6 32 89 02 9a c0 8f 4f b8 0a ba |^..Y..2.....O...|
1117 0320: 5e 19 1d 59 12 c6 32 89 02 9a c0 8f 4f b8 0a ba |^..Y..2.....O...|
1118 0330: 5e ec 58 37 44 a3 2f dd 33 ed c9 d3 dd c7 22 1b |^.X7D./.3.....".|
1118 0330: 5e ec 58 37 44 a3 2f dd 33 ed c9 d3 dd c7 22 1b |^.X7D./.3.....".|
1119 0340: 2f d4 94 8e 95 3f 77 a7 ae 6e f3 32 8d bb 4a 4c |/....?w..n.2..JL|
1119 0340: 2f d4 94 8e 95 3f 77 a7 ae 6e f3 32 8d bb 4a 4c |/....?w..n.2..JL|
1120 0350: b8 0a 5a 43 34 3a b3 3a d6 77 ff 5c b6 fa ad f9 |..ZC4:.:.w.\....|
1120 0350: b8 0a 5a 43 34 3a b3 3a d6 77 ff 5c b6 fa ad f9 |..ZC4:.:.w.\....|
1121 0360: db fb 6a 33 df c1 7d 99 cf ef d4 d5 6d da 77 7c |..j3..}.....m.w||
1121 0360: db fb 6a 33 df c1 7d 99 cf ef d4 d5 6d da 77 7c |..j3..}.....m.w||
1122 0370: 3b 19 fd af c5 3f f1 60 c3 17 |;....?.`..|
1122 0370: 3b 19 fd af c5 3f f1 60 c3 17 |;....?.`..|
1123 $ hg debugbundle ../rev.hg2.bz
1123 $ hg debugbundle ../rev.hg2.bz
1124 Stream params: {Compression: GZ}
1124 Stream params: {Compression: GZ}
1125 changegroup -- {} (mandatory: False)
1125 changegroup -- {} (mandatory: False)
1126 32af7686d403cf45b5d95f2d70cebea587ac806a
1126 32af7686d403cf45b5d95f2d70cebea587ac806a
1127 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
1127 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
1128 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
1128 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
1129 02de42196ebee42ef284b6780a87cdc96e8eaab6
1129 02de42196ebee42ef284b6780a87cdc96e8eaab6
1130 $ hg unbundle ../rev.hg2.bz
1130 $ hg unbundle ../rev.hg2.bz
1131 adding changesets
1131 adding changesets
1132 adding manifests
1132 adding manifests
1133 adding file changes
1133 adding file changes
1134 added 0 changesets with 0 changes to 3 files
1134 added 0 changesets with 0 changes to 3 files
1135 (run 'hg update' to get a working copy)
1135 (run 'hg update' to get a working copy)
1136 Simple case where it just work: BZ
1136 Simple case where it just work: BZ
1137 ----------------------------------
1137 ----------------------------------
1138
1138
1139 $ hg bundle2 --compress BZ --rev '8+7+5+4' ../rev.hg2.bz
1139 $ hg bundle2 --compress BZ --rev '8+7+5+4' ../rev.hg2.bz
1140 $ f --hexdump ../rev.hg2.bz
1140 $ f --hexdump ../rev.hg2.bz
1141 ../rev.hg2.bz:
1141 ../rev.hg2.bz:
1142 0000: 48 47 32 30 00 00 00 0e 43 6f 6d 70 72 65 73 73 |HG20....Compress|
1142 0000: 48 47 32 30 00 00 00 0e 43 6f 6d 70 72 65 73 73 |HG20....Compress|
1143 0010: 69 6f 6e 3d 42 5a 42 5a 68 39 31 41 59 26 53 59 |ion=BZBZh91AY&SY|
1143 0010: 69 6f 6e 3d 42 5a 42 5a 68 39 31 41 59 26 53 59 |ion=BZBZh91AY&SY|
1144 0020: a3 4b 18 3d 00 00 1a 7f ff ff bf 5f f6 ef ef 7f |.K.=......._....|
1144 0020: a3 4b 18 3d 00 00 1a 7f ff ff bf 5f f6 ef ef 7f |.K.=......._....|
1145 0030: f6 3f f7 d1 d9 ff ff f7 6e ff ff 6e f7 f6 bd df |.?......n..n....|
1145 0030: f6 3f f7 d1 d9 ff ff f7 6e ff ff 6e f7 f6 bd df |.?......n..n....|
1146 0040: b5 ab ff cf 67 f6 e7 7b f7 c0 02 d7 33 82 8b 51 |....g..{....3..Q|
1146 0040: b5 ab ff cf 67 f6 e7 7b f7 c0 02 d7 33 82 8b 51 |....g..{....3..Q|
1147 0050: 04 a5 53 d5 3d 27 a0 99 18 4d 0d 34 00 d1 a1 e8 |..S.='...M.4....|
1147 0050: 04 a5 53 d5 3d 27 a0 99 18 4d 0d 34 00 d1 a1 e8 |..S.='...M.4....|
1148 0060: 80 c8 7a 87 a9 a3 43 6a 3d 46 86 26 80 34 3d 40 |..z...Cj=F.&.4=@|
1148 0060: 80 c8 7a 87 a9 a3 43 6a 3d 46 86 26 80 34 3d 40 |..z...Cj=F.&.4=@|
1149 0070: c8 c9 b5 34 f4 8f 48 0f 51 ea 34 34 fd 4d aa 19 |...4..H.Q.44.M..|
1149 0070: c8 c9 b5 34 f4 8f 48 0f 51 ea 34 34 fd 4d aa 19 |...4..H.Q.44.M..|
1150 0080: 03 40 0c 08 da 86 43 d4 f5 0f 42 1e a0 f3 54 33 |.@....C...B...T3|
1150 0080: 03 40 0c 08 da 86 43 d4 f5 0f 42 1e a0 f3 54 33 |.@....C...B...T3|
1151 0090: 54 d3 13 4d 03 40 32 00 00 32 03 26 80 0d 00 0d |T..M.@2..2.&....|
1151 0090: 54 d3 13 4d 03 40 32 00 00 32 03 26 80 0d 00 0d |T..M.@2..2.&....|
1152 00a0: 00 68 c8 c8 03 20 32 30 98 8c 80 00 00 03 4d 00 |.h... 20......M.|
1152 00a0: 00 68 c8 c8 03 20 32 30 98 8c 80 00 00 03 4d 00 |.h... 20......M.|
1153 00b0: c8 00 00 0d 00 00 22 99 a1 34 c2 64 a6 d5 34 1a |......"..4.d..4.|
1153 00b0: c8 00 00 0d 00 00 22 99 a1 34 c2 64 a6 d5 34 1a |......"..4.d..4.|
1154 00c0: 00 00 06 86 83 4d 07 a8 d1 a0 68 01 a0 00 00 00 |.....M....h.....|
1154 00c0: 00 00 06 86 83 4d 07 a8 d1 a0 68 01 a0 00 00 00 |.....M....h.....|
1155 00d0: 00 0d 06 80 00 00 00 0d 00 03 40 00 00 04 a4 a1 |..........@.....|
1155 00d0: 00 0d 06 80 00 00 00 0d 00 03 40 00 00 04 a4 a1 |..........@.....|
1156 00e0: 4d a9 89 89 b4 9a 32 0c 43 46 86 87 a9 8d 41 9a |M.....2.CF....A.|
1156 00e0: 4d a9 89 89 b4 9a 32 0c 43 46 86 87 a9 8d 41 9a |M.....2.CF....A.|
1157 00f0: 98 46 9a 0d 31 32 1a 34 0d 0c 8d a2 0c 98 4d 06 |.F..12.4......M.|
1157 00f0: 98 46 9a 0d 31 32 1a 34 0d 0c 8d a2 0c 98 4d 06 |.F..12.4......M.|
1158 0100: 8c 40 c2 60 8d 0d 0c 20 c9 89 fa a0 d0 d3 21 a1 |.@.`... ......!.|
1158 0100: 8c 40 c2 60 8d 0d 0c 20 c9 89 fa a0 d0 d3 21 a1 |.@.`... ......!.|
1159 0110: ea 34 d3 68 9e a6 d1 74 05 33 cb 66 96 93 28 64 |.4.h...t.3.f..(d|
1159 0110: ea 34 d3 68 9e a6 d1 74 05 33 cb 66 96 93 28 64 |.4.h...t.3.f..(d|
1160 0120: 40 91 22 ac 55 9b ea 40 7b 38 94 e2 f8 06 00 cb |@.".U..@{8......|
1160 0120: 40 91 22 ac 55 9b ea 40 7b 38 94 e2 f8 06 00 cb |@.".U..@{8......|
1161 0130: 28 02 00 4d ab 40 24 10 43 18 cf 64 b4 06 83 0c |(..M.@$.C..d....|
1161 0130: 28 02 00 4d ab 40 24 10 43 18 cf 64 b4 06 83 0c |(..M.@$.C..d....|
1162 0140: 34 6c b4 a3 d4 0a 0a e4 a8 5c 4e 23 c0 c9 7a 31 |4l.......\N#..z1|
1162 0140: 34 6c b4 a3 d4 0a 0a e4 a8 5c 4e 23 c0 c9 7a 31 |4l.......\N#..z1|
1163 0150: 97 87 77 7a 64 88 80 8e 60 97 20 93 0f 8e eb c4 |..wzd...`. .....|
1163 0150: 97 87 77 7a 64 88 80 8e 60 97 20 93 0f 8e eb c4 |..wzd...`. .....|
1164 0160: 62 a4 44 a3 52 20 b2 99 a9 2e e1 d7 29 4a 54 ac |b.D.R ......)JT.|
1164 0160: 62 a4 44 a3 52 20 b2 99 a9 2e e1 d7 29 4a 54 ac |b.D.R ......)JT.|
1165 0170: 44 7a bb cc 04 3d e0 aa bd 6a 33 5e 9b a2 57 36 |Dz...=...j3^..W6|
1165 0170: 44 7a bb cc 04 3d e0 aa bd 6a 33 5e 9b a2 57 36 |Dz...=...j3^..W6|
1166 0180: fa cb 45 bb 6d 3e c1 d9 d9 f5 83 69 8a d0 e0 e2 |..E.m>.....i....|
1166 0180: fa cb 45 bb 6d 3e c1 d9 d9 f5 83 69 8a d0 e0 e2 |..E.m>.....i....|
1167 0190: e7 ae 90 55 24 da 3f ab 78 c0 4c b4 56 a3 9e a4 |...U$.?.x.L.V...|
1167 0190: e7 ae 90 55 24 da 3f ab 78 c0 4c b4 56 a3 9e a4 |...U$.?.x.L.V...|
1168 01a0: af 9c 65 74 86 ec 6d dc 62 dc 33 ca c8 50 dd 9d |..et..m.b.3..P..|
1168 01a0: af 9c 65 74 86 ec 6d dc 62 dc 33 ca c8 50 dd 9d |..et..m.b.3..P..|
1169 01b0: 98 8e 9e 59 20 f3 f0 42 91 4a 09 f5 75 8d 3d a5 |...Y ..B.J..u.=.|
1169 01b0: 98 8e 9e 59 20 f3 f0 42 91 4a 09 f5 75 8d 3d a5 |...Y ..B.J..u.=.|
1170 01c0: a5 15 cb 8d 10 63 b0 c2 2e b2 81 f7 c1 76 0e 53 |.....c.......v.S|
1170 01c0: a5 15 cb 8d 10 63 b0 c2 2e b2 81 f7 c1 76 0e 53 |.....c.......v.S|
1171 01d0: 6c 0e 46 73 b5 ae 67 f9 4c 0b 45 6b a8 32 2a 2f |l.Fs..g.L.Ek.2*/|
1171 01d0: 6c 0e 46 73 b5 ae 67 f9 4c 0b 45 6b a8 32 2a 2f |l.Fs..g.L.Ek.2*/|
1172 01e0: a2 54 a4 44 05 20 a1 38 d1 a4 c6 09 a8 2b 08 99 |.T.D. .8.....+..|
1172 01e0: a2 54 a4 44 05 20 a1 38 d1 a4 c6 09 a8 2b 08 99 |.T.D. .8.....+..|
1173 01f0: a4 14 ae 8d a3 e3 aa 34 27 d8 44 ca c3 5d 21 8b |.......4'.D..]!.|
1173 01f0: a4 14 ae 8d a3 e3 aa 34 27 d8 44 ca c3 5d 21 8b |.......4'.D..]!.|
1174 0200: 1a 1e 97 29 71 2b 09 4a 4a 55 55 94 58 65 b2 bc |...)q+.JJUU.Xe..|
1174 0200: 1a 1e 97 29 71 2b 09 4a 4a 55 55 94 58 65 b2 bc |...)q+.JJUU.Xe..|
1175 0210: f3 a5 90 26 36 76 67 7a 51 98 d6 8a 4a 99 50 b5 |...&6vgzQ...J.P.|
1175 0210: f3 a5 90 26 36 76 67 7a 51 98 d6 8a 4a 99 50 b5 |...&6vgzQ...J.P.|
1176 0220: 99 8f 94 21 17 a9 8b f3 ad 4c 33 d4 2e 40 c8 0c |...!.....L3..@..|
1176 0220: 99 8f 94 21 17 a9 8b f3 ad 4c 33 d4 2e 40 c8 0c |...!.....L3..@..|
1177 0230: 3b 90 53 39 db 48 02 34 83 48 d6 b3 99 13 d2 58 |;.S9.H.4.H.....X|
1177 0230: 3b 90 53 39 db 48 02 34 83 48 d6 b3 99 13 d2 58 |;.S9.H.4.H.....X|
1178 0240: 65 8e 71 ac a9 06 95 f2 c4 8e b4 08 6b d3 0c ae |e.q.........k...|
1178 0240: 65 8e 71 ac a9 06 95 f2 c4 8e b4 08 6b d3 0c ae |e.q.........k...|
1179 0250: d9 90 56 71 43 a7 a2 62 16 3e 50 63 d3 57 3c 2d |..VqC..b.>Pc.W<-|
1179 0250: d9 90 56 71 43 a7 a2 62 16 3e 50 63 d3 57 3c 2d |..VqC..b.>Pc.W<-|
1180 0260: 9f 0f 34 05 08 d8 a6 4b 59 31 54 66 3a 45 0c 8a |..4....KY1Tf:E..|
1180 0260: 9f 0f 34 05 08 d8 a6 4b 59 31 54 66 3a 45 0c 8a |..4....KY1Tf:E..|
1181 0270: c7 90 3a f0 6a 83 1b f5 ca fb 80 2b 50 06 fb 51 |..:.j......+P..Q|
1181 0270: c7 90 3a f0 6a 83 1b f5 ca fb 80 2b 50 06 fb 51 |..:.j......+P..Q|
1182 0280: 7e a6 a4 d4 81 44 82 21 54 00 5b 1a 30 83 62 a3 |~....D.!T.[.0.b.|
1182 0280: 7e a6 a4 d4 81 44 82 21 54 00 5b 1a 30 83 62 a3 |~....D.!T.[.0.b.|
1183 0290: 18 b6 24 19 1e 45 df 4d 5c db a6 af 5b ac 90 fa |..$..E.M\...[...|
1183 0290: 18 b6 24 19 1e 45 df 4d 5c db a6 af 5b ac 90 fa |..$..E.M\...[...|
1184 02a0: 3e ed f9 ec 4c ba 36 ee d8 60 20 a7 c7 3b cb d1 |>...L.6..` ..;..|
1184 02a0: 3e ed f9 ec 4c ba 36 ee d8 60 20 a7 c7 3b cb d1 |>...L.6..` ..;..|
1185 02b0: 90 43 7d 27 16 50 5d ad f4 14 07 0b 90 5c cc 6b |.C}'.P]......\.k|
1185 02b0: 90 43 7d 27 16 50 5d ad f4 14 07 0b 90 5c cc 6b |.C}'.P]......\.k|
1186 02c0: 8d 3f a6 88 f4 34 37 a8 cf 14 63 36 19 f7 3e 28 |.?...47...c6..>(|
1186 02c0: 8d 3f a6 88 f4 34 37 a8 cf 14 63 36 19 f7 3e 28 |.?...47...c6..>(|
1187 02d0: de 99 e8 16 a4 9d 0d 40 a1 a7 24 52 14 a6 72 62 |.......@..$R..rb|
1187 02d0: de 99 e8 16 a4 9d 0d 40 a1 a7 24 52 14 a6 72 62 |.......@..$R..rb|
1188 02e0: 59 5a ca 2d e5 51 90 78 88 d9 c6 c7 21 d0 f7 46 |YZ.-.Q.x....!..F|
1188 02e0: 59 5a ca 2d e5 51 90 78 88 d9 c6 c7 21 d0 f7 46 |YZ.-.Q.x....!..F|
1189 02f0: b2 04 46 44 4e 20 9c 12 b1 03 4e 25 e0 a9 0c 58 |..FDN ....N%...X|
1189 02f0: b2 04 46 44 4e 20 9c 12 b1 03 4e 25 e0 a9 0c 58 |..FDN ....N%...X|
1190 0300: 5b 1d 3c 93 20 01 51 de a9 1c 69 23 32 46 14 b4 |[.<. .Q...i#2F..|
1190 0300: 5b 1d 3c 93 20 01 51 de a9 1c 69 23 32 46 14 b4 |[.<. .Q...i#2F..|
1191 0310: 90 db 17 98 98 50 03 90 29 aa 40 b0 13 d8 43 d2 |.....P..).@...C.|
1191 0310: 90 db 17 98 98 50 03 90 29 aa 40 b0 13 d8 43 d2 |.....P..).@...C.|
1192 0320: 5f c5 9d eb f3 f2 ad 41 e8 7a a9 ed a1 58 84 a6 |_......A.z...X..|
1192 0320: 5f c5 9d eb f3 f2 ad 41 e8 7a a9 ed a1 58 84 a6 |_......A.z...X..|
1193 0330: 42 bf d6 fc 24 82 c1 20 32 26 4a 15 a6 1d 29 7f |B...$.. 2&J...).|
1193 0330: 42 bf d6 fc 24 82 c1 20 32 26 4a 15 a6 1d 29 7f |B...$.. 2&J...).|
1194 0340: 7e f4 3d 07 bc 62 9a 5b ec 44 3d 72 1d 41 8b 5c |~.=..b.[.D=r.A.\|
1194 0340: 7e f4 3d 07 bc 62 9a 5b ec 44 3d 72 1d 41 8b 5c |~.=..b.[.D=r.A.\|
1195 0350: 80 de 0e 62 9a 2e f8 83 00 d5 07 a0 9c c6 74 98 |...b..........t.|
1195 0350: 80 de 0e 62 9a 2e f8 83 00 d5 07 a0 9c c6 74 98 |...b..........t.|
1196 0360: 11 b2 5e a9 38 02 03 ee fd 86 5c f4 86 b3 ae da |..^.8.....\.....|
1196 0360: 11 b2 5e a9 38 02 03 ee fd 86 5c f4 86 b3 ae da |..^.8.....\.....|
1197 0370: 05 94 01 c5 c6 ea 18 e6 ba 2a ba b3 04 5c 96 89 |.........*...\..|
1197 0370: 05 94 01 c5 c6 ea 18 e6 ba 2a ba b3 04 5c 96 89 |.........*...\..|
1198 0380: 72 63 5b 10 11 f6 67 34 98 cb e4 c0 4e fa e6 99 |rc[...g4....N...|
1198 0380: 72 63 5b 10 11 f6 67 34 98 cb e4 c0 4e fa e6 99 |rc[...g4....N...|
1199 0390: 19 6e 50 e8 26 8d 0c 17 e0 be ef e1 8e 02 6f 32 |.nP.&.........o2|
1199 0390: 19 6e 50 e8 26 8d 0c 17 e0 be ef e1 8e 02 6f 32 |.nP.&.........o2|
1200 03a0: 82 dc 26 f8 a1 08 f3 8a 0d f3 c4 75 00 48 73 b8 |..&........u.Hs.|
1200 03a0: 82 dc 26 f8 a1 08 f3 8a 0d f3 c4 75 00 48 73 b8 |..&........u.Hs.|
1201 03b0: be 3b 0d 7f d0 fd c7 78 96 ec e0 03 80 68 4d 8d |.;.....x.....hM.|
1201 03b0: be 3b 0d 7f d0 fd c7 78 96 ec e0 03 80 68 4d 8d |.;.....x.....hM.|
1202 03c0: 43 8c d7 68 58 f9 50 f0 18 cb 21 58 1b 60 cd 1f |C..hX.P...!X.`..|
1202 03c0: 43 8c d7 68 58 f9 50 f0 18 cb 21 58 1b 60 cd 1f |C..hX.P...!X.`..|
1203 03d0: 84 36 2e 16 1f 0a f7 4e 8f eb df 01 2d c2 79 0b |.6.....N....-.y.|
1203 03d0: 84 36 2e 16 1f 0a f7 4e 8f eb df 01 2d c2 79 0b |.6.....N....-.y.|
1204 03e0: f7 24 ea 0d e8 59 86 51 6e 1c 30 a3 ad 2f ee 8c |.$...Y.Qn.0../..|
1204 03e0: f7 24 ea 0d e8 59 86 51 6e 1c 30 a3 ad 2f ee 8c |.$...Y.Qn.0../..|
1205 03f0: 90 c8 84 d5 e8 34 c1 95 b2 c9 f6 4d 87 1c 7d 19 |.....4.....M..}.|
1205 03f0: 90 c8 84 d5 e8 34 c1 95 b2 c9 f6 4d 87 1c 7d 19 |.....4.....M..}.|
1206 0400: d6 41 58 56 7a e0 6c ba 10 c7 e8 33 39 36 96 e7 |.AXVz.l....396..|
1206 0400: d6 41 58 56 7a e0 6c ba 10 c7 e8 33 39 36 96 e7 |.AXVz.l....396..|
1207 0410: d2 f9 59 9a 08 95 48 38 e7 0b b7 0a 24 67 c4 39 |..Y...H8....$g.9|
1207 0410: d2 f9 59 9a 08 95 48 38 e7 0b b7 0a 24 67 c4 39 |..Y...H8....$g.9|
1208 0420: 8b 43 88 57 9c 01 f5 61 b5 e1 27 41 7e af 83 fe |.C.W...a..'A~...|
1208 0420: 8b 43 88 57 9c 01 f5 61 b5 e1 27 41 7e af 83 fe |.C.W...a..'A~...|
1209 0430: 2e e4 8a 70 a1 21 46 96 30 7a |...p.!F.0z|
1209 0430: 2e e4 8a 70 a1 21 46 96 30 7a |...p.!F.0z|
1210 $ hg debugbundle ../rev.hg2.bz
1210 $ hg debugbundle ../rev.hg2.bz
1211 Stream params: {Compression: BZ}
1211 Stream params: {Compression: BZ}
1212 changegroup -- {} (mandatory: False)
1212 changegroup -- {} (mandatory: False)
1213 32af7686d403cf45b5d95f2d70cebea587ac806a
1213 32af7686d403cf45b5d95f2d70cebea587ac806a
1214 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
1214 9520eea781bcca16c1e15acc0ba14335a0e8e5ba
1215 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
1215 eea13746799a9e0bfd88f29d3c2e9dc9389f524f
1216 02de42196ebee42ef284b6780a87cdc96e8eaab6
1216 02de42196ebee42ef284b6780a87cdc96e8eaab6
1217 $ hg unbundle ../rev.hg2.bz
1217 $ hg unbundle ../rev.hg2.bz
1218 adding changesets
1218 adding changesets
1219 adding manifests
1219 adding manifests
1220 adding file changes
1220 adding file changes
1221 added 0 changesets with 0 changes to 3 files
1221 added 0 changesets with 0 changes to 3 files
1222 (run 'hg update' to get a working copy)
1222 (run 'hg update' to get a working copy)
1223
1223
1224 unknown compression while unbundling
1224 unknown compression while unbundling
1225 -----------------------------
1225 -----------------------------
1226
1226
1227 $ hg bundle2 --param Compression=FooBarUnknown --rev '8+7+5+4' ../rev.hg2.bz
1227 $ hg bundle2 --param Compression=FooBarUnknown --rev '8+7+5+4' ../rev.hg2.bz
1228 $ cat ../rev.hg2.bz | hg statbundle2
1228 $ cat ../rev.hg2.bz | hg statbundle2
1229 abort: unknown parameters: Stream Parameter - Compression='FooBarUnknown'
1229 abort: unknown parameters: Stream Parameter - Compression='FooBarUnknown'
1230 [255]
1230 [255]
1231 $ hg unbundle ../rev.hg2.bz
1231 $ hg unbundle ../rev.hg2.bz
1232 abort: ../rev.hg2.bz: unknown bundle feature, Stream Parameter - Compression='FooBarUnknown'
1232 abort: ../rev.hg2.bz: unknown bundle feature, Stream Parameter - Compression='FooBarUnknown'
1233 (see https://mercurial-scm.org/wiki/BundleFeature for more information)
1233 (see https://mercurial-scm.org/wiki/BundleFeature for more information)
1234 [255]
1234 [255]
1235
1235
1236 $ cd ..
1236 $ cd ..
@@ -1,1892 +1,1892
1 ============================================================================================
1 ============================================================================================
2 Test cases where there are race condition between two clients pushing to the same repository
2 Test cases where there are race condition between two clients pushing to the same repository
3 ============================================================================================
3 ============================================================================================
4
4
5 This file tests cases where two clients push to a server at the same time. The
5 This file tests cases where two clients push to a server at the same time. The
6 "raced" client is done preparing it push bundle when the "racing" client
6 "raced" client is done preparing it push bundle when the "racing" client
7 perform its push. The "raced" client starts its actual push after the "racing"
7 perform its push. The "raced" client starts its actual push after the "racing"
8 client push is fully complete.
8 client push is fully complete.
9
9
10 A set of extension and shell functions ensures this scheduling.
10 A set of extension and shell functions ensures this scheduling.
11
11
12 $ cat >> delaypush.py << EOF
12 $ cat >> delaypush.py << EOF
13 > """small extension orchestrate push race
13 > """small extension orchestrate push race
14 >
14 >
15 > Client with the extensions will create a file when ready and get stuck until
15 > Client with the extensions will create a file when ready and get stuck until
16 > a file is created."""
16 > a file is created."""
17 >
17 >
18 > import errno
18 > import errno
19 > import os
19 > import os
20 > import time
20 > import time
21 >
21 >
22 > from mercurial import (
22 > from mercurial import (
23 > exchange,
23 > exchange,
24 > extensions,
24 > extensions,
25 > registrar,
25 > registrar,
26 > )
26 > )
27 >
27 >
28 > configtable = {}
28 > configtable = {}
29 > configitem = registrar.configitem(configtable)
29 > configitem = registrar.configitem(configtable)
30 >
30 >
31 > configitem('delaypush', 'ready-path',
31 > configitem('delaypush', 'ready-path',
32 > default=None,
32 > default=None,
33 > )
33 > )
34 > configitem('delaypush', 'release-path',
34 > configitem('delaypush', 'release-path',
35 > default=None,
35 > default=None,
36 > )
36 > )
37 >
37 >
38 > def delaypush(orig, pushop):
38 > def delaypush(orig, pushop):
39 > # notify we are done preparing
39 > # notify we are done preparing
40 > ui = pushop.repo.ui
40 > ui = pushop.repo.ui
41 > readypath = ui.config('delaypush', 'ready-path')
41 > readypath = ui.config('delaypush', 'ready-path')
42 > if readypath is not None:
42 > if readypath is not None:
43 > with open(readypath, 'w') as r:
43 > with open(readypath, 'w') as r:
44 > r.write('foo')
44 > r.write('foo')
45 > ui.status('wrote ready: %s\n' % readypath)
45 > ui.status('wrote ready: %s\n' % readypath)
46 > # now wait for the other process to be done
46 > # now wait for the other process to be done
47 > watchpath = ui.config('delaypush', 'release-path')
47 > watchpath = ui.config('delaypush', 'release-path')
48 > if watchpath is not None:
48 > if watchpath is not None:
49 > ui.status('waiting on: %s\n' % watchpath)
49 > ui.status('waiting on: %s\n' % watchpath)
50 > limit = 100
50 > limit = 100
51 > while 0 < limit and not os.path.exists(watchpath):
51 > while 0 < limit and not os.path.exists(watchpath):
52 > limit -= 1
52 > limit -= 1
53 > time.sleep(0.1)
53 > time.sleep(0.1)
54 > if limit <= 0:
54 > if limit <= 0:
55 > ui.warn('exiting without watchfile: %s' % watchpath)
55 > ui.warn('exiting without watchfile: %s' % watchpath)
56 > else:
56 > else:
57 > # delete the file at the end of the push
57 > # delete the file at the end of the push
58 > def delete():
58 > def delete():
59 > try:
59 > try:
60 > os.unlink(watchpath)
60 > os.unlink(watchpath)
61 > except OSError as exc:
61 > except OSError as exc:
62 > if exc.errno != errno.ENOENT:
62 > if exc.errno != errno.ENOENT:
63 > raise
63 > raise
64 > ui.atexit(delete)
64 > ui.atexit(delete)
65 > return orig(pushop)
65 > return orig(pushop)
66 >
66 >
67 > def uisetup(ui):
67 > def uisetup(ui):
68 > extensions.wrapfunction(exchange, '_pushbundle2', delaypush)
68 > extensions.wrapfunction(exchange, '_pushbundle2', delaypush)
69 > EOF
69 > EOF
70
70
71 $ waiton () {
71 $ waiton () {
72 > # wait for a file to be created (then delete it)
72 > # wait for a file to be created (then delete it)
73 > count=100
73 > count=100
74 > while [ ! -f $1 ] ;
74 > while [ ! -f $1 ] ;
75 > do
75 > do
76 > sleep 0.1;
76 > sleep 0.1;
77 > count=`expr $count - 1`;
77 > count=`expr $count - 1`;
78 > if [ $count -lt 0 ];
78 > if [ $count -lt 0 ];
79 > then
79 > then
80 > break
80 > break
81 > fi;
81 > fi;
82 > done
82 > done
83 > [ -f $1 ] || echo "ready file still missing: $1"
83 > [ -f $1 ] || echo "ready file still missing: $1"
84 > rm -f $1
84 > rm -f $1
85 > }
85 > }
86
86
87 $ release () {
87 $ release () {
88 > # create a file and wait for it be deleted
88 > # create a file and wait for it be deleted
89 > count=100
89 > count=100
90 > touch $1
90 > touch $1
91 > while [ -f $1 ] ;
91 > while [ -f $1 ] ;
92 > do
92 > do
93 > sleep 0.1;
93 > sleep 0.1;
94 > count=`expr $count - 1`;
94 > count=`expr $count - 1`;
95 > if [ $count -lt 0 ];
95 > if [ $count -lt 0 ];
96 > then
96 > then
97 > break
97 > break
98 > fi;
98 > fi;
99 > done
99 > done
100 > [ ! -f $1 ] || echo "delay file still exist: $1"
100 > [ ! -f $1 ] || echo "delay file still exist: $1"
101 > }
101 > }
102
102
103 $ cat >> $HGRCPATH << EOF
103 $ cat >> $HGRCPATH << EOF
104 > [ui]
104 > [ui]
105 > ssh = "$PYTHON" "$TESTDIR/dummyssh"
105 > ssh = "$PYTHON" "$TESTDIR/dummyssh"
106 > # simplify output
106 > # simplify output
107 > logtemplate = {node|short} {desc} ({branch})
107 > logtemplate = {node|short} {desc} ({branch})
108 > [phases]
108 > [phases]
109 > publish = no
109 > publish = no
110 > [experimental]
110 > [experimental]
111 > evolution=true
111 > evolution=true
112 > [alias]
112 > [alias]
113 > graph = log -G --rev 'sort(all(), "topo")'
113 > graph = log -G --rev 'sort(all(), "topo")'
114 > EOF
114 > EOF
115
115
116 We tests multiple cases:
116 We tests multiple cases:
117 * strict: no race detected,
117 * strict: no race detected,
118 * unrelated: race on unrelated heads are allowed.
118 * unrelated: race on unrelated heads are allowed.
119
119
120 #testcases strict unrelated
120 #testcases strict unrelated
121
121
122 #if unrelated
122 #if unrelated
123
123
124 $ cat >> $HGRCPATH << EOF
124 $ cat >> $HGRCPATH << EOF
125 > [server]
125 > [server]
126 > concurrent-push-mode = check-related
126 > concurrent-push-mode = check-related
127 > EOF
127 > EOF
128
128
129 #endif
129 #endif
130
130
131 Setup
131 Setup
132 -----
132 -----
133
133
134 create a repo with one root
134 create a repo with one root
135
135
136 $ hg init server
136 $ hg init server
137 $ cd server
137 $ cd server
138 $ echo root > root
138 $ echo root > root
139 $ hg ci -Am "C-ROOT"
139 $ hg ci -Am "C-ROOT"
140 adding root
140 adding root
141 $ cd ..
141 $ cd ..
142
142
143 clone it in two clients
143 clone it in two clients
144
144
145 $ hg clone ssh://user@dummy/server client-racy
145 $ hg clone ssh://user@dummy/server client-racy
146 requesting all changes
146 requesting all changes
147 adding changesets
147 adding changesets
148 adding manifests
148 adding manifests
149 adding file changes
149 adding file changes
150 added 1 changesets with 1 changes to 1 files
150 added 1 changesets with 1 changes to 1 files
151 new changesets 842e2fac6304 (1 drafts)
151 new changesets 842e2fac6304 (1 drafts)
152 updating to branch default
152 updating to branch default
153 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
153 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
154 $ hg clone ssh://user@dummy/server client-other
154 $ hg clone ssh://user@dummy/server client-other
155 requesting all changes
155 requesting all changes
156 adding changesets
156 adding changesets
157 adding manifests
157 adding manifests
158 adding file changes
158 adding file changes
159 added 1 changesets with 1 changes to 1 files
159 added 1 changesets with 1 changes to 1 files
160 new changesets 842e2fac6304 (1 drafts)
160 new changesets 842e2fac6304 (1 drafts)
161 updating to branch default
161 updating to branch default
162 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
162 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
163
163
164 setup one to allow race on push
164 setup one to allow race on push
165
165
166 $ cat >> client-racy/.hg/hgrc << EOF
166 $ cat >> client-racy/.hg/hgrc << EOF
167 > [extensions]
167 > [extensions]
168 > delaypush = $TESTTMP/delaypush.py
168 > delaypush = $TESTTMP/delaypush.py
169 > [delaypush]
169 > [delaypush]
170 > ready-path = $TESTTMP/readyfile
170 > ready-path = $TESTTMP/readyfile
171 > release-path = $TESTTMP/watchfile
171 > release-path = $TESTTMP/watchfile
172 > EOF
172 > EOF
173
173
174 Simple race, both try to push to the server at the same time
174 Simple race, both try to push to the server at the same time
175 ------------------------------------------------------------
175 ------------------------------------------------------------
176
176
177 Both try to replace the same head
177 Both try to replace the same head
178
178
179 # a
179 # a
180 # | b
180 # | b
181 # |/
181 # |/
182 # *
182 # *
183
183
184 Creating changesets
184 Creating changesets
185
185
186 $ echo b > client-other/a
186 $ echo b > client-other/a
187 $ hg -R client-other/ add client-other/a
187 $ hg -R client-other/ add client-other/a
188 $ hg -R client-other/ commit -m "C-A"
188 $ hg -R client-other/ commit -m "C-A"
189 $ echo b > client-racy/b
189 $ echo b > client-racy/b
190 $ hg -R client-racy/ add client-racy/b
190 $ hg -R client-racy/ add client-racy/b
191 $ hg -R client-racy/ commit -m "C-B"
191 $ hg -R client-racy/ commit -m "C-B"
192
192
193 Pushing
193 Pushing
194
194
195 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
195 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
196
196
197 $ waiton $TESTTMP/readyfile
197 $ waiton $TESTTMP/readyfile
198
198
199 $ hg -R client-other push -r 'tip'
199 $ hg -R client-other push -r 'tip'
200 pushing to ssh://user@dummy/server
200 pushing to ssh://user@dummy/server
201 searching for changes
201 searching for changes
202 remote: adding changesets
202 remote: adding changesets
203 remote: adding manifests
203 remote: adding manifests
204 remote: adding file changes
204 remote: adding file changes
205 remote: added 1 changesets with 1 changes to 1 files
205 remote: added 1 changesets with 1 changes to 1 files
206
206
207 $ release $TESTTMP/watchfile
207 $ release $TESTTMP/watchfile
208
208
209 Check the result of the push
209 Check the result of the push
210
210
211 $ cat ./push-log
211 $ cat ./push-log
212 pushing to ssh://user@dummy/server
212 pushing to ssh://user@dummy/server
213 searching for changes
213 searching for changes
214 wrote ready: $TESTTMP/readyfile
214 wrote ready: $TESTTMP/readyfile
215 waiting on: $TESTTMP/watchfile
215 waiting on: $TESTTMP/watchfile
216 abort: push failed:
216 abort: push failed:
217 'repository changed while pushing - please try again'
217 'remote repository changed while pushing - please try again'
218
218
219 $ hg -R server graph
219 $ hg -R server graph
220 o 98217d5a1659 C-A (default)
220 o 98217d5a1659 C-A (default)
221 |
221 |
222 @ 842e2fac6304 C-ROOT (default)
222 @ 842e2fac6304 C-ROOT (default)
223
223
224
224
225 Pushing on two different heads
225 Pushing on two different heads
226 ------------------------------
226 ------------------------------
227
227
228 Both try to replace a different head
228 Both try to replace a different head
229
229
230 # a b
230 # a b
231 # | |
231 # | |
232 # * *
232 # * *
233 # |/
233 # |/
234 # *
234 # *
235
235
236 (resync-all)
236 (resync-all)
237
237
238 $ hg -R ./server pull ./client-racy
238 $ hg -R ./server pull ./client-racy
239 pulling from ./client-racy
239 pulling from ./client-racy
240 searching for changes
240 searching for changes
241 adding changesets
241 adding changesets
242 adding manifests
242 adding manifests
243 adding file changes
243 adding file changes
244 added 1 changesets with 1 changes to 1 files (+1 heads)
244 added 1 changesets with 1 changes to 1 files (+1 heads)
245 new changesets a9149a1428e2 (1 drafts)
245 new changesets a9149a1428e2 (1 drafts)
246 (run 'hg heads' to see heads, 'hg merge' to merge)
246 (run 'hg heads' to see heads, 'hg merge' to merge)
247 $ hg -R ./client-other pull
247 $ hg -R ./client-other pull
248 pulling from ssh://user@dummy/server
248 pulling from ssh://user@dummy/server
249 searching for changes
249 searching for changes
250 adding changesets
250 adding changesets
251 adding manifests
251 adding manifests
252 adding file changes
252 adding file changes
253 added 1 changesets with 1 changes to 1 files (+1 heads)
253 added 1 changesets with 1 changes to 1 files (+1 heads)
254 new changesets a9149a1428e2 (1 drafts)
254 new changesets a9149a1428e2 (1 drafts)
255 (run 'hg heads' to see heads, 'hg merge' to merge)
255 (run 'hg heads' to see heads, 'hg merge' to merge)
256 $ hg -R ./client-racy pull
256 $ hg -R ./client-racy pull
257 pulling from ssh://user@dummy/server
257 pulling from ssh://user@dummy/server
258 searching for changes
258 searching for changes
259 adding changesets
259 adding changesets
260 adding manifests
260 adding manifests
261 adding file changes
261 adding file changes
262 added 1 changesets with 1 changes to 1 files (+1 heads)
262 added 1 changesets with 1 changes to 1 files (+1 heads)
263 new changesets 98217d5a1659 (1 drafts)
263 new changesets 98217d5a1659 (1 drafts)
264 (run 'hg heads' to see heads, 'hg merge' to merge)
264 (run 'hg heads' to see heads, 'hg merge' to merge)
265
265
266 $ hg -R server graph
266 $ hg -R server graph
267 o a9149a1428e2 C-B (default)
267 o a9149a1428e2 C-B (default)
268 |
268 |
269 | o 98217d5a1659 C-A (default)
269 | o 98217d5a1659 C-A (default)
270 |/
270 |/
271 @ 842e2fac6304 C-ROOT (default)
271 @ 842e2fac6304 C-ROOT (default)
272
272
273
273
274 Creating changesets
274 Creating changesets
275
275
276 $ echo aa >> client-other/a
276 $ echo aa >> client-other/a
277 $ hg -R client-other/ commit -m "C-C"
277 $ hg -R client-other/ commit -m "C-C"
278 $ echo bb >> client-racy/b
278 $ echo bb >> client-racy/b
279 $ hg -R client-racy/ commit -m "C-D"
279 $ hg -R client-racy/ commit -m "C-D"
280
280
281 Pushing
281 Pushing
282
282
283 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
283 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
284
284
285 $ waiton $TESTTMP/readyfile
285 $ waiton $TESTTMP/readyfile
286
286
287 $ hg -R client-other push -r 'tip'
287 $ hg -R client-other push -r 'tip'
288 pushing to ssh://user@dummy/server
288 pushing to ssh://user@dummy/server
289 searching for changes
289 searching for changes
290 remote: adding changesets
290 remote: adding changesets
291 remote: adding manifests
291 remote: adding manifests
292 remote: adding file changes
292 remote: adding file changes
293 remote: added 1 changesets with 1 changes to 1 files
293 remote: added 1 changesets with 1 changes to 1 files
294
294
295 $ release $TESTTMP/watchfile
295 $ release $TESTTMP/watchfile
296
296
297 Check the result of the push
297 Check the result of the push
298
298
299 #if strict
299 #if strict
300 $ cat ./push-log
300 $ cat ./push-log
301 pushing to ssh://user@dummy/server
301 pushing to ssh://user@dummy/server
302 searching for changes
302 searching for changes
303 wrote ready: $TESTTMP/readyfile
303 wrote ready: $TESTTMP/readyfile
304 waiting on: $TESTTMP/watchfile
304 waiting on: $TESTTMP/watchfile
305 abort: push failed:
305 abort: push failed:
306 'repository changed while pushing - please try again'
306 'remote repository changed while pushing - please try again'
307
307
308 $ hg -R server graph
308 $ hg -R server graph
309 o 51c544a58128 C-C (default)
309 o 51c544a58128 C-C (default)
310 |
310 |
311 o 98217d5a1659 C-A (default)
311 o 98217d5a1659 C-A (default)
312 |
312 |
313 | o a9149a1428e2 C-B (default)
313 | o a9149a1428e2 C-B (default)
314 |/
314 |/
315 @ 842e2fac6304 C-ROOT (default)
315 @ 842e2fac6304 C-ROOT (default)
316
316
317 #endif
317 #endif
318 #if unrelated
318 #if unrelated
319
319
320 (The two heads are unrelated, push should be allowed)
320 (The two heads are unrelated, push should be allowed)
321
321
322 $ cat ./push-log
322 $ cat ./push-log
323 pushing to ssh://user@dummy/server
323 pushing to ssh://user@dummy/server
324 searching for changes
324 searching for changes
325 wrote ready: $TESTTMP/readyfile
325 wrote ready: $TESTTMP/readyfile
326 waiting on: $TESTTMP/watchfile
326 waiting on: $TESTTMP/watchfile
327 remote: adding changesets
327 remote: adding changesets
328 remote: adding manifests
328 remote: adding manifests
329 remote: adding file changes
329 remote: adding file changes
330 remote: added 1 changesets with 1 changes to 1 files
330 remote: added 1 changesets with 1 changes to 1 files
331
331
332 $ hg -R server graph
332 $ hg -R server graph
333 o 59e76faf78bd C-D (default)
333 o 59e76faf78bd C-D (default)
334 |
334 |
335 o a9149a1428e2 C-B (default)
335 o a9149a1428e2 C-B (default)
336 |
336 |
337 | o 51c544a58128 C-C (default)
337 | o 51c544a58128 C-C (default)
338 | |
338 | |
339 | o 98217d5a1659 C-A (default)
339 | o 98217d5a1659 C-A (default)
340 |/
340 |/
341 @ 842e2fac6304 C-ROOT (default)
341 @ 842e2fac6304 C-ROOT (default)
342
342
343 #endif
343 #endif
344
344
345 Pushing while someone creates a new head
345 Pushing while someone creates a new head
346 -----------------------------------------
346 -----------------------------------------
347
347
348 Pushing a new changeset while someone creates a new branch.
348 Pushing a new changeset while someone creates a new branch.
349
349
350 # a (raced)
350 # a (raced)
351 # |
351 # |
352 # * b
352 # * b
353 # |/
353 # |/
354 # *
354 # *
355
355
356 (resync-all)
356 (resync-all)
357
357
358 #if strict
358 #if strict
359
359
360 $ hg -R ./server pull ./client-racy
360 $ hg -R ./server pull ./client-racy
361 pulling from ./client-racy
361 pulling from ./client-racy
362 searching for changes
362 searching for changes
363 adding changesets
363 adding changesets
364 adding manifests
364 adding manifests
365 adding file changes
365 adding file changes
366 added 1 changesets with 1 changes to 1 files
366 added 1 changesets with 1 changes to 1 files
367 new changesets 59e76faf78bd (1 drafts)
367 new changesets 59e76faf78bd (1 drafts)
368 (run 'hg update' to get a working copy)
368 (run 'hg update' to get a working copy)
369
369
370 #endif
370 #endif
371 #if unrelated
371 #if unrelated
372
372
373 $ hg -R ./server pull ./client-racy
373 $ hg -R ./server pull ./client-racy
374 pulling from ./client-racy
374 pulling from ./client-racy
375 searching for changes
375 searching for changes
376 no changes found
376 no changes found
377
377
378 #endif
378 #endif
379
379
380 $ hg -R ./client-other pull
380 $ hg -R ./client-other pull
381 pulling from ssh://user@dummy/server
381 pulling from ssh://user@dummy/server
382 searching for changes
382 searching for changes
383 adding changesets
383 adding changesets
384 adding manifests
384 adding manifests
385 adding file changes
385 adding file changes
386 added 1 changesets with 1 changes to 1 files
386 added 1 changesets with 1 changes to 1 files
387 new changesets 59e76faf78bd (1 drafts)
387 new changesets 59e76faf78bd (1 drafts)
388 (run 'hg update' to get a working copy)
388 (run 'hg update' to get a working copy)
389 $ hg -R ./client-racy pull
389 $ hg -R ./client-racy pull
390 pulling from ssh://user@dummy/server
390 pulling from ssh://user@dummy/server
391 searching for changes
391 searching for changes
392 adding changesets
392 adding changesets
393 adding manifests
393 adding manifests
394 adding file changes
394 adding file changes
395 added 1 changesets with 1 changes to 1 files
395 added 1 changesets with 1 changes to 1 files
396 new changesets 51c544a58128 (1 drafts)
396 new changesets 51c544a58128 (1 drafts)
397 (run 'hg update' to get a working copy)
397 (run 'hg update' to get a working copy)
398
398
399 $ hg -R server graph
399 $ hg -R server graph
400 o 59e76faf78bd C-D (default)
400 o 59e76faf78bd C-D (default)
401 |
401 |
402 o a9149a1428e2 C-B (default)
402 o a9149a1428e2 C-B (default)
403 |
403 |
404 | o 51c544a58128 C-C (default)
404 | o 51c544a58128 C-C (default)
405 | |
405 | |
406 | o 98217d5a1659 C-A (default)
406 | o 98217d5a1659 C-A (default)
407 |/
407 |/
408 @ 842e2fac6304 C-ROOT (default)
408 @ 842e2fac6304 C-ROOT (default)
409
409
410
410
411 Creating changesets
411 Creating changesets
412
412
413 (new head)
413 (new head)
414
414
415 $ hg -R client-other/ up 'desc("C-A")'
415 $ hg -R client-other/ up 'desc("C-A")'
416 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
416 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
417 $ echo aaa >> client-other/a
417 $ echo aaa >> client-other/a
418 $ hg -R client-other/ commit -m "C-E"
418 $ hg -R client-other/ commit -m "C-E"
419 created new head
419 created new head
420
420
421 (children of existing head)
421 (children of existing head)
422
422
423 $ hg -R client-racy/ up 'desc("C-C")'
423 $ hg -R client-racy/ up 'desc("C-C")'
424 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
424 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
425 $ echo bbb >> client-racy/a
425 $ echo bbb >> client-racy/a
426 $ hg -R client-racy/ commit -m "C-F"
426 $ hg -R client-racy/ commit -m "C-F"
427
427
428 Pushing
428 Pushing
429
429
430 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
430 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
431
431
432 $ waiton $TESTTMP/readyfile
432 $ waiton $TESTTMP/readyfile
433
433
434 $ hg -R client-other push -fr 'tip'
434 $ hg -R client-other push -fr 'tip'
435 pushing to ssh://user@dummy/server
435 pushing to ssh://user@dummy/server
436 searching for changes
436 searching for changes
437 remote: adding changesets
437 remote: adding changesets
438 remote: adding manifests
438 remote: adding manifests
439 remote: adding file changes
439 remote: adding file changes
440 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
440 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
441
441
442 $ release $TESTTMP/watchfile
442 $ release $TESTTMP/watchfile
443
443
444 Check the result of the push
444 Check the result of the push
445
445
446 #if strict
446 #if strict
447
447
448 $ cat ./push-log
448 $ cat ./push-log
449 pushing to ssh://user@dummy/server
449 pushing to ssh://user@dummy/server
450 searching for changes
450 searching for changes
451 wrote ready: $TESTTMP/readyfile
451 wrote ready: $TESTTMP/readyfile
452 waiting on: $TESTTMP/watchfile
452 waiting on: $TESTTMP/watchfile
453 abort: push failed:
453 abort: push failed:
454 'repository changed while pushing - please try again'
454 'remote repository changed while pushing - please try again'
455
455
456 $ hg -R server graph
456 $ hg -R server graph
457 o d603e2c0cdd7 C-E (default)
457 o d603e2c0cdd7 C-E (default)
458 |
458 |
459 | o 51c544a58128 C-C (default)
459 | o 51c544a58128 C-C (default)
460 |/
460 |/
461 o 98217d5a1659 C-A (default)
461 o 98217d5a1659 C-A (default)
462 |
462 |
463 | o 59e76faf78bd C-D (default)
463 | o 59e76faf78bd C-D (default)
464 | |
464 | |
465 | o a9149a1428e2 C-B (default)
465 | o a9149a1428e2 C-B (default)
466 |/
466 |/
467 @ 842e2fac6304 C-ROOT (default)
467 @ 842e2fac6304 C-ROOT (default)
468
468
469
469
470 #endif
470 #endif
471
471
472 #if unrelated
472 #if unrelated
473
473
474 (The racing new head do not affect existing heads, push should go through)
474 (The racing new head do not affect existing heads, push should go through)
475
475
476 $ cat ./push-log
476 $ cat ./push-log
477 pushing to ssh://user@dummy/server
477 pushing to ssh://user@dummy/server
478 searching for changes
478 searching for changes
479 wrote ready: $TESTTMP/readyfile
479 wrote ready: $TESTTMP/readyfile
480 waiting on: $TESTTMP/watchfile
480 waiting on: $TESTTMP/watchfile
481 remote: adding changesets
481 remote: adding changesets
482 remote: adding manifests
482 remote: adding manifests
483 remote: adding file changes
483 remote: adding file changes
484 remote: added 1 changesets with 1 changes to 1 files
484 remote: added 1 changesets with 1 changes to 1 files
485
485
486 $ hg -R server graph
486 $ hg -R server graph
487 o d9e379a8c432 C-F (default)
487 o d9e379a8c432 C-F (default)
488 |
488 |
489 o 51c544a58128 C-C (default)
489 o 51c544a58128 C-C (default)
490 |
490 |
491 | o d603e2c0cdd7 C-E (default)
491 | o d603e2c0cdd7 C-E (default)
492 |/
492 |/
493 o 98217d5a1659 C-A (default)
493 o 98217d5a1659 C-A (default)
494 |
494 |
495 | o 59e76faf78bd C-D (default)
495 | o 59e76faf78bd C-D (default)
496 | |
496 | |
497 | o a9149a1428e2 C-B (default)
497 | o a9149a1428e2 C-B (default)
498 |/
498 |/
499 @ 842e2fac6304 C-ROOT (default)
499 @ 842e2fac6304 C-ROOT (default)
500
500
501 #endif
501 #endif
502
502
503 Pushing touching different named branch (same topo): new branch raced
503 Pushing touching different named branch (same topo): new branch raced
504 ---------------------------------------------------------------------
504 ---------------------------------------------------------------------
505
505
506 Pushing two children on the same head, one is a different named branch
506 Pushing two children on the same head, one is a different named branch
507
507
508 # a (raced, branch-a)
508 # a (raced, branch-a)
509 # |
509 # |
510 # | b (default branch)
510 # | b (default branch)
511 # |/
511 # |/
512 # *
512 # *
513
513
514 (resync-all)
514 (resync-all)
515
515
516 #if strict
516 #if strict
517
517
518 $ hg -R ./server pull ./client-racy
518 $ hg -R ./server pull ./client-racy
519 pulling from ./client-racy
519 pulling from ./client-racy
520 searching for changes
520 searching for changes
521 adding changesets
521 adding changesets
522 adding manifests
522 adding manifests
523 adding file changes
523 adding file changes
524 added 1 changesets with 1 changes to 1 files
524 added 1 changesets with 1 changes to 1 files
525 new changesets d9e379a8c432 (1 drafts)
525 new changesets d9e379a8c432 (1 drafts)
526 (run 'hg update' to get a working copy)
526 (run 'hg update' to get a working copy)
527
527
528 #endif
528 #endif
529 #if unrelated
529 #if unrelated
530
530
531 $ hg -R ./server pull ./client-racy
531 $ hg -R ./server pull ./client-racy
532 pulling from ./client-racy
532 pulling from ./client-racy
533 searching for changes
533 searching for changes
534 no changes found
534 no changes found
535
535
536 #endif
536 #endif
537
537
538 $ hg -R ./client-other pull
538 $ hg -R ./client-other pull
539 pulling from ssh://user@dummy/server
539 pulling from ssh://user@dummy/server
540 searching for changes
540 searching for changes
541 adding changesets
541 adding changesets
542 adding manifests
542 adding manifests
543 adding file changes
543 adding file changes
544 added 1 changesets with 1 changes to 1 files
544 added 1 changesets with 1 changes to 1 files
545 new changesets d9e379a8c432 (1 drafts)
545 new changesets d9e379a8c432 (1 drafts)
546 (run 'hg update' to get a working copy)
546 (run 'hg update' to get a working copy)
547 $ hg -R ./client-racy pull
547 $ hg -R ./client-racy pull
548 pulling from ssh://user@dummy/server
548 pulling from ssh://user@dummy/server
549 searching for changes
549 searching for changes
550 adding changesets
550 adding changesets
551 adding manifests
551 adding manifests
552 adding file changes
552 adding file changes
553 added 1 changesets with 1 changes to 1 files (+1 heads)
553 added 1 changesets with 1 changes to 1 files (+1 heads)
554 new changesets d603e2c0cdd7 (1 drafts)
554 new changesets d603e2c0cdd7 (1 drafts)
555 (run 'hg heads .' to see heads, 'hg merge' to merge)
555 (run 'hg heads .' to see heads, 'hg merge' to merge)
556
556
557 $ hg -R server graph
557 $ hg -R server graph
558 o d9e379a8c432 C-F (default)
558 o d9e379a8c432 C-F (default)
559 |
559 |
560 o 51c544a58128 C-C (default)
560 o 51c544a58128 C-C (default)
561 |
561 |
562 | o d603e2c0cdd7 C-E (default)
562 | o d603e2c0cdd7 C-E (default)
563 |/
563 |/
564 o 98217d5a1659 C-A (default)
564 o 98217d5a1659 C-A (default)
565 |
565 |
566 | o 59e76faf78bd C-D (default)
566 | o 59e76faf78bd C-D (default)
567 | |
567 | |
568 | o a9149a1428e2 C-B (default)
568 | o a9149a1428e2 C-B (default)
569 |/
569 |/
570 @ 842e2fac6304 C-ROOT (default)
570 @ 842e2fac6304 C-ROOT (default)
571
571
572
572
573 Creating changesets
573 Creating changesets
574
574
575 (update existing head)
575 (update existing head)
576
576
577 $ hg -R client-other/ up 'desc("C-F")'
577 $ hg -R client-other/ up 'desc("C-F")'
578 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
578 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
579 $ echo aaa >> client-other/a
579 $ echo aaa >> client-other/a
580 $ hg -R client-other/ commit -m "C-G"
580 $ hg -R client-other/ commit -m "C-G"
581
581
582 (new named branch from that existing head)
582 (new named branch from that existing head)
583
583
584 $ hg -R client-racy/ up 'desc("C-F")'
584 $ hg -R client-racy/ up 'desc("C-F")'
585 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
585 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
586 $ echo bbb >> client-racy/a
586 $ echo bbb >> client-racy/a
587 $ hg -R client-racy/ branch my-first-test-branch
587 $ hg -R client-racy/ branch my-first-test-branch
588 marked working directory as branch my-first-test-branch
588 marked working directory as branch my-first-test-branch
589 (branches are permanent and global, did you want a bookmark?)
589 (branches are permanent and global, did you want a bookmark?)
590 $ hg -R client-racy/ commit -m "C-H"
590 $ hg -R client-racy/ commit -m "C-H"
591
591
592 Pushing
592 Pushing
593
593
594 $ hg -R client-racy push -r 'tip' --new-branch > ./push-log 2>&1 &
594 $ hg -R client-racy push -r 'tip' --new-branch > ./push-log 2>&1 &
595
595
596 $ waiton $TESTTMP/readyfile
596 $ waiton $TESTTMP/readyfile
597
597
598 $ hg -R client-other push -fr 'tip'
598 $ hg -R client-other push -fr 'tip'
599 pushing to ssh://user@dummy/server
599 pushing to ssh://user@dummy/server
600 searching for changes
600 searching for changes
601 remote: adding changesets
601 remote: adding changesets
602 remote: adding manifests
602 remote: adding manifests
603 remote: adding file changes
603 remote: adding file changes
604 remote: added 1 changesets with 1 changes to 1 files
604 remote: added 1 changesets with 1 changes to 1 files
605
605
606 $ release $TESTTMP/watchfile
606 $ release $TESTTMP/watchfile
607
607
608 Check the result of the push
608 Check the result of the push
609
609
610 #if strict
610 #if strict
611 $ cat ./push-log
611 $ cat ./push-log
612 pushing to ssh://user@dummy/server
612 pushing to ssh://user@dummy/server
613 searching for changes
613 searching for changes
614 wrote ready: $TESTTMP/readyfile
614 wrote ready: $TESTTMP/readyfile
615 waiting on: $TESTTMP/watchfile
615 waiting on: $TESTTMP/watchfile
616 abort: push failed:
616 abort: push failed:
617 'repository changed while pushing - please try again'
617 'remote repository changed while pushing - please try again'
618
618
619 $ hg -R server graph
619 $ hg -R server graph
620 o 75d69cba5402 C-G (default)
620 o 75d69cba5402 C-G (default)
621 |
621 |
622 o d9e379a8c432 C-F (default)
622 o d9e379a8c432 C-F (default)
623 |
623 |
624 o 51c544a58128 C-C (default)
624 o 51c544a58128 C-C (default)
625 |
625 |
626 | o d603e2c0cdd7 C-E (default)
626 | o d603e2c0cdd7 C-E (default)
627 |/
627 |/
628 o 98217d5a1659 C-A (default)
628 o 98217d5a1659 C-A (default)
629 |
629 |
630 | o 59e76faf78bd C-D (default)
630 | o 59e76faf78bd C-D (default)
631 | |
631 | |
632 | o a9149a1428e2 C-B (default)
632 | o a9149a1428e2 C-B (default)
633 |/
633 |/
634 @ 842e2fac6304 C-ROOT (default)
634 @ 842e2fac6304 C-ROOT (default)
635
635
636 #endif
636 #endif
637 #if unrelated
637 #if unrelated
638
638
639 (unrelated named branches are unrelated)
639 (unrelated named branches are unrelated)
640
640
641 $ cat ./push-log
641 $ cat ./push-log
642 pushing to ssh://user@dummy/server
642 pushing to ssh://user@dummy/server
643 searching for changes
643 searching for changes
644 wrote ready: $TESTTMP/readyfile
644 wrote ready: $TESTTMP/readyfile
645 waiting on: $TESTTMP/watchfile
645 waiting on: $TESTTMP/watchfile
646 remote: adding changesets
646 remote: adding changesets
647 remote: adding manifests
647 remote: adding manifests
648 remote: adding file changes
648 remote: adding file changes
649 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
649 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
650
650
651 $ hg -R server graph
651 $ hg -R server graph
652 o 833be552cfe6 C-H (my-first-test-branch)
652 o 833be552cfe6 C-H (my-first-test-branch)
653 |
653 |
654 | o 75d69cba5402 C-G (default)
654 | o 75d69cba5402 C-G (default)
655 |/
655 |/
656 o d9e379a8c432 C-F (default)
656 o d9e379a8c432 C-F (default)
657 |
657 |
658 o 51c544a58128 C-C (default)
658 o 51c544a58128 C-C (default)
659 |
659 |
660 | o d603e2c0cdd7 C-E (default)
660 | o d603e2c0cdd7 C-E (default)
661 |/
661 |/
662 o 98217d5a1659 C-A (default)
662 o 98217d5a1659 C-A (default)
663 |
663 |
664 | o 59e76faf78bd C-D (default)
664 | o 59e76faf78bd C-D (default)
665 | |
665 | |
666 | o a9149a1428e2 C-B (default)
666 | o a9149a1428e2 C-B (default)
667 |/
667 |/
668 @ 842e2fac6304 C-ROOT (default)
668 @ 842e2fac6304 C-ROOT (default)
669
669
670 #endif
670 #endif
671
671
672 The racing new head do not affect existing heads, push should go through
672 The racing new head do not affect existing heads, push should go through
673
673
674 pushing touching different named branch (same topo): old branch raced
674 pushing touching different named branch (same topo): old branch raced
675 ---------------------------------------------------------------------
675 ---------------------------------------------------------------------
676
676
677 Pushing two children on the same head, one is a different named branch
677 Pushing two children on the same head, one is a different named branch
678
678
679 # a (raced, default-branch)
679 # a (raced, default-branch)
680 # |
680 # |
681 # | b (new branch)
681 # | b (new branch)
682 # |/
682 # |/
683 # * (default-branch)
683 # * (default-branch)
684
684
685 (resync-all)
685 (resync-all)
686
686
687 #if strict
687 #if strict
688
688
689 $ hg -R ./server pull ./client-racy
689 $ hg -R ./server pull ./client-racy
690 pulling from ./client-racy
690 pulling from ./client-racy
691 searching for changes
691 searching for changes
692 adding changesets
692 adding changesets
693 adding manifests
693 adding manifests
694 adding file changes
694 adding file changes
695 added 1 changesets with 1 changes to 1 files (+1 heads)
695 added 1 changesets with 1 changes to 1 files (+1 heads)
696 new changesets 833be552cfe6 (1 drafts)
696 new changesets 833be552cfe6 (1 drafts)
697 (run 'hg heads .' to see heads, 'hg merge' to merge)
697 (run 'hg heads .' to see heads, 'hg merge' to merge)
698
698
699 #endif
699 #endif
700 #if unrelated
700 #if unrelated
701
701
702 $ hg -R ./server pull ./client-racy
702 $ hg -R ./server pull ./client-racy
703 pulling from ./client-racy
703 pulling from ./client-racy
704 searching for changes
704 searching for changes
705 no changes found
705 no changes found
706
706
707 #endif
707 #endif
708
708
709 $ hg -R ./client-other pull
709 $ hg -R ./client-other pull
710 pulling from ssh://user@dummy/server
710 pulling from ssh://user@dummy/server
711 searching for changes
711 searching for changes
712 adding changesets
712 adding changesets
713 adding manifests
713 adding manifests
714 adding file changes
714 adding file changes
715 added 1 changesets with 1 changes to 1 files (+1 heads)
715 added 1 changesets with 1 changes to 1 files (+1 heads)
716 new changesets 833be552cfe6 (1 drafts)
716 new changesets 833be552cfe6 (1 drafts)
717 (run 'hg heads .' to see heads, 'hg merge' to merge)
717 (run 'hg heads .' to see heads, 'hg merge' to merge)
718 $ hg -R ./client-racy pull
718 $ hg -R ./client-racy pull
719 pulling from ssh://user@dummy/server
719 pulling from ssh://user@dummy/server
720 searching for changes
720 searching for changes
721 adding changesets
721 adding changesets
722 adding manifests
722 adding manifests
723 adding file changes
723 adding file changes
724 added 1 changesets with 1 changes to 1 files (+1 heads)
724 added 1 changesets with 1 changes to 1 files (+1 heads)
725 new changesets 75d69cba5402 (1 drafts)
725 new changesets 75d69cba5402 (1 drafts)
726 (run 'hg heads' to see heads)
726 (run 'hg heads' to see heads)
727
727
728 $ hg -R server graph
728 $ hg -R server graph
729 o 833be552cfe6 C-H (my-first-test-branch)
729 o 833be552cfe6 C-H (my-first-test-branch)
730 |
730 |
731 | o 75d69cba5402 C-G (default)
731 | o 75d69cba5402 C-G (default)
732 |/
732 |/
733 o d9e379a8c432 C-F (default)
733 o d9e379a8c432 C-F (default)
734 |
734 |
735 o 51c544a58128 C-C (default)
735 o 51c544a58128 C-C (default)
736 |
736 |
737 | o d603e2c0cdd7 C-E (default)
737 | o d603e2c0cdd7 C-E (default)
738 |/
738 |/
739 o 98217d5a1659 C-A (default)
739 o 98217d5a1659 C-A (default)
740 |
740 |
741 | o 59e76faf78bd C-D (default)
741 | o 59e76faf78bd C-D (default)
742 | |
742 | |
743 | o a9149a1428e2 C-B (default)
743 | o a9149a1428e2 C-B (default)
744 |/
744 |/
745 @ 842e2fac6304 C-ROOT (default)
745 @ 842e2fac6304 C-ROOT (default)
746
746
747
747
748 Creating changesets
748 Creating changesets
749
749
750 (new named branch from one head)
750 (new named branch from one head)
751
751
752 $ hg -R client-other/ up 'desc("C-G")'
752 $ hg -R client-other/ up 'desc("C-G")'
753 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
753 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
754 $ echo aaa >> client-other/a
754 $ echo aaa >> client-other/a
755 $ hg -R client-other/ branch my-second-test-branch
755 $ hg -R client-other/ branch my-second-test-branch
756 marked working directory as branch my-second-test-branch
756 marked working directory as branch my-second-test-branch
757 $ hg -R client-other/ commit -m "C-I"
757 $ hg -R client-other/ commit -m "C-I"
758
758
759 (children "updating" that same head)
759 (children "updating" that same head)
760
760
761 $ hg -R client-racy/ up 'desc("C-G")'
761 $ hg -R client-racy/ up 'desc("C-G")'
762 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
762 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
763 $ echo bbb >> client-racy/a
763 $ echo bbb >> client-racy/a
764 $ hg -R client-racy/ commit -m "C-J"
764 $ hg -R client-racy/ commit -m "C-J"
765
765
766 Pushing
766 Pushing
767
767
768 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
768 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
769
769
770 $ waiton $TESTTMP/readyfile
770 $ waiton $TESTTMP/readyfile
771
771
772 $ hg -R client-other push -fr 'tip' --new-branch
772 $ hg -R client-other push -fr 'tip' --new-branch
773 pushing to ssh://user@dummy/server
773 pushing to ssh://user@dummy/server
774 searching for changes
774 searching for changes
775 remote: adding changesets
775 remote: adding changesets
776 remote: adding manifests
776 remote: adding manifests
777 remote: adding file changes
777 remote: adding file changes
778 remote: added 1 changesets with 1 changes to 1 files
778 remote: added 1 changesets with 1 changes to 1 files
779
779
780 $ release $TESTTMP/watchfile
780 $ release $TESTTMP/watchfile
781
781
782 Check the result of the push
782 Check the result of the push
783
783
784 #if strict
784 #if strict
785
785
786 $ cat ./push-log
786 $ cat ./push-log
787 pushing to ssh://user@dummy/server
787 pushing to ssh://user@dummy/server
788 searching for changes
788 searching for changes
789 wrote ready: $TESTTMP/readyfile
789 wrote ready: $TESTTMP/readyfile
790 waiting on: $TESTTMP/watchfile
790 waiting on: $TESTTMP/watchfile
791 abort: push failed:
791 abort: push failed:
792 'repository changed while pushing - please try again'
792 'remote repository changed while pushing - please try again'
793
793
794 $ hg -R server graph
794 $ hg -R server graph
795 o b35ed749f288 C-I (my-second-test-branch)
795 o b35ed749f288 C-I (my-second-test-branch)
796 |
796 |
797 o 75d69cba5402 C-G (default)
797 o 75d69cba5402 C-G (default)
798 |
798 |
799 | o 833be552cfe6 C-H (my-first-test-branch)
799 | o 833be552cfe6 C-H (my-first-test-branch)
800 |/
800 |/
801 o d9e379a8c432 C-F (default)
801 o d9e379a8c432 C-F (default)
802 |
802 |
803 o 51c544a58128 C-C (default)
803 o 51c544a58128 C-C (default)
804 |
804 |
805 | o d603e2c0cdd7 C-E (default)
805 | o d603e2c0cdd7 C-E (default)
806 |/
806 |/
807 o 98217d5a1659 C-A (default)
807 o 98217d5a1659 C-A (default)
808 |
808 |
809 | o 59e76faf78bd C-D (default)
809 | o 59e76faf78bd C-D (default)
810 | |
810 | |
811 | o a9149a1428e2 C-B (default)
811 | o a9149a1428e2 C-B (default)
812 |/
812 |/
813 @ 842e2fac6304 C-ROOT (default)
813 @ 842e2fac6304 C-ROOT (default)
814
814
815
815
816 #endif
816 #endif
817
817
818 #if unrelated
818 #if unrelated
819
819
820 (unrelated named branches are unrelated)
820 (unrelated named branches are unrelated)
821
821
822 $ cat ./push-log
822 $ cat ./push-log
823 pushing to ssh://user@dummy/server
823 pushing to ssh://user@dummy/server
824 searching for changes
824 searching for changes
825 wrote ready: $TESTTMP/readyfile
825 wrote ready: $TESTTMP/readyfile
826 waiting on: $TESTTMP/watchfile
826 waiting on: $TESTTMP/watchfile
827 remote: adding changesets
827 remote: adding changesets
828 remote: adding manifests
828 remote: adding manifests
829 remote: adding file changes
829 remote: adding file changes
830 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
830 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
831
831
832 $ hg -R server graph
832 $ hg -R server graph
833 o 89420bf00fae C-J (default)
833 o 89420bf00fae C-J (default)
834 |
834 |
835 | o b35ed749f288 C-I (my-second-test-branch)
835 | o b35ed749f288 C-I (my-second-test-branch)
836 |/
836 |/
837 o 75d69cba5402 C-G (default)
837 o 75d69cba5402 C-G (default)
838 |
838 |
839 | o 833be552cfe6 C-H (my-first-test-branch)
839 | o 833be552cfe6 C-H (my-first-test-branch)
840 |/
840 |/
841 o d9e379a8c432 C-F (default)
841 o d9e379a8c432 C-F (default)
842 |
842 |
843 o 51c544a58128 C-C (default)
843 o 51c544a58128 C-C (default)
844 |
844 |
845 | o d603e2c0cdd7 C-E (default)
845 | o d603e2c0cdd7 C-E (default)
846 |/
846 |/
847 o 98217d5a1659 C-A (default)
847 o 98217d5a1659 C-A (default)
848 |
848 |
849 | o 59e76faf78bd C-D (default)
849 | o 59e76faf78bd C-D (default)
850 | |
850 | |
851 | o a9149a1428e2 C-B (default)
851 | o a9149a1428e2 C-B (default)
852 |/
852 |/
853 @ 842e2fac6304 C-ROOT (default)
853 @ 842e2fac6304 C-ROOT (default)
854
854
855
855
856 #endif
856 #endif
857
857
858 pushing racing push touch multiple heads
858 pushing racing push touch multiple heads
859 ----------------------------------------
859 ----------------------------------------
860
860
861 There are multiple heads, but the racing push touch all of them
861 There are multiple heads, but the racing push touch all of them
862
862
863 # a (raced)
863 # a (raced)
864 # | b
864 # | b
865 # |/|
865 # |/|
866 # * *
866 # * *
867 # |/
867 # |/
868 # *
868 # *
869
869
870 (resync-all)
870 (resync-all)
871
871
872 #if strict
872 #if strict
873
873
874 $ hg -R ./server pull ./client-racy
874 $ hg -R ./server pull ./client-racy
875 pulling from ./client-racy
875 pulling from ./client-racy
876 searching for changes
876 searching for changes
877 adding changesets
877 adding changesets
878 adding manifests
878 adding manifests
879 adding file changes
879 adding file changes
880 added 1 changesets with 1 changes to 1 files (+1 heads)
880 added 1 changesets with 1 changes to 1 files (+1 heads)
881 new changesets 89420bf00fae (1 drafts)
881 new changesets 89420bf00fae (1 drafts)
882 (run 'hg heads .' to see heads, 'hg merge' to merge)
882 (run 'hg heads .' to see heads, 'hg merge' to merge)
883
883
884 #endif
884 #endif
885
885
886 #if unrelated
886 #if unrelated
887
887
888 $ hg -R ./server pull ./client-racy
888 $ hg -R ./server pull ./client-racy
889 pulling from ./client-racy
889 pulling from ./client-racy
890 searching for changes
890 searching for changes
891 no changes found
891 no changes found
892
892
893 #endif
893 #endif
894
894
895 $ hg -R ./client-other pull
895 $ hg -R ./client-other pull
896 pulling from ssh://user@dummy/server
896 pulling from ssh://user@dummy/server
897 searching for changes
897 searching for changes
898 adding changesets
898 adding changesets
899 adding manifests
899 adding manifests
900 adding file changes
900 adding file changes
901 added 1 changesets with 1 changes to 1 files (+1 heads)
901 added 1 changesets with 1 changes to 1 files (+1 heads)
902 new changesets 89420bf00fae (1 drafts)
902 new changesets 89420bf00fae (1 drafts)
903 (run 'hg heads' to see heads)
903 (run 'hg heads' to see heads)
904 $ hg -R ./client-racy pull
904 $ hg -R ./client-racy pull
905 pulling from ssh://user@dummy/server
905 pulling from ssh://user@dummy/server
906 searching for changes
906 searching for changes
907 adding changesets
907 adding changesets
908 adding manifests
908 adding manifests
909 adding file changes
909 adding file changes
910 added 1 changesets with 1 changes to 1 files (+1 heads)
910 added 1 changesets with 1 changes to 1 files (+1 heads)
911 new changesets b35ed749f288 (1 drafts)
911 new changesets b35ed749f288 (1 drafts)
912 (run 'hg heads .' to see heads, 'hg merge' to merge)
912 (run 'hg heads .' to see heads, 'hg merge' to merge)
913
913
914 $ hg -R server graph
914 $ hg -R server graph
915 o 89420bf00fae C-J (default)
915 o 89420bf00fae C-J (default)
916 |
916 |
917 | o b35ed749f288 C-I (my-second-test-branch)
917 | o b35ed749f288 C-I (my-second-test-branch)
918 |/
918 |/
919 o 75d69cba5402 C-G (default)
919 o 75d69cba5402 C-G (default)
920 |
920 |
921 | o 833be552cfe6 C-H (my-first-test-branch)
921 | o 833be552cfe6 C-H (my-first-test-branch)
922 |/
922 |/
923 o d9e379a8c432 C-F (default)
923 o d9e379a8c432 C-F (default)
924 |
924 |
925 o 51c544a58128 C-C (default)
925 o 51c544a58128 C-C (default)
926 |
926 |
927 | o d603e2c0cdd7 C-E (default)
927 | o d603e2c0cdd7 C-E (default)
928 |/
928 |/
929 o 98217d5a1659 C-A (default)
929 o 98217d5a1659 C-A (default)
930 |
930 |
931 | o 59e76faf78bd C-D (default)
931 | o 59e76faf78bd C-D (default)
932 | |
932 | |
933 | o a9149a1428e2 C-B (default)
933 | o a9149a1428e2 C-B (default)
934 |/
934 |/
935 @ 842e2fac6304 C-ROOT (default)
935 @ 842e2fac6304 C-ROOT (default)
936
936
937
937
938 Creating changesets
938 Creating changesets
939
939
940 (merges heads)
940 (merges heads)
941
941
942 $ hg -R client-other/ up 'desc("C-E")'
942 $ hg -R client-other/ up 'desc("C-E")'
943 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
943 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
944 $ hg -R client-other/ merge 'desc("C-D")'
944 $ hg -R client-other/ merge 'desc("C-D")'
945 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
945 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
946 (branch merge, don't forget to commit)
946 (branch merge, don't forget to commit)
947 $ hg -R client-other/ commit -m "C-K"
947 $ hg -R client-other/ commit -m "C-K"
948
948
949 (update one head)
949 (update one head)
950
950
951 $ hg -R client-racy/ up 'desc("C-D")'
951 $ hg -R client-racy/ up 'desc("C-D")'
952 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
952 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
953 $ echo bbb >> client-racy/b
953 $ echo bbb >> client-racy/b
954 $ hg -R client-racy/ commit -m "C-L"
954 $ hg -R client-racy/ commit -m "C-L"
955
955
956 Pushing
956 Pushing
957
957
958 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
958 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
959
959
960 $ waiton $TESTTMP/readyfile
960 $ waiton $TESTTMP/readyfile
961
961
962 $ hg -R client-other push -fr 'tip' --new-branch
962 $ hg -R client-other push -fr 'tip' --new-branch
963 pushing to ssh://user@dummy/server
963 pushing to ssh://user@dummy/server
964 searching for changes
964 searching for changes
965 remote: adding changesets
965 remote: adding changesets
966 remote: adding manifests
966 remote: adding manifests
967 remote: adding file changes
967 remote: adding file changes
968 remote: added 1 changesets with 0 changes to 0 files (-1 heads)
968 remote: added 1 changesets with 0 changes to 0 files (-1 heads)
969
969
970 $ release $TESTTMP/watchfile
970 $ release $TESTTMP/watchfile
971
971
972 Check the result of the push
972 Check the result of the push
973
973
974 $ cat ./push-log
974 $ cat ./push-log
975 pushing to ssh://user@dummy/server
975 pushing to ssh://user@dummy/server
976 searching for changes
976 searching for changes
977 wrote ready: $TESTTMP/readyfile
977 wrote ready: $TESTTMP/readyfile
978 waiting on: $TESTTMP/watchfile
978 waiting on: $TESTTMP/watchfile
979 abort: push failed:
979 abort: push failed:
980 'repository changed while pushing - please try again'
980 'remote repository changed while pushing - please try again'
981
981
982 $ hg -R server graph
982 $ hg -R server graph
983 o be705100c623 C-K (default)
983 o be705100c623 C-K (default)
984 |\
984 |\
985 | o d603e2c0cdd7 C-E (default)
985 | o d603e2c0cdd7 C-E (default)
986 | |
986 | |
987 o | 59e76faf78bd C-D (default)
987 o | 59e76faf78bd C-D (default)
988 | |
988 | |
989 | | o 89420bf00fae C-J (default)
989 | | o 89420bf00fae C-J (default)
990 | | |
990 | | |
991 | | | o b35ed749f288 C-I (my-second-test-branch)
991 | | | o b35ed749f288 C-I (my-second-test-branch)
992 | | |/
992 | | |/
993 | | o 75d69cba5402 C-G (default)
993 | | o 75d69cba5402 C-G (default)
994 | | |
994 | | |
995 | | | o 833be552cfe6 C-H (my-first-test-branch)
995 | | | o 833be552cfe6 C-H (my-first-test-branch)
996 | | |/
996 | | |/
997 | | o d9e379a8c432 C-F (default)
997 | | o d9e379a8c432 C-F (default)
998 | | |
998 | | |
999 | | o 51c544a58128 C-C (default)
999 | | o 51c544a58128 C-C (default)
1000 | |/
1000 | |/
1001 o | a9149a1428e2 C-B (default)
1001 o | a9149a1428e2 C-B (default)
1002 | |
1002 | |
1003 | o 98217d5a1659 C-A (default)
1003 | o 98217d5a1659 C-A (default)
1004 |/
1004 |/
1005 @ 842e2fac6304 C-ROOT (default)
1005 @ 842e2fac6304 C-ROOT (default)
1006
1006
1007
1007
1008 pushing raced push touch multiple heads
1008 pushing raced push touch multiple heads
1009 ---------------------------------------
1009 ---------------------------------------
1010
1010
1011 There are multiple heads, the raced push touch all of them
1011 There are multiple heads, the raced push touch all of them
1012
1012
1013 # b
1013 # b
1014 # | a (raced)
1014 # | a (raced)
1015 # |/|
1015 # |/|
1016 # * *
1016 # * *
1017 # |/
1017 # |/
1018 # *
1018 # *
1019
1019
1020 (resync-all)
1020 (resync-all)
1021
1021
1022 $ hg -R ./server pull ./client-racy
1022 $ hg -R ./server pull ./client-racy
1023 pulling from ./client-racy
1023 pulling from ./client-racy
1024 searching for changes
1024 searching for changes
1025 adding changesets
1025 adding changesets
1026 adding manifests
1026 adding manifests
1027 adding file changes
1027 adding file changes
1028 added 1 changesets with 1 changes to 1 files (+1 heads)
1028 added 1 changesets with 1 changes to 1 files (+1 heads)
1029 new changesets cac2cead0ff0 (1 drafts)
1029 new changesets cac2cead0ff0 (1 drafts)
1030 (run 'hg heads .' to see heads, 'hg merge' to merge)
1030 (run 'hg heads .' to see heads, 'hg merge' to merge)
1031 $ hg -R ./client-other pull
1031 $ hg -R ./client-other pull
1032 pulling from ssh://user@dummy/server
1032 pulling from ssh://user@dummy/server
1033 searching for changes
1033 searching for changes
1034 adding changesets
1034 adding changesets
1035 adding manifests
1035 adding manifests
1036 adding file changes
1036 adding file changes
1037 added 1 changesets with 1 changes to 1 files (+1 heads)
1037 added 1 changesets with 1 changes to 1 files (+1 heads)
1038 new changesets cac2cead0ff0 (1 drafts)
1038 new changesets cac2cead0ff0 (1 drafts)
1039 (run 'hg heads .' to see heads, 'hg merge' to merge)
1039 (run 'hg heads .' to see heads, 'hg merge' to merge)
1040 $ hg -R ./client-racy pull
1040 $ hg -R ./client-racy pull
1041 pulling from ssh://user@dummy/server
1041 pulling from ssh://user@dummy/server
1042 searching for changes
1042 searching for changes
1043 adding changesets
1043 adding changesets
1044 adding manifests
1044 adding manifests
1045 adding file changes
1045 adding file changes
1046 added 1 changesets with 0 changes to 0 files
1046 added 1 changesets with 0 changes to 0 files
1047 new changesets be705100c623 (1 drafts)
1047 new changesets be705100c623 (1 drafts)
1048 (run 'hg update' to get a working copy)
1048 (run 'hg update' to get a working copy)
1049
1049
1050 $ hg -R server graph
1050 $ hg -R server graph
1051 o cac2cead0ff0 C-L (default)
1051 o cac2cead0ff0 C-L (default)
1052 |
1052 |
1053 | o be705100c623 C-K (default)
1053 | o be705100c623 C-K (default)
1054 |/|
1054 |/|
1055 | o d603e2c0cdd7 C-E (default)
1055 | o d603e2c0cdd7 C-E (default)
1056 | |
1056 | |
1057 o | 59e76faf78bd C-D (default)
1057 o | 59e76faf78bd C-D (default)
1058 | |
1058 | |
1059 | | o 89420bf00fae C-J (default)
1059 | | o 89420bf00fae C-J (default)
1060 | | |
1060 | | |
1061 | | | o b35ed749f288 C-I (my-second-test-branch)
1061 | | | o b35ed749f288 C-I (my-second-test-branch)
1062 | | |/
1062 | | |/
1063 | | o 75d69cba5402 C-G (default)
1063 | | o 75d69cba5402 C-G (default)
1064 | | |
1064 | | |
1065 | | | o 833be552cfe6 C-H (my-first-test-branch)
1065 | | | o 833be552cfe6 C-H (my-first-test-branch)
1066 | | |/
1066 | | |/
1067 | | o d9e379a8c432 C-F (default)
1067 | | o d9e379a8c432 C-F (default)
1068 | | |
1068 | | |
1069 | | o 51c544a58128 C-C (default)
1069 | | o 51c544a58128 C-C (default)
1070 | |/
1070 | |/
1071 o | a9149a1428e2 C-B (default)
1071 o | a9149a1428e2 C-B (default)
1072 | |
1072 | |
1073 | o 98217d5a1659 C-A (default)
1073 | o 98217d5a1659 C-A (default)
1074 |/
1074 |/
1075 @ 842e2fac6304 C-ROOT (default)
1075 @ 842e2fac6304 C-ROOT (default)
1076
1076
1077
1077
1078 Creating changesets
1078 Creating changesets
1079
1079
1080 (update existing head)
1080 (update existing head)
1081
1081
1082 $ echo aaa >> client-other/a
1082 $ echo aaa >> client-other/a
1083 $ hg -R client-other/ commit -m "C-M"
1083 $ hg -R client-other/ commit -m "C-M"
1084
1084
1085 (merge heads)
1085 (merge heads)
1086
1086
1087 $ hg -R client-racy/ merge 'desc("C-K")'
1087 $ hg -R client-racy/ merge 'desc("C-K")'
1088 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1088 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1089 (branch merge, don't forget to commit)
1089 (branch merge, don't forget to commit)
1090 $ hg -R client-racy/ commit -m "C-N"
1090 $ hg -R client-racy/ commit -m "C-N"
1091
1091
1092 Pushing
1092 Pushing
1093
1093
1094 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1094 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1095
1095
1096 $ waiton $TESTTMP/readyfile
1096 $ waiton $TESTTMP/readyfile
1097
1097
1098 $ hg -R client-other push -fr 'tip' --new-branch
1098 $ hg -R client-other push -fr 'tip' --new-branch
1099 pushing to ssh://user@dummy/server
1099 pushing to ssh://user@dummy/server
1100 searching for changes
1100 searching for changes
1101 remote: adding changesets
1101 remote: adding changesets
1102 remote: adding manifests
1102 remote: adding manifests
1103 remote: adding file changes
1103 remote: adding file changes
1104 remote: added 1 changesets with 1 changes to 1 files
1104 remote: added 1 changesets with 1 changes to 1 files
1105
1105
1106 $ release $TESTTMP/watchfile
1106 $ release $TESTTMP/watchfile
1107
1107
1108 Check the result of the push
1108 Check the result of the push
1109
1109
1110 $ cat ./push-log
1110 $ cat ./push-log
1111 pushing to ssh://user@dummy/server
1111 pushing to ssh://user@dummy/server
1112 searching for changes
1112 searching for changes
1113 wrote ready: $TESTTMP/readyfile
1113 wrote ready: $TESTTMP/readyfile
1114 waiting on: $TESTTMP/watchfile
1114 waiting on: $TESTTMP/watchfile
1115 abort: push failed:
1115 abort: push failed:
1116 'repository changed while pushing - please try again'
1116 'remote repository changed while pushing - please try again'
1117
1117
1118 $ hg -R server graph
1118 $ hg -R server graph
1119 o 6fd3090135df C-M (default)
1119 o 6fd3090135df C-M (default)
1120 |
1120 |
1121 o be705100c623 C-K (default)
1121 o be705100c623 C-K (default)
1122 |\
1122 |\
1123 | o d603e2c0cdd7 C-E (default)
1123 | o d603e2c0cdd7 C-E (default)
1124 | |
1124 | |
1125 +---o cac2cead0ff0 C-L (default)
1125 +---o cac2cead0ff0 C-L (default)
1126 | |
1126 | |
1127 o | 59e76faf78bd C-D (default)
1127 o | 59e76faf78bd C-D (default)
1128 | |
1128 | |
1129 | | o 89420bf00fae C-J (default)
1129 | | o 89420bf00fae C-J (default)
1130 | | |
1130 | | |
1131 | | | o b35ed749f288 C-I (my-second-test-branch)
1131 | | | o b35ed749f288 C-I (my-second-test-branch)
1132 | | |/
1132 | | |/
1133 | | o 75d69cba5402 C-G (default)
1133 | | o 75d69cba5402 C-G (default)
1134 | | |
1134 | | |
1135 | | | o 833be552cfe6 C-H (my-first-test-branch)
1135 | | | o 833be552cfe6 C-H (my-first-test-branch)
1136 | | |/
1136 | | |/
1137 | | o d9e379a8c432 C-F (default)
1137 | | o d9e379a8c432 C-F (default)
1138 | | |
1138 | | |
1139 | | o 51c544a58128 C-C (default)
1139 | | o 51c544a58128 C-C (default)
1140 | |/
1140 | |/
1141 o | a9149a1428e2 C-B (default)
1141 o | a9149a1428e2 C-B (default)
1142 | |
1142 | |
1143 | o 98217d5a1659 C-A (default)
1143 | o 98217d5a1659 C-A (default)
1144 |/
1144 |/
1145 @ 842e2fac6304 C-ROOT (default)
1145 @ 842e2fac6304 C-ROOT (default)
1146
1146
1147
1147
1148 racing commit push a new head behind another named branch
1148 racing commit push a new head behind another named branch
1149 ---------------------------------------------------------
1149 ---------------------------------------------------------
1150
1150
1151 non-continuous branch are valid case, we tests for them.
1151 non-continuous branch are valid case, we tests for them.
1152
1152
1153 # b (branch default)
1153 # b (branch default)
1154 # |
1154 # |
1155 # o (branch foo)
1155 # o (branch foo)
1156 # |
1156 # |
1157 # | a (raced, branch default)
1157 # | a (raced, branch default)
1158 # |/
1158 # |/
1159 # * (branch foo)
1159 # * (branch foo)
1160 # |
1160 # |
1161 # * (branch default)
1161 # * (branch default)
1162
1162
1163 (resync-all + other branch)
1163 (resync-all + other branch)
1164
1164
1165 $ hg -R ./server pull ./client-racy
1165 $ hg -R ./server pull ./client-racy
1166 pulling from ./client-racy
1166 pulling from ./client-racy
1167 searching for changes
1167 searching for changes
1168 adding changesets
1168 adding changesets
1169 adding manifests
1169 adding manifests
1170 adding file changes
1170 adding file changes
1171 added 1 changesets with 0 changes to 0 files
1171 added 1 changesets with 0 changes to 0 files
1172 new changesets 866a66e18630 (1 drafts)
1172 new changesets 866a66e18630 (1 drafts)
1173 (run 'hg update' to get a working copy)
1173 (run 'hg update' to get a working copy)
1174
1174
1175 (creates named branch on head)
1175 (creates named branch on head)
1176
1176
1177 $ hg -R ./server/ up 'desc("C-N")'
1177 $ hg -R ./server/ up 'desc("C-N")'
1178 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1178 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1179 $ hg -R ./server/ branch other
1179 $ hg -R ./server/ branch other
1180 marked working directory as branch other
1180 marked working directory as branch other
1181 $ hg -R ./server/ ci -m "C-Z"
1181 $ hg -R ./server/ ci -m "C-Z"
1182 $ hg -R ./server/ up null
1182 $ hg -R ./server/ up null
1183 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
1183 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
1184
1184
1185 (sync client)
1185 (sync client)
1186
1186
1187 $ hg -R ./client-other pull
1187 $ hg -R ./client-other pull
1188 pulling from ssh://user@dummy/server
1188 pulling from ssh://user@dummy/server
1189 searching for changes
1189 searching for changes
1190 adding changesets
1190 adding changesets
1191 adding manifests
1191 adding manifests
1192 adding file changes
1192 adding file changes
1193 added 2 changesets with 0 changes to 0 files
1193 added 2 changesets with 0 changes to 0 files
1194 new changesets 866a66e18630:55a6f1c01b48 (2 drafts)
1194 new changesets 866a66e18630:55a6f1c01b48 (2 drafts)
1195 (run 'hg update' to get a working copy)
1195 (run 'hg update' to get a working copy)
1196 $ hg -R ./client-racy pull
1196 $ hg -R ./client-racy pull
1197 pulling from ssh://user@dummy/server
1197 pulling from ssh://user@dummy/server
1198 searching for changes
1198 searching for changes
1199 adding changesets
1199 adding changesets
1200 adding manifests
1200 adding manifests
1201 adding file changes
1201 adding file changes
1202 added 2 changesets with 1 changes to 1 files (+1 heads)
1202 added 2 changesets with 1 changes to 1 files (+1 heads)
1203 new changesets 6fd3090135df:55a6f1c01b48 (2 drafts)
1203 new changesets 6fd3090135df:55a6f1c01b48 (2 drafts)
1204 (run 'hg heads .' to see heads, 'hg merge' to merge)
1204 (run 'hg heads .' to see heads, 'hg merge' to merge)
1205
1205
1206 $ hg -R server graph
1206 $ hg -R server graph
1207 o 55a6f1c01b48 C-Z (other)
1207 o 55a6f1c01b48 C-Z (other)
1208 |
1208 |
1209 o 866a66e18630 C-N (default)
1209 o 866a66e18630 C-N (default)
1210 |\
1210 |\
1211 +---o 6fd3090135df C-M (default)
1211 +---o 6fd3090135df C-M (default)
1212 | |
1212 | |
1213 | o cac2cead0ff0 C-L (default)
1213 | o cac2cead0ff0 C-L (default)
1214 | |
1214 | |
1215 o | be705100c623 C-K (default)
1215 o | be705100c623 C-K (default)
1216 |\|
1216 |\|
1217 o | d603e2c0cdd7 C-E (default)
1217 o | d603e2c0cdd7 C-E (default)
1218 | |
1218 | |
1219 | o 59e76faf78bd C-D (default)
1219 | o 59e76faf78bd C-D (default)
1220 | |
1220 | |
1221 | | o 89420bf00fae C-J (default)
1221 | | o 89420bf00fae C-J (default)
1222 | | |
1222 | | |
1223 | | | o b35ed749f288 C-I (my-second-test-branch)
1223 | | | o b35ed749f288 C-I (my-second-test-branch)
1224 | | |/
1224 | | |/
1225 | | o 75d69cba5402 C-G (default)
1225 | | o 75d69cba5402 C-G (default)
1226 | | |
1226 | | |
1227 | | | o 833be552cfe6 C-H (my-first-test-branch)
1227 | | | o 833be552cfe6 C-H (my-first-test-branch)
1228 | | |/
1228 | | |/
1229 | | o d9e379a8c432 C-F (default)
1229 | | o d9e379a8c432 C-F (default)
1230 | | |
1230 | | |
1231 +---o 51c544a58128 C-C (default)
1231 +---o 51c544a58128 C-C (default)
1232 | |
1232 | |
1233 | o a9149a1428e2 C-B (default)
1233 | o a9149a1428e2 C-B (default)
1234 | |
1234 | |
1235 o | 98217d5a1659 C-A (default)
1235 o | 98217d5a1659 C-A (default)
1236 |/
1236 |/
1237 o 842e2fac6304 C-ROOT (default)
1237 o 842e2fac6304 C-ROOT (default)
1238
1238
1239
1239
1240 Creating changesets
1240 Creating changesets
1241
1241
1242 (update default head through another named branch one)
1242 (update default head through another named branch one)
1243
1243
1244 $ hg -R client-other/ up 'desc("C-Z")'
1244 $ hg -R client-other/ up 'desc("C-Z")'
1245 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1245 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1246 $ echo aaa >> client-other/a
1246 $ echo aaa >> client-other/a
1247 $ hg -R client-other/ commit -m "C-O"
1247 $ hg -R client-other/ commit -m "C-O"
1248 $ echo aaa >> client-other/a
1248 $ echo aaa >> client-other/a
1249 $ hg -R client-other/ branch --force default
1249 $ hg -R client-other/ branch --force default
1250 marked working directory as branch default
1250 marked working directory as branch default
1251 $ hg -R client-other/ commit -m "C-P"
1251 $ hg -R client-other/ commit -m "C-P"
1252 created new head
1252 created new head
1253
1253
1254 (update default head)
1254 (update default head)
1255
1255
1256 $ hg -R client-racy/ up 'desc("C-Z")'
1256 $ hg -R client-racy/ up 'desc("C-Z")'
1257 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1257 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1258 $ echo bbb >> client-other/a
1258 $ echo bbb >> client-other/a
1259 $ hg -R client-racy/ branch --force default
1259 $ hg -R client-racy/ branch --force default
1260 marked working directory as branch default
1260 marked working directory as branch default
1261 $ hg -R client-racy/ commit -m "C-Q"
1261 $ hg -R client-racy/ commit -m "C-Q"
1262 created new head
1262 created new head
1263
1263
1264 Pushing
1264 Pushing
1265
1265
1266 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1266 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1267
1267
1268 $ waiton $TESTTMP/readyfile
1268 $ waiton $TESTTMP/readyfile
1269
1269
1270 $ hg -R client-other push -fr 'tip' --new-branch
1270 $ hg -R client-other push -fr 'tip' --new-branch
1271 pushing to ssh://user@dummy/server
1271 pushing to ssh://user@dummy/server
1272 searching for changes
1272 searching for changes
1273 remote: adding changesets
1273 remote: adding changesets
1274 remote: adding manifests
1274 remote: adding manifests
1275 remote: adding file changes
1275 remote: adding file changes
1276 remote: added 2 changesets with 1 changes to 1 files
1276 remote: added 2 changesets with 1 changes to 1 files
1277
1277
1278 $ release $TESTTMP/watchfile
1278 $ release $TESTTMP/watchfile
1279
1279
1280 Check the result of the push
1280 Check the result of the push
1281
1281
1282 $ cat ./push-log
1282 $ cat ./push-log
1283 pushing to ssh://user@dummy/server
1283 pushing to ssh://user@dummy/server
1284 searching for changes
1284 searching for changes
1285 wrote ready: $TESTTMP/readyfile
1285 wrote ready: $TESTTMP/readyfile
1286 waiting on: $TESTTMP/watchfile
1286 waiting on: $TESTTMP/watchfile
1287 abort: push failed:
1287 abort: push failed:
1288 'repository changed while pushing - please try again'
1288 'remote repository changed while pushing - please try again'
1289
1289
1290 $ hg -R server graph
1290 $ hg -R server graph
1291 o 1b58ee3f79e5 C-P (default)
1291 o 1b58ee3f79e5 C-P (default)
1292 |
1292 |
1293 o d0a85b2252a9 C-O (other)
1293 o d0a85b2252a9 C-O (other)
1294 |
1294 |
1295 o 55a6f1c01b48 C-Z (other)
1295 o 55a6f1c01b48 C-Z (other)
1296 |
1296 |
1297 o 866a66e18630 C-N (default)
1297 o 866a66e18630 C-N (default)
1298 |\
1298 |\
1299 +---o 6fd3090135df C-M (default)
1299 +---o 6fd3090135df C-M (default)
1300 | |
1300 | |
1301 | o cac2cead0ff0 C-L (default)
1301 | o cac2cead0ff0 C-L (default)
1302 | |
1302 | |
1303 o | be705100c623 C-K (default)
1303 o | be705100c623 C-K (default)
1304 |\|
1304 |\|
1305 o | d603e2c0cdd7 C-E (default)
1305 o | d603e2c0cdd7 C-E (default)
1306 | |
1306 | |
1307 | o 59e76faf78bd C-D (default)
1307 | o 59e76faf78bd C-D (default)
1308 | |
1308 | |
1309 | | o 89420bf00fae C-J (default)
1309 | | o 89420bf00fae C-J (default)
1310 | | |
1310 | | |
1311 | | | o b35ed749f288 C-I (my-second-test-branch)
1311 | | | o b35ed749f288 C-I (my-second-test-branch)
1312 | | |/
1312 | | |/
1313 | | o 75d69cba5402 C-G (default)
1313 | | o 75d69cba5402 C-G (default)
1314 | | |
1314 | | |
1315 | | | o 833be552cfe6 C-H (my-first-test-branch)
1315 | | | o 833be552cfe6 C-H (my-first-test-branch)
1316 | | |/
1316 | | |/
1317 | | o d9e379a8c432 C-F (default)
1317 | | o d9e379a8c432 C-F (default)
1318 | | |
1318 | | |
1319 +---o 51c544a58128 C-C (default)
1319 +---o 51c544a58128 C-C (default)
1320 | |
1320 | |
1321 | o a9149a1428e2 C-B (default)
1321 | o a9149a1428e2 C-B (default)
1322 | |
1322 | |
1323 o | 98217d5a1659 C-A (default)
1323 o | 98217d5a1659 C-A (default)
1324 |/
1324 |/
1325 o 842e2fac6304 C-ROOT (default)
1325 o 842e2fac6304 C-ROOT (default)
1326
1326
1327
1327
1328 raced commit push a new head behind another named branch
1328 raced commit push a new head behind another named branch
1329 ---------------------------------------------------------
1329 ---------------------------------------------------------
1330
1330
1331 non-continuous branch are valid case, we tests for them.
1331 non-continuous branch are valid case, we tests for them.
1332
1332
1333 # b (raced branch default)
1333 # b (raced branch default)
1334 # |
1334 # |
1335 # o (branch foo)
1335 # o (branch foo)
1336 # |
1336 # |
1337 # | a (branch default)
1337 # | a (branch default)
1338 # |/
1338 # |/
1339 # * (branch foo)
1339 # * (branch foo)
1340 # |
1340 # |
1341 # * (branch default)
1341 # * (branch default)
1342
1342
1343 (resync-all)
1343 (resync-all)
1344
1344
1345 $ hg -R ./server pull ./client-racy
1345 $ hg -R ./server pull ./client-racy
1346 pulling from ./client-racy
1346 pulling from ./client-racy
1347 searching for changes
1347 searching for changes
1348 adding changesets
1348 adding changesets
1349 adding manifests
1349 adding manifests
1350 adding file changes
1350 adding file changes
1351 added 1 changesets with 0 changes to 0 files (+1 heads)
1351 added 1 changesets with 0 changes to 0 files (+1 heads)
1352 new changesets b0ee3d6f51bc (1 drafts)
1352 new changesets b0ee3d6f51bc (1 drafts)
1353 (run 'hg heads .' to see heads, 'hg merge' to merge)
1353 (run 'hg heads .' to see heads, 'hg merge' to merge)
1354 $ hg -R ./client-other pull
1354 $ hg -R ./client-other pull
1355 pulling from ssh://user@dummy/server
1355 pulling from ssh://user@dummy/server
1356 searching for changes
1356 searching for changes
1357 adding changesets
1357 adding changesets
1358 adding manifests
1358 adding manifests
1359 adding file changes
1359 adding file changes
1360 added 1 changesets with 0 changes to 0 files (+1 heads)
1360 added 1 changesets with 0 changes to 0 files (+1 heads)
1361 new changesets b0ee3d6f51bc (1 drafts)
1361 new changesets b0ee3d6f51bc (1 drafts)
1362 (run 'hg heads .' to see heads, 'hg merge' to merge)
1362 (run 'hg heads .' to see heads, 'hg merge' to merge)
1363 $ hg -R ./client-racy pull
1363 $ hg -R ./client-racy pull
1364 pulling from ssh://user@dummy/server
1364 pulling from ssh://user@dummy/server
1365 searching for changes
1365 searching for changes
1366 adding changesets
1366 adding changesets
1367 adding manifests
1367 adding manifests
1368 adding file changes
1368 adding file changes
1369 added 2 changesets with 1 changes to 1 files (+1 heads)
1369 added 2 changesets with 1 changes to 1 files (+1 heads)
1370 new changesets d0a85b2252a9:1b58ee3f79e5 (2 drafts)
1370 new changesets d0a85b2252a9:1b58ee3f79e5 (2 drafts)
1371 (run 'hg heads .' to see heads, 'hg merge' to merge)
1371 (run 'hg heads .' to see heads, 'hg merge' to merge)
1372
1372
1373 $ hg -R server graph
1373 $ hg -R server graph
1374 o b0ee3d6f51bc C-Q (default)
1374 o b0ee3d6f51bc C-Q (default)
1375 |
1375 |
1376 | o 1b58ee3f79e5 C-P (default)
1376 | o 1b58ee3f79e5 C-P (default)
1377 | |
1377 | |
1378 | o d0a85b2252a9 C-O (other)
1378 | o d0a85b2252a9 C-O (other)
1379 |/
1379 |/
1380 o 55a6f1c01b48 C-Z (other)
1380 o 55a6f1c01b48 C-Z (other)
1381 |
1381 |
1382 o 866a66e18630 C-N (default)
1382 o 866a66e18630 C-N (default)
1383 |\
1383 |\
1384 +---o 6fd3090135df C-M (default)
1384 +---o 6fd3090135df C-M (default)
1385 | |
1385 | |
1386 | o cac2cead0ff0 C-L (default)
1386 | o cac2cead0ff0 C-L (default)
1387 | |
1387 | |
1388 o | be705100c623 C-K (default)
1388 o | be705100c623 C-K (default)
1389 |\|
1389 |\|
1390 o | d603e2c0cdd7 C-E (default)
1390 o | d603e2c0cdd7 C-E (default)
1391 | |
1391 | |
1392 | o 59e76faf78bd C-D (default)
1392 | o 59e76faf78bd C-D (default)
1393 | |
1393 | |
1394 | | o 89420bf00fae C-J (default)
1394 | | o 89420bf00fae C-J (default)
1395 | | |
1395 | | |
1396 | | | o b35ed749f288 C-I (my-second-test-branch)
1396 | | | o b35ed749f288 C-I (my-second-test-branch)
1397 | | |/
1397 | | |/
1398 | | o 75d69cba5402 C-G (default)
1398 | | o 75d69cba5402 C-G (default)
1399 | | |
1399 | | |
1400 | | | o 833be552cfe6 C-H (my-first-test-branch)
1400 | | | o 833be552cfe6 C-H (my-first-test-branch)
1401 | | |/
1401 | | |/
1402 | | o d9e379a8c432 C-F (default)
1402 | | o d9e379a8c432 C-F (default)
1403 | | |
1403 | | |
1404 +---o 51c544a58128 C-C (default)
1404 +---o 51c544a58128 C-C (default)
1405 | |
1405 | |
1406 | o a9149a1428e2 C-B (default)
1406 | o a9149a1428e2 C-B (default)
1407 | |
1407 | |
1408 o | 98217d5a1659 C-A (default)
1408 o | 98217d5a1659 C-A (default)
1409 |/
1409 |/
1410 o 842e2fac6304 C-ROOT (default)
1410 o 842e2fac6304 C-ROOT (default)
1411
1411
1412
1412
1413 Creating changesets
1413 Creating changesets
1414
1414
1415 (update 'other' named branch head)
1415 (update 'other' named branch head)
1416
1416
1417 $ hg -R client-other/ up 'desc("C-P")'
1417 $ hg -R client-other/ up 'desc("C-P")'
1418 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1418 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1419 $ echo aaa >> client-other/a
1419 $ echo aaa >> client-other/a
1420 $ hg -R client-other/ branch --force other
1420 $ hg -R client-other/ branch --force other
1421 marked working directory as branch other
1421 marked working directory as branch other
1422 $ hg -R client-other/ commit -m "C-R"
1422 $ hg -R client-other/ commit -m "C-R"
1423 created new head
1423 created new head
1424
1424
1425 (update 'other named brnach through a 'default' changeset')
1425 (update 'other named brnach through a 'default' changeset')
1426
1426
1427 $ hg -R client-racy/ up 'desc("C-P")'
1427 $ hg -R client-racy/ up 'desc("C-P")'
1428 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1428 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1429 $ echo bbb >> client-racy/a
1429 $ echo bbb >> client-racy/a
1430 $ hg -R client-racy/ commit -m "C-S"
1430 $ hg -R client-racy/ commit -m "C-S"
1431 $ echo bbb >> client-racy/a
1431 $ echo bbb >> client-racy/a
1432 $ hg -R client-racy/ branch --force other
1432 $ hg -R client-racy/ branch --force other
1433 marked working directory as branch other
1433 marked working directory as branch other
1434 $ hg -R client-racy/ commit -m "C-T"
1434 $ hg -R client-racy/ commit -m "C-T"
1435 created new head
1435 created new head
1436
1436
1437 Pushing
1437 Pushing
1438
1438
1439 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1439 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1440
1440
1441 $ waiton $TESTTMP/readyfile
1441 $ waiton $TESTTMP/readyfile
1442
1442
1443 $ hg -R client-other push -fr 'tip' --new-branch
1443 $ hg -R client-other push -fr 'tip' --new-branch
1444 pushing to ssh://user@dummy/server
1444 pushing to ssh://user@dummy/server
1445 searching for changes
1445 searching for changes
1446 remote: adding changesets
1446 remote: adding changesets
1447 remote: adding manifests
1447 remote: adding manifests
1448 remote: adding file changes
1448 remote: adding file changes
1449 remote: added 1 changesets with 1 changes to 1 files
1449 remote: added 1 changesets with 1 changes to 1 files
1450
1450
1451 $ release $TESTTMP/watchfile
1451 $ release $TESTTMP/watchfile
1452
1452
1453 Check the result of the push
1453 Check the result of the push
1454
1454
1455 $ cat ./push-log
1455 $ cat ./push-log
1456 pushing to ssh://user@dummy/server
1456 pushing to ssh://user@dummy/server
1457 searching for changes
1457 searching for changes
1458 wrote ready: $TESTTMP/readyfile
1458 wrote ready: $TESTTMP/readyfile
1459 waiting on: $TESTTMP/watchfile
1459 waiting on: $TESTTMP/watchfile
1460 abort: push failed:
1460 abort: push failed:
1461 'repository changed while pushing - please try again'
1461 'remote repository changed while pushing - please try again'
1462
1462
1463 $ hg -R server graph
1463 $ hg -R server graph
1464 o de7b9e2ba3f6 C-R (other)
1464 o de7b9e2ba3f6 C-R (other)
1465 |
1465 |
1466 o 1b58ee3f79e5 C-P (default)
1466 o 1b58ee3f79e5 C-P (default)
1467 |
1467 |
1468 o d0a85b2252a9 C-O (other)
1468 o d0a85b2252a9 C-O (other)
1469 |
1469 |
1470 | o b0ee3d6f51bc C-Q (default)
1470 | o b0ee3d6f51bc C-Q (default)
1471 |/
1471 |/
1472 o 55a6f1c01b48 C-Z (other)
1472 o 55a6f1c01b48 C-Z (other)
1473 |
1473 |
1474 o 866a66e18630 C-N (default)
1474 o 866a66e18630 C-N (default)
1475 |\
1475 |\
1476 +---o 6fd3090135df C-M (default)
1476 +---o 6fd3090135df C-M (default)
1477 | |
1477 | |
1478 | o cac2cead0ff0 C-L (default)
1478 | o cac2cead0ff0 C-L (default)
1479 | |
1479 | |
1480 o | be705100c623 C-K (default)
1480 o | be705100c623 C-K (default)
1481 |\|
1481 |\|
1482 o | d603e2c0cdd7 C-E (default)
1482 o | d603e2c0cdd7 C-E (default)
1483 | |
1483 | |
1484 | o 59e76faf78bd C-D (default)
1484 | o 59e76faf78bd C-D (default)
1485 | |
1485 | |
1486 | | o 89420bf00fae C-J (default)
1486 | | o 89420bf00fae C-J (default)
1487 | | |
1487 | | |
1488 | | | o b35ed749f288 C-I (my-second-test-branch)
1488 | | | o b35ed749f288 C-I (my-second-test-branch)
1489 | | |/
1489 | | |/
1490 | | o 75d69cba5402 C-G (default)
1490 | | o 75d69cba5402 C-G (default)
1491 | | |
1491 | | |
1492 | | | o 833be552cfe6 C-H (my-first-test-branch)
1492 | | | o 833be552cfe6 C-H (my-first-test-branch)
1493 | | |/
1493 | | |/
1494 | | o d9e379a8c432 C-F (default)
1494 | | o d9e379a8c432 C-F (default)
1495 | | |
1495 | | |
1496 +---o 51c544a58128 C-C (default)
1496 +---o 51c544a58128 C-C (default)
1497 | |
1497 | |
1498 | o a9149a1428e2 C-B (default)
1498 | o a9149a1428e2 C-B (default)
1499 | |
1499 | |
1500 o | 98217d5a1659 C-A (default)
1500 o | 98217d5a1659 C-A (default)
1501 |/
1501 |/
1502 o 842e2fac6304 C-ROOT (default)
1502 o 842e2fac6304 C-ROOT (default)
1503
1503
1504
1504
1505 raced commit push a new head obsoleting the one touched by the racing push
1505 raced commit push a new head obsoleting the one touched by the racing push
1506 --------------------------------------------------------------------------
1506 --------------------------------------------------------------------------
1507
1507
1508 # b (racing)
1508 # b (racing)
1509 # |
1509 # |
1510 # ΓΈβ‡ β—” a (raced)
1510 # ΓΈβ‡ β—” a (raced)
1511 # |/
1511 # |/
1512 # *
1512 # *
1513
1513
1514 (resync-all)
1514 (resync-all)
1515
1515
1516 $ hg -R ./server pull ./client-racy
1516 $ hg -R ./server pull ./client-racy
1517 pulling from ./client-racy
1517 pulling from ./client-racy
1518 searching for changes
1518 searching for changes
1519 adding changesets
1519 adding changesets
1520 adding manifests
1520 adding manifests
1521 adding file changes
1521 adding file changes
1522 added 2 changesets with 2 changes to 1 files (+1 heads)
1522 added 2 changesets with 2 changes to 1 files (+1 heads)
1523 new changesets 2efd43f7b5ba:3d57ed3c1091 (2 drafts)
1523 new changesets 2efd43f7b5ba:3d57ed3c1091 (2 drafts)
1524 (run 'hg heads .' to see heads, 'hg merge' to merge)
1524 (run 'hg heads .' to see heads, 'hg merge' to merge)
1525 $ hg -R ./client-other pull
1525 $ hg -R ./client-other pull
1526 pulling from ssh://user@dummy/server
1526 pulling from ssh://user@dummy/server
1527 searching for changes
1527 searching for changes
1528 adding changesets
1528 adding changesets
1529 adding manifests
1529 adding manifests
1530 adding file changes
1530 adding file changes
1531 added 2 changesets with 2 changes to 1 files (+1 heads)
1531 added 2 changesets with 2 changes to 1 files (+1 heads)
1532 new changesets 2efd43f7b5ba:3d57ed3c1091 (2 drafts)
1532 new changesets 2efd43f7b5ba:3d57ed3c1091 (2 drafts)
1533 (run 'hg heads' to see heads, 'hg merge' to merge)
1533 (run 'hg heads' to see heads, 'hg merge' to merge)
1534 $ hg -R ./client-racy pull
1534 $ hg -R ./client-racy pull
1535 pulling from ssh://user@dummy/server
1535 pulling from ssh://user@dummy/server
1536 searching for changes
1536 searching for changes
1537 adding changesets
1537 adding changesets
1538 adding manifests
1538 adding manifests
1539 adding file changes
1539 adding file changes
1540 added 1 changesets with 1 changes to 1 files (+1 heads)
1540 added 1 changesets with 1 changes to 1 files (+1 heads)
1541 new changesets de7b9e2ba3f6 (1 drafts)
1541 new changesets de7b9e2ba3f6 (1 drafts)
1542 (run 'hg heads' to see heads, 'hg merge' to merge)
1542 (run 'hg heads' to see heads, 'hg merge' to merge)
1543
1543
1544 $ hg -R server graph
1544 $ hg -R server graph
1545 o 3d57ed3c1091 C-T (other)
1545 o 3d57ed3c1091 C-T (other)
1546 |
1546 |
1547 o 2efd43f7b5ba C-S (default)
1547 o 2efd43f7b5ba C-S (default)
1548 |
1548 |
1549 | o de7b9e2ba3f6 C-R (other)
1549 | o de7b9e2ba3f6 C-R (other)
1550 |/
1550 |/
1551 o 1b58ee3f79e5 C-P (default)
1551 o 1b58ee3f79e5 C-P (default)
1552 |
1552 |
1553 o d0a85b2252a9 C-O (other)
1553 o d0a85b2252a9 C-O (other)
1554 |
1554 |
1555 | o b0ee3d6f51bc C-Q (default)
1555 | o b0ee3d6f51bc C-Q (default)
1556 |/
1556 |/
1557 o 55a6f1c01b48 C-Z (other)
1557 o 55a6f1c01b48 C-Z (other)
1558 |
1558 |
1559 o 866a66e18630 C-N (default)
1559 o 866a66e18630 C-N (default)
1560 |\
1560 |\
1561 +---o 6fd3090135df C-M (default)
1561 +---o 6fd3090135df C-M (default)
1562 | |
1562 | |
1563 | o cac2cead0ff0 C-L (default)
1563 | o cac2cead0ff0 C-L (default)
1564 | |
1564 | |
1565 o | be705100c623 C-K (default)
1565 o | be705100c623 C-K (default)
1566 |\|
1566 |\|
1567 o | d603e2c0cdd7 C-E (default)
1567 o | d603e2c0cdd7 C-E (default)
1568 | |
1568 | |
1569 | o 59e76faf78bd C-D (default)
1569 | o 59e76faf78bd C-D (default)
1570 | |
1570 | |
1571 | | o 89420bf00fae C-J (default)
1571 | | o 89420bf00fae C-J (default)
1572 | | |
1572 | | |
1573 | | | o b35ed749f288 C-I (my-second-test-branch)
1573 | | | o b35ed749f288 C-I (my-second-test-branch)
1574 | | |/
1574 | | |/
1575 | | o 75d69cba5402 C-G (default)
1575 | | o 75d69cba5402 C-G (default)
1576 | | |
1576 | | |
1577 | | | o 833be552cfe6 C-H (my-first-test-branch)
1577 | | | o 833be552cfe6 C-H (my-first-test-branch)
1578 | | |/
1578 | | |/
1579 | | o d9e379a8c432 C-F (default)
1579 | | o d9e379a8c432 C-F (default)
1580 | | |
1580 | | |
1581 +---o 51c544a58128 C-C (default)
1581 +---o 51c544a58128 C-C (default)
1582 | |
1582 | |
1583 | o a9149a1428e2 C-B (default)
1583 | o a9149a1428e2 C-B (default)
1584 | |
1584 | |
1585 o | 98217d5a1659 C-A (default)
1585 o | 98217d5a1659 C-A (default)
1586 |/
1586 |/
1587 o 842e2fac6304 C-ROOT (default)
1587 o 842e2fac6304 C-ROOT (default)
1588
1588
1589
1589
1590 Creating changesets and markers
1590 Creating changesets and markers
1591
1591
1592 (continue existing head)
1592 (continue existing head)
1593
1593
1594 $ hg -R client-other/ up 'desc("C-Q")'
1594 $ hg -R client-other/ up 'desc("C-Q")'
1595 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1595 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1596 $ echo aaa >> client-other/a
1596 $ echo aaa >> client-other/a
1597 $ hg -R client-other/ commit -m "C-U"
1597 $ hg -R client-other/ commit -m "C-U"
1598
1598
1599 (new topo branch obsoleting that same head)
1599 (new topo branch obsoleting that same head)
1600
1600
1601 $ hg -R client-racy/ up 'desc("C-Z")'
1601 $ hg -R client-racy/ up 'desc("C-Z")'
1602 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1602 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1603 $ echo bbb >> client-racy/a
1603 $ echo bbb >> client-racy/a
1604 $ hg -R client-racy/ branch --force default
1604 $ hg -R client-racy/ branch --force default
1605 marked working directory as branch default
1605 marked working directory as branch default
1606 $ hg -R client-racy/ commit -m "C-V"
1606 $ hg -R client-racy/ commit -m "C-V"
1607 created new head
1607 created new head
1608 $ ID_Q=`hg -R client-racy log -T '{node}\n' -r 'desc("C-Q")'`
1608 $ ID_Q=`hg -R client-racy log -T '{node}\n' -r 'desc("C-Q")'`
1609 $ ID_V=`hg -R client-racy log -T '{node}\n' -r 'desc("C-V")'`
1609 $ ID_V=`hg -R client-racy log -T '{node}\n' -r 'desc("C-V")'`
1610 $ hg -R client-racy debugobsolete $ID_Q $ID_V
1610 $ hg -R client-racy debugobsolete $ID_Q $ID_V
1611 obsoleted 1 changesets
1611 obsoleted 1 changesets
1612
1612
1613 Pushing
1613 Pushing
1614
1614
1615 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1615 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1616
1616
1617 $ waiton $TESTTMP/readyfile
1617 $ waiton $TESTTMP/readyfile
1618
1618
1619 $ hg -R client-other push -fr 'tip' --new-branch
1619 $ hg -R client-other push -fr 'tip' --new-branch
1620 pushing to ssh://user@dummy/server
1620 pushing to ssh://user@dummy/server
1621 searching for changes
1621 searching for changes
1622 remote: adding changesets
1622 remote: adding changesets
1623 remote: adding manifests
1623 remote: adding manifests
1624 remote: adding file changes
1624 remote: adding file changes
1625 remote: added 1 changesets with 0 changes to 0 files
1625 remote: added 1 changesets with 0 changes to 0 files
1626
1626
1627 $ release $TESTTMP/watchfile
1627 $ release $TESTTMP/watchfile
1628
1628
1629 Check the result of the push
1629 Check the result of the push
1630
1630
1631 $ cat ./push-log
1631 $ cat ./push-log
1632 pushing to ssh://user@dummy/server
1632 pushing to ssh://user@dummy/server
1633 searching for changes
1633 searching for changes
1634 wrote ready: $TESTTMP/readyfile
1634 wrote ready: $TESTTMP/readyfile
1635 waiting on: $TESTTMP/watchfile
1635 waiting on: $TESTTMP/watchfile
1636 abort: push failed:
1636 abort: push failed:
1637 'repository changed while pushing - please try again'
1637 'remote repository changed while pushing - please try again'
1638
1638
1639 $ hg -R server debugobsolete
1639 $ hg -R server debugobsolete
1640 $ hg -R server graph
1640 $ hg -R server graph
1641 o a98a47d8b85b C-U (default)
1641 o a98a47d8b85b C-U (default)
1642 |
1642 |
1643 o b0ee3d6f51bc C-Q (default)
1643 o b0ee3d6f51bc C-Q (default)
1644 |
1644 |
1645 | o 3d57ed3c1091 C-T (other)
1645 | o 3d57ed3c1091 C-T (other)
1646 | |
1646 | |
1647 | o 2efd43f7b5ba C-S (default)
1647 | o 2efd43f7b5ba C-S (default)
1648 | |
1648 | |
1649 | | o de7b9e2ba3f6 C-R (other)
1649 | | o de7b9e2ba3f6 C-R (other)
1650 | |/
1650 | |/
1651 | o 1b58ee3f79e5 C-P (default)
1651 | o 1b58ee3f79e5 C-P (default)
1652 | |
1652 | |
1653 | o d0a85b2252a9 C-O (other)
1653 | o d0a85b2252a9 C-O (other)
1654 |/
1654 |/
1655 o 55a6f1c01b48 C-Z (other)
1655 o 55a6f1c01b48 C-Z (other)
1656 |
1656 |
1657 o 866a66e18630 C-N (default)
1657 o 866a66e18630 C-N (default)
1658 |\
1658 |\
1659 +---o 6fd3090135df C-M (default)
1659 +---o 6fd3090135df C-M (default)
1660 | |
1660 | |
1661 | o cac2cead0ff0 C-L (default)
1661 | o cac2cead0ff0 C-L (default)
1662 | |
1662 | |
1663 o | be705100c623 C-K (default)
1663 o | be705100c623 C-K (default)
1664 |\|
1664 |\|
1665 o | d603e2c0cdd7 C-E (default)
1665 o | d603e2c0cdd7 C-E (default)
1666 | |
1666 | |
1667 | o 59e76faf78bd C-D (default)
1667 | o 59e76faf78bd C-D (default)
1668 | |
1668 | |
1669 | | o 89420bf00fae C-J (default)
1669 | | o 89420bf00fae C-J (default)
1670 | | |
1670 | | |
1671 | | | o b35ed749f288 C-I (my-second-test-branch)
1671 | | | o b35ed749f288 C-I (my-second-test-branch)
1672 | | |/
1672 | | |/
1673 | | o 75d69cba5402 C-G (default)
1673 | | o 75d69cba5402 C-G (default)
1674 | | |
1674 | | |
1675 | | | o 833be552cfe6 C-H (my-first-test-branch)
1675 | | | o 833be552cfe6 C-H (my-first-test-branch)
1676 | | |/
1676 | | |/
1677 | | o d9e379a8c432 C-F (default)
1677 | | o d9e379a8c432 C-F (default)
1678 | | |
1678 | | |
1679 +---o 51c544a58128 C-C (default)
1679 +---o 51c544a58128 C-C (default)
1680 | |
1680 | |
1681 | o a9149a1428e2 C-B (default)
1681 | o a9149a1428e2 C-B (default)
1682 | |
1682 | |
1683 o | 98217d5a1659 C-A (default)
1683 o | 98217d5a1659 C-A (default)
1684 |/
1684 |/
1685 o 842e2fac6304 C-ROOT (default)
1685 o 842e2fac6304 C-ROOT (default)
1686
1686
1687
1687
1688 racing commit push a new head obsoleting the one touched by the raced push
1688 racing commit push a new head obsoleting the one touched by the raced push
1689 --------------------------------------------------------------------------
1689 --------------------------------------------------------------------------
1690
1690
1691 (mirror test case of the previous one
1691 (mirror test case of the previous one
1692
1692
1693 # a (raced branch default)
1693 # a (raced branch default)
1694 # |
1694 # |
1695 # ΓΈβ‡ β—” b (racing)
1695 # ΓΈβ‡ β—” b (racing)
1696 # |/
1696 # |/
1697 # *
1697 # *
1698
1698
1699 (resync-all)
1699 (resync-all)
1700
1700
1701 $ hg -R ./server pull ./client-racy
1701 $ hg -R ./server pull ./client-racy
1702 pulling from ./client-racy
1702 pulling from ./client-racy
1703 searching for changes
1703 searching for changes
1704 adding changesets
1704 adding changesets
1705 adding manifests
1705 adding manifests
1706 adding file changes
1706 adding file changes
1707 added 1 changesets with 1 changes to 1 files (+1 heads)
1707 added 1 changesets with 1 changes to 1 files (+1 heads)
1708 1 new obsolescence markers
1708 1 new obsolescence markers
1709 obsoleted 1 changesets
1709 obsoleted 1 changesets
1710 1 new orphan changesets
1710 1 new orphan changesets
1711 new changesets 720c5163ecf6 (1 drafts)
1711 new changesets 720c5163ecf6 (1 drafts)
1712 (run 'hg heads .' to see heads, 'hg merge' to merge)
1712 (run 'hg heads .' to see heads, 'hg merge' to merge)
1713 $ hg -R ./client-other pull
1713 $ hg -R ./client-other pull
1714 pulling from ssh://user@dummy/server
1714 pulling from ssh://user@dummy/server
1715 searching for changes
1715 searching for changes
1716 adding changesets
1716 adding changesets
1717 adding manifests
1717 adding manifests
1718 adding file changes
1718 adding file changes
1719 added 1 changesets with 1 changes to 1 files (+1 heads)
1719 added 1 changesets with 1 changes to 1 files (+1 heads)
1720 1 new obsolescence markers
1720 1 new obsolescence markers
1721 obsoleted 1 changesets
1721 obsoleted 1 changesets
1722 1 new orphan changesets
1722 1 new orphan changesets
1723 new changesets 720c5163ecf6 (1 drafts)
1723 new changesets 720c5163ecf6 (1 drafts)
1724 (run 'hg heads .' to see heads, 'hg merge' to merge)
1724 (run 'hg heads .' to see heads, 'hg merge' to merge)
1725 $ hg -R ./client-racy pull
1725 $ hg -R ./client-racy pull
1726 pulling from ssh://user@dummy/server
1726 pulling from ssh://user@dummy/server
1727 searching for changes
1727 searching for changes
1728 adding changesets
1728 adding changesets
1729 adding manifests
1729 adding manifests
1730 adding file changes
1730 adding file changes
1731 added 1 changesets with 0 changes to 0 files
1731 added 1 changesets with 0 changes to 0 files
1732 1 new orphan changesets
1732 1 new orphan changesets
1733 new changesets a98a47d8b85b (1 drafts)
1733 new changesets a98a47d8b85b (1 drafts)
1734 (run 'hg update' to get a working copy)
1734 (run 'hg update' to get a working copy)
1735
1735
1736 $ hg -R server debugobsolete
1736 $ hg -R server debugobsolete
1737 b0ee3d6f51bc4c0ca6d4f2907708027a6c376233 720c5163ecf64dcc6216bee2d62bf3edb1882499 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1737 b0ee3d6f51bc4c0ca6d4f2907708027a6c376233 720c5163ecf64dcc6216bee2d62bf3edb1882499 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1738 $ hg -R server graph
1738 $ hg -R server graph
1739 o 720c5163ecf6 C-V (default)
1739 o 720c5163ecf6 C-V (default)
1740 |
1740 |
1741 | * a98a47d8b85b C-U (default)
1741 | * a98a47d8b85b C-U (default)
1742 | |
1742 | |
1743 | x b0ee3d6f51bc C-Q (default)
1743 | x b0ee3d6f51bc C-Q (default)
1744 |/
1744 |/
1745 | o 3d57ed3c1091 C-T (other)
1745 | o 3d57ed3c1091 C-T (other)
1746 | |
1746 | |
1747 | o 2efd43f7b5ba C-S (default)
1747 | o 2efd43f7b5ba C-S (default)
1748 | |
1748 | |
1749 | | o de7b9e2ba3f6 C-R (other)
1749 | | o de7b9e2ba3f6 C-R (other)
1750 | |/
1750 | |/
1751 | o 1b58ee3f79e5 C-P (default)
1751 | o 1b58ee3f79e5 C-P (default)
1752 | |
1752 | |
1753 | o d0a85b2252a9 C-O (other)
1753 | o d0a85b2252a9 C-O (other)
1754 |/
1754 |/
1755 o 55a6f1c01b48 C-Z (other)
1755 o 55a6f1c01b48 C-Z (other)
1756 |
1756 |
1757 o 866a66e18630 C-N (default)
1757 o 866a66e18630 C-N (default)
1758 |\
1758 |\
1759 +---o 6fd3090135df C-M (default)
1759 +---o 6fd3090135df C-M (default)
1760 | |
1760 | |
1761 | o cac2cead0ff0 C-L (default)
1761 | o cac2cead0ff0 C-L (default)
1762 | |
1762 | |
1763 o | be705100c623 C-K (default)
1763 o | be705100c623 C-K (default)
1764 |\|
1764 |\|
1765 o | d603e2c0cdd7 C-E (default)
1765 o | d603e2c0cdd7 C-E (default)
1766 | |
1766 | |
1767 | o 59e76faf78bd C-D (default)
1767 | o 59e76faf78bd C-D (default)
1768 | |
1768 | |
1769 | | o 89420bf00fae C-J (default)
1769 | | o 89420bf00fae C-J (default)
1770 | | |
1770 | | |
1771 | | | o b35ed749f288 C-I (my-second-test-branch)
1771 | | | o b35ed749f288 C-I (my-second-test-branch)
1772 | | |/
1772 | | |/
1773 | | o 75d69cba5402 C-G (default)
1773 | | o 75d69cba5402 C-G (default)
1774 | | |
1774 | | |
1775 | | | o 833be552cfe6 C-H (my-first-test-branch)
1775 | | | o 833be552cfe6 C-H (my-first-test-branch)
1776 | | |/
1776 | | |/
1777 | | o d9e379a8c432 C-F (default)
1777 | | o d9e379a8c432 C-F (default)
1778 | | |
1778 | | |
1779 +---o 51c544a58128 C-C (default)
1779 +---o 51c544a58128 C-C (default)
1780 | |
1780 | |
1781 | o a9149a1428e2 C-B (default)
1781 | o a9149a1428e2 C-B (default)
1782 | |
1782 | |
1783 o | 98217d5a1659 C-A (default)
1783 o | 98217d5a1659 C-A (default)
1784 |/
1784 |/
1785 o 842e2fac6304 C-ROOT (default)
1785 o 842e2fac6304 C-ROOT (default)
1786
1786
1787
1787
1788 Creating changesets and markers
1788 Creating changesets and markers
1789
1789
1790 (new topo branch obsoleting that same head)
1790 (new topo branch obsoleting that same head)
1791
1791
1792 $ hg -R client-other/ up 'desc("C-Q")'
1792 $ hg -R client-other/ up 'desc("C-Q")'
1793 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1793 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1794 $ echo bbb >> client-other/a
1794 $ echo bbb >> client-other/a
1795 $ hg -R client-other/ branch --force default
1795 $ hg -R client-other/ branch --force default
1796 marked working directory as branch default
1796 marked working directory as branch default
1797 $ hg -R client-other/ commit -m "C-W"
1797 $ hg -R client-other/ commit -m "C-W"
1798 1 new orphan changesets
1798 1 new orphan changesets
1799 created new head
1799 created new head
1800 $ ID_V=`hg -R client-other log -T '{node}\n' -r 'desc("C-V")'`
1800 $ ID_V=`hg -R client-other log -T '{node}\n' -r 'desc("C-V")'`
1801 $ ID_W=`hg -R client-other log -T '{node}\n' -r 'desc("C-W")'`
1801 $ ID_W=`hg -R client-other log -T '{node}\n' -r 'desc("C-W")'`
1802 $ hg -R client-other debugobsolete $ID_V $ID_W
1802 $ hg -R client-other debugobsolete $ID_V $ID_W
1803 obsoleted 1 changesets
1803 obsoleted 1 changesets
1804
1804
1805 (continue the same head)
1805 (continue the same head)
1806
1806
1807 $ echo aaa >> client-racy/a
1807 $ echo aaa >> client-racy/a
1808 $ hg -R client-racy/ commit -m "C-X"
1808 $ hg -R client-racy/ commit -m "C-X"
1809
1809
1810 Pushing
1810 Pushing
1811
1811
1812 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1812 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1813
1813
1814 $ waiton $TESTTMP/readyfile
1814 $ waiton $TESTTMP/readyfile
1815
1815
1816 $ hg -R client-other push -fr 'tip' --new-branch
1816 $ hg -R client-other push -fr 'tip' --new-branch
1817 pushing to ssh://user@dummy/server
1817 pushing to ssh://user@dummy/server
1818 searching for changes
1818 searching for changes
1819 remote: adding changesets
1819 remote: adding changesets
1820 remote: adding manifests
1820 remote: adding manifests
1821 remote: adding file changes
1821 remote: adding file changes
1822 remote: added 1 changesets with 0 changes to 1 files (+1 heads)
1822 remote: added 1 changesets with 0 changes to 1 files (+1 heads)
1823 remote: 1 new obsolescence markers
1823 remote: 1 new obsolescence markers
1824 remote: obsoleted 1 changesets
1824 remote: obsoleted 1 changesets
1825 remote: 1 new orphan changesets
1825 remote: 1 new orphan changesets
1826
1826
1827 $ release $TESTTMP/watchfile
1827 $ release $TESTTMP/watchfile
1828
1828
1829 Check the result of the push
1829 Check the result of the push
1830
1830
1831 $ cat ./push-log
1831 $ cat ./push-log
1832 pushing to ssh://user@dummy/server
1832 pushing to ssh://user@dummy/server
1833 searching for changes
1833 searching for changes
1834 wrote ready: $TESTTMP/readyfile
1834 wrote ready: $TESTTMP/readyfile
1835 waiting on: $TESTTMP/watchfile
1835 waiting on: $TESTTMP/watchfile
1836 abort: push failed:
1836 abort: push failed:
1837 'repository changed while pushing - please try again'
1837 'remote repository changed while pushing - please try again'
1838
1838
1839 $ hg -R server debugobsolete
1839 $ hg -R server debugobsolete
1840 b0ee3d6f51bc4c0ca6d4f2907708027a6c376233 720c5163ecf64dcc6216bee2d62bf3edb1882499 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1840 b0ee3d6f51bc4c0ca6d4f2907708027a6c376233 720c5163ecf64dcc6216bee2d62bf3edb1882499 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1841 720c5163ecf64dcc6216bee2d62bf3edb1882499 39bc0598afe90ab18da460bafecc0fa953b77596 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1841 720c5163ecf64dcc6216bee2d62bf3edb1882499 39bc0598afe90ab18da460bafecc0fa953b77596 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1842 $ hg -R server graph --hidden
1842 $ hg -R server graph --hidden
1843 * 39bc0598afe9 C-W (default)
1843 * 39bc0598afe9 C-W (default)
1844 |
1844 |
1845 | * a98a47d8b85b C-U (default)
1845 | * a98a47d8b85b C-U (default)
1846 |/
1846 |/
1847 x b0ee3d6f51bc C-Q (default)
1847 x b0ee3d6f51bc C-Q (default)
1848 |
1848 |
1849 | o 3d57ed3c1091 C-T (other)
1849 | o 3d57ed3c1091 C-T (other)
1850 | |
1850 | |
1851 | o 2efd43f7b5ba C-S (default)
1851 | o 2efd43f7b5ba C-S (default)
1852 | |
1852 | |
1853 | | o de7b9e2ba3f6 C-R (other)
1853 | | o de7b9e2ba3f6 C-R (other)
1854 | |/
1854 | |/
1855 | o 1b58ee3f79e5 C-P (default)
1855 | o 1b58ee3f79e5 C-P (default)
1856 | |
1856 | |
1857 | o d0a85b2252a9 C-O (other)
1857 | o d0a85b2252a9 C-O (other)
1858 |/
1858 |/
1859 | x 720c5163ecf6 C-V (default)
1859 | x 720c5163ecf6 C-V (default)
1860 |/
1860 |/
1861 o 55a6f1c01b48 C-Z (other)
1861 o 55a6f1c01b48 C-Z (other)
1862 |
1862 |
1863 o 866a66e18630 C-N (default)
1863 o 866a66e18630 C-N (default)
1864 |\
1864 |\
1865 +---o 6fd3090135df C-M (default)
1865 +---o 6fd3090135df C-M (default)
1866 | |
1866 | |
1867 | o cac2cead0ff0 C-L (default)
1867 | o cac2cead0ff0 C-L (default)
1868 | |
1868 | |
1869 o | be705100c623 C-K (default)
1869 o | be705100c623 C-K (default)
1870 |\|
1870 |\|
1871 o | d603e2c0cdd7 C-E (default)
1871 o | d603e2c0cdd7 C-E (default)
1872 | |
1872 | |
1873 | o 59e76faf78bd C-D (default)
1873 | o 59e76faf78bd C-D (default)
1874 | |
1874 | |
1875 | | o 89420bf00fae C-J (default)
1875 | | o 89420bf00fae C-J (default)
1876 | | |
1876 | | |
1877 | | | o b35ed749f288 C-I (my-second-test-branch)
1877 | | | o b35ed749f288 C-I (my-second-test-branch)
1878 | | |/
1878 | | |/
1879 | | o 75d69cba5402 C-G (default)
1879 | | o 75d69cba5402 C-G (default)
1880 | | |
1880 | | |
1881 | | | o 833be552cfe6 C-H (my-first-test-branch)
1881 | | | o 833be552cfe6 C-H (my-first-test-branch)
1882 | | |/
1882 | | |/
1883 | | o d9e379a8c432 C-F (default)
1883 | | o d9e379a8c432 C-F (default)
1884 | | |
1884 | | |
1885 +---o 51c544a58128 C-C (default)
1885 +---o 51c544a58128 C-C (default)
1886 | |
1886 | |
1887 | o a9149a1428e2 C-B (default)
1887 | o a9149a1428e2 C-B (default)
1888 | |
1888 | |
1889 o | 98217d5a1659 C-A (default)
1889 o | 98217d5a1659 C-A (default)
1890 |/
1890 |/
1891 o 842e2fac6304 C-ROOT (default)
1891 o 842e2fac6304 C-ROOT (default)
1892
1892
General Comments 0
You need to be logged in to leave comments. Login now