##// END OF EJS Templates
bundle2: store changeset count when creating file bundles...
Gregory Szorc -
r29593:953839de default
parent child Browse files
Show More
@@ -1,1608 +1,1611 b''
1 1 # bundle2.py - generic container format to transmit arbitrary data.
2 2 #
3 3 # Copyright 2013 Facebook, Inc.
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7 """Handling of the new bundle2 format
8 8
9 9 The goal of bundle2 is to act as an atomically packet to transmit a set of
10 10 payloads in an application agnostic way. It consist in a sequence of "parts"
11 11 that will be handed to and processed by the application layer.
12 12
13 13
14 14 General format architecture
15 15 ===========================
16 16
17 17 The format is architectured as follow
18 18
19 19 - magic string
20 20 - stream level parameters
21 21 - payload parts (any number)
22 22 - end of stream marker.
23 23
24 24 the Binary format
25 25 ============================
26 26
27 27 All numbers are unsigned and big-endian.
28 28
29 29 stream level parameters
30 30 ------------------------
31 31
32 32 Binary format is as follow
33 33
34 34 :params size: int32
35 35
36 36 The total number of Bytes used by the parameters
37 37
38 38 :params value: arbitrary number of Bytes
39 39
40 40 A blob of `params size` containing the serialized version of all stream level
41 41 parameters.
42 42
43 43 The blob contains a space separated list of parameters. Parameters with value
44 44 are stored in the form `<name>=<value>`. Both name and value are urlquoted.
45 45
46 46 Empty name are obviously forbidden.
47 47
48 48 Name MUST start with a letter. If this first letter is lower case, the
49 49 parameter is advisory and can be safely ignored. However when the first
50 50 letter is capital, the parameter is mandatory and the bundling process MUST
51 51 stop if he is not able to proceed it.
52 52
53 53 Stream parameters use a simple textual format for two main reasons:
54 54
55 55 - Stream level parameters should remain simple and we want to discourage any
56 56 crazy usage.
57 57 - Textual data allow easy human inspection of a bundle2 header in case of
58 58 troubles.
59 59
60 60 Any Applicative level options MUST go into a bundle2 part instead.
61 61
62 62 Payload part
63 63 ------------------------
64 64
65 65 Binary format is as follow
66 66
67 67 :header size: int32
68 68
69 69 The total number of Bytes used by the part header. When the header is empty
70 70 (size = 0) this is interpreted as the end of stream marker.
71 71
72 72 :header:
73 73
74 74 The header defines how to interpret the part. It contains two piece of
75 75 data: the part type, and the part parameters.
76 76
77 77 The part type is used to route an application level handler, that can
78 78 interpret payload.
79 79
80 80 Part parameters are passed to the application level handler. They are
81 81 meant to convey information that will help the application level object to
82 82 interpret the part payload.
83 83
84 84 The binary format of the header is has follow
85 85
86 86 :typesize: (one byte)
87 87
88 88 :parttype: alphanumerical part name (restricted to [a-zA-Z0-9_:-]*)
89 89
90 90 :partid: A 32bits integer (unique in the bundle) that can be used to refer
91 91 to this part.
92 92
93 93 :parameters:
94 94
95 95 Part's parameter may have arbitrary content, the binary structure is::
96 96
97 97 <mandatory-count><advisory-count><param-sizes><param-data>
98 98
99 99 :mandatory-count: 1 byte, number of mandatory parameters
100 100
101 101 :advisory-count: 1 byte, number of advisory parameters
102 102
103 103 :param-sizes:
104 104
105 105 N couple of bytes, where N is the total number of parameters. Each
106 106 couple contains (<size-of-key>, <size-of-value) for one parameter.
107 107
108 108 :param-data:
109 109
110 110 A blob of bytes from which each parameter key and value can be
111 111 retrieved using the list of size couples stored in the previous
112 112 field.
113 113
114 114 Mandatory parameters comes first, then the advisory ones.
115 115
116 116 Each parameter's key MUST be unique within the part.
117 117
118 118 :payload:
119 119
120 120 payload is a series of `<chunksize><chunkdata>`.
121 121
122 122 `chunksize` is an int32, `chunkdata` are plain bytes (as much as
123 123 `chunksize` says)` The payload part is concluded by a zero size chunk.
124 124
125 125 The current implementation always produces either zero or one chunk.
126 126 This is an implementation limitation that will ultimately be lifted.
127 127
128 128 `chunksize` can be negative to trigger special case processing. No such
129 129 processing is in place yet.
130 130
131 131 Bundle processing
132 132 ============================
133 133
134 134 Each part is processed in order using a "part handler". Handler are registered
135 135 for a certain part type.
136 136
137 137 The matching of a part to its handler is case insensitive. The case of the
138 138 part type is used to know if a part is mandatory or advisory. If the Part type
139 139 contains any uppercase char it is considered mandatory. When no handler is
140 140 known for a Mandatory part, the process is aborted and an exception is raised.
141 141 If the part is advisory and no handler is known, the part is ignored. When the
142 142 process is aborted, the full bundle is still read from the stream to keep the
143 143 channel usable. But none of the part read from an abort are processed. In the
144 144 future, dropping the stream may become an option for channel we do not care to
145 145 preserve.
146 146 """
147 147
148 148 from __future__ import absolute_import
149 149
150 150 import errno
151 151 import re
152 152 import string
153 153 import struct
154 154 import sys
155 155
156 156 from .i18n import _
157 157 from . import (
158 158 changegroup,
159 159 error,
160 160 obsolete,
161 161 pushkey,
162 162 tags,
163 163 url,
164 164 util,
165 165 )
166 166
167 167 urlerr = util.urlerr
168 168 urlreq = util.urlreq
169 169
170 170 _pack = struct.pack
171 171 _unpack = struct.unpack
172 172
173 173 _fstreamparamsize = '>i'
174 174 _fpartheadersize = '>i'
175 175 _fparttypesize = '>B'
176 176 _fpartid = '>I'
177 177 _fpayloadsize = '>i'
178 178 _fpartparamcount = '>BB'
179 179
180 180 preferedchunksize = 4096
181 181
182 182 _parttypeforbidden = re.compile('[^a-zA-Z0-9_:-]')
183 183
184 184 def outdebug(ui, message):
185 185 """debug regarding output stream (bundling)"""
186 186 if ui.configbool('devel', 'bundle2.debug', False):
187 187 ui.debug('bundle2-output: %s\n' % message)
188 188
189 189 def indebug(ui, message):
190 190 """debug on input stream (unbundling)"""
191 191 if ui.configbool('devel', 'bundle2.debug', False):
192 192 ui.debug('bundle2-input: %s\n' % message)
193 193
194 194 def validateparttype(parttype):
195 195 """raise ValueError if a parttype contains invalid character"""
196 196 if _parttypeforbidden.search(parttype):
197 197 raise ValueError(parttype)
198 198
199 199 def _makefpartparamsizes(nbparams):
200 200 """return a struct format to read part parameter sizes
201 201
202 202 The number parameters is variable so we need to build that format
203 203 dynamically.
204 204 """
205 205 return '>'+('BB'*nbparams)
206 206
207 207 parthandlermapping = {}
208 208
209 209 def parthandler(parttype, params=()):
210 210 """decorator that register a function as a bundle2 part handler
211 211
212 212 eg::
213 213
214 214 @parthandler('myparttype', ('mandatory', 'param', 'handled'))
215 215 def myparttypehandler(...):
216 216 '''process a part of type "my part".'''
217 217 ...
218 218 """
219 219 validateparttype(parttype)
220 220 def _decorator(func):
221 221 lparttype = parttype.lower() # enforce lower case matching.
222 222 assert lparttype not in parthandlermapping
223 223 parthandlermapping[lparttype] = func
224 224 func.params = frozenset(params)
225 225 return func
226 226 return _decorator
227 227
228 228 class unbundlerecords(object):
229 229 """keep record of what happens during and unbundle
230 230
231 231 New records are added using `records.add('cat', obj)`. Where 'cat' is a
232 232 category of record and obj is an arbitrary object.
233 233
234 234 `records['cat']` will return all entries of this category 'cat'.
235 235
236 236 Iterating on the object itself will yield `('category', obj)` tuples
237 237 for all entries.
238 238
239 239 All iterations happens in chronological order.
240 240 """
241 241
242 242 def __init__(self):
243 243 self._categories = {}
244 244 self._sequences = []
245 245 self._replies = {}
246 246
247 247 def add(self, category, entry, inreplyto=None):
248 248 """add a new record of a given category.
249 249
250 250 The entry can then be retrieved in the list returned by
251 251 self['category']."""
252 252 self._categories.setdefault(category, []).append(entry)
253 253 self._sequences.append((category, entry))
254 254 if inreplyto is not None:
255 255 self.getreplies(inreplyto).add(category, entry)
256 256
257 257 def getreplies(self, partid):
258 258 """get the records that are replies to a specific part"""
259 259 return self._replies.setdefault(partid, unbundlerecords())
260 260
261 261 def __getitem__(self, cat):
262 262 return tuple(self._categories.get(cat, ()))
263 263
264 264 def __iter__(self):
265 265 return iter(self._sequences)
266 266
267 267 def __len__(self):
268 268 return len(self._sequences)
269 269
270 270 def __nonzero__(self):
271 271 return bool(self._sequences)
272 272
273 273 class bundleoperation(object):
274 274 """an object that represents a single bundling process
275 275
276 276 Its purpose is to carry unbundle-related objects and states.
277 277
278 278 A new object should be created at the beginning of each bundle processing.
279 279 The object is to be returned by the processing function.
280 280
281 281 The object has very little content now it will ultimately contain:
282 282 * an access to the repo the bundle is applied to,
283 283 * a ui object,
284 284 * a way to retrieve a transaction to add changes to the repo,
285 285 * a way to record the result of processing each part,
286 286 * a way to construct a bundle response when applicable.
287 287 """
288 288
289 289 def __init__(self, repo, transactiongetter, captureoutput=True):
290 290 self.repo = repo
291 291 self.ui = repo.ui
292 292 self.records = unbundlerecords()
293 293 self.gettransaction = transactiongetter
294 294 self.reply = None
295 295 self.captureoutput = captureoutput
296 296
297 297 class TransactionUnavailable(RuntimeError):
298 298 pass
299 299
300 300 def _notransaction():
301 301 """default method to get a transaction while processing a bundle
302 302
303 303 Raise an exception to highlight the fact that no transaction was expected
304 304 to be created"""
305 305 raise TransactionUnavailable()
306 306
307 307 def applybundle(repo, unbundler, tr, source=None, url=None, op=None):
308 308 # transform me into unbundler.apply() as soon as the freeze is lifted
309 309 tr.hookargs['bundle2'] = '1'
310 310 if source is not None and 'source' not in tr.hookargs:
311 311 tr.hookargs['source'] = source
312 312 if url is not None and 'url' not in tr.hookargs:
313 313 tr.hookargs['url'] = url
314 314 return processbundle(repo, unbundler, lambda: tr, op=op)
315 315
316 316 def processbundle(repo, unbundler, transactiongetter=None, op=None):
317 317 """This function process a bundle, apply effect to/from a repo
318 318
319 319 It iterates over each part then searches for and uses the proper handling
320 320 code to process the part. Parts are processed in order.
321 321
322 322 This is very early version of this function that will be strongly reworked
323 323 before final usage.
324 324
325 325 Unknown Mandatory part will abort the process.
326 326
327 327 It is temporarily possible to provide a prebuilt bundleoperation to the
328 328 function. This is used to ensure output is properly propagated in case of
329 329 an error during the unbundling. This output capturing part will likely be
330 330 reworked and this ability will probably go away in the process.
331 331 """
332 332 if op is None:
333 333 if transactiongetter is None:
334 334 transactiongetter = _notransaction
335 335 op = bundleoperation(repo, transactiongetter)
336 336 # todo:
337 337 # - replace this is a init function soon.
338 338 # - exception catching
339 339 unbundler.params
340 340 if repo.ui.debugflag:
341 341 msg = ['bundle2-input-bundle:']
342 342 if unbundler.params:
343 343 msg.append(' %i params')
344 344 if op.gettransaction is None:
345 345 msg.append(' no-transaction')
346 346 else:
347 347 msg.append(' with-transaction')
348 348 msg.append('\n')
349 349 repo.ui.debug(''.join(msg))
350 350 iterparts = enumerate(unbundler.iterparts())
351 351 part = None
352 352 nbpart = 0
353 353 try:
354 354 for nbpart, part in iterparts:
355 355 _processpart(op, part)
356 356 except BaseException as exc:
357 357 for nbpart, part in iterparts:
358 358 # consume the bundle content
359 359 part.seek(0, 2)
360 360 # Small hack to let caller code distinguish exceptions from bundle2
361 361 # processing from processing the old format. This is mostly
362 362 # needed to handle different return codes to unbundle according to the
363 363 # type of bundle. We should probably clean up or drop this return code
364 364 # craziness in a future version.
365 365 exc.duringunbundle2 = True
366 366 salvaged = []
367 367 replycaps = None
368 368 if op.reply is not None:
369 369 salvaged = op.reply.salvageoutput()
370 370 replycaps = op.reply.capabilities
371 371 exc._replycaps = replycaps
372 372 exc._bundle2salvagedoutput = salvaged
373 373 raise
374 374 finally:
375 375 repo.ui.debug('bundle2-input-bundle: %i parts total\n' % nbpart)
376 376
377 377 return op
378 378
379 379 def _processpart(op, part):
380 380 """process a single part from a bundle
381 381
382 382 The part is guaranteed to have been fully consumed when the function exits
383 383 (even if an exception is raised)."""
384 384 status = 'unknown' # used by debug output
385 385 try:
386 386 try:
387 387 handler = parthandlermapping.get(part.type)
388 388 if handler is None:
389 389 status = 'unsupported-type'
390 390 raise error.BundleUnknownFeatureError(parttype=part.type)
391 391 indebug(op.ui, 'found a handler for part %r' % part.type)
392 392 unknownparams = part.mandatorykeys - handler.params
393 393 if unknownparams:
394 394 unknownparams = list(unknownparams)
395 395 unknownparams.sort()
396 396 status = 'unsupported-params (%s)' % unknownparams
397 397 raise error.BundleUnknownFeatureError(parttype=part.type,
398 398 params=unknownparams)
399 399 status = 'supported'
400 400 except error.BundleUnknownFeatureError as exc:
401 401 if part.mandatory: # mandatory parts
402 402 raise
403 403 indebug(op.ui, 'ignoring unsupported advisory part %s' % exc)
404 404 return # skip to part processing
405 405 finally:
406 406 if op.ui.debugflag:
407 407 msg = ['bundle2-input-part: "%s"' % part.type]
408 408 if not part.mandatory:
409 409 msg.append(' (advisory)')
410 410 nbmp = len(part.mandatorykeys)
411 411 nbap = len(part.params) - nbmp
412 412 if nbmp or nbap:
413 413 msg.append(' (params:')
414 414 if nbmp:
415 415 msg.append(' %i mandatory' % nbmp)
416 416 if nbap:
417 417 msg.append(' %i advisory' % nbmp)
418 418 msg.append(')')
419 419 msg.append(' %s\n' % status)
420 420 op.ui.debug(''.join(msg))
421 421
422 422 # handler is called outside the above try block so that we don't
423 423 # risk catching KeyErrors from anything other than the
424 424 # parthandlermapping lookup (any KeyError raised by handler()
425 425 # itself represents a defect of a different variety).
426 426 output = None
427 427 if op.captureoutput and op.reply is not None:
428 428 op.ui.pushbuffer(error=True, subproc=True)
429 429 output = ''
430 430 try:
431 431 handler(op, part)
432 432 finally:
433 433 if output is not None:
434 434 output = op.ui.popbuffer()
435 435 if output:
436 436 outpart = op.reply.newpart('output', data=output,
437 437 mandatory=False)
438 438 outpart.addparam('in-reply-to', str(part.id), mandatory=False)
439 439 finally:
440 440 # consume the part content to not corrupt the stream.
441 441 part.seek(0, 2)
442 442
443 443
444 444 def decodecaps(blob):
445 445 """decode a bundle2 caps bytes blob into a dictionary
446 446
447 447 The blob is a list of capabilities (one per line)
448 448 Capabilities may have values using a line of the form::
449 449
450 450 capability=value1,value2,value3
451 451
452 452 The values are always a list."""
453 453 caps = {}
454 454 for line in blob.splitlines():
455 455 if not line:
456 456 continue
457 457 if '=' not in line:
458 458 key, vals = line, ()
459 459 else:
460 460 key, vals = line.split('=', 1)
461 461 vals = vals.split(',')
462 462 key = urlreq.unquote(key)
463 463 vals = [urlreq.unquote(v) for v in vals]
464 464 caps[key] = vals
465 465 return caps
466 466
467 467 def encodecaps(caps):
468 468 """encode a bundle2 caps dictionary into a bytes blob"""
469 469 chunks = []
470 470 for ca in sorted(caps):
471 471 vals = caps[ca]
472 472 ca = urlreq.quote(ca)
473 473 vals = [urlreq.quote(v) for v in vals]
474 474 if vals:
475 475 ca = "%s=%s" % (ca, ','.join(vals))
476 476 chunks.append(ca)
477 477 return '\n'.join(chunks)
478 478
479 479 bundletypes = {
480 480 "": ("", None), # only when using unbundle on ssh and old http servers
481 481 # since the unification ssh accepts a header but there
482 482 # is no capability signaling it.
483 483 "HG20": (), # special-cased below
484 484 "HG10UN": ("HG10UN", None),
485 485 "HG10BZ": ("HG10", 'BZ'),
486 486 "HG10GZ": ("HG10GZ", 'GZ'),
487 487 }
488 488
489 489 # hgweb uses this list to communicate its preferred type
490 490 bundlepriority = ['HG10GZ', 'HG10BZ', 'HG10UN']
491 491
492 492 class bundle20(object):
493 493 """represent an outgoing bundle2 container
494 494
495 495 Use the `addparam` method to add stream level parameter. and `newpart` to
496 496 populate it. Then call `getchunks` to retrieve all the binary chunks of
497 497 data that compose the bundle2 container."""
498 498
499 499 _magicstring = 'HG20'
500 500
501 501 def __init__(self, ui, capabilities=()):
502 502 self.ui = ui
503 503 self._params = []
504 504 self._parts = []
505 505 self.capabilities = dict(capabilities)
506 506 self._compressor = util.compressors[None]()
507 507
508 508 def setcompression(self, alg):
509 509 """setup core part compression to <alg>"""
510 510 if alg is None:
511 511 return
512 512 assert not any(n.lower() == 'Compression' for n, v in self._params)
513 513 self.addparam('Compression', alg)
514 514 self._compressor = util.compressors[alg]()
515 515
516 516 @property
517 517 def nbparts(self):
518 518 """total number of parts added to the bundler"""
519 519 return len(self._parts)
520 520
521 521 # methods used to defines the bundle2 content
522 522 def addparam(self, name, value=None):
523 523 """add a stream level parameter"""
524 524 if not name:
525 525 raise ValueError('empty parameter name')
526 526 if name[0] not in string.letters:
527 527 raise ValueError('non letter first character: %r' % name)
528 528 self._params.append((name, value))
529 529
530 530 def addpart(self, part):
531 531 """add a new part to the bundle2 container
532 532
533 533 Parts contains the actual applicative payload."""
534 534 assert part.id is None
535 535 part.id = len(self._parts) # very cheap counter
536 536 self._parts.append(part)
537 537
538 538 def newpart(self, typeid, *args, **kwargs):
539 539 """create a new part and add it to the containers
540 540
541 541 As the part is directly added to the containers. For now, this means
542 542 that any failure to properly initialize the part after calling
543 543 ``newpart`` should result in a failure of the whole bundling process.
544 544
545 545 You can still fall back to manually create and add if you need better
546 546 control."""
547 547 part = bundlepart(typeid, *args, **kwargs)
548 548 self.addpart(part)
549 549 return part
550 550
551 551 # methods used to generate the bundle2 stream
552 552 def getchunks(self):
553 553 if self.ui.debugflag:
554 554 msg = ['bundle2-output-bundle: "%s",' % self._magicstring]
555 555 if self._params:
556 556 msg.append(' (%i params)' % len(self._params))
557 557 msg.append(' %i parts total\n' % len(self._parts))
558 558 self.ui.debug(''.join(msg))
559 559 outdebug(self.ui, 'start emission of %s stream' % self._magicstring)
560 560 yield self._magicstring
561 561 param = self._paramchunk()
562 562 outdebug(self.ui, 'bundle parameter: %s' % param)
563 563 yield _pack(_fstreamparamsize, len(param))
564 564 if param:
565 565 yield param
566 566 # starting compression
567 567 for chunk in self._getcorechunk():
568 568 yield self._compressor.compress(chunk)
569 569 yield self._compressor.flush()
570 570
571 571 def _paramchunk(self):
572 572 """return a encoded version of all stream parameters"""
573 573 blocks = []
574 574 for par, value in self._params:
575 575 par = urlreq.quote(par)
576 576 if value is not None:
577 577 value = urlreq.quote(value)
578 578 par = '%s=%s' % (par, value)
579 579 blocks.append(par)
580 580 return ' '.join(blocks)
581 581
582 582 def _getcorechunk(self):
583 583 """yield chunk for the core part of the bundle
584 584
585 585 (all but headers and parameters)"""
586 586 outdebug(self.ui, 'start of parts')
587 587 for part in self._parts:
588 588 outdebug(self.ui, 'bundle part: "%s"' % part.type)
589 589 for chunk in part.getchunks(ui=self.ui):
590 590 yield chunk
591 591 outdebug(self.ui, 'end of bundle')
592 592 yield _pack(_fpartheadersize, 0)
593 593
594 594
595 595 def salvageoutput(self):
596 596 """return a list with a copy of all output parts in the bundle
597 597
598 598 This is meant to be used during error handling to make sure we preserve
599 599 server output"""
600 600 salvaged = []
601 601 for part in self._parts:
602 602 if part.type.startswith('output'):
603 603 salvaged.append(part.copy())
604 604 return salvaged
605 605
606 606
607 607 class unpackermixin(object):
608 608 """A mixin to extract bytes and struct data from a stream"""
609 609
610 610 def __init__(self, fp):
611 611 self._fp = fp
612 612 self._seekable = (util.safehasattr(fp, 'seek') and
613 613 util.safehasattr(fp, 'tell'))
614 614
615 615 def _unpack(self, format):
616 616 """unpack this struct format from the stream"""
617 617 data = self._readexact(struct.calcsize(format))
618 618 return _unpack(format, data)
619 619
620 620 def _readexact(self, size):
621 621 """read exactly <size> bytes from the stream"""
622 622 return changegroup.readexactly(self._fp, size)
623 623
624 624 def seek(self, offset, whence=0):
625 625 """move the underlying file pointer"""
626 626 if self._seekable:
627 627 return self._fp.seek(offset, whence)
628 628 else:
629 629 raise NotImplementedError(_('File pointer is not seekable'))
630 630
631 631 def tell(self):
632 632 """return the file offset, or None if file is not seekable"""
633 633 if self._seekable:
634 634 try:
635 635 return self._fp.tell()
636 636 except IOError as e:
637 637 if e.errno == errno.ESPIPE:
638 638 self._seekable = False
639 639 else:
640 640 raise
641 641 return None
642 642
643 643 def close(self):
644 644 """close underlying file"""
645 645 if util.safehasattr(self._fp, 'close'):
646 646 return self._fp.close()
647 647
648 648 def getunbundler(ui, fp, magicstring=None):
649 649 """return a valid unbundler object for a given magicstring"""
650 650 if magicstring is None:
651 651 magicstring = changegroup.readexactly(fp, 4)
652 652 magic, version = magicstring[0:2], magicstring[2:4]
653 653 if magic != 'HG':
654 654 raise error.Abort(_('not a Mercurial bundle'))
655 655 unbundlerclass = formatmap.get(version)
656 656 if unbundlerclass is None:
657 657 raise error.Abort(_('unknown bundle version %s') % version)
658 658 unbundler = unbundlerclass(ui, fp)
659 659 indebug(ui, 'start processing of %s stream' % magicstring)
660 660 return unbundler
661 661
662 662 class unbundle20(unpackermixin):
663 663 """interpret a bundle2 stream
664 664
665 665 This class is fed with a binary stream and yields parts through its
666 666 `iterparts` methods."""
667 667
668 668 _magicstring = 'HG20'
669 669
670 670 def __init__(self, ui, fp):
671 671 """If header is specified, we do not read it out of the stream."""
672 672 self.ui = ui
673 673 self._decompressor = util.decompressors[None]
674 674 self._compressed = None
675 675 super(unbundle20, self).__init__(fp)
676 676
677 677 @util.propertycache
678 678 def params(self):
679 679 """dictionary of stream level parameters"""
680 680 indebug(self.ui, 'reading bundle2 stream parameters')
681 681 params = {}
682 682 paramssize = self._unpack(_fstreamparamsize)[0]
683 683 if paramssize < 0:
684 684 raise error.BundleValueError('negative bundle param size: %i'
685 685 % paramssize)
686 686 if paramssize:
687 687 params = self._readexact(paramssize)
688 688 params = self._processallparams(params)
689 689 return params
690 690
691 691 def _processallparams(self, paramsblock):
692 692 """"""
693 693 params = util.sortdict()
694 694 for p in paramsblock.split(' '):
695 695 p = p.split('=', 1)
696 696 p = [urlreq.unquote(i) for i in p]
697 697 if len(p) < 2:
698 698 p.append(None)
699 699 self._processparam(*p)
700 700 params[p[0]] = p[1]
701 701 return params
702 702
703 703
704 704 def _processparam(self, name, value):
705 705 """process a parameter, applying its effect if needed
706 706
707 707 Parameter starting with a lower case letter are advisory and will be
708 708 ignored when unknown. Those starting with an upper case letter are
709 709 mandatory and will this function will raise a KeyError when unknown.
710 710
711 711 Note: no option are currently supported. Any input will be either
712 712 ignored or failing.
713 713 """
714 714 if not name:
715 715 raise ValueError('empty parameter name')
716 716 if name[0] not in string.letters:
717 717 raise ValueError('non letter first character: %r' % name)
718 718 try:
719 719 handler = b2streamparamsmap[name.lower()]
720 720 except KeyError:
721 721 if name[0].islower():
722 722 indebug(self.ui, "ignoring unknown parameter %r" % name)
723 723 else:
724 724 raise error.BundleUnknownFeatureError(params=(name,))
725 725 else:
726 726 handler(self, name, value)
727 727
728 728 def _forwardchunks(self):
729 729 """utility to transfer a bundle2 as binary
730 730
731 731 This is made necessary by the fact the 'getbundle' command over 'ssh'
732 732 have no way to know then the reply end, relying on the bundle to be
733 733 interpreted to know its end. This is terrible and we are sorry, but we
734 734 needed to move forward to get general delta enabled.
735 735 """
736 736 yield self._magicstring
737 737 assert 'params' not in vars(self)
738 738 paramssize = self._unpack(_fstreamparamsize)[0]
739 739 if paramssize < 0:
740 740 raise error.BundleValueError('negative bundle param size: %i'
741 741 % paramssize)
742 742 yield _pack(_fstreamparamsize, paramssize)
743 743 if paramssize:
744 744 params = self._readexact(paramssize)
745 745 self._processallparams(params)
746 746 yield params
747 747 assert self._decompressor is util.decompressors[None]
748 748 # From there, payload might need to be decompressed
749 749 self._fp = self._decompressor(self._fp)
750 750 emptycount = 0
751 751 while emptycount < 2:
752 752 # so we can brainlessly loop
753 753 assert _fpartheadersize == _fpayloadsize
754 754 size = self._unpack(_fpartheadersize)[0]
755 755 yield _pack(_fpartheadersize, size)
756 756 if size:
757 757 emptycount = 0
758 758 else:
759 759 emptycount += 1
760 760 continue
761 761 if size == flaginterrupt:
762 762 continue
763 763 elif size < 0:
764 764 raise error.BundleValueError('negative chunk size: %i')
765 765 yield self._readexact(size)
766 766
767 767
768 768 def iterparts(self):
769 769 """yield all parts contained in the stream"""
770 770 # make sure param have been loaded
771 771 self.params
772 772 # From there, payload need to be decompressed
773 773 self._fp = self._decompressor(self._fp)
774 774 indebug(self.ui, 'start extraction of bundle2 parts')
775 775 headerblock = self._readpartheader()
776 776 while headerblock is not None:
777 777 part = unbundlepart(self.ui, headerblock, self._fp)
778 778 yield part
779 779 part.seek(0, 2)
780 780 headerblock = self._readpartheader()
781 781 indebug(self.ui, 'end of bundle2 stream')
782 782
783 783 def _readpartheader(self):
784 784 """reads a part header size and return the bytes blob
785 785
786 786 returns None if empty"""
787 787 headersize = self._unpack(_fpartheadersize)[0]
788 788 if headersize < 0:
789 789 raise error.BundleValueError('negative part header size: %i'
790 790 % headersize)
791 791 indebug(self.ui, 'part header size: %i' % headersize)
792 792 if headersize:
793 793 return self._readexact(headersize)
794 794 return None
795 795
796 796 def compressed(self):
797 797 self.params # load params
798 798 return self._compressed
799 799
800 800 formatmap = {'20': unbundle20}
801 801
802 802 b2streamparamsmap = {}
803 803
804 804 def b2streamparamhandler(name):
805 805 """register a handler for a stream level parameter"""
806 806 def decorator(func):
807 807 assert name not in formatmap
808 808 b2streamparamsmap[name] = func
809 809 return func
810 810 return decorator
811 811
812 812 @b2streamparamhandler('compression')
813 813 def processcompression(unbundler, param, value):
814 814 """read compression parameter and install payload decompression"""
815 815 if value not in util.decompressors:
816 816 raise error.BundleUnknownFeatureError(params=(param,),
817 817 values=(value,))
818 818 unbundler._decompressor = util.decompressors[value]
819 819 if value is not None:
820 820 unbundler._compressed = True
821 821
822 822 class bundlepart(object):
823 823 """A bundle2 part contains application level payload
824 824
825 825 The part `type` is used to route the part to the application level
826 826 handler.
827 827
828 828 The part payload is contained in ``part.data``. It could be raw bytes or a
829 829 generator of byte chunks.
830 830
831 831 You can add parameters to the part using the ``addparam`` method.
832 832 Parameters can be either mandatory (default) or advisory. Remote side
833 833 should be able to safely ignore the advisory ones.
834 834
835 835 Both data and parameters cannot be modified after the generation has begun.
836 836 """
837 837
838 838 def __init__(self, parttype, mandatoryparams=(), advisoryparams=(),
839 839 data='', mandatory=True):
840 840 validateparttype(parttype)
841 841 self.id = None
842 842 self.type = parttype
843 843 self._data = data
844 844 self._mandatoryparams = list(mandatoryparams)
845 845 self._advisoryparams = list(advisoryparams)
846 846 # checking for duplicated entries
847 847 self._seenparams = set()
848 848 for pname, __ in self._mandatoryparams + self._advisoryparams:
849 849 if pname in self._seenparams:
850 850 raise RuntimeError('duplicated params: %s' % pname)
851 851 self._seenparams.add(pname)
852 852 # status of the part's generation:
853 853 # - None: not started,
854 854 # - False: currently generated,
855 855 # - True: generation done.
856 856 self._generated = None
857 857 self.mandatory = mandatory
858 858
859 859 def copy(self):
860 860 """return a copy of the part
861 861
862 862 The new part have the very same content but no partid assigned yet.
863 863 Parts with generated data cannot be copied."""
864 864 assert not util.safehasattr(self.data, 'next')
865 865 return self.__class__(self.type, self._mandatoryparams,
866 866 self._advisoryparams, self._data, self.mandatory)
867 867
868 868 # methods used to defines the part content
869 869 @property
870 870 def data(self):
871 871 return self._data
872 872
873 873 @data.setter
874 874 def data(self, data):
875 875 if self._generated is not None:
876 876 raise error.ReadOnlyPartError('part is being generated')
877 877 self._data = data
878 878
879 879 @property
880 880 def mandatoryparams(self):
881 881 # make it an immutable tuple to force people through ``addparam``
882 882 return tuple(self._mandatoryparams)
883 883
884 884 @property
885 885 def advisoryparams(self):
886 886 # make it an immutable tuple to force people through ``addparam``
887 887 return tuple(self._advisoryparams)
888 888
889 889 def addparam(self, name, value='', mandatory=True):
890 890 if self._generated is not None:
891 891 raise error.ReadOnlyPartError('part is being generated')
892 892 if name in self._seenparams:
893 893 raise ValueError('duplicated params: %s' % name)
894 894 self._seenparams.add(name)
895 895 params = self._advisoryparams
896 896 if mandatory:
897 897 params = self._mandatoryparams
898 898 params.append((name, value))
899 899
900 900 # methods used to generates the bundle2 stream
901 901 def getchunks(self, ui):
902 902 if self._generated is not None:
903 903 raise RuntimeError('part can only be consumed once')
904 904 self._generated = False
905 905
906 906 if ui.debugflag:
907 907 msg = ['bundle2-output-part: "%s"' % self.type]
908 908 if not self.mandatory:
909 909 msg.append(' (advisory)')
910 910 nbmp = len(self.mandatoryparams)
911 911 nbap = len(self.advisoryparams)
912 912 if nbmp or nbap:
913 913 msg.append(' (params:')
914 914 if nbmp:
915 915 msg.append(' %i mandatory' % nbmp)
916 916 if nbap:
917 917 msg.append(' %i advisory' % nbmp)
918 918 msg.append(')')
919 919 if not self.data:
920 920 msg.append(' empty payload')
921 921 elif util.safehasattr(self.data, 'next'):
922 922 msg.append(' streamed payload')
923 923 else:
924 924 msg.append(' %i bytes payload' % len(self.data))
925 925 msg.append('\n')
926 926 ui.debug(''.join(msg))
927 927
928 928 #### header
929 929 if self.mandatory:
930 930 parttype = self.type.upper()
931 931 else:
932 932 parttype = self.type.lower()
933 933 outdebug(ui, 'part %s: "%s"' % (self.id, parttype))
934 934 ## parttype
935 935 header = [_pack(_fparttypesize, len(parttype)),
936 936 parttype, _pack(_fpartid, self.id),
937 937 ]
938 938 ## parameters
939 939 # count
940 940 manpar = self.mandatoryparams
941 941 advpar = self.advisoryparams
942 942 header.append(_pack(_fpartparamcount, len(manpar), len(advpar)))
943 943 # size
944 944 parsizes = []
945 945 for key, value in manpar:
946 946 parsizes.append(len(key))
947 947 parsizes.append(len(value))
948 948 for key, value in advpar:
949 949 parsizes.append(len(key))
950 950 parsizes.append(len(value))
951 951 paramsizes = _pack(_makefpartparamsizes(len(parsizes) / 2), *parsizes)
952 952 header.append(paramsizes)
953 953 # key, value
954 954 for key, value in manpar:
955 955 header.append(key)
956 956 header.append(value)
957 957 for key, value in advpar:
958 958 header.append(key)
959 959 header.append(value)
960 960 ## finalize header
961 961 headerchunk = ''.join(header)
962 962 outdebug(ui, 'header chunk size: %i' % len(headerchunk))
963 963 yield _pack(_fpartheadersize, len(headerchunk))
964 964 yield headerchunk
965 965 ## payload
966 966 try:
967 967 for chunk in self._payloadchunks():
968 968 outdebug(ui, 'payload chunk size: %i' % len(chunk))
969 969 yield _pack(_fpayloadsize, len(chunk))
970 970 yield chunk
971 971 except GeneratorExit:
972 972 # GeneratorExit means that nobody is listening for our
973 973 # results anyway, so just bail quickly rather than trying
974 974 # to produce an error part.
975 975 ui.debug('bundle2-generatorexit\n')
976 976 raise
977 977 except BaseException as exc:
978 978 # backup exception data for later
979 979 ui.debug('bundle2-input-stream-interrupt: encoding exception %s'
980 980 % exc)
981 981 exc_info = sys.exc_info()
982 982 msg = 'unexpected error: %s' % exc
983 983 interpart = bundlepart('error:abort', [('message', msg)],
984 984 mandatory=False)
985 985 interpart.id = 0
986 986 yield _pack(_fpayloadsize, -1)
987 987 for chunk in interpart.getchunks(ui=ui):
988 988 yield chunk
989 989 outdebug(ui, 'closing payload chunk')
990 990 # abort current part payload
991 991 yield _pack(_fpayloadsize, 0)
992 992 raise exc_info[0], exc_info[1], exc_info[2]
993 993 # end of payload
994 994 outdebug(ui, 'closing payload chunk')
995 995 yield _pack(_fpayloadsize, 0)
996 996 self._generated = True
997 997
998 998 def _payloadchunks(self):
999 999 """yield chunks of a the part payload
1000 1000
1001 1001 Exists to handle the different methods to provide data to a part."""
1002 1002 # we only support fixed size data now.
1003 1003 # This will be improved in the future.
1004 1004 if util.safehasattr(self.data, 'next'):
1005 1005 buff = util.chunkbuffer(self.data)
1006 1006 chunk = buff.read(preferedchunksize)
1007 1007 while chunk:
1008 1008 yield chunk
1009 1009 chunk = buff.read(preferedchunksize)
1010 1010 elif len(self.data):
1011 1011 yield self.data
1012 1012
1013 1013
1014 1014 flaginterrupt = -1
1015 1015
1016 1016 class interrupthandler(unpackermixin):
1017 1017 """read one part and process it with restricted capability
1018 1018
1019 1019 This allows to transmit exception raised on the producer size during part
1020 1020 iteration while the consumer is reading a part.
1021 1021
1022 1022 Part processed in this manner only have access to a ui object,"""
1023 1023
1024 1024 def __init__(self, ui, fp):
1025 1025 super(interrupthandler, self).__init__(fp)
1026 1026 self.ui = ui
1027 1027
1028 1028 def _readpartheader(self):
1029 1029 """reads a part header size and return the bytes blob
1030 1030
1031 1031 returns None if empty"""
1032 1032 headersize = self._unpack(_fpartheadersize)[0]
1033 1033 if headersize < 0:
1034 1034 raise error.BundleValueError('negative part header size: %i'
1035 1035 % headersize)
1036 1036 indebug(self.ui, 'part header size: %i\n' % headersize)
1037 1037 if headersize:
1038 1038 return self._readexact(headersize)
1039 1039 return None
1040 1040
1041 1041 def __call__(self):
1042 1042
1043 1043 self.ui.debug('bundle2-input-stream-interrupt:'
1044 1044 ' opening out of band context\n')
1045 1045 indebug(self.ui, 'bundle2 stream interruption, looking for a part.')
1046 1046 headerblock = self._readpartheader()
1047 1047 if headerblock is None:
1048 1048 indebug(self.ui, 'no part found during interruption.')
1049 1049 return
1050 1050 part = unbundlepart(self.ui, headerblock, self._fp)
1051 1051 op = interruptoperation(self.ui)
1052 1052 _processpart(op, part)
1053 1053 self.ui.debug('bundle2-input-stream-interrupt:'
1054 1054 ' closing out of band context\n')
1055 1055
1056 1056 class interruptoperation(object):
1057 1057 """A limited operation to be use by part handler during interruption
1058 1058
1059 1059 It only have access to an ui object.
1060 1060 """
1061 1061
1062 1062 def __init__(self, ui):
1063 1063 self.ui = ui
1064 1064 self.reply = None
1065 1065 self.captureoutput = False
1066 1066
1067 1067 @property
1068 1068 def repo(self):
1069 1069 raise RuntimeError('no repo access from stream interruption')
1070 1070
1071 1071 def gettransaction(self):
1072 1072 raise TransactionUnavailable('no repo access from stream interruption')
1073 1073
1074 1074 class unbundlepart(unpackermixin):
1075 1075 """a bundle part read from a bundle"""
1076 1076
1077 1077 def __init__(self, ui, header, fp):
1078 1078 super(unbundlepart, self).__init__(fp)
1079 1079 self.ui = ui
1080 1080 # unbundle state attr
1081 1081 self._headerdata = header
1082 1082 self._headeroffset = 0
1083 1083 self._initialized = False
1084 1084 self.consumed = False
1085 1085 # part data
1086 1086 self.id = None
1087 1087 self.type = None
1088 1088 self.mandatoryparams = None
1089 1089 self.advisoryparams = None
1090 1090 self.params = None
1091 1091 self.mandatorykeys = ()
1092 1092 self._payloadstream = None
1093 1093 self._readheader()
1094 1094 self._mandatory = None
1095 1095 self._chunkindex = [] #(payload, file) position tuples for chunk starts
1096 1096 self._pos = 0
1097 1097
1098 1098 def _fromheader(self, size):
1099 1099 """return the next <size> byte from the header"""
1100 1100 offset = self._headeroffset
1101 1101 data = self._headerdata[offset:(offset + size)]
1102 1102 self._headeroffset = offset + size
1103 1103 return data
1104 1104
1105 1105 def _unpackheader(self, format):
1106 1106 """read given format from header
1107 1107
1108 1108 This automatically compute the size of the format to read."""
1109 1109 data = self._fromheader(struct.calcsize(format))
1110 1110 return _unpack(format, data)
1111 1111
1112 1112 def _initparams(self, mandatoryparams, advisoryparams):
1113 1113 """internal function to setup all logic related parameters"""
1114 1114 # make it read only to prevent people touching it by mistake.
1115 1115 self.mandatoryparams = tuple(mandatoryparams)
1116 1116 self.advisoryparams = tuple(advisoryparams)
1117 1117 # user friendly UI
1118 1118 self.params = util.sortdict(self.mandatoryparams)
1119 1119 self.params.update(self.advisoryparams)
1120 1120 self.mandatorykeys = frozenset(p[0] for p in mandatoryparams)
1121 1121
1122 1122 def _payloadchunks(self, chunknum=0):
1123 1123 '''seek to specified chunk and start yielding data'''
1124 1124 if len(self._chunkindex) == 0:
1125 1125 assert chunknum == 0, 'Must start with chunk 0'
1126 1126 self._chunkindex.append((0, super(unbundlepart, self).tell()))
1127 1127 else:
1128 1128 assert chunknum < len(self._chunkindex), \
1129 1129 'Unknown chunk %d' % chunknum
1130 1130 super(unbundlepart, self).seek(self._chunkindex[chunknum][1])
1131 1131
1132 1132 pos = self._chunkindex[chunknum][0]
1133 1133 payloadsize = self._unpack(_fpayloadsize)[0]
1134 1134 indebug(self.ui, 'payload chunk size: %i' % payloadsize)
1135 1135 while payloadsize:
1136 1136 if payloadsize == flaginterrupt:
1137 1137 # interruption detection, the handler will now read a
1138 1138 # single part and process it.
1139 1139 interrupthandler(self.ui, self._fp)()
1140 1140 elif payloadsize < 0:
1141 1141 msg = 'negative payload chunk size: %i' % payloadsize
1142 1142 raise error.BundleValueError(msg)
1143 1143 else:
1144 1144 result = self._readexact(payloadsize)
1145 1145 chunknum += 1
1146 1146 pos += payloadsize
1147 1147 if chunknum == len(self._chunkindex):
1148 1148 self._chunkindex.append((pos,
1149 1149 super(unbundlepart, self).tell()))
1150 1150 yield result
1151 1151 payloadsize = self._unpack(_fpayloadsize)[0]
1152 1152 indebug(self.ui, 'payload chunk size: %i' % payloadsize)
1153 1153
1154 1154 def _findchunk(self, pos):
1155 1155 '''for a given payload position, return a chunk number and offset'''
1156 1156 for chunk, (ppos, fpos) in enumerate(self._chunkindex):
1157 1157 if ppos == pos:
1158 1158 return chunk, 0
1159 1159 elif ppos > pos:
1160 1160 return chunk - 1, pos - self._chunkindex[chunk - 1][0]
1161 1161 raise ValueError('Unknown chunk')
1162 1162
1163 1163 def _readheader(self):
1164 1164 """read the header and setup the object"""
1165 1165 typesize = self._unpackheader(_fparttypesize)[0]
1166 1166 self.type = self._fromheader(typesize)
1167 1167 indebug(self.ui, 'part type: "%s"' % self.type)
1168 1168 self.id = self._unpackheader(_fpartid)[0]
1169 1169 indebug(self.ui, 'part id: "%s"' % self.id)
1170 1170 # extract mandatory bit from type
1171 1171 self.mandatory = (self.type != self.type.lower())
1172 1172 self.type = self.type.lower()
1173 1173 ## reading parameters
1174 1174 # param count
1175 1175 mancount, advcount = self._unpackheader(_fpartparamcount)
1176 1176 indebug(self.ui, 'part parameters: %i' % (mancount + advcount))
1177 1177 # param size
1178 1178 fparamsizes = _makefpartparamsizes(mancount + advcount)
1179 1179 paramsizes = self._unpackheader(fparamsizes)
1180 1180 # make it a list of couple again
1181 1181 paramsizes = zip(paramsizes[::2], paramsizes[1::2])
1182 1182 # split mandatory from advisory
1183 1183 mansizes = paramsizes[:mancount]
1184 1184 advsizes = paramsizes[mancount:]
1185 1185 # retrieve param value
1186 1186 manparams = []
1187 1187 for key, value in mansizes:
1188 1188 manparams.append((self._fromheader(key), self._fromheader(value)))
1189 1189 advparams = []
1190 1190 for key, value in advsizes:
1191 1191 advparams.append((self._fromheader(key), self._fromheader(value)))
1192 1192 self._initparams(manparams, advparams)
1193 1193 ## part payload
1194 1194 self._payloadstream = util.chunkbuffer(self._payloadchunks())
1195 1195 # we read the data, tell it
1196 1196 self._initialized = True
1197 1197
1198 1198 def read(self, size=None):
1199 1199 """read payload data"""
1200 1200 if not self._initialized:
1201 1201 self._readheader()
1202 1202 if size is None:
1203 1203 data = self._payloadstream.read()
1204 1204 else:
1205 1205 data = self._payloadstream.read(size)
1206 1206 self._pos += len(data)
1207 1207 if size is None or len(data) < size:
1208 1208 if not self.consumed and self._pos:
1209 1209 self.ui.debug('bundle2-input-part: total payload size %i\n'
1210 1210 % self._pos)
1211 1211 self.consumed = True
1212 1212 return data
1213 1213
1214 1214 def tell(self):
1215 1215 return self._pos
1216 1216
1217 1217 def seek(self, offset, whence=0):
1218 1218 if whence == 0:
1219 1219 newpos = offset
1220 1220 elif whence == 1:
1221 1221 newpos = self._pos + offset
1222 1222 elif whence == 2:
1223 1223 if not self.consumed:
1224 1224 self.read()
1225 1225 newpos = self._chunkindex[-1][0] - offset
1226 1226 else:
1227 1227 raise ValueError('Unknown whence value: %r' % (whence,))
1228 1228
1229 1229 if newpos > self._chunkindex[-1][0] and not self.consumed:
1230 1230 self.read()
1231 1231 if not 0 <= newpos <= self._chunkindex[-1][0]:
1232 1232 raise ValueError('Offset out of range')
1233 1233
1234 1234 if self._pos != newpos:
1235 1235 chunk, internaloffset = self._findchunk(newpos)
1236 1236 self._payloadstream = util.chunkbuffer(self._payloadchunks(chunk))
1237 1237 adjust = self.read(internaloffset)
1238 1238 if len(adjust) != internaloffset:
1239 1239 raise error.Abort(_('Seek failed\n'))
1240 1240 self._pos = newpos
1241 1241
1242 1242 # These are only the static capabilities.
1243 1243 # Check the 'getrepocaps' function for the rest.
1244 1244 capabilities = {'HG20': (),
1245 1245 'error': ('abort', 'unsupportedcontent', 'pushraced',
1246 1246 'pushkey'),
1247 1247 'listkeys': (),
1248 1248 'pushkey': (),
1249 1249 'digests': tuple(sorted(util.DIGESTS.keys())),
1250 1250 'remote-changegroup': ('http', 'https'),
1251 1251 'hgtagsfnodes': (),
1252 1252 }
1253 1253
1254 1254 def getrepocaps(repo, allowpushback=False):
1255 1255 """return the bundle2 capabilities for a given repo
1256 1256
1257 1257 Exists to allow extensions (like evolution) to mutate the capabilities.
1258 1258 """
1259 1259 caps = capabilities.copy()
1260 1260 caps['changegroup'] = tuple(sorted(
1261 1261 changegroup.supportedincomingversions(repo)))
1262 1262 if obsolete.isenabled(repo, obsolete.exchangeopt):
1263 1263 supportedformat = tuple('V%i' % v for v in obsolete.formats)
1264 1264 caps['obsmarkers'] = supportedformat
1265 1265 if allowpushback:
1266 1266 caps['pushback'] = ()
1267 1267 return caps
1268 1268
1269 1269 def bundle2caps(remote):
1270 1270 """return the bundle capabilities of a peer as dict"""
1271 1271 raw = remote.capable('bundle2')
1272 1272 if not raw and raw != '':
1273 1273 return {}
1274 1274 capsblob = urlreq.unquote(remote.capable('bundle2'))
1275 1275 return decodecaps(capsblob)
1276 1276
1277 1277 def obsmarkersversion(caps):
1278 1278 """extract the list of supported obsmarkers versions from a bundle2caps dict
1279 1279 """
1280 1280 obscaps = caps.get('obsmarkers', ())
1281 1281 return [int(c[1:]) for c in obscaps if c.startswith('V')]
1282 1282
1283 1283 def writebundle(ui, cg, filename, bundletype, vfs=None, compression=None):
1284 1284 """Write a bundle file and return its filename.
1285 1285
1286 1286 Existing files will not be overwritten.
1287 1287 If no filename is specified, a temporary file is created.
1288 1288 bz2 compression can be turned off.
1289 1289 The bundle file will be deleted in case of errors.
1290 1290 """
1291 1291
1292 1292 if bundletype == "HG20":
1293 1293 bundle = bundle20(ui)
1294 1294 bundle.setcompression(compression)
1295 1295 part = bundle.newpart('changegroup', data=cg.getchunks())
1296 1296 part.addparam('version', cg.version)
1297 if 'clcount' in cg.extras:
1298 part.addparam('nbchanges', str(cg.extras['clcount']),
1299 mandatory=False)
1297 1300 chunkiter = bundle.getchunks()
1298 1301 else:
1299 1302 # compression argument is only for the bundle2 case
1300 1303 assert compression is None
1301 1304 if cg.version != '01':
1302 1305 raise error.Abort(_('old bundle types only supports v1 '
1303 1306 'changegroups'))
1304 1307 header, comp = bundletypes[bundletype]
1305 1308 if comp not in util.compressors:
1306 1309 raise error.Abort(_('unknown stream compression type: %s')
1307 1310 % comp)
1308 1311 z = util.compressors[comp]()
1309 1312 subchunkiter = cg.getchunks()
1310 1313 def chunkiter():
1311 1314 yield header
1312 1315 for chunk in subchunkiter:
1313 1316 yield z.compress(chunk)
1314 1317 yield z.flush()
1315 1318 chunkiter = chunkiter()
1316 1319
1317 1320 # parse the changegroup data, otherwise we will block
1318 1321 # in case of sshrepo because we don't know the end of the stream
1319 1322 return changegroup.writechunks(ui, chunkiter, filename, vfs=vfs)
1320 1323
1321 1324 @parthandler('changegroup', ('version', 'nbchanges', 'treemanifest'))
1322 1325 def handlechangegroup(op, inpart):
1323 1326 """apply a changegroup part on the repo
1324 1327
1325 1328 This is a very early implementation that will massive rework before being
1326 1329 inflicted to any end-user.
1327 1330 """
1328 1331 # Make sure we trigger a transaction creation
1329 1332 #
1330 1333 # The addchangegroup function will get a transaction object by itself, but
1331 1334 # we need to make sure we trigger the creation of a transaction object used
1332 1335 # for the whole processing scope.
1333 1336 op.gettransaction()
1334 1337 unpackerversion = inpart.params.get('version', '01')
1335 1338 # We should raise an appropriate exception here
1336 1339 cg = changegroup.getunbundler(unpackerversion, inpart, None)
1337 1340 # the source and url passed here are overwritten by the one contained in
1338 1341 # the transaction.hookargs argument. So 'bundle2' is a placeholder
1339 1342 nbchangesets = None
1340 1343 if 'nbchanges' in inpart.params:
1341 1344 nbchangesets = int(inpart.params.get('nbchanges'))
1342 1345 if ('treemanifest' in inpart.params and
1343 1346 'treemanifest' not in op.repo.requirements):
1344 1347 if len(op.repo.changelog) != 0:
1345 1348 raise error.Abort(_(
1346 1349 "bundle contains tree manifests, but local repo is "
1347 1350 "non-empty and does not use tree manifests"))
1348 1351 op.repo.requirements.add('treemanifest')
1349 1352 op.repo._applyopenerreqs()
1350 1353 op.repo._writerequirements()
1351 1354 ret = cg.apply(op.repo, 'bundle2', 'bundle2', expectedtotal=nbchangesets)
1352 1355 op.records.add('changegroup', {'return': ret})
1353 1356 if op.reply is not None:
1354 1357 # This is definitely not the final form of this
1355 1358 # return. But one need to start somewhere.
1356 1359 part = op.reply.newpart('reply:changegroup', mandatory=False)
1357 1360 part.addparam('in-reply-to', str(inpart.id), mandatory=False)
1358 1361 part.addparam('return', '%i' % ret, mandatory=False)
1359 1362 assert not inpart.read()
1360 1363
1361 1364 _remotechangegroupparams = tuple(['url', 'size', 'digests'] +
1362 1365 ['digest:%s' % k for k in util.DIGESTS.keys()])
1363 1366 @parthandler('remote-changegroup', _remotechangegroupparams)
1364 1367 def handleremotechangegroup(op, inpart):
1365 1368 """apply a bundle10 on the repo, given an url and validation information
1366 1369
1367 1370 All the information about the remote bundle to import are given as
1368 1371 parameters. The parameters include:
1369 1372 - url: the url to the bundle10.
1370 1373 - size: the bundle10 file size. It is used to validate what was
1371 1374 retrieved by the client matches the server knowledge about the bundle.
1372 1375 - digests: a space separated list of the digest types provided as
1373 1376 parameters.
1374 1377 - digest:<digest-type>: the hexadecimal representation of the digest with
1375 1378 that name. Like the size, it is used to validate what was retrieved by
1376 1379 the client matches what the server knows about the bundle.
1377 1380
1378 1381 When multiple digest types are given, all of them are checked.
1379 1382 """
1380 1383 try:
1381 1384 raw_url = inpart.params['url']
1382 1385 except KeyError:
1383 1386 raise error.Abort(_('remote-changegroup: missing "%s" param') % 'url')
1384 1387 parsed_url = util.url(raw_url)
1385 1388 if parsed_url.scheme not in capabilities['remote-changegroup']:
1386 1389 raise error.Abort(_('remote-changegroup does not support %s urls') %
1387 1390 parsed_url.scheme)
1388 1391
1389 1392 try:
1390 1393 size = int(inpart.params['size'])
1391 1394 except ValueError:
1392 1395 raise error.Abort(_('remote-changegroup: invalid value for param "%s"')
1393 1396 % 'size')
1394 1397 except KeyError:
1395 1398 raise error.Abort(_('remote-changegroup: missing "%s" param') % 'size')
1396 1399
1397 1400 digests = {}
1398 1401 for typ in inpart.params.get('digests', '').split():
1399 1402 param = 'digest:%s' % typ
1400 1403 try:
1401 1404 value = inpart.params[param]
1402 1405 except KeyError:
1403 1406 raise error.Abort(_('remote-changegroup: missing "%s" param') %
1404 1407 param)
1405 1408 digests[typ] = value
1406 1409
1407 1410 real_part = util.digestchecker(url.open(op.ui, raw_url), size, digests)
1408 1411
1409 1412 # Make sure we trigger a transaction creation
1410 1413 #
1411 1414 # The addchangegroup function will get a transaction object by itself, but
1412 1415 # we need to make sure we trigger the creation of a transaction object used
1413 1416 # for the whole processing scope.
1414 1417 op.gettransaction()
1415 1418 from . import exchange
1416 1419 cg = exchange.readbundle(op.repo.ui, real_part, raw_url)
1417 1420 if not isinstance(cg, changegroup.cg1unpacker):
1418 1421 raise error.Abort(_('%s: not a bundle version 1.0') %
1419 1422 util.hidepassword(raw_url))
1420 1423 ret = cg.apply(op.repo, 'bundle2', 'bundle2')
1421 1424 op.records.add('changegroup', {'return': ret})
1422 1425 if op.reply is not None:
1423 1426 # This is definitely not the final form of this
1424 1427 # return. But one need to start somewhere.
1425 1428 part = op.reply.newpart('reply:changegroup')
1426 1429 part.addparam('in-reply-to', str(inpart.id), mandatory=False)
1427 1430 part.addparam('return', '%i' % ret, mandatory=False)
1428 1431 try:
1429 1432 real_part.validate()
1430 1433 except error.Abort as e:
1431 1434 raise error.Abort(_('bundle at %s is corrupted:\n%s') %
1432 1435 (util.hidepassword(raw_url), str(e)))
1433 1436 assert not inpart.read()
1434 1437
1435 1438 @parthandler('reply:changegroup', ('return', 'in-reply-to'))
1436 1439 def handlereplychangegroup(op, inpart):
1437 1440 ret = int(inpart.params['return'])
1438 1441 replyto = int(inpart.params['in-reply-to'])
1439 1442 op.records.add('changegroup', {'return': ret}, replyto)
1440 1443
1441 1444 @parthandler('check:heads')
1442 1445 def handlecheckheads(op, inpart):
1443 1446 """check that head of the repo did not change
1444 1447
1445 1448 This is used to detect a push race when using unbundle.
1446 1449 This replaces the "heads" argument of unbundle."""
1447 1450 h = inpart.read(20)
1448 1451 heads = []
1449 1452 while len(h) == 20:
1450 1453 heads.append(h)
1451 1454 h = inpart.read(20)
1452 1455 assert not h
1453 1456 # Trigger a transaction so that we are guaranteed to have the lock now.
1454 1457 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1455 1458 op.gettransaction()
1456 1459 if sorted(heads) != sorted(op.repo.heads()):
1457 1460 raise error.PushRaced('repository changed while pushing - '
1458 1461 'please try again')
1459 1462
1460 1463 @parthandler('output')
1461 1464 def handleoutput(op, inpart):
1462 1465 """forward output captured on the server to the client"""
1463 1466 for line in inpart.read().splitlines():
1464 1467 op.ui.status(('remote: %s\n' % line))
1465 1468
1466 1469 @parthandler('replycaps')
1467 1470 def handlereplycaps(op, inpart):
1468 1471 """Notify that a reply bundle should be created
1469 1472
1470 1473 The payload contains the capabilities information for the reply"""
1471 1474 caps = decodecaps(inpart.read())
1472 1475 if op.reply is None:
1473 1476 op.reply = bundle20(op.ui, caps)
1474 1477
1475 1478 class AbortFromPart(error.Abort):
1476 1479 """Sub-class of Abort that denotes an error from a bundle2 part."""
1477 1480
1478 1481 @parthandler('error:abort', ('message', 'hint'))
1479 1482 def handleerrorabort(op, inpart):
1480 1483 """Used to transmit abort error over the wire"""
1481 1484 raise AbortFromPart(inpart.params['message'],
1482 1485 hint=inpart.params.get('hint'))
1483 1486
1484 1487 @parthandler('error:pushkey', ('namespace', 'key', 'new', 'old', 'ret',
1485 1488 'in-reply-to'))
1486 1489 def handleerrorpushkey(op, inpart):
1487 1490 """Used to transmit failure of a mandatory pushkey over the wire"""
1488 1491 kwargs = {}
1489 1492 for name in ('namespace', 'key', 'new', 'old', 'ret'):
1490 1493 value = inpart.params.get(name)
1491 1494 if value is not None:
1492 1495 kwargs[name] = value
1493 1496 raise error.PushkeyFailed(inpart.params['in-reply-to'], **kwargs)
1494 1497
1495 1498 @parthandler('error:unsupportedcontent', ('parttype', 'params'))
1496 1499 def handleerrorunsupportedcontent(op, inpart):
1497 1500 """Used to transmit unknown content error over the wire"""
1498 1501 kwargs = {}
1499 1502 parttype = inpart.params.get('parttype')
1500 1503 if parttype is not None:
1501 1504 kwargs['parttype'] = parttype
1502 1505 params = inpart.params.get('params')
1503 1506 if params is not None:
1504 1507 kwargs['params'] = params.split('\0')
1505 1508
1506 1509 raise error.BundleUnknownFeatureError(**kwargs)
1507 1510
1508 1511 @parthandler('error:pushraced', ('message',))
1509 1512 def handleerrorpushraced(op, inpart):
1510 1513 """Used to transmit push race error over the wire"""
1511 1514 raise error.ResponseError(_('push failed:'), inpart.params['message'])
1512 1515
1513 1516 @parthandler('listkeys', ('namespace',))
1514 1517 def handlelistkeys(op, inpart):
1515 1518 """retrieve pushkey namespace content stored in a bundle2"""
1516 1519 namespace = inpart.params['namespace']
1517 1520 r = pushkey.decodekeys(inpart.read())
1518 1521 op.records.add('listkeys', (namespace, r))
1519 1522
1520 1523 @parthandler('pushkey', ('namespace', 'key', 'old', 'new'))
1521 1524 def handlepushkey(op, inpart):
1522 1525 """process a pushkey request"""
1523 1526 dec = pushkey.decode
1524 1527 namespace = dec(inpart.params['namespace'])
1525 1528 key = dec(inpart.params['key'])
1526 1529 old = dec(inpart.params['old'])
1527 1530 new = dec(inpart.params['new'])
1528 1531 # Grab the transaction to ensure that we have the lock before performing the
1529 1532 # pushkey.
1530 1533 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1531 1534 op.gettransaction()
1532 1535 ret = op.repo.pushkey(namespace, key, old, new)
1533 1536 record = {'namespace': namespace,
1534 1537 'key': key,
1535 1538 'old': old,
1536 1539 'new': new}
1537 1540 op.records.add('pushkey', record)
1538 1541 if op.reply is not None:
1539 1542 rpart = op.reply.newpart('reply:pushkey')
1540 1543 rpart.addparam('in-reply-to', str(inpart.id), mandatory=False)
1541 1544 rpart.addparam('return', '%i' % ret, mandatory=False)
1542 1545 if inpart.mandatory and not ret:
1543 1546 kwargs = {}
1544 1547 for key in ('namespace', 'key', 'new', 'old', 'ret'):
1545 1548 if key in inpart.params:
1546 1549 kwargs[key] = inpart.params[key]
1547 1550 raise error.PushkeyFailed(partid=str(inpart.id), **kwargs)
1548 1551
1549 1552 @parthandler('reply:pushkey', ('return', 'in-reply-to'))
1550 1553 def handlepushkeyreply(op, inpart):
1551 1554 """retrieve the result of a pushkey request"""
1552 1555 ret = int(inpart.params['return'])
1553 1556 partid = int(inpart.params['in-reply-to'])
1554 1557 op.records.add('pushkey', {'return': ret}, partid)
1555 1558
1556 1559 @parthandler('obsmarkers')
1557 1560 def handleobsmarker(op, inpart):
1558 1561 """add a stream of obsmarkers to the repo"""
1559 1562 tr = op.gettransaction()
1560 1563 markerdata = inpart.read()
1561 1564 if op.ui.config('experimental', 'obsmarkers-exchange-debug', False):
1562 1565 op.ui.write(('obsmarker-exchange: %i bytes received\n')
1563 1566 % len(markerdata))
1564 1567 # The mergemarkers call will crash if marker creation is not enabled.
1565 1568 # we want to avoid this if the part is advisory.
1566 1569 if not inpart.mandatory and op.repo.obsstore.readonly:
1567 1570 op.repo.ui.debug('ignoring obsolescence markers, feature not enabled')
1568 1571 return
1569 1572 new = op.repo.obsstore.mergemarkers(tr, markerdata)
1570 1573 if new:
1571 1574 op.repo.ui.status(_('%i new obsolescence markers\n') % new)
1572 1575 op.records.add('obsmarkers', {'new': new})
1573 1576 if op.reply is not None:
1574 1577 rpart = op.reply.newpart('reply:obsmarkers')
1575 1578 rpart.addparam('in-reply-to', str(inpart.id), mandatory=False)
1576 1579 rpart.addparam('new', '%i' % new, mandatory=False)
1577 1580
1578 1581
1579 1582 @parthandler('reply:obsmarkers', ('new', 'in-reply-to'))
1580 1583 def handleobsmarkerreply(op, inpart):
1581 1584 """retrieve the result of a pushkey request"""
1582 1585 ret = int(inpart.params['new'])
1583 1586 partid = int(inpart.params['in-reply-to'])
1584 1587 op.records.add('obsmarkers', {'new': ret}, partid)
1585 1588
1586 1589 @parthandler('hgtagsfnodes')
1587 1590 def handlehgtagsfnodes(op, inpart):
1588 1591 """Applies .hgtags fnodes cache entries to the local repo.
1589 1592
1590 1593 Payload is pairs of 20 byte changeset nodes and filenodes.
1591 1594 """
1592 1595 # Grab the transaction so we ensure that we have the lock at this point.
1593 1596 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1594 1597 op.gettransaction()
1595 1598 cache = tags.hgtagsfnodescache(op.repo.unfiltered())
1596 1599
1597 1600 count = 0
1598 1601 while True:
1599 1602 node = inpart.read(20)
1600 1603 fnode = inpart.read(20)
1601 1604 if len(node) < 20 or len(fnode) < 20:
1602 1605 op.ui.debug('ignoring incomplete received .hgtags fnodes data\n')
1603 1606 break
1604 1607 cache.setfnode(node, fnode)
1605 1608 count += 1
1606 1609
1607 1610 cache.write()
1608 1611 op.ui.debug('applied %i hgtags fnodes cache entries\n' % count)
@@ -1,1063 +1,1065 b''
1 1 # changegroup.py - Mercurial changegroup manipulation functions
2 2 #
3 3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import os
11 11 import struct
12 12 import tempfile
13 13 import weakref
14 14
15 15 from .i18n import _
16 16 from .node import (
17 17 hex,
18 18 nullid,
19 19 nullrev,
20 20 short,
21 21 )
22 22
23 23 from . import (
24 24 branchmap,
25 25 dagutil,
26 26 discovery,
27 27 error,
28 28 mdiff,
29 29 phases,
30 30 util,
31 31 )
32 32
33 33 _CHANGEGROUPV1_DELTA_HEADER = "20s20s20s20s"
34 34 _CHANGEGROUPV2_DELTA_HEADER = "20s20s20s20s20s"
35 35 _CHANGEGROUPV3_DELTA_HEADER = ">20s20s20s20s20sH"
36 36
37 37 def readexactly(stream, n):
38 38 '''read n bytes from stream.read and abort if less was available'''
39 39 s = stream.read(n)
40 40 if len(s) < n:
41 41 raise error.Abort(_("stream ended unexpectedly"
42 42 " (got %d bytes, expected %d)")
43 43 % (len(s), n))
44 44 return s
45 45
46 46 def getchunk(stream):
47 47 """return the next chunk from stream as a string"""
48 48 d = readexactly(stream, 4)
49 49 l = struct.unpack(">l", d)[0]
50 50 if l <= 4:
51 51 if l:
52 52 raise error.Abort(_("invalid chunk length %d") % l)
53 53 return ""
54 54 return readexactly(stream, l - 4)
55 55
56 56 def chunkheader(length):
57 57 """return a changegroup chunk header (string)"""
58 58 return struct.pack(">l", length + 4)
59 59
60 60 def closechunk():
61 61 """return a changegroup chunk header (string) for a zero-length chunk"""
62 62 return struct.pack(">l", 0)
63 63
64 64 def combineresults(results):
65 65 """logic to combine 0 or more addchangegroup results into one"""
66 66 changedheads = 0
67 67 result = 1
68 68 for ret in results:
69 69 # If any changegroup result is 0, return 0
70 70 if ret == 0:
71 71 result = 0
72 72 break
73 73 if ret < -1:
74 74 changedheads += ret + 1
75 75 elif ret > 1:
76 76 changedheads += ret - 1
77 77 if changedheads > 0:
78 78 result = 1 + changedheads
79 79 elif changedheads < 0:
80 80 result = -1 + changedheads
81 81 return result
82 82
83 83 def writechunks(ui, chunks, filename, vfs=None):
84 84 """Write chunks to a file and return its filename.
85 85
86 86 The stream is assumed to be a bundle file.
87 87 Existing files will not be overwritten.
88 88 If no filename is specified, a temporary file is created.
89 89 """
90 90 fh = None
91 91 cleanup = None
92 92 try:
93 93 if filename:
94 94 if vfs:
95 95 fh = vfs.open(filename, "wb")
96 96 else:
97 97 fh = open(filename, "wb")
98 98 else:
99 99 fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg")
100 100 fh = os.fdopen(fd, "wb")
101 101 cleanup = filename
102 102 for c in chunks:
103 103 fh.write(c)
104 104 cleanup = None
105 105 return filename
106 106 finally:
107 107 if fh is not None:
108 108 fh.close()
109 109 if cleanup is not None:
110 110 if filename and vfs:
111 111 vfs.unlink(cleanup)
112 112 else:
113 113 os.unlink(cleanup)
114 114
115 115 class cg1unpacker(object):
116 116 """Unpacker for cg1 changegroup streams.
117 117
118 118 A changegroup unpacker handles the framing of the revision data in
119 119 the wire format. Most consumers will want to use the apply()
120 120 method to add the changes from the changegroup to a repository.
121 121
122 122 If you're forwarding a changegroup unmodified to another consumer,
123 123 use getchunks(), which returns an iterator of changegroup
124 124 chunks. This is mostly useful for cases where you need to know the
125 125 data stream has ended by observing the end of the changegroup.
126 126
127 127 deltachunk() is useful only if you're applying delta data. Most
128 128 consumers should prefer apply() instead.
129 129
130 130 A few other public methods exist. Those are used only for
131 131 bundlerepo and some debug commands - their use is discouraged.
132 132 """
133 133 deltaheader = _CHANGEGROUPV1_DELTA_HEADER
134 134 deltaheadersize = struct.calcsize(deltaheader)
135 135 version = '01'
136 136 _grouplistcount = 1 # One list of files after the manifests
137 137
138 def __init__(self, fh, alg):
138 def __init__(self, fh, alg, extras=None):
139 139 if alg == 'UN':
140 140 alg = None # get more modern without breaking too much
141 141 if not alg in util.decompressors:
142 142 raise error.Abort(_('unknown stream compression type: %s')
143 143 % alg)
144 144 if alg == 'BZ':
145 145 alg = '_truncatedBZ'
146 146 self._stream = util.decompressors[alg](fh)
147 147 self._type = alg
148 self.extras = extras or {}
148 149 self.callback = None
149 150
150 151 # These methods (compressed, read, seek, tell) all appear to only
151 152 # be used by bundlerepo, but it's a little hard to tell.
152 153 def compressed(self):
153 154 return self._type is not None
154 155 def read(self, l):
155 156 return self._stream.read(l)
156 157 def seek(self, pos):
157 158 return self._stream.seek(pos)
158 159 def tell(self):
159 160 return self._stream.tell()
160 161 def close(self):
161 162 return self._stream.close()
162 163
163 164 def _chunklength(self):
164 165 d = readexactly(self._stream, 4)
165 166 l = struct.unpack(">l", d)[0]
166 167 if l <= 4:
167 168 if l:
168 169 raise error.Abort(_("invalid chunk length %d") % l)
169 170 return 0
170 171 if self.callback:
171 172 self.callback()
172 173 return l - 4
173 174
174 175 def changelogheader(self):
175 176 """v10 does not have a changelog header chunk"""
176 177 return {}
177 178
178 179 def manifestheader(self):
179 180 """v10 does not have a manifest header chunk"""
180 181 return {}
181 182
182 183 def filelogheader(self):
183 184 """return the header of the filelogs chunk, v10 only has the filename"""
184 185 l = self._chunklength()
185 186 if not l:
186 187 return {}
187 188 fname = readexactly(self._stream, l)
188 189 return {'filename': fname}
189 190
190 191 def _deltaheader(self, headertuple, prevnode):
191 192 node, p1, p2, cs = headertuple
192 193 if prevnode is None:
193 194 deltabase = p1
194 195 else:
195 196 deltabase = prevnode
196 197 flags = 0
197 198 return node, p1, p2, deltabase, cs, flags
198 199
199 200 def deltachunk(self, prevnode):
200 201 l = self._chunklength()
201 202 if not l:
202 203 return {}
203 204 headerdata = readexactly(self._stream, self.deltaheadersize)
204 205 header = struct.unpack(self.deltaheader, headerdata)
205 206 delta = readexactly(self._stream, l - self.deltaheadersize)
206 207 node, p1, p2, deltabase, cs, flags = self._deltaheader(header, prevnode)
207 208 return {'node': node, 'p1': p1, 'p2': p2, 'cs': cs,
208 209 'deltabase': deltabase, 'delta': delta, 'flags': flags}
209 210
210 211 def getchunks(self):
211 212 """returns all the chunks contains in the bundle
212 213
213 214 Used when you need to forward the binary stream to a file or another
214 215 network API. To do so, it parse the changegroup data, otherwise it will
215 216 block in case of sshrepo because it don't know the end of the stream.
216 217 """
217 218 # an empty chunkgroup is the end of the changegroup
218 219 # a changegroup has at least 2 chunkgroups (changelog and manifest).
219 220 # after that, changegroup versions 1 and 2 have a series of groups
220 221 # with one group per file. changegroup 3 has a series of directory
221 222 # manifests before the files.
222 223 count = 0
223 224 emptycount = 0
224 225 while emptycount < self._grouplistcount:
225 226 empty = True
226 227 count += 1
227 228 while True:
228 229 chunk = getchunk(self)
229 230 if not chunk:
230 231 if empty and count > 2:
231 232 emptycount += 1
232 233 break
233 234 empty = False
234 235 yield chunkheader(len(chunk))
235 236 pos = 0
236 237 while pos < len(chunk):
237 238 next = pos + 2**20
238 239 yield chunk[pos:next]
239 240 pos = next
240 241 yield closechunk()
241 242
242 243 def _unpackmanifests(self, repo, revmap, trp, prog, numchanges):
243 244 # We know that we'll never have more manifests than we had
244 245 # changesets.
245 246 self.callback = prog(_('manifests'), numchanges)
246 247 # no need to check for empty manifest group here:
247 248 # if the result of the merge of 1 and 2 is the same in 3 and 4,
248 249 # no new manifest will be created and the manifest group will
249 250 # be empty during the pull
250 251 self.manifestheader()
251 252 repo.manifest.addgroup(self, revmap, trp)
252 253 repo.ui.progress(_('manifests'), None)
253 254 self.callback = None
254 255
255 256 def apply(self, repo, srctype, url, emptyok=False,
256 257 targetphase=phases.draft, expectedtotal=None):
257 258 """Add the changegroup returned by source.read() to this repo.
258 259 srctype is a string like 'push', 'pull', or 'unbundle'. url is
259 260 the URL of the repo where this changegroup is coming from.
260 261
261 262 Return an integer summarizing the change to this repo:
262 263 - nothing changed or no source: 0
263 264 - more heads than before: 1+added heads (2..n)
264 265 - fewer heads than before: -1-removed heads (-2..-n)
265 266 - number of heads stays the same: 1
266 267 """
267 268 repo = repo.unfiltered()
268 269 def csmap(x):
269 270 repo.ui.debug("add changeset %s\n" % short(x))
270 271 return len(cl)
271 272
272 273 def revmap(x):
273 274 return cl.rev(x)
274 275
275 276 changesets = files = revisions = 0
276 277
277 278 try:
278 279 with repo.transaction("\n".join([srctype,
279 280 util.hidepassword(url)])) as tr:
280 281 # The transaction could have been created before and already
281 282 # carries source information. In this case we use the top
282 283 # level data. We overwrite the argument because we need to use
283 284 # the top level value (if they exist) in this function.
284 285 srctype = tr.hookargs.setdefault('source', srctype)
285 286 url = tr.hookargs.setdefault('url', url)
286 287 repo.hook('prechangegroup', throw=True, **tr.hookargs)
287 288
288 289 # write changelog data to temp files so concurrent readers
289 290 # will not see an inconsistent view
290 291 cl = repo.changelog
291 292 cl.delayupdate(tr)
292 293 oldheads = cl.heads()
293 294
294 295 trp = weakref.proxy(tr)
295 296 # pull off the changeset group
296 297 repo.ui.status(_("adding changesets\n"))
297 298 clstart = len(cl)
298 299 class prog(object):
299 300 def __init__(self, step, total):
300 301 self._step = step
301 302 self._total = total
302 303 self._count = 1
303 304 def __call__(self):
304 305 repo.ui.progress(self._step, self._count,
305 306 unit=_('chunks'), total=self._total)
306 307 self._count += 1
307 308 self.callback = prog(_('changesets'), expectedtotal)
308 309
309 310 efiles = set()
310 311 def onchangelog(cl, node):
311 312 efiles.update(cl.readfiles(node))
312 313
313 314 self.changelogheader()
314 315 srccontent = cl.addgroup(self, csmap, trp,
315 316 addrevisioncb=onchangelog)
316 317 efiles = len(efiles)
317 318
318 319 if not (srccontent or emptyok):
319 320 raise error.Abort(_("received changelog group is empty"))
320 321 clend = len(cl)
321 322 changesets = clend - clstart
322 323 repo.ui.progress(_('changesets'), None)
323 324 self.callback = None
324 325
325 326 # pull off the manifest group
326 327 repo.ui.status(_("adding manifests\n"))
327 328 self._unpackmanifests(repo, revmap, trp, prog, changesets)
328 329
329 330 needfiles = {}
330 331 if repo.ui.configbool('server', 'validate', default=False):
331 332 # validate incoming csets have their manifests
332 333 for cset in xrange(clstart, clend):
333 334 mfnode = repo.changelog.read(
334 335 repo.changelog.node(cset))[0]
335 336 mfest = repo.manifest.readdelta(mfnode)
336 337 # store file nodes we must see
337 338 for f, n in mfest.iteritems():
338 339 needfiles.setdefault(f, set()).add(n)
339 340
340 341 # process the files
341 342 repo.ui.status(_("adding file changes\n"))
342 343 newrevs, newfiles = _addchangegroupfiles(
343 344 repo, self, revmap, trp, efiles, needfiles)
344 345 revisions += newrevs
345 346 files += newfiles
346 347
347 348 dh = 0
348 349 if oldheads:
349 350 heads = cl.heads()
350 351 dh = len(heads) - len(oldheads)
351 352 for h in heads:
352 353 if h not in oldheads and repo[h].closesbranch():
353 354 dh -= 1
354 355 htext = ""
355 356 if dh:
356 357 htext = _(" (%+d heads)") % dh
357 358
358 359 repo.ui.status(_("added %d changesets"
359 360 " with %d changes to %d files%s\n")
360 361 % (changesets, revisions, files, htext))
361 362 repo.invalidatevolatilesets()
362 363
363 364 if changesets > 0:
364 365 if 'node' not in tr.hookargs:
365 366 tr.hookargs['node'] = hex(cl.node(clstart))
366 367 tr.hookargs['node_last'] = hex(cl.node(clend - 1))
367 368 hookargs = dict(tr.hookargs)
368 369 else:
369 370 hookargs = dict(tr.hookargs)
370 371 hookargs['node'] = hex(cl.node(clstart))
371 372 hookargs['node_last'] = hex(cl.node(clend - 1))
372 373 repo.hook('pretxnchangegroup', throw=True, **hookargs)
373 374
374 375 added = [cl.node(r) for r in xrange(clstart, clend)]
375 376 publishing = repo.publishing()
376 377 if srctype in ('push', 'serve'):
377 378 # Old servers can not push the boundary themselves.
378 379 # New servers won't push the boundary if changeset already
379 380 # exists locally as secret
380 381 #
381 382 # We should not use added here but the list of all change in
382 383 # the bundle
383 384 if publishing:
384 385 phases.advanceboundary(repo, tr, phases.public,
385 386 srccontent)
386 387 else:
387 388 # Those changesets have been pushed from the
388 389 # outside, their phases are going to be pushed
389 390 # alongside. Therefor `targetphase` is
390 391 # ignored.
391 392 phases.advanceboundary(repo, tr, phases.draft,
392 393 srccontent)
393 394 phases.retractboundary(repo, tr, phases.draft, added)
394 395 elif srctype != 'strip':
395 396 # publishing only alter behavior during push
396 397 #
397 398 # strip should not touch boundary at all
398 399 phases.retractboundary(repo, tr, targetphase, added)
399 400
400 401 if changesets > 0:
401 402 if srctype != 'strip':
402 403 # During strip, branchcache is invalid but
403 404 # coming call to `destroyed` will repair it.
404 405 # In other case we can safely update cache on
405 406 # disk.
406 407 branchmap.updatecache(repo.filtered('served'))
407 408
408 409 def runhooks():
409 410 # These hooks run when the lock releases, not when the
410 411 # transaction closes. So it's possible for the changelog
411 412 # to have changed since we last saw it.
412 413 if clstart >= len(repo):
413 414 return
414 415
415 416 # forcefully update the on-disk branch cache
416 417 repo.ui.debug("updating the branch cache\n")
417 418 repo.hook("changegroup", **hookargs)
418 419
419 420 for n in added:
420 421 args = hookargs.copy()
421 422 args['node'] = hex(n)
422 423 del args['node_last']
423 424 repo.hook("incoming", **args)
424 425
425 426 newheads = [h for h in repo.heads()
426 427 if h not in oldheads]
427 428 repo.ui.log("incoming",
428 429 "%s incoming changes - new heads: %s\n",
429 430 len(added),
430 431 ', '.join([hex(c[:6]) for c in newheads]))
431 432
432 433 tr.addpostclose('changegroup-runhooks-%020i' % clstart,
433 434 lambda tr: repo._afterlock(runhooks))
434 435 finally:
435 436 repo.ui.flush()
436 437 # never return 0 here:
437 438 if dh < 0:
438 439 return dh - 1
439 440 else:
440 441 return dh + 1
441 442
442 443 class cg2unpacker(cg1unpacker):
443 444 """Unpacker for cg2 streams.
444 445
445 446 cg2 streams add support for generaldelta, so the delta header
446 447 format is slightly different. All other features about the data
447 448 remain the same.
448 449 """
449 450 deltaheader = _CHANGEGROUPV2_DELTA_HEADER
450 451 deltaheadersize = struct.calcsize(deltaheader)
451 452 version = '02'
452 453
453 454 def _deltaheader(self, headertuple, prevnode):
454 455 node, p1, p2, deltabase, cs = headertuple
455 456 flags = 0
456 457 return node, p1, p2, deltabase, cs, flags
457 458
458 459 class cg3unpacker(cg2unpacker):
459 460 """Unpacker for cg3 streams.
460 461
461 462 cg3 streams add support for exchanging treemanifests and revlog
462 463 flags. It adds the revlog flags to the delta header and an empty chunk
463 464 separating manifests and files.
464 465 """
465 466 deltaheader = _CHANGEGROUPV3_DELTA_HEADER
466 467 deltaheadersize = struct.calcsize(deltaheader)
467 468 version = '03'
468 469 _grouplistcount = 2 # One list of manifests and one list of files
469 470
470 471 def _deltaheader(self, headertuple, prevnode):
471 472 node, p1, p2, deltabase, cs, flags = headertuple
472 473 return node, p1, p2, deltabase, cs, flags
473 474
474 475 def _unpackmanifests(self, repo, revmap, trp, prog, numchanges):
475 476 super(cg3unpacker, self)._unpackmanifests(repo, revmap, trp, prog,
476 477 numchanges)
477 478 while True:
478 479 chunkdata = self.filelogheader()
479 480 if not chunkdata:
480 481 break
481 482 # If we get here, there are directory manifests in the changegroup
482 483 d = chunkdata["filename"]
483 484 repo.ui.debug("adding %s revisions\n" % d)
484 485 dirlog = repo.manifest.dirlog(d)
485 486 if not dirlog.addgroup(self, revmap, trp):
486 487 raise error.Abort(_("received dir revlog group is empty"))
487 488
488 489 class headerlessfixup(object):
489 490 def __init__(self, fh, h):
490 491 self._h = h
491 492 self._fh = fh
492 493 def read(self, n):
493 494 if self._h:
494 495 d, self._h = self._h[:n], self._h[n:]
495 496 if len(d) < n:
496 497 d += readexactly(self._fh, n - len(d))
497 498 return d
498 499 return readexactly(self._fh, n)
499 500
500 501 class cg1packer(object):
501 502 deltaheader = _CHANGEGROUPV1_DELTA_HEADER
502 503 version = '01'
503 504 def __init__(self, repo, bundlecaps=None):
504 505 """Given a source repo, construct a bundler.
505 506
506 507 bundlecaps is optional and can be used to specify the set of
507 508 capabilities which can be used to build the bundle.
508 509 """
509 510 # Set of capabilities we can use to build the bundle.
510 511 if bundlecaps is None:
511 512 bundlecaps = set()
512 513 self._bundlecaps = bundlecaps
513 514 # experimental config: bundle.reorder
514 515 reorder = repo.ui.config('bundle', 'reorder', 'auto')
515 516 if reorder == 'auto':
516 517 reorder = None
517 518 else:
518 519 reorder = util.parsebool(reorder)
519 520 self._repo = repo
520 521 self._reorder = reorder
521 522 self._progress = repo.ui.progress
522 523 if self._repo.ui.verbose and not self._repo.ui.debugflag:
523 524 self._verbosenote = self._repo.ui.note
524 525 else:
525 526 self._verbosenote = lambda s: None
526 527
527 528 def close(self):
528 529 return closechunk()
529 530
530 531 def fileheader(self, fname):
531 532 return chunkheader(len(fname)) + fname
532 533
533 534 # Extracted both for clarity and for overriding in extensions.
534 535 def _sortgroup(self, revlog, nodelist, lookup):
535 536 """Sort nodes for change group and turn them into revnums."""
536 537 # for generaldelta revlogs, we linearize the revs; this will both be
537 538 # much quicker and generate a much smaller bundle
538 539 if (revlog._generaldelta and self._reorder is None) or self._reorder:
539 540 dag = dagutil.revlogdag(revlog)
540 541 return dag.linearize(set(revlog.rev(n) for n in nodelist))
541 542 else:
542 543 return sorted([revlog.rev(n) for n in nodelist])
543 544
544 545 def group(self, nodelist, revlog, lookup, units=None):
545 546 """Calculate a delta group, yielding a sequence of changegroup chunks
546 547 (strings).
547 548
548 549 Given a list of changeset revs, return a set of deltas and
549 550 metadata corresponding to nodes. The first delta is
550 551 first parent(nodelist[0]) -> nodelist[0], the receiver is
551 552 guaranteed to have this parent as it has all history before
552 553 these changesets. In the case firstparent is nullrev the
553 554 changegroup starts with a full revision.
554 555
555 556 If units is not None, progress detail will be generated, units specifies
556 557 the type of revlog that is touched (changelog, manifest, etc.).
557 558 """
558 559 # if we don't have any revisions touched by these changesets, bail
559 560 if len(nodelist) == 0:
560 561 yield self.close()
561 562 return
562 563
563 564 revs = self._sortgroup(revlog, nodelist, lookup)
564 565
565 566 # add the parent of the first rev
566 567 p = revlog.parentrevs(revs[0])[0]
567 568 revs.insert(0, p)
568 569
569 570 # build deltas
570 571 total = len(revs) - 1
571 572 msgbundling = _('bundling')
572 573 for r in xrange(len(revs) - 1):
573 574 if units is not None:
574 575 self._progress(msgbundling, r + 1, unit=units, total=total)
575 576 prev, curr = revs[r], revs[r + 1]
576 577 linknode = lookup(revlog.node(curr))
577 578 for c in self.revchunk(revlog, curr, prev, linknode):
578 579 yield c
579 580
580 581 if units is not None:
581 582 self._progress(msgbundling, None)
582 583 yield self.close()
583 584
584 585 # filter any nodes that claim to be part of the known set
585 586 def prune(self, revlog, missing, commonrevs):
586 587 rr, rl = revlog.rev, revlog.linkrev
587 588 return [n for n in missing if rl(rr(n)) not in commonrevs]
588 589
589 590 def _packmanifests(self, dir, mfnodes, lookuplinknode):
590 591 """Pack flat manifests into a changegroup stream."""
591 592 assert not dir
592 593 for chunk in self.group(mfnodes, self._repo.manifest,
593 594 lookuplinknode, units=_('manifests')):
594 595 yield chunk
595 596
596 597 def _manifestsdone(self):
597 598 return ''
598 599
599 600 def generate(self, commonrevs, clnodes, fastpathlinkrev, source):
600 601 '''yield a sequence of changegroup chunks (strings)'''
601 602 repo = self._repo
602 603 cl = repo.changelog
603 604
604 605 clrevorder = {}
605 606 mfs = {} # needed manifests
606 607 fnodes = {} # needed file nodes
607 608 changedfiles = set()
608 609
609 610 # Callback for the changelog, used to collect changed files and manifest
610 611 # nodes.
611 612 # Returns the linkrev node (identity in the changelog case).
612 613 def lookupcl(x):
613 614 c = cl.read(x)
614 615 clrevorder[x] = len(clrevorder)
615 616 n = c[0]
616 617 # record the first changeset introducing this manifest version
617 618 mfs.setdefault(n, x)
618 619 # Record a complete list of potentially-changed files in
619 620 # this manifest.
620 621 changedfiles.update(c[3])
621 622 return x
622 623
623 624 self._verbosenote(_('uncompressed size of bundle content:\n'))
624 625 size = 0
625 626 for chunk in self.group(clnodes, cl, lookupcl, units=_('changesets')):
626 627 size += len(chunk)
627 628 yield chunk
628 629 self._verbosenote(_('%8.i (changelog)\n') % size)
629 630
630 631 # We need to make sure that the linkrev in the changegroup refers to
631 632 # the first changeset that introduced the manifest or file revision.
632 633 # The fastpath is usually safer than the slowpath, because the filelogs
633 634 # are walked in revlog order.
634 635 #
635 636 # When taking the slowpath with reorder=None and the manifest revlog
636 637 # uses generaldelta, the manifest may be walked in the "wrong" order.
637 638 # Without 'clrevorder', we would get an incorrect linkrev (see fix in
638 639 # cc0ff93d0c0c).
639 640 #
640 641 # When taking the fastpath, we are only vulnerable to reordering
641 642 # of the changelog itself. The changelog never uses generaldelta, so
642 643 # it is only reordered when reorder=True. To handle this case, we
643 644 # simply take the slowpath, which already has the 'clrevorder' logic.
644 645 # This was also fixed in cc0ff93d0c0c.
645 646 fastpathlinkrev = fastpathlinkrev and not self._reorder
646 647 # Treemanifests don't work correctly with fastpathlinkrev
647 648 # either, because we don't discover which directory nodes to
648 649 # send along with files. This could probably be fixed.
649 650 fastpathlinkrev = fastpathlinkrev and (
650 651 'treemanifest' not in repo.requirements)
651 652
652 653 for chunk in self.generatemanifests(commonrevs, clrevorder,
653 654 fastpathlinkrev, mfs, fnodes):
654 655 yield chunk
655 656 mfs.clear()
656 657 clrevs = set(cl.rev(x) for x in clnodes)
657 658
658 659 if not fastpathlinkrev:
659 660 def linknodes(unused, fname):
660 661 return fnodes.get(fname, {})
661 662 else:
662 663 cln = cl.node
663 664 def linknodes(filerevlog, fname):
664 665 llr = filerevlog.linkrev
665 666 fln = filerevlog.node
666 667 revs = ((r, llr(r)) for r in filerevlog)
667 668 return dict((fln(r), cln(lr)) for r, lr in revs if lr in clrevs)
668 669
669 670 for chunk in self.generatefiles(changedfiles, linknodes, commonrevs,
670 671 source):
671 672 yield chunk
672 673
673 674 yield self.close()
674 675
675 676 if clnodes:
676 677 repo.hook('outgoing', node=hex(clnodes[0]), source=source)
677 678
678 679 def generatemanifests(self, commonrevs, clrevorder, fastpathlinkrev, mfs,
679 680 fnodes):
680 681 repo = self._repo
681 682 dirlog = repo.manifest.dirlog
682 683 tmfnodes = {'': mfs}
683 684
684 685 # Callback for the manifest, used to collect linkrevs for filelog
685 686 # revisions.
686 687 # Returns the linkrev node (collected in lookupcl).
687 688 def makelookupmflinknode(dir):
688 689 if fastpathlinkrev:
689 690 assert not dir
690 691 return mfs.__getitem__
691 692
692 693 def lookupmflinknode(x):
693 694 """Callback for looking up the linknode for manifests.
694 695
695 696 Returns the linkrev node for the specified manifest.
696 697
697 698 SIDE EFFECT:
698 699
699 700 1) fclnodes gets populated with the list of relevant
700 701 file nodes if we're not using fastpathlinkrev
701 702 2) When treemanifests are in use, collects treemanifest nodes
702 703 to send
703 704
704 705 Note that this means manifests must be completely sent to
705 706 the client before you can trust the list of files and
706 707 treemanifests to send.
707 708 """
708 709 clnode = tmfnodes[dir][x]
709 710 mdata = dirlog(dir).readshallowfast(x)
710 711 for p, n, fl in mdata.iterentries():
711 712 if fl == 't': # subdirectory manifest
712 713 subdir = dir + p + '/'
713 714 tmfclnodes = tmfnodes.setdefault(subdir, {})
714 715 tmfclnode = tmfclnodes.setdefault(n, clnode)
715 716 if clrevorder[clnode] < clrevorder[tmfclnode]:
716 717 tmfclnodes[n] = clnode
717 718 else:
718 719 f = dir + p
719 720 fclnodes = fnodes.setdefault(f, {})
720 721 fclnode = fclnodes.setdefault(n, clnode)
721 722 if clrevorder[clnode] < clrevorder[fclnode]:
722 723 fclnodes[n] = clnode
723 724 return clnode
724 725 return lookupmflinknode
725 726
726 727 size = 0
727 728 while tmfnodes:
728 729 dir = min(tmfnodes)
729 730 nodes = tmfnodes[dir]
730 731 prunednodes = self.prune(dirlog(dir), nodes, commonrevs)
731 732 if not dir or prunednodes:
732 733 for x in self._packmanifests(dir, prunednodes,
733 734 makelookupmflinknode(dir)):
734 735 size += len(x)
735 736 yield x
736 737 del tmfnodes[dir]
737 738 self._verbosenote(_('%8.i (manifests)\n') % size)
738 739 yield self._manifestsdone()
739 740
740 741 # The 'source' parameter is useful for extensions
741 742 def generatefiles(self, changedfiles, linknodes, commonrevs, source):
742 743 repo = self._repo
743 744 progress = self._progress
744 745 msgbundling = _('bundling')
745 746
746 747 total = len(changedfiles)
747 748 # for progress output
748 749 msgfiles = _('files')
749 750 for i, fname in enumerate(sorted(changedfiles)):
750 751 filerevlog = repo.file(fname)
751 752 if not filerevlog:
752 753 raise error.Abort(_("empty or missing revlog for %s") % fname)
753 754
754 755 linkrevnodes = linknodes(filerevlog, fname)
755 756 # Lookup for filenodes, we collected the linkrev nodes above in the
756 757 # fastpath case and with lookupmf in the slowpath case.
757 758 def lookupfilelog(x):
758 759 return linkrevnodes[x]
759 760
760 761 filenodes = self.prune(filerevlog, linkrevnodes, commonrevs)
761 762 if filenodes:
762 763 progress(msgbundling, i + 1, item=fname, unit=msgfiles,
763 764 total=total)
764 765 h = self.fileheader(fname)
765 766 size = len(h)
766 767 yield h
767 768 for chunk in self.group(filenodes, filerevlog, lookupfilelog):
768 769 size += len(chunk)
769 770 yield chunk
770 771 self._verbosenote(_('%8.i %s\n') % (size, fname))
771 772 progress(msgbundling, None)
772 773
773 774 def deltaparent(self, revlog, rev, p1, p2, prev):
774 775 return prev
775 776
776 777 def revchunk(self, revlog, rev, prev, linknode):
777 778 node = revlog.node(rev)
778 779 p1, p2 = revlog.parentrevs(rev)
779 780 base = self.deltaparent(revlog, rev, p1, p2, prev)
780 781
781 782 prefix = ''
782 783 if revlog.iscensored(base) or revlog.iscensored(rev):
783 784 try:
784 785 delta = revlog.revision(node)
785 786 except error.CensoredNodeError as e:
786 787 delta = e.tombstone
787 788 if base == nullrev:
788 789 prefix = mdiff.trivialdiffheader(len(delta))
789 790 else:
790 791 baselen = revlog.rawsize(base)
791 792 prefix = mdiff.replacediffheader(baselen, len(delta))
792 793 elif base == nullrev:
793 794 delta = revlog.revision(node)
794 795 prefix = mdiff.trivialdiffheader(len(delta))
795 796 else:
796 797 delta = revlog.revdiff(base, rev)
797 798 p1n, p2n = revlog.parents(node)
798 799 basenode = revlog.node(base)
799 800 flags = revlog.flags(rev)
800 801 meta = self.builddeltaheader(node, p1n, p2n, basenode, linknode, flags)
801 802 meta += prefix
802 803 l = len(meta) + len(delta)
803 804 yield chunkheader(l)
804 805 yield meta
805 806 yield delta
806 807 def builddeltaheader(self, node, p1n, p2n, basenode, linknode, flags):
807 808 # do nothing with basenode, it is implicitly the previous one in HG10
808 809 # do nothing with flags, it is implicitly 0 for cg1 and cg2
809 810 return struct.pack(self.deltaheader, node, p1n, p2n, linknode)
810 811
811 812 class cg2packer(cg1packer):
812 813 version = '02'
813 814 deltaheader = _CHANGEGROUPV2_DELTA_HEADER
814 815
815 816 def __init__(self, repo, bundlecaps=None):
816 817 super(cg2packer, self).__init__(repo, bundlecaps)
817 818 if self._reorder is None:
818 819 # Since generaldelta is directly supported by cg2, reordering
819 820 # generally doesn't help, so we disable it by default (treating
820 821 # bundle.reorder=auto just like bundle.reorder=False).
821 822 self._reorder = False
822 823
823 824 def deltaparent(self, revlog, rev, p1, p2, prev):
824 825 dp = revlog.deltaparent(rev)
825 826 # avoid storing full revisions; pick prev in those cases
826 827 # also pick prev when we can't be sure remote has dp
827 828 if dp == nullrev or (dp != p1 and dp != p2 and dp != prev):
828 829 return prev
829 830 return dp
830 831
831 832 def builddeltaheader(self, node, p1n, p2n, basenode, linknode, flags):
832 833 # Do nothing with flags, it is implicitly 0 in cg1 and cg2
833 834 return struct.pack(self.deltaheader, node, p1n, p2n, basenode, linknode)
834 835
835 836 class cg3packer(cg2packer):
836 837 version = '03'
837 838 deltaheader = _CHANGEGROUPV3_DELTA_HEADER
838 839
839 840 def _packmanifests(self, dir, mfnodes, lookuplinknode):
840 841 if dir:
841 842 yield self.fileheader(dir)
842 843 for chunk in self.group(mfnodes, self._repo.manifest.dirlog(dir),
843 844 lookuplinknode, units=_('manifests')):
844 845 yield chunk
845 846
846 847 def _manifestsdone(self):
847 848 return self.close()
848 849
849 850 def builddeltaheader(self, node, p1n, p2n, basenode, linknode, flags):
850 851 return struct.pack(
851 852 self.deltaheader, node, p1n, p2n, basenode, linknode, flags)
852 853
853 854 _packermap = {'01': (cg1packer, cg1unpacker),
854 855 # cg2 adds support for exchanging generaldelta
855 856 '02': (cg2packer, cg2unpacker),
856 857 # cg3 adds support for exchanging revlog flags and treemanifests
857 858 '03': (cg3packer, cg3unpacker),
858 859 }
859 860
860 861 def allsupportedversions(ui):
861 862 versions = set(_packermap.keys())
862 863 versions.discard('03')
863 864 if (ui.configbool('experimental', 'changegroup3') or
864 865 ui.configbool('experimental', 'treemanifest')):
865 866 versions.add('03')
866 867 return versions
867 868
868 869 # Changegroup versions that can be applied to the repo
869 870 def supportedincomingversions(repo):
870 871 versions = allsupportedversions(repo.ui)
871 872 if 'treemanifest' in repo.requirements:
872 873 versions.add('03')
873 874 return versions
874 875
875 876 # Changegroup versions that can be created from the repo
876 877 def supportedoutgoingversions(repo):
877 878 versions = allsupportedversions(repo.ui)
878 879 if 'treemanifest' in repo.requirements:
879 880 # Versions 01 and 02 support only flat manifests and it's just too
880 881 # expensive to convert between the flat manifest and tree manifest on
881 882 # the fly. Since tree manifests are hashed differently, all of history
882 883 # would have to be converted. Instead, we simply don't even pretend to
883 884 # support versions 01 and 02.
884 885 versions.discard('01')
885 886 versions.discard('02')
886 887 versions.add('03')
887 888 return versions
888 889
889 890 def safeversion(repo):
890 891 # Finds the smallest version that it's safe to assume clients of the repo
891 892 # will support. For example, all hg versions that support generaldelta also
892 893 # support changegroup 02.
893 894 versions = supportedoutgoingversions(repo)
894 895 if 'generaldelta' in repo.requirements:
895 896 versions.discard('01')
896 897 assert versions
897 898 return min(versions)
898 899
899 900 def getbundler(version, repo, bundlecaps=None):
900 901 assert version in supportedoutgoingversions(repo)
901 902 return _packermap[version][0](repo, bundlecaps)
902 903
903 def getunbundler(version, fh, alg):
904 return _packermap[version][1](fh, alg)
904 def getunbundler(version, fh, alg, extras=None):
905 return _packermap[version][1](fh, alg, extras=extras)
905 906
906 907 def _changegroupinfo(repo, nodes, source):
907 908 if repo.ui.verbose or source == 'bundle':
908 909 repo.ui.status(_("%d changesets found\n") % len(nodes))
909 910 if repo.ui.debugflag:
910 911 repo.ui.debug("list of changesets:\n")
911 912 for node in nodes:
912 913 repo.ui.debug("%s\n" % hex(node))
913 914
914 915 def getsubsetraw(repo, outgoing, bundler, source, fastpath=False):
915 916 repo = repo.unfiltered()
916 917 commonrevs = outgoing.common
917 918 csets = outgoing.missing
918 919 heads = outgoing.missingheads
919 920 # We go through the fast path if we get told to, or if all (unfiltered
920 921 # heads have been requested (since we then know there all linkrevs will
921 922 # be pulled by the client).
922 923 heads.sort()
923 924 fastpathlinkrev = fastpath or (
924 925 repo.filtername is None and heads == sorted(repo.heads()))
925 926
926 927 repo.hook('preoutgoing', throw=True, source=source)
927 928 _changegroupinfo(repo, csets, source)
928 929 return bundler.generate(commonrevs, csets, fastpathlinkrev, source)
929 930
930 931 def getsubset(repo, outgoing, bundler, source, fastpath=False):
931 932 gengroup = getsubsetraw(repo, outgoing, bundler, source, fastpath)
932 return getunbundler(bundler.version, util.chunkbuffer(gengroup), None)
933 return getunbundler(bundler.version, util.chunkbuffer(gengroup), None,
934 {'clcount': len(outgoing.missing)})
933 935
934 936 def changegroupsubset(repo, roots, heads, source, version='01'):
935 937 """Compute a changegroup consisting of all the nodes that are
936 938 descendants of any of the roots and ancestors of any of the heads.
937 939 Return a chunkbuffer object whose read() method will return
938 940 successive changegroup chunks.
939 941
940 942 It is fairly complex as determining which filenodes and which
941 943 manifest nodes need to be included for the changeset to be complete
942 944 is non-trivial.
943 945
944 946 Another wrinkle is doing the reverse, figuring out which changeset in
945 947 the changegroup a particular filenode or manifestnode belongs to.
946 948 """
947 949 cl = repo.changelog
948 950 if not roots:
949 951 roots = [nullid]
950 952 discbases = []
951 953 for n in roots:
952 954 discbases.extend([p for p in cl.parents(n) if p != nullid])
953 955 # TODO: remove call to nodesbetween.
954 956 csets, roots, heads = cl.nodesbetween(roots, heads)
955 957 included = set(csets)
956 958 discbases = [n for n in discbases if n not in included]
957 959 outgoing = discovery.outgoing(cl, discbases, heads)
958 960 bundler = getbundler(version, repo)
959 961 return getsubset(repo, outgoing, bundler, source)
960 962
961 963 def getlocalchangegroupraw(repo, source, outgoing, bundlecaps=None,
962 964 version='01'):
963 965 """Like getbundle, but taking a discovery.outgoing as an argument.
964 966
965 967 This is only implemented for local repos and reuses potentially
966 968 precomputed sets in outgoing. Returns a raw changegroup generator."""
967 969 if not outgoing.missing:
968 970 return None
969 971 bundler = getbundler(version, repo, bundlecaps)
970 972 return getsubsetraw(repo, outgoing, bundler, source)
971 973
972 974 def getlocalchangegroup(repo, source, outgoing, bundlecaps=None,
973 975 version='01'):
974 976 """Like getbundle, but taking a discovery.outgoing as an argument.
975 977
976 978 This is only implemented for local repos and reuses potentially
977 979 precomputed sets in outgoing."""
978 980 if not outgoing.missing:
979 981 return None
980 982 bundler = getbundler(version, repo, bundlecaps)
981 983 return getsubset(repo, outgoing, bundler, source)
982 984
983 985 def computeoutgoing(repo, heads, common):
984 986 """Computes which revs are outgoing given a set of common
985 987 and a set of heads.
986 988
987 989 This is a separate function so extensions can have access to
988 990 the logic.
989 991
990 992 Returns a discovery.outgoing object.
991 993 """
992 994 cl = repo.changelog
993 995 if common:
994 996 hasnode = cl.hasnode
995 997 common = [n for n in common if hasnode(n)]
996 998 else:
997 999 common = [nullid]
998 1000 if not heads:
999 1001 heads = cl.heads()
1000 1002 return discovery.outgoing(cl, common, heads)
1001 1003
1002 1004 def getchangegroup(repo, source, heads=None, common=None, bundlecaps=None,
1003 1005 version='01'):
1004 1006 """Like changegroupsubset, but returns the set difference between the
1005 1007 ancestors of heads and the ancestors common.
1006 1008
1007 1009 If heads is None, use the local heads. If common is None, use [nullid].
1008 1010
1009 1011 The nodes in common might not all be known locally due to the way the
1010 1012 current discovery protocol works.
1011 1013 """
1012 1014 outgoing = computeoutgoing(repo, heads, common)
1013 1015 return getlocalchangegroup(repo, source, outgoing, bundlecaps=bundlecaps,
1014 1016 version=version)
1015 1017
1016 1018 def changegroup(repo, basenodes, source):
1017 1019 # to avoid a race we use changegroupsubset() (issue1320)
1018 1020 return changegroupsubset(repo, basenodes, repo.heads(), source)
1019 1021
1020 1022 def _addchangegroupfiles(repo, source, revmap, trp, expectedfiles, needfiles):
1021 1023 revisions = 0
1022 1024 files = 0
1023 1025 while True:
1024 1026 chunkdata = source.filelogheader()
1025 1027 if not chunkdata:
1026 1028 break
1027 1029 files += 1
1028 1030 f = chunkdata["filename"]
1029 1031 repo.ui.debug("adding %s revisions\n" % f)
1030 1032 repo.ui.progress(_('files'), files, unit=_('files'),
1031 1033 total=expectedfiles)
1032 1034 fl = repo.file(f)
1033 1035 o = len(fl)
1034 1036 try:
1035 1037 if not fl.addgroup(source, revmap, trp):
1036 1038 raise error.Abort(_("received file revlog group is empty"))
1037 1039 except error.CensoredBaseError as e:
1038 1040 raise error.Abort(_("received delta base is censored: %s") % e)
1039 1041 revisions += len(fl) - o
1040 1042 if f in needfiles:
1041 1043 needs = needfiles[f]
1042 1044 for new in xrange(o, len(fl)):
1043 1045 n = fl.node(new)
1044 1046 if n in needs:
1045 1047 needs.remove(n)
1046 1048 else:
1047 1049 raise error.Abort(
1048 1050 _("received spurious file revlog entry"))
1049 1051 if not needs:
1050 1052 del needfiles[f]
1051 1053 repo.ui.progress(_('files'), None)
1052 1054
1053 1055 for f, needs in needfiles.iteritems():
1054 1056 fl = repo.file(f)
1055 1057 for n in needs:
1056 1058 try:
1057 1059 fl.rev(n)
1058 1060 except error.LookupError:
1059 1061 raise error.Abort(
1060 1062 _('missing file data for %s:%s - run hg verify') %
1061 1063 (f, hex(n)))
1062 1064
1063 1065 return revisions, files
@@ -1,128 +1,128 b''
1 1
2 2 $ cat << EOF >> $HGRCPATH
3 3 > [format]
4 4 > usegeneraldelta=yes
5 5 > EOF
6 6
7 7 bundle w/o type option
8 8
9 9 $ hg init t1
10 10 $ hg init t2
11 11 $ cd t1
12 12 $ echo blablablablabla > file.txt
13 13 $ hg ci -Ama
14 14 adding file.txt
15 15 $ hg log | grep summary
16 16 summary: a
17 17 $ hg bundle ../b1 ../t2
18 18 searching for changes
19 19 1 changesets found
20 20
21 21 $ cd ../t2
22 22 $ hg pull ../b1
23 23 pulling from ../b1
24 24 requesting all changes
25 25 adding changesets
26 26 adding manifests
27 27 adding file changes
28 28 added 1 changesets with 1 changes to 1 files
29 29 (run 'hg update' to get a working copy)
30 30 $ hg up
31 31 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
32 32 $ hg log | grep summary
33 33 summary: a
34 34 $ cd ..
35 35
36 36 test bundle types
37 37
38 38 $ for t in "None" "bzip2" "gzip" "none-v2" "v2" "v1" "gzip-v1"; do
39 39 > echo % test bundle type $t
40 40 > hg init t$t
41 41 > cd t1
42 42 > hg bundle -t $t ../b$t ../t$t
43 43 > f -q -B6 -D ../b$t; echo
44 44 > cd ../t$t
45 45 > hg debugbundle ../b$t
46 46 > hg debugbundle --spec ../b$t
47 47 > echo
48 48 > cd ..
49 49 > done
50 50 % test bundle type None
51 51 searching for changes
52 52 1 changesets found
53 53 HG20\x00\x00 (esc)
54 54 Stream params: {}
55 changegroup -- "sortdict([('version', '02')])"
55 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
56 56 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
57 57 none-v2
58 58
59 59 % test bundle type bzip2
60 60 searching for changes
61 61 1 changesets found
62 62 HG20\x00\x00 (esc)
63 63 Stream params: sortdict([('Compression', 'BZ')])
64 changegroup -- "sortdict([('version', '02')])"
64 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
65 65 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
66 66 bzip2-v2
67 67
68 68 % test bundle type gzip
69 69 searching for changes
70 70 1 changesets found
71 71 HG20\x00\x00 (esc)
72 72 Stream params: sortdict([('Compression', 'GZ')])
73 changegroup -- "sortdict([('version', '02')])"
73 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
74 74 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
75 75 gzip-v2
76 76
77 77 % test bundle type none-v2
78 78 searching for changes
79 79 1 changesets found
80 80 HG20\x00\x00 (esc)
81 81 Stream params: {}
82 changegroup -- "sortdict([('version', '02')])"
82 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
83 83 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
84 84 none-v2
85 85
86 86 % test bundle type v2
87 87 searching for changes
88 88 1 changesets found
89 89 HG20\x00\x00 (esc)
90 90 Stream params: sortdict([('Compression', 'BZ')])
91 changegroup -- "sortdict([('version', '02')])"
91 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
92 92 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
93 93 bzip2-v2
94 94
95 95 % test bundle type v1
96 96 searching for changes
97 97 1 changesets found
98 98 HG10BZ
99 99 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
100 100 bzip2-v1
101 101
102 102 % test bundle type gzip-v1
103 103 searching for changes
104 104 1 changesets found
105 105 HG10GZ
106 106 c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
107 107 gzip-v1
108 108
109 109
110 110 test garbage file
111 111
112 112 $ echo garbage > bgarbage
113 113 $ hg init tgarbage
114 114 $ cd tgarbage
115 115 $ hg pull ../bgarbage
116 116 pulling from ../bgarbage
117 117 abort: ../bgarbage: not a Mercurial bundle
118 118 [255]
119 119 $ cd ..
120 120
121 121 test invalid bundle type
122 122
123 123 $ cd t1
124 124 $ hg bundle -a -t garbage ../bgarbage
125 125 abort: garbage is not a recognized bundle specification
126 126 (see "hg help bundle" for supported values for --type)
127 127 [255]
128 128 $ cd ..
@@ -1,809 +1,809 b''
1 1
2 2 $ cat << EOF >> $HGRCPATH
3 3 > [format]
4 4 > usegeneraldelta=yes
5 5 > EOF
6 6
7 7 Setting up test
8 8
9 9 $ hg init test
10 10 $ cd test
11 11 $ echo 0 > afile
12 12 $ hg add afile
13 13 $ hg commit -m "0.0"
14 14 $ echo 1 >> afile
15 15 $ hg commit -m "0.1"
16 16 $ echo 2 >> afile
17 17 $ hg commit -m "0.2"
18 18 $ echo 3 >> afile
19 19 $ hg commit -m "0.3"
20 20 $ hg update -C 0
21 21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 22 $ echo 1 >> afile
23 23 $ hg commit -m "1.1"
24 24 created new head
25 25 $ echo 2 >> afile
26 26 $ hg commit -m "1.2"
27 27 $ echo "a line" > fred
28 28 $ echo 3 >> afile
29 29 $ hg add fred
30 30 $ hg commit -m "1.3"
31 31 $ hg mv afile adifferentfile
32 32 $ hg commit -m "1.3m"
33 33 $ hg update -C 3
34 34 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
35 35 $ hg mv afile anotherfile
36 36 $ hg commit -m "0.3m"
37 37 $ hg verify
38 38 checking changesets
39 39 checking manifests
40 40 crosschecking files in changesets and manifests
41 41 checking files
42 42 4 files, 9 changesets, 7 total revisions
43 43 $ cd ..
44 44 $ hg init empty
45 45
46 46 Bundle and phase
47 47
48 48 $ hg -R test phase --force --secret 0
49 49 $ hg -R test bundle phase.hg empty
50 50 searching for changes
51 51 no changes found (ignored 9 secret changesets)
52 52 [1]
53 53 $ hg -R test phase --draft -r 'head()'
54 54
55 55 Bundle --all
56 56
57 57 $ hg -R test bundle --all all.hg
58 58 9 changesets found
59 59
60 60 Bundle test to full.hg
61 61
62 62 $ hg -R test bundle full.hg empty
63 63 searching for changes
64 64 9 changesets found
65 65
66 66 Unbundle full.hg in test
67 67
68 68 $ hg -R test unbundle full.hg
69 69 adding changesets
70 70 adding manifests
71 71 adding file changes
72 72 added 0 changesets with 0 changes to 4 files
73 73 (run 'hg update' to get a working copy)
74 74
75 75 Verify empty
76 76
77 77 $ hg -R empty heads
78 78 [1]
79 79 $ hg -R empty verify
80 80 checking changesets
81 81 checking manifests
82 82 crosschecking files in changesets and manifests
83 83 checking files
84 84 0 files, 0 changesets, 0 total revisions
85 85
86 86 Pull full.hg into test (using --cwd)
87 87
88 88 $ hg --cwd test pull ../full.hg
89 89 pulling from ../full.hg
90 90 searching for changes
91 91 no changes found
92 92
93 93 Verify that there are no leaked temporary files after pull (issue2797)
94 94
95 95 $ ls test/.hg | grep .hg10un
96 96 [1]
97 97
98 98 Pull full.hg into empty (using --cwd)
99 99
100 100 $ hg --cwd empty pull ../full.hg
101 101 pulling from ../full.hg
102 102 requesting all changes
103 103 adding changesets
104 104 adding manifests
105 105 adding file changes
106 106 added 9 changesets with 7 changes to 4 files (+1 heads)
107 107 (run 'hg heads' to see heads, 'hg merge' to merge)
108 108
109 109 Rollback empty
110 110
111 111 $ hg -R empty rollback
112 112 repository tip rolled back to revision -1 (undo pull)
113 113
114 114 Pull full.hg into empty again (using --cwd)
115 115
116 116 $ hg --cwd empty pull ../full.hg
117 117 pulling from ../full.hg
118 118 requesting all changes
119 119 adding changesets
120 120 adding manifests
121 121 adding file changes
122 122 added 9 changesets with 7 changes to 4 files (+1 heads)
123 123 (run 'hg heads' to see heads, 'hg merge' to merge)
124 124
125 125 Pull full.hg into test (using -R)
126 126
127 127 $ hg -R test pull full.hg
128 128 pulling from full.hg
129 129 searching for changes
130 130 no changes found
131 131
132 132 Pull full.hg into empty (using -R)
133 133
134 134 $ hg -R empty pull full.hg
135 135 pulling from full.hg
136 136 searching for changes
137 137 no changes found
138 138
139 139 Rollback empty
140 140
141 141 $ hg -R empty rollback
142 142 repository tip rolled back to revision -1 (undo pull)
143 143
144 144 Pull full.hg into empty again (using -R)
145 145
146 146 $ hg -R empty pull full.hg
147 147 pulling from full.hg
148 148 requesting all changes
149 149 adding changesets
150 150 adding manifests
151 151 adding file changes
152 152 added 9 changesets with 7 changes to 4 files (+1 heads)
153 153 (run 'hg heads' to see heads, 'hg merge' to merge)
154 154
155 155 Log -R full.hg in fresh empty
156 156
157 157 $ rm -r empty
158 158 $ hg init empty
159 159 $ cd empty
160 160 $ hg -R bundle://../full.hg log
161 161 changeset: 8:aa35859c02ea
162 162 tag: tip
163 163 parent: 3:eebf5a27f8ca
164 164 user: test
165 165 date: Thu Jan 01 00:00:00 1970 +0000
166 166 summary: 0.3m
167 167
168 168 changeset: 7:a6a34bfa0076
169 169 user: test
170 170 date: Thu Jan 01 00:00:00 1970 +0000
171 171 summary: 1.3m
172 172
173 173 changeset: 6:7373c1169842
174 174 user: test
175 175 date: Thu Jan 01 00:00:00 1970 +0000
176 176 summary: 1.3
177 177
178 178 changeset: 5:1bb50a9436a7
179 179 user: test
180 180 date: Thu Jan 01 00:00:00 1970 +0000
181 181 summary: 1.2
182 182
183 183 changeset: 4:095197eb4973
184 184 parent: 0:f9ee2f85a263
185 185 user: test
186 186 date: Thu Jan 01 00:00:00 1970 +0000
187 187 summary: 1.1
188 188
189 189 changeset: 3:eebf5a27f8ca
190 190 user: test
191 191 date: Thu Jan 01 00:00:00 1970 +0000
192 192 summary: 0.3
193 193
194 194 changeset: 2:e38ba6f5b7e0
195 195 user: test
196 196 date: Thu Jan 01 00:00:00 1970 +0000
197 197 summary: 0.2
198 198
199 199 changeset: 1:34c2bf6b0626
200 200 user: test
201 201 date: Thu Jan 01 00:00:00 1970 +0000
202 202 summary: 0.1
203 203
204 204 changeset: 0:f9ee2f85a263
205 205 user: test
206 206 date: Thu Jan 01 00:00:00 1970 +0000
207 207 summary: 0.0
208 208
209 209 Make sure bundlerepo doesn't leak tempfiles (issue2491)
210 210
211 211 $ ls .hg
212 212 00changelog.i
213 213 cache
214 214 requires
215 215 store
216 216
217 217 Pull ../full.hg into empty (with hook)
218 218
219 219 $ echo "[hooks]" >> .hg/hgrc
220 220 $ echo "changegroup = printenv.py changegroup" >> .hg/hgrc
221 221
222 222 doesn't work (yet ?)
223 223
224 224 hg -R bundle://../full.hg verify
225 225
226 226 $ hg pull bundle://../full.hg
227 227 pulling from bundle:../full.hg
228 228 requesting all changes
229 229 adding changesets
230 230 adding manifests
231 231 adding file changes
232 232 added 9 changesets with 7 changes to 4 files (+1 heads)
233 233 changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=bundle:../full.hg (glob)
234 234 (run 'hg heads' to see heads, 'hg merge' to merge)
235 235
236 236 Rollback empty
237 237
238 238 $ hg rollback
239 239 repository tip rolled back to revision -1 (undo pull)
240 240 $ cd ..
241 241
242 242 Log -R bundle:empty+full.hg
243 243
244 244 $ hg -R bundle:empty+full.hg log --template="{rev} "; echo ""
245 245 8 7 6 5 4 3 2 1 0
246 246
247 247 Pull full.hg into empty again (using -R; with hook)
248 248
249 249 $ hg -R empty pull full.hg
250 250 pulling from full.hg
251 251 requesting all changes
252 252 adding changesets
253 253 adding manifests
254 254 adding file changes
255 255 added 9 changesets with 7 changes to 4 files (+1 heads)
256 256 changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=bundle:empty+full.hg (glob)
257 257 (run 'hg heads' to see heads, 'hg merge' to merge)
258 258
259 259 Cannot produce streaming clone bundles with "hg bundle"
260 260
261 261 $ hg -R test bundle -t packed1 packed.hg
262 262 abort: packed bundles cannot be produced by "hg bundle"
263 263 (use 'hg debugcreatestreamclonebundle')
264 264 [255]
265 265
266 266 packed1 is produced properly
267 267
268 268 $ hg -R test debugcreatestreamclonebundle packed.hg
269 269 writing 2663 bytes for 6 files
270 270 bundle requirements: generaldelta, revlogv1
271 271
272 272 $ f -B 64 --size --sha1 --hexdump packed.hg
273 273 packed.hg: size=2826, sha1=e139f97692a142b19cdcff64a69697d5307ce6d4
274 274 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 06 00 00 |HGS1UN..........|
275 275 0010: 00 00 00 00 0a 67 00 16 67 65 6e 65 72 61 6c 64 |.....g..generald|
276 276 0020: 65 6c 74 61 2c 72 65 76 6c 6f 67 76 31 00 64 61 |elta,revlogv1.da|
277 277 0030: 74 61 2f 61 64 69 66 66 65 72 65 6e 74 66 69 6c |ta/adifferentfil|
278 278
279 279 $ hg debugbundle --spec packed.hg
280 280 none-packed1;requirements%3Dgeneraldelta%2Crevlogv1
281 281
282 282 generaldelta requirement is listed in stream clone bundles
283 283
284 284 $ hg --config format.generaldelta=true init testgd
285 285 $ cd testgd
286 286 $ touch foo
287 287 $ hg -q commit -A -m initial
288 288 $ cd ..
289 289 $ hg -R testgd debugcreatestreamclonebundle packedgd.hg
290 290 writing 301 bytes for 3 files
291 291 bundle requirements: generaldelta, revlogv1
292 292
293 293 $ f -B 64 --size --sha1 --hexdump packedgd.hg
294 294 packedgd.hg: size=396, sha1=981f9e589799335304a5a9a44caa3623a48d2a9f
295 295 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 03 00 00 |HGS1UN..........|
296 296 0010: 00 00 00 00 01 2d 00 16 67 65 6e 65 72 61 6c 64 |.....-..generald|
297 297 0020: 65 6c 74 61 2c 72 65 76 6c 6f 67 76 31 00 64 61 |elta,revlogv1.da|
298 298 0030: 74 61 2f 66 6f 6f 2e 69 00 36 34 0a 00 03 00 01 |ta/foo.i.64.....|
299 299
300 300 $ hg debugbundle --spec packedgd.hg
301 301 none-packed1;requirements%3Dgeneraldelta%2Crevlogv1
302 302
303 303 Unpacking packed1 bundles with "hg unbundle" isn't allowed
304 304
305 305 $ hg init packed
306 306 $ hg -R packed unbundle packed.hg
307 307 abort: packed bundles cannot be applied with "hg unbundle"
308 308 (use "hg debugapplystreamclonebundle")
309 309 [255]
310 310
311 311 packed1 can be consumed from debug command
312 312
313 313 $ hg -R packed debugapplystreamclonebundle packed.hg
314 314 6 files to transfer, 2.60 KB of data
315 315 transferred 2.60 KB in *.* seconds (* */sec) (glob)
316 316
317 317 Does not work on non-empty repo
318 318
319 319 $ hg -R packed debugapplystreamclonebundle packed.hg
320 320 abort: cannot apply stream clone bundle on non-empty repo
321 321 [255]
322 322
323 323 Create partial clones
324 324
325 325 $ rm -r empty
326 326 $ hg init empty
327 327 $ hg clone -r 3 test partial
328 328 adding changesets
329 329 adding manifests
330 330 adding file changes
331 331 added 4 changesets with 4 changes to 1 files
332 332 updating to branch default
333 333 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
334 334 $ hg clone partial partial2
335 335 updating to branch default
336 336 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
337 337 $ cd partial
338 338
339 339 Log -R full.hg in partial
340 340
341 341 $ hg -R bundle://../full.hg log -T phases
342 342 changeset: 8:aa35859c02ea
343 343 tag: tip
344 344 phase: draft
345 345 parent: 3:eebf5a27f8ca
346 346 user: test
347 347 date: Thu Jan 01 00:00:00 1970 +0000
348 348 summary: 0.3m
349 349
350 350 changeset: 7:a6a34bfa0076
351 351 phase: draft
352 352 user: test
353 353 date: Thu Jan 01 00:00:00 1970 +0000
354 354 summary: 1.3m
355 355
356 356 changeset: 6:7373c1169842
357 357 phase: draft
358 358 user: test
359 359 date: Thu Jan 01 00:00:00 1970 +0000
360 360 summary: 1.3
361 361
362 362 changeset: 5:1bb50a9436a7
363 363 phase: draft
364 364 user: test
365 365 date: Thu Jan 01 00:00:00 1970 +0000
366 366 summary: 1.2
367 367
368 368 changeset: 4:095197eb4973
369 369 phase: draft
370 370 parent: 0:f9ee2f85a263
371 371 user: test
372 372 date: Thu Jan 01 00:00:00 1970 +0000
373 373 summary: 1.1
374 374
375 375 changeset: 3:eebf5a27f8ca
376 376 phase: public
377 377 user: test
378 378 date: Thu Jan 01 00:00:00 1970 +0000
379 379 summary: 0.3
380 380
381 381 changeset: 2:e38ba6f5b7e0
382 382 phase: public
383 383 user: test
384 384 date: Thu Jan 01 00:00:00 1970 +0000
385 385 summary: 0.2
386 386
387 387 changeset: 1:34c2bf6b0626
388 388 phase: public
389 389 user: test
390 390 date: Thu Jan 01 00:00:00 1970 +0000
391 391 summary: 0.1
392 392
393 393 changeset: 0:f9ee2f85a263
394 394 phase: public
395 395 user: test
396 396 date: Thu Jan 01 00:00:00 1970 +0000
397 397 summary: 0.0
398 398
399 399
400 400 Incoming full.hg in partial
401 401
402 402 $ hg incoming bundle://../full.hg
403 403 comparing with bundle:../full.hg
404 404 searching for changes
405 405 changeset: 4:095197eb4973
406 406 parent: 0:f9ee2f85a263
407 407 user: test
408 408 date: Thu Jan 01 00:00:00 1970 +0000
409 409 summary: 1.1
410 410
411 411 changeset: 5:1bb50a9436a7
412 412 user: test
413 413 date: Thu Jan 01 00:00:00 1970 +0000
414 414 summary: 1.2
415 415
416 416 changeset: 6:7373c1169842
417 417 user: test
418 418 date: Thu Jan 01 00:00:00 1970 +0000
419 419 summary: 1.3
420 420
421 421 changeset: 7:a6a34bfa0076
422 422 user: test
423 423 date: Thu Jan 01 00:00:00 1970 +0000
424 424 summary: 1.3m
425 425
426 426 changeset: 8:aa35859c02ea
427 427 tag: tip
428 428 parent: 3:eebf5a27f8ca
429 429 user: test
430 430 date: Thu Jan 01 00:00:00 1970 +0000
431 431 summary: 0.3m
432 432
433 433
434 434 Outgoing -R full.hg vs partial2 in partial
435 435
436 436 $ hg -R bundle://../full.hg outgoing ../partial2
437 437 comparing with ../partial2
438 438 searching for changes
439 439 changeset: 4:095197eb4973
440 440 parent: 0:f9ee2f85a263
441 441 user: test
442 442 date: Thu Jan 01 00:00:00 1970 +0000
443 443 summary: 1.1
444 444
445 445 changeset: 5:1bb50a9436a7
446 446 user: test
447 447 date: Thu Jan 01 00:00:00 1970 +0000
448 448 summary: 1.2
449 449
450 450 changeset: 6:7373c1169842
451 451 user: test
452 452 date: Thu Jan 01 00:00:00 1970 +0000
453 453 summary: 1.3
454 454
455 455 changeset: 7:a6a34bfa0076
456 456 user: test
457 457 date: Thu Jan 01 00:00:00 1970 +0000
458 458 summary: 1.3m
459 459
460 460 changeset: 8:aa35859c02ea
461 461 tag: tip
462 462 parent: 3:eebf5a27f8ca
463 463 user: test
464 464 date: Thu Jan 01 00:00:00 1970 +0000
465 465 summary: 0.3m
466 466
467 467
468 468 Outgoing -R does-not-exist.hg vs partial2 in partial
469 469
470 470 $ hg -R bundle://../does-not-exist.hg outgoing ../partial2
471 471 abort: *../does-not-exist.hg* (glob)
472 472 [255]
473 473 $ cd ..
474 474
475 475 hide outer repo
476 476 $ hg init
477 477
478 478 Direct clone from bundle (all-history)
479 479
480 480 $ hg clone full.hg full-clone
481 481 requesting all changes
482 482 adding changesets
483 483 adding manifests
484 484 adding file changes
485 485 added 9 changesets with 7 changes to 4 files (+1 heads)
486 486 updating to branch default
487 487 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
488 488 $ hg -R full-clone heads
489 489 changeset: 8:aa35859c02ea
490 490 tag: tip
491 491 parent: 3:eebf5a27f8ca
492 492 user: test
493 493 date: Thu Jan 01 00:00:00 1970 +0000
494 494 summary: 0.3m
495 495
496 496 changeset: 7:a6a34bfa0076
497 497 user: test
498 498 date: Thu Jan 01 00:00:00 1970 +0000
499 499 summary: 1.3m
500 500
501 501 $ rm -r full-clone
502 502
503 503 When cloning from a non-copiable repository into '', do not
504 504 recurse infinitely (issue2528)
505 505
506 506 $ hg clone full.hg ''
507 507 abort: empty destination path is not valid
508 508 [255]
509 509
510 510 test for https://bz.mercurial-scm.org/216
511 511
512 512 Unbundle incremental bundles into fresh empty in one go
513 513
514 514 $ rm -r empty
515 515 $ hg init empty
516 516 $ hg -R test bundle --base null -r 0 ../0.hg
517 517 1 changesets found
518 518 $ hg -R test bundle --base 0 -r 1 ../1.hg
519 519 1 changesets found
520 520 $ hg -R empty unbundle -u ../0.hg ../1.hg
521 521 adding changesets
522 522 adding manifests
523 523 adding file changes
524 524 added 1 changesets with 1 changes to 1 files
525 525 adding changesets
526 526 adding manifests
527 527 adding file changes
528 528 added 1 changesets with 1 changes to 1 files
529 529 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
530 530
531 531 View full contents of the bundle
532 532 $ hg -R test bundle --base null -r 3 ../partial.hg
533 533 4 changesets found
534 534 $ cd test
535 535 $ hg -R ../../partial.hg log -r "bundle()"
536 536 changeset: 0:f9ee2f85a263
537 537 user: test
538 538 date: Thu Jan 01 00:00:00 1970 +0000
539 539 summary: 0.0
540 540
541 541 changeset: 1:34c2bf6b0626
542 542 user: test
543 543 date: Thu Jan 01 00:00:00 1970 +0000
544 544 summary: 0.1
545 545
546 546 changeset: 2:e38ba6f5b7e0
547 547 user: test
548 548 date: Thu Jan 01 00:00:00 1970 +0000
549 549 summary: 0.2
550 550
551 551 changeset: 3:eebf5a27f8ca
552 552 user: test
553 553 date: Thu Jan 01 00:00:00 1970 +0000
554 554 summary: 0.3
555 555
556 556 $ cd ..
557 557
558 558 test for 540d1059c802
559 559
560 560 test for 540d1059c802
561 561
562 562 $ hg init orig
563 563 $ cd orig
564 564 $ echo foo > foo
565 565 $ hg add foo
566 566 $ hg ci -m 'add foo'
567 567
568 568 $ hg clone . ../copy
569 569 updating to branch default
570 570 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
571 571 $ hg tag foo
572 572
573 573 $ cd ../copy
574 574 $ echo >> foo
575 575 $ hg ci -m 'change foo'
576 576 $ hg bundle ../bundle.hg ../orig
577 577 searching for changes
578 578 1 changesets found
579 579
580 580 $ cd ../orig
581 581 $ hg incoming ../bundle.hg
582 582 comparing with ../bundle.hg
583 583 searching for changes
584 584 changeset: 2:ed1b79f46b9a
585 585 tag: tip
586 586 parent: 0:bbd179dfa0a7
587 587 user: test
588 588 date: Thu Jan 01 00:00:00 1970 +0000
589 589 summary: change foo
590 590
591 591 $ cd ..
592 592
593 593 test bundle with # in the filename (issue2154):
594 594
595 595 $ cp bundle.hg 'test#bundle.hg'
596 596 $ cd orig
597 597 $ hg incoming '../test#bundle.hg'
598 598 comparing with ../test
599 599 abort: unknown revision 'bundle.hg'!
600 600 [255]
601 601
602 602 note that percent encoding is not handled:
603 603
604 604 $ hg incoming ../test%23bundle.hg
605 605 abort: repository ../test%23bundle.hg not found!
606 606 [255]
607 607 $ cd ..
608 608
609 609 test to bundle revisions on the newly created branch (issue3828):
610 610
611 611 $ hg -q clone -U test test-clone
612 612 $ cd test
613 613
614 614 $ hg -q branch foo
615 615 $ hg commit -m "create foo branch"
616 616 $ hg -q outgoing ../test-clone
617 617 9:b4f5acb1ee27
618 618 $ hg -q bundle --branch foo foo.hg ../test-clone
619 619 $ hg -R foo.hg -q log -r "bundle()"
620 620 9:b4f5acb1ee27
621 621
622 622 $ cd ..
623 623
624 624 test for https://bz.mercurial-scm.org/1144
625 625
626 626 test that verify bundle does not traceback
627 627
628 628 partial history bundle, fails w/ unknown parent
629 629
630 630 $ hg -R bundle.hg verify
631 631 abort: 00changelog.i@bbd179dfa0a7: unknown parent!
632 632 [255]
633 633
634 634 full history bundle, refuses to verify non-local repo
635 635
636 636 $ hg -R all.hg verify
637 637 abort: cannot verify bundle or remote repos
638 638 [255]
639 639
640 640 but, regular verify must continue to work
641 641
642 642 $ hg -R orig verify
643 643 checking changesets
644 644 checking manifests
645 645 crosschecking files in changesets and manifests
646 646 checking files
647 647 2 files, 2 changesets, 2 total revisions
648 648
649 649 diff against bundle
650 650
651 651 $ hg init b
652 652 $ cd b
653 653 $ hg -R ../all.hg diff -r tip
654 654 diff -r aa35859c02ea anotherfile
655 655 --- a/anotherfile Thu Jan 01 00:00:00 1970 +0000
656 656 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
657 657 @@ -1,4 +0,0 @@
658 658 -0
659 659 -1
660 660 -2
661 661 -3
662 662 $ cd ..
663 663
664 664 bundle single branch
665 665
666 666 $ hg init branchy
667 667 $ cd branchy
668 668 $ echo a >a
669 669 $ echo x >x
670 670 $ hg ci -Ama
671 671 adding a
672 672 adding x
673 673 $ echo c >c
674 674 $ echo xx >x
675 675 $ hg ci -Amc
676 676 adding c
677 677 $ echo c1 >c1
678 678 $ hg ci -Amc1
679 679 adding c1
680 680 $ hg up 0
681 681 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
682 682 $ echo b >b
683 683 $ hg ci -Amb
684 684 adding b
685 685 created new head
686 686 $ echo b1 >b1
687 687 $ echo xx >x
688 688 $ hg ci -Amb1
689 689 adding b1
690 690 $ hg clone -q -r2 . part
691 691
692 692 == bundling via incoming
693 693
694 694 $ hg in -R part --bundle incoming.hg --template "{node}\n" .
695 695 comparing with .
696 696 searching for changes
697 697 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
698 698 057f4db07f61970e1c11e83be79e9d08adc4dc31
699 699
700 700 == bundling
701 701
702 702 $ hg bundle bundle.hg part --debug --config progress.debug=true
703 703 query 1; heads
704 704 searching for changes
705 705 all remote heads known locally
706 706 2 changesets found
707 707 list of changesets:
708 708 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
709 709 057f4db07f61970e1c11e83be79e9d08adc4dc31
710 710 bundle2-output-bundle: "HG20", (1 params) 1 parts total
711 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
711 bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
712 712 bundling: 1/2 changesets (50.00%)
713 713 bundling: 2/2 changesets (100.00%)
714 714 bundling: 1/2 manifests (50.00%)
715 715 bundling: 2/2 manifests (100.00%)
716 716 bundling: b 1/3 files (33.33%)
717 717 bundling: b1 2/3 files (66.67%)
718 718 bundling: x 3/3 files (100.00%)
719 719
720 720 == Test for issue3441
721 721
722 722 $ hg clone -q -r0 . part2
723 723 $ hg -q -R part2 pull bundle.hg
724 724 $ hg -R part2 verify
725 725 checking changesets
726 726 checking manifests
727 727 crosschecking files in changesets and manifests
728 728 checking files
729 729 4 files, 3 changesets, 5 total revisions
730 730
731 731 == Test bundling no commits
732 732
733 733 $ hg bundle -r 'public()' no-output.hg
734 734 abort: no commits to bundle
735 735 [255]
736 736
737 737 $ cd ..
738 738
739 739 When user merges to the revision existing only in the bundle,
740 740 it should show warning that second parent of the working
741 741 directory does not exist
742 742
743 743 $ hg init update2bundled
744 744 $ cd update2bundled
745 745 $ cat <<EOF >> .hg/hgrc
746 746 > [extensions]
747 747 > strip =
748 748 > EOF
749 749 $ echo "aaa" >> a
750 750 $ hg commit -A -m 0
751 751 adding a
752 752 $ echo "bbb" >> b
753 753 $ hg commit -A -m 1
754 754 adding b
755 755 $ echo "ccc" >> c
756 756 $ hg commit -A -m 2
757 757 adding c
758 758 $ hg update -r 1
759 759 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
760 760 $ echo "ddd" >> d
761 761 $ hg commit -A -m 3
762 762 adding d
763 763 created new head
764 764 $ hg update -r 2
765 765 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
766 766 $ hg log -G
767 767 o changeset: 3:8bd3e1f196af
768 768 | tag: tip
769 769 | parent: 1:a01eca7af26d
770 770 | user: test
771 771 | date: Thu Jan 01 00:00:00 1970 +0000
772 772 | summary: 3
773 773 |
774 774 | @ changeset: 2:4652c276ac4f
775 775 |/ user: test
776 776 | date: Thu Jan 01 00:00:00 1970 +0000
777 777 | summary: 2
778 778 |
779 779 o changeset: 1:a01eca7af26d
780 780 | user: test
781 781 | date: Thu Jan 01 00:00:00 1970 +0000
782 782 | summary: 1
783 783 |
784 784 o changeset: 0:4fe08cd4693e
785 785 user: test
786 786 date: Thu Jan 01 00:00:00 1970 +0000
787 787 summary: 0
788 788
789 789 $ hg bundle --base 1 -r 3 ../update2bundled.hg
790 790 1 changesets found
791 791 $ hg strip -r 3
792 792 saved backup bundle to $TESTTMP/update2bundled/.hg/strip-backup/8bd3e1f196af-017e56d8-backup.hg (glob)
793 793 $ hg merge -R ../update2bundled.hg -r 3
794 794 setting parent to node 8bd3e1f196af289b2b121be08031e76d7ae92098 that only exists in the bundle
795 795 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
796 796 (branch merge, don't forget to commit)
797 797
798 798 When user updates to the revision existing only in the bundle,
799 799 it should show warning
800 800
801 801 $ hg update -R ../update2bundled.hg --clean -r 3
802 802 setting parent to node 8bd3e1f196af289b2b121be08031e76d7ae92098 that only exists in the bundle
803 803 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
804 804
805 805 When user updates to the revision existing in the local repository
806 806 the warning shouldn't be emitted
807 807
808 808 $ hg update -R ../update2bundled.hg -r 0
809 809 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
@@ -1,433 +1,434 b''
1 1 Set up a server
2 2
3 3 $ cat >> $HGRCPATH << EOF
4 4 > [format]
5 5 > usegeneraldelta=yes
6 6 > EOF
7 7 $ hg init server
8 8 $ cd server
9 9 $ cat >> .hg/hgrc << EOF
10 10 > [extensions]
11 11 > clonebundles =
12 12 > EOF
13 13
14 14 $ touch foo
15 15 $ hg -q commit -A -m 'add foo'
16 16 $ touch bar
17 17 $ hg -q commit -A -m 'add bar'
18 18
19 19 $ hg serve -d -p $HGPORT --pid-file hg.pid --accesslog access.log
20 20 $ cat hg.pid >> $DAEMON_PIDS
21 21 $ cd ..
22 22
23 23 Missing manifest should not result in server lookup
24 24
25 25 $ hg --verbose clone -U http://localhost:$HGPORT no-manifest
26 26 requesting all changes
27 27 adding changesets
28 28 adding manifests
29 29 adding file changes
30 30 added 2 changesets with 2 changes to 2 files
31 31
32 32 $ cat server/access.log
33 33 * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
34 34 * - - [*] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob)
35 35 * - - [*] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=aaff8d2ffbbf07a46dd1f05d8ae7877e3f56e2a2&listkeys=phases%2Cbookmarks (glob)
36 36
37 37 Empty manifest file results in retrieval
38 38 (the extension only checks if the manifest file exists)
39 39
40 40 $ touch server/.hg/clonebundles.manifest
41 41 $ hg --verbose clone -U http://localhost:$HGPORT empty-manifest
42 42 no clone bundles available on remote; falling back to regular clone
43 43 requesting all changes
44 44 adding changesets
45 45 adding manifests
46 46 adding file changes
47 47 added 2 changesets with 2 changes to 2 files
48 48
49 49 Manifest file with invalid URL aborts
50 50
51 51 $ echo 'http://does.not.exist/bundle.hg' > server/.hg/clonebundles.manifest
52 52 $ hg clone http://localhost:$HGPORT 404-url
53 53 applying clone bundle from http://does.not.exist/bundle.hg
54 54 error fetching bundle: (.* not known|getaddrinfo failed|No address associated with hostname) (re)
55 55 abort: error applying bundle
56 56 (if this error persists, consider contacting the server operator or disable clone bundles via "--config ui.clonebundles=false")
57 57 [255]
58 58
59 59 Server is not running aborts
60 60
61 61 $ echo "http://localhost:$HGPORT1/bundle.hg" > server/.hg/clonebundles.manifest
62 62 $ hg clone http://localhost:$HGPORT server-not-runner
63 63 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
64 64 error fetching bundle: * refused* (glob)
65 65 abort: error applying bundle
66 66 (if this error persists, consider contacting the server operator or disable clone bundles via "--config ui.clonebundles=false")
67 67 [255]
68 68
69 69 Server returns 404
70 70
71 71 $ python $TESTDIR/dumbhttp.py -p $HGPORT1 --pid http.pid
72 72 $ cat http.pid >> $DAEMON_PIDS
73 73 $ hg clone http://localhost:$HGPORT running-404
74 74 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
75 75 HTTP error fetching bundle: HTTP Error 404: File not found
76 76 abort: error applying bundle
77 77 (if this error persists, consider contacting the server operator or disable clone bundles via "--config ui.clonebundles=false")
78 78 [255]
79 79
80 80 We can override failure to fall back to regular clone
81 81
82 82 $ hg --config ui.clonebundlefallback=true clone -U http://localhost:$HGPORT 404-fallback
83 83 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
84 84 HTTP error fetching bundle: HTTP Error 404: File not found
85 85 falling back to normal clone
86 86 requesting all changes
87 87 adding changesets
88 88 adding manifests
89 89 adding file changes
90 90 added 2 changesets with 2 changes to 2 files
91 91
92 92 Bundle with partial content works
93 93
94 94 $ hg -R server bundle --type gzip-v1 --base null -r 53245c60e682 partial.hg
95 95 1 changesets found
96 96
97 97 We verify exact bundle content as an extra check against accidental future
98 98 changes. If this output changes, we could break old clients.
99 99
100 100 $ f --size --hexdump partial.hg
101 101 partial.hg: size=207
102 102 0000: 48 47 31 30 47 5a 78 9c 63 60 60 98 17 ac 12 93 |HG10GZx.c``.....|
103 103 0010: f0 ac a9 23 45 70 cb bf 0d 5f 59 4e 4a 7f 79 21 |...#Ep..._YNJ.y!|
104 104 0020: 9b cc 40 24 20 a0 d7 ce 2c d1 38 25 cd 24 25 d5 |..@$ ...,.8%.$%.|
105 105 0030: d8 c2 22 cd 38 d9 24 cd 22 d5 c8 22 cd 24 cd 32 |..".8.$."..".$.2|
106 106 0040: d1 c2 d0 c4 c8 d2 32 d1 38 39 29 c9 34 cd d4 80 |......2.89).4...|
107 107 0050: ab 24 b5 b8 84 cb 40 c1 80 2b 2d 3f 9f 8b 2b 31 |.$....@..+-?..+1|
108 108 0060: 25 45 01 c8 80 9a d2 9b 65 fb e5 9e 45 bf 8d 7f |%E......e...E...|
109 109 0070: 9f c6 97 9f 2b 44 34 67 d9 ec 8e 0f a0 92 0b 75 |....+D4g.......u|
110 110 0080: 41 d6 24 59 18 a4 a4 9a a6 18 1a 5b 98 9b 5a 98 |A.$Y.......[..Z.|
111 111 0090: 9a 18 26 9b a6 19 98 1a 99 99 26 a6 18 9a 98 24 |..&.......&....$|
112 112 00a0: 26 59 a6 25 5a 98 a5 18 a6 24 71 41 35 b1 43 dc |&Y.%Z....$qA5.C.|
113 113 00b0: 16 b2 83 f7 e9 45 8b d2 56 c7 a3 1f 82 52 d7 8a |.....E..V....R..|
114 114 00c0: 78 ed fc d5 76 f1 36 35 dc 05 00 36 ed 5e c7 |x...v.65...6.^.|
115 115
116 116 $ echo "http://localhost:$HGPORT1/partial.hg" > server/.hg/clonebundles.manifest
117 117 $ hg clone -U http://localhost:$HGPORT partial-bundle
118 118 applying clone bundle from http://localhost:$HGPORT1/partial.hg
119 119 adding changesets
120 120 adding manifests
121 121 adding file changes
122 122 added 1 changesets with 1 changes to 1 files
123 123 finished applying clone bundle
124 124 searching for changes
125 125 adding changesets
126 126 adding manifests
127 127 adding file changes
128 128 added 1 changesets with 1 changes to 1 files
129 129
130 130 Incremental pull doesn't fetch bundle
131 131
132 132 $ hg clone -r 53245c60e682 -U http://localhost:$HGPORT partial-clone
133 133 adding changesets
134 134 adding manifests
135 135 adding file changes
136 136 added 1 changesets with 1 changes to 1 files
137 137
138 138 $ cd partial-clone
139 139 $ hg pull
140 140 pulling from http://localhost:$HGPORT/
141 141 searching for changes
142 142 adding changesets
143 143 adding manifests
144 144 adding file changes
145 145 added 1 changesets with 1 changes to 1 files
146 146 (run 'hg update' to get a working copy)
147 147 $ cd ..
148 148
149 149 Bundle with full content works
150 150
151 151 $ hg -R server bundle --type gzip-v2 --base null -r tip full.hg
152 152 2 changesets found
153 153
154 154 Again, we perform an extra check against bundle content changes. If this content
155 155 changes, clone bundles produced by new Mercurial versions may not be readable
156 156 by old clients.
157 157
158 158 $ f --size --hexdump full.hg
159 full.hg: size=406
159 full.hg: size=418
160 160 0000: 48 47 32 30 00 00 00 0e 43 6f 6d 70 72 65 73 73 |HG20....Compress|
161 0010: 69 6f 6e 3d 47 5a 78 9c 63 60 60 90 e5 76 f6 70 |ion=GZx.c``..v.p|
162 0020: f4 73 77 75 0f f2 0f 0d 60 00 02 46 06 76 a6 b2 |.swu....`..F.v..|
163 0030: d4 a2 e2 cc fc 3c 03 23 06 06 e6 65 40 b1 4d c1 |.....<.#...e@.M.|
164 0040: 2a 31 09 cf 9a 3a 52 04 b7 fc db f0 95 e5 a4 f4 |*1...:R.........|
165 0050: 97 17 b2 c9 0c 14 00 02 e6 d9 99 25 1a a7 a4 99 |...........%....|
166 0060: a4 a4 1a 5b 58 a4 19 27 9b a4 59 a4 1a 59 a4 99 |...[X..'..Y..Y..|
167 0070: a4 59 26 5a 18 9a 18 59 5a 26 1a 27 27 25 99 a6 |.Y&Z...YZ&.''%..|
168 0080: 99 1a 70 95 a4 16 97 70 19 28 18 70 a5 e5 e7 73 |..p....p.(.p...s|
169 0090: 71 25 a6 a4 28 00 19 40 13 0e ac fa df ab ff 7b |q%..(..@.......{|
170 00a0: 3f fb 92 dc 8b 1f 62 bb 9e b7 d7 d9 87 3d 5a 44 |?.....b......=ZD|
171 00b0: ac 2f b0 a9 c3 66 1e 54 b9 26 08 a7 1a 1b 1a a7 |./...f.T.&......|
172 00c0: 25 1b 9a 1b 99 19 9a 5a 18 9b a6 18 19 00 dd 67 |%......Z.......g|
173 00d0: 61 61 98 06 f4 80 49 4a 8a 65 52 92 41 9a 81 81 |aa....IJ.eR.A...|
174 00e0: a5 11 17 50 31 30 58 19 cc 80 98 25 29 b1 08 c4 |...P10X....%)...|
175 00f0: 37 07 79 19 88 d9 41 ee 07 8a 41 cd 5d 98 65 fb |7.y...A...A.].e.|
176 0100: e5 9e 45 bf 8d 7f 9f c6 97 9f 2b 44 34 67 d9 ec |..E.......+D4g..|
177 0110: 8e 0f a0 61 a8 eb 82 82 2e c9 c2 20 25 d5 34 c5 |...a....... %.4.|
178 0120: d0 d8 c2 dc d4 c2 d4 c4 30 d9 34 cd c0 d4 c8 cc |........0.4.....|
179 0130: 34 31 c5 d0 c4 24 31 c9 32 2d d1 c2 2c c5 30 25 |41...$1.2-..,.0%|
180 0140: 09 e4 ee 85 8f 85 ff 88 ab 89 36 c7 2a c4 47 34 |..........6.*.G4|
181 0150: fe f8 ec 7b 73 37 3f c3 24 62 1d 8d 4d 1d 9e 40 |...{s7?.$b..M..@|
182 0160: 06 3b 10 14 36 a4 38 10 04 d8 21 01 9a b1 83 f7 |.;..6.8...!.....|
183 0170: e9 45 8b d2 56 c7 a3 1f 82 52 d7 8a 78 ed fc d5 |.E..V....R..x...|
184 0180: 76 f1 36 25 81 89 c7 ad ec 90 34 48 75 2b 89 49 |v.6%......4Hu+.I|
185 0190: bf 00 d6 97 f0 8d |......|
161 0010: 69 6f 6e 3d 47 5a 78 9c 63 60 60 d0 e4 76 f6 70 |ion=GZx.c``..v.p|
162 0020: f4 73 77 75 0f f2 0f 0d 60 00 02 46 46 76 26 4e |.swu....`..FFv&N|
163 0030: c6 b2 d4 a2 e2 cc fc 3c 03 a3 bc a4 e4 8c c4 bc |.......<........|
164 0040: f4 d4 62 23 06 06 e6 65 40 f9 4d c1 2a 31 09 cf |..b#...e@.M.*1..|
165 0050: 9a 3a 52 04 b7 fc db f0 95 e5 a4 f4 97 17 b2 c9 |.:R.............|
166 0060: 0c 14 00 02 e6 d9 99 25 1a a7 a4 99 a4 a4 1a 5b |.......%.......[|
167 0070: 58 a4 19 27 9b a4 59 a4 1a 59 a4 99 a4 59 26 5a |X..'..Y..Y...Y&Z|
168 0080: 18 9a 18 59 5a 26 1a 27 27 25 99 a6 99 1a 70 95 |...YZ&.''%....p.|
169 0090: a4 16 97 70 19 28 18 70 a5 e5 e7 73 71 25 a6 a4 |...p.(.p...sq%..|
170 00a0: 28 00 19 40 13 0e ac fa df ab ff 7b 3f fb 92 dc |(..@.......{?...|
171 00b0: 8b 1f 62 bb 9e b7 d7 d9 87 3d 5a 44 ac 2f b0 a9 |..b......=ZD./..|
172 00c0: c3 66 1e 54 b9 26 08 a7 1a 1b 1a a7 25 1b 9a 1b |.f.T.&......%...|
173 00d0: 99 19 9a 5a 18 9b a6 18 19 00 dd 67 61 61 98 06 |...Z.......gaa..|
174 00e0: f4 80 49 4a 8a 65 52 92 41 9a 81 81 a5 11 17 50 |..IJ.eR.A......P|
175 00f0: 31 30 58 19 cc 80 98 25 29 b1 08 c4 37 07 79 19 |10X....%)...7.y.|
176 0100: 88 d9 41 ee 07 8a 41 cd 5d 98 65 fb e5 9e 45 bf |..A...A.].e...E.|
177 0110: 8d 7f 9f c6 97 9f 2b 44 34 67 d9 ec 8e 0f a0 61 |......+D4g.....a|
178 0120: a8 eb 82 82 2e c9 c2 20 25 d5 34 c5 d0 d8 c2 dc |....... %.4.....|
179 0130: d4 c2 d4 c4 30 d9 34 cd c0 d4 c8 cc 34 31 c5 d0 |....0.4.....41..|
180 0140: c4 24 31 c9 32 2d d1 c2 2c c5 30 25 09 e4 ee 85 |.$1.2-..,.0%....|
181 0150: 8f 85 ff 88 ab 89 36 c7 2a c4 47 34 fe f8 ec 7b |......6.*.G4...{|
182 0160: 73 37 3f c3 24 62 1d 8d 4d 1d 9e 40 06 3b 10 14 |s7?.$b..M..@.;..|
183 0170: 36 a4 38 10 04 d8 21 01 9a b1 83 f7 e9 45 8b d2 |6.8...!......E..|
184 0180: 56 c7 a3 1f 82 52 d7 8a 78 ed fc d5 76 f1 36 25 |V....R..x...v.6%|
185 0190: 81 89 c7 ad ec 90 34 48 75 2b 89 49 bf 00 cf 72 |......4Hu+.I...r|
186 01a0: f4 7f |..|
186 187
187 188 $ echo "http://localhost:$HGPORT1/full.hg" > server/.hg/clonebundles.manifest
188 189 $ hg clone -U http://localhost:$HGPORT full-bundle
189 190 applying clone bundle from http://localhost:$HGPORT1/full.hg
190 191 adding changesets
191 192 adding manifests
192 193 adding file changes
193 194 added 2 changesets with 2 changes to 2 files
194 195 finished applying clone bundle
195 196 searching for changes
196 197 no changes found
197 198
198 199 Feature works over SSH
199 200
200 201 $ hg clone -U -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/server ssh-full-clone
201 202 applying clone bundle from http://localhost:$HGPORT1/full.hg
202 203 adding changesets
203 204 adding manifests
204 205 adding file changes
205 206 added 2 changesets with 2 changes to 2 files
206 207 finished applying clone bundle
207 208 searching for changes
208 209 no changes found
209 210
210 211 Entry with unknown BUNDLESPEC is filtered and not used
211 212
212 213 $ cat > server/.hg/clonebundles.manifest << EOF
213 214 > http://bad.entry1 BUNDLESPEC=UNKNOWN
214 215 > http://bad.entry2 BUNDLESPEC=xz-v1
215 216 > http://bad.entry3 BUNDLESPEC=none-v100
216 217 > http://localhost:$HGPORT1/full.hg BUNDLESPEC=gzip-v2
217 218 > EOF
218 219
219 220 $ hg clone -U http://localhost:$HGPORT filter-unknown-type
220 221 applying clone bundle from http://localhost:$HGPORT1/full.hg
221 222 adding changesets
222 223 adding manifests
223 224 adding file changes
224 225 added 2 changesets with 2 changes to 2 files
225 226 finished applying clone bundle
226 227 searching for changes
227 228 no changes found
228 229
229 230 Automatic fallback when all entries are filtered
230 231
231 232 $ cat > server/.hg/clonebundles.manifest << EOF
232 233 > http://bad.entry BUNDLESPEC=UNKNOWN
233 234 > EOF
234 235
235 236 $ hg clone -U http://localhost:$HGPORT filter-all
236 237 no compatible clone bundles available on server; falling back to regular clone
237 238 (you may want to report this to the server operator)
238 239 requesting all changes
239 240 adding changesets
240 241 adding manifests
241 242 adding file changes
242 243 added 2 changesets with 2 changes to 2 files
243 244
244 245 URLs requiring SNI are filtered in Python <2.7.9
245 246
246 247 $ cp full.hg sni.hg
247 248 $ cat > server/.hg/clonebundles.manifest << EOF
248 249 > http://localhost:$HGPORT1/sni.hg REQUIRESNI=true
249 250 > http://localhost:$HGPORT1/full.hg
250 251 > EOF
251 252
252 253 #if sslcontext
253 254 Python 2.7.9+ support SNI
254 255
255 256 $ hg clone -U http://localhost:$HGPORT sni-supported
256 257 applying clone bundle from http://localhost:$HGPORT1/sni.hg
257 258 adding changesets
258 259 adding manifests
259 260 adding file changes
260 261 added 2 changesets with 2 changes to 2 files
261 262 finished applying clone bundle
262 263 searching for changes
263 264 no changes found
264 265 #else
265 266 Python <2.7.9 will filter SNI URLs
266 267
267 268 $ hg clone -U http://localhost:$HGPORT sni-unsupported
268 269 applying clone bundle from http://localhost:$HGPORT1/full.hg
269 270 adding changesets
270 271 adding manifests
271 272 adding file changes
272 273 added 2 changesets with 2 changes to 2 files
273 274 finished applying clone bundle
274 275 searching for changes
275 276 no changes found
276 277 #endif
277 278
278 279 Stream clone bundles are supported
279 280
280 281 $ hg -R server debugcreatestreamclonebundle packed.hg
281 282 writing 613 bytes for 4 files
282 283 bundle requirements: generaldelta, revlogv1
283 284
284 285 No bundle spec should work
285 286
286 287 $ cat > server/.hg/clonebundles.manifest << EOF
287 288 > http://localhost:$HGPORT1/packed.hg
288 289 > EOF
289 290
290 291 $ hg clone -U http://localhost:$HGPORT stream-clone-no-spec
291 292 applying clone bundle from http://localhost:$HGPORT1/packed.hg
292 293 4 files to transfer, 613 bytes of data
293 294 transferred 613 bytes in *.* seconds (*) (glob)
294 295 finished applying clone bundle
295 296 searching for changes
296 297 no changes found
297 298
298 299 Bundle spec without parameters should work
299 300
300 301 $ cat > server/.hg/clonebundles.manifest << EOF
301 302 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1
302 303 > EOF
303 304
304 305 $ hg clone -U http://localhost:$HGPORT stream-clone-vanilla-spec
305 306 applying clone bundle from http://localhost:$HGPORT1/packed.hg
306 307 4 files to transfer, 613 bytes of data
307 308 transferred 613 bytes in *.* seconds (*) (glob)
308 309 finished applying clone bundle
309 310 searching for changes
310 311 no changes found
311 312
312 313 Bundle spec with format requirements should work
313 314
314 315 $ cat > server/.hg/clonebundles.manifest << EOF
315 316 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1;requirements%3Drevlogv1
316 317 > EOF
317 318
318 319 $ hg clone -U http://localhost:$HGPORT stream-clone-supported-requirements
319 320 applying clone bundle from http://localhost:$HGPORT1/packed.hg
320 321 4 files to transfer, 613 bytes of data
321 322 transferred 613 bytes in *.* seconds (*) (glob)
322 323 finished applying clone bundle
323 324 searching for changes
324 325 no changes found
325 326
326 327 Stream bundle spec with unknown requirements should be filtered out
327 328
328 329 $ cat > server/.hg/clonebundles.manifest << EOF
329 330 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1;requirements%3Drevlogv42
330 331 > EOF
331 332
332 333 $ hg clone -U http://localhost:$HGPORT stream-clone-unsupported-requirements
333 334 no compatible clone bundles available on server; falling back to regular clone
334 335 (you may want to report this to the server operator)
335 336 requesting all changes
336 337 adding changesets
337 338 adding manifests
338 339 adding file changes
339 340 added 2 changesets with 2 changes to 2 files
340 341
341 342 Set up manifest for testing preferences
342 343 (Remember, the TYPE does not have to match reality - the URL is
343 344 important)
344 345
345 346 $ cp full.hg gz-a.hg
346 347 $ cp full.hg gz-b.hg
347 348 $ cp full.hg bz2-a.hg
348 349 $ cp full.hg bz2-b.hg
349 350 $ cat > server/.hg/clonebundles.manifest << EOF
350 351 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2 extra=a
351 352 > http://localhost:$HGPORT1/bz2-a.hg BUNDLESPEC=bzip2-v2 extra=a
352 353 > http://localhost:$HGPORT1/gz-b.hg BUNDLESPEC=gzip-v2 extra=b
353 354 > http://localhost:$HGPORT1/bz2-b.hg BUNDLESPEC=bzip2-v2 extra=b
354 355 > EOF
355 356
356 357 Preferring an undefined attribute will take first entry
357 358
358 359 $ hg --config ui.clonebundleprefers=foo=bar clone -U http://localhost:$HGPORT prefer-foo
359 360 applying clone bundle from http://localhost:$HGPORT1/gz-a.hg
360 361 adding changesets
361 362 adding manifests
362 363 adding file changes
363 364 added 2 changesets with 2 changes to 2 files
364 365 finished applying clone bundle
365 366 searching for changes
366 367 no changes found
367 368
368 369 Preferring bz2 type will download first entry of that type
369 370
370 371 $ hg --config ui.clonebundleprefers=COMPRESSION=bzip2 clone -U http://localhost:$HGPORT prefer-bz
371 372 applying clone bundle from http://localhost:$HGPORT1/bz2-a.hg
372 373 adding changesets
373 374 adding manifests
374 375 adding file changes
375 376 added 2 changesets with 2 changes to 2 files
376 377 finished applying clone bundle
377 378 searching for changes
378 379 no changes found
379 380
380 381 Preferring multiple values of an option works
381 382
382 383 $ hg --config ui.clonebundleprefers=COMPRESSION=unknown,COMPRESSION=bzip2 clone -U http://localhost:$HGPORT prefer-multiple-bz
383 384 applying clone bundle from http://localhost:$HGPORT1/bz2-a.hg
384 385 adding changesets
385 386 adding manifests
386 387 adding file changes
387 388 added 2 changesets with 2 changes to 2 files
388 389 finished applying clone bundle
389 390 searching for changes
390 391 no changes found
391 392
392 393 Sorting multiple values should get us back to original first entry
393 394
394 395 $ hg --config ui.clonebundleprefers=BUNDLESPEC=unknown,BUNDLESPEC=gzip-v2,BUNDLESPEC=bzip2-v2 clone -U http://localhost:$HGPORT prefer-multiple-gz
395 396 applying clone bundle from http://localhost:$HGPORT1/gz-a.hg
396 397 adding changesets
397 398 adding manifests
398 399 adding file changes
399 400 added 2 changesets with 2 changes to 2 files
400 401 finished applying clone bundle
401 402 searching for changes
402 403 no changes found
403 404
404 405 Preferring multiple attributes has correct order
405 406
406 407 $ hg --config ui.clonebundleprefers=extra=b,BUNDLESPEC=bzip2-v2 clone -U http://localhost:$HGPORT prefer-separate-attributes
407 408 applying clone bundle from http://localhost:$HGPORT1/bz2-b.hg
408 409 adding changesets
409 410 adding manifests
410 411 adding file changes
411 412 added 2 changesets with 2 changes to 2 files
412 413 finished applying clone bundle
413 414 searching for changes
414 415 no changes found
415 416
416 417 Test where attribute is missing from some entries
417 418
418 419 $ cat > server/.hg/clonebundles.manifest << EOF
419 420 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
420 421 > http://localhost:$HGPORT1/bz2-a.hg BUNDLESPEC=bzip2-v2
421 422 > http://localhost:$HGPORT1/gz-b.hg BUNDLESPEC=gzip-v2 extra=b
422 423 > http://localhost:$HGPORT1/bz2-b.hg BUNDLESPEC=bzip2-v2 extra=b
423 424 > EOF
424 425
425 426 $ hg --config ui.clonebundleprefers=extra=b clone -U http://localhost:$HGPORT prefer-partially-defined-attribute
426 427 applying clone bundle from http://localhost:$HGPORT1/gz-b.hg
427 428 adding changesets
428 429 adding manifests
429 430 adding file changes
430 431 added 2 changesets with 2 changes to 2 files
431 432 finished applying clone bundle
432 433 searching for changes
433 434 no changes found
@@ -1,76 +1,76 b''
1 1
2 2 Create a test repository:
3 3
4 4 $ hg init repo
5 5 $ cd repo
6 6 $ touch a ; hg add a ; hg ci -ma
7 7 $ touch b ; hg add b ; hg ci -mb
8 8 $ touch c ; hg add c ; hg ci -mc
9 9 $ hg bundle --base 0 --rev tip bundle.hg -v --type v1
10 10 2 changesets found
11 11 uncompressed size of bundle content:
12 12 332 (changelog)
13 13 282 (manifests)
14 14 93 b
15 15 93 c
16 16 $ hg bundle --base 0 --rev tip bundle2.hg -v --type none-v2
17 17 2 changesets found
18 18 uncompressed size of bundle content:
19 19 372 (changelog)
20 20 322 (manifests)
21 21 113 b
22 22 113 c
23 23
24 24 Terse output:
25 25
26 26 $ hg debugbundle bundle.hg
27 27 0e067c57feba1a5694ca4844f05588bb1bf82342
28 28 991a3460af53952d10ec8a295d3d2cc2e5fa9690
29 29
30 30 Terse output:
31 31
32 32 $ hg debugbundle bundle2.hg
33 33 Stream params: {}
34 changegroup -- "sortdict([('version', '02')])"
34 changegroup -- "sortdict([('version', '02'), ('nbchanges', '2')])"
35 35 0e067c57feba1a5694ca4844f05588bb1bf82342
36 36 991a3460af53952d10ec8a295d3d2cc2e5fa9690
37 37
38 38 Verbose output:
39 39
40 40 $ hg debugbundle --all bundle.hg
41 41 format: id, p1, p2, cset, delta base, len(delta)
42 42
43 43 changelog
44 44 0e067c57feba1a5694ca4844f05588bb1bf82342 3903775176ed42b1458a6281db4a0ccf4d9f287a 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 3903775176ed42b1458a6281db4a0ccf4d9f287a 80
45 45 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 80
46 46
47 47 manifest
48 48 686dbf0aeca417636fa26a9121c681eabbb15a20 8515d4bfda768e04af4c13a69a72e28c7effbea7 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 8515d4bfda768e04af4c13a69a72e28c7effbea7 55
49 49 ae25a31b30b3490a981e7b96a3238cc69583fda1 686dbf0aeca417636fa26a9121c681eabbb15a20 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 686dbf0aeca417636fa26a9121c681eabbb15a20 55
50 50
51 51 b
52 52 b80de5d138758541c5f05265ad144ab9fa86d1db 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 0000000000000000000000000000000000000000 0
53 53
54 54 c
55 55 b80de5d138758541c5f05265ad144ab9fa86d1db 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0000000000000000000000000000000000000000 0
56 56
57 57 $ hg debugbundle --all bundle2.hg
58 58 Stream params: {}
59 changegroup -- "sortdict([('version', '02')])"
59 changegroup -- "sortdict([('version', '02'), ('nbchanges', '2')])"
60 60 format: id, p1, p2, cset, delta base, len(delta)
61 61
62 62 changelog
63 63 0e067c57feba1a5694ca4844f05588bb1bf82342 3903775176ed42b1458a6281db4a0ccf4d9f287a 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 3903775176ed42b1458a6281db4a0ccf4d9f287a 80
64 64 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 80
65 65
66 66 manifest
67 67 686dbf0aeca417636fa26a9121c681eabbb15a20 8515d4bfda768e04af4c13a69a72e28c7effbea7 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 8515d4bfda768e04af4c13a69a72e28c7effbea7 55
68 68 ae25a31b30b3490a981e7b96a3238cc69583fda1 686dbf0aeca417636fa26a9121c681eabbb15a20 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 686dbf0aeca417636fa26a9121c681eabbb15a20 55
69 69
70 70 b
71 71 b80de5d138758541c5f05265ad144ab9fa86d1db 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0e067c57feba1a5694ca4844f05588bb1bf82342 0000000000000000000000000000000000000000 0
72 72
73 73 c
74 74 b80de5d138758541c5f05265ad144ab9fa86d1db 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0000000000000000000000000000000000000000 0
75 75
76 76 $ cd ..
@@ -1,161 +1,161 b''
1 1 Check whether size of generaldelta revlog is not bigger than its
2 2 regular equivalent. Test would fail if generaldelta was naive
3 3 implementation of parentdelta: third manifest revision would be fully
4 4 inserted due to big distance from its paren revision (zero).
5 5
6 6 $ hg init repo --config format.generaldelta=no --config format.usegeneraldelta=no
7 7 $ cd repo
8 8 $ echo foo > foo
9 9 $ echo bar > bar
10 10 $ echo baz > baz
11 11 $ hg commit -q -Am boo
12 12 $ hg clone --pull . ../gdrepo -q --config format.generaldelta=yes
13 13 $ for r in 1 2 3; do
14 14 > echo $r > foo
15 15 > hg commit -q -m $r
16 16 > hg up -q -r 0
17 17 > hg pull . -q -r $r -R ../gdrepo
18 18 > done
19 19
20 20 $ cd ..
21 21 >>> from __future__ import print_function
22 22 >>> import os
23 23 >>> regsize = os.stat("repo/.hg/store/00manifest.i").st_size
24 24 >>> gdsize = os.stat("gdrepo/.hg/store/00manifest.i").st_size
25 25 >>> if regsize < gdsize:
26 26 ... print('generaldata increased size of manifest')
27 27
28 28 Verify rev reordering doesnt create invalid bundles (issue4462)
29 29 This requires a commit tree that when pulled will reorder manifest revs such
30 30 that the second manifest to create a file rev will be ordered before the first
31 31 manifest to create that file rev. We also need to do a partial pull to ensure
32 32 reordering happens. At the end we verify the linkrev points at the earliest
33 33 commit.
34 34
35 35 $ hg init server --config format.generaldelta=True
36 36 $ cd server
37 37 $ touch a
38 38 $ hg commit -Aqm a
39 39 $ echo x > x
40 40 $ echo y > y
41 41 $ hg commit -Aqm xy
42 42 $ hg up -q '.^'
43 43 $ echo x > x
44 44 $ echo z > z
45 45 $ hg commit -Aqm xz
46 46 $ hg up -q 1
47 47 $ echo b > b
48 48 $ hg commit -Aqm b
49 49 $ hg merge -q 2
50 50 $ hg commit -Aqm merge
51 51 $ echo c > c
52 52 $ hg commit -Aqm c
53 53 $ hg log -G -T '{rev} {shortest(node)} {desc}'
54 54 @ 5 ebb8 c
55 55 |
56 56 o 4 baf7 merge
57 57 |\
58 58 | o 3 a129 b
59 59 | |
60 60 o | 2 958c xz
61 61 | |
62 62 | o 1 f00c xy
63 63 |/
64 64 o 0 3903 a
65 65
66 66 $ cd ..
67 67 $ hg init client --config format.generaldelta=false --config format.usegeneraldelta=false
68 68 $ cd client
69 69 $ hg pull -q ../server -r 4
70 70 $ hg debugindex x
71 71 rev offset length base linkrev nodeid p1 p2
72 72 0 0 3 0 1 1406e7411862 000000000000 000000000000
73 73
74 74 $ cd ..
75 75
76 76 Test "usegeneraldelta" config
77 77 (repo are general delta, but incoming bundle are not re-deltified)
78 78
79 79 delta coming from the server base delta server are not recompressed.
80 80 (also include the aggressive version for comparison)
81 81
82 82 $ hg clone repo --pull --config format.usegeneraldelta=1 usegd
83 83 requesting all changes
84 84 adding changesets
85 85 adding manifests
86 86 adding file changes
87 87 added 4 changesets with 6 changes to 3 files (+2 heads)
88 88 updating to branch default
89 89 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 90 $ hg clone repo --pull --config format.generaldelta=1 full
91 91 requesting all changes
92 92 adding changesets
93 93 adding manifests
94 94 adding file changes
95 95 added 4 changesets with 6 changes to 3 files (+2 heads)
96 96 updating to branch default
97 97 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
98 98 $ hg -R repo debugindex -m
99 99 rev offset length base linkrev nodeid p1 p2
100 100 0 0 104 0 0 cef96823c800 000000000000 000000000000
101 101 1 104 57 0 1 58ab9a8d541d cef96823c800 000000000000
102 102 2 161 57 0 2 134fdc6fd680 cef96823c800 000000000000
103 103 3 218 104 3 3 723508934dad cef96823c800 000000000000
104 104 $ hg -R usegd debugindex -m
105 105 rev offset length delta linkrev nodeid p1 p2
106 106 0 0 104 -1 0 cef96823c800 000000000000 000000000000
107 107 1 104 57 0 1 58ab9a8d541d cef96823c800 000000000000
108 108 2 161 57 1 2 134fdc6fd680 cef96823c800 000000000000
109 109 3 218 57 0 3 723508934dad cef96823c800 000000000000
110 110 $ hg -R full debugindex -m
111 111 rev offset length delta linkrev nodeid p1 p2
112 112 0 0 104 -1 0 cef96823c800 000000000000 000000000000
113 113 1 104 57 0 1 58ab9a8d541d cef96823c800 000000000000
114 114 2 161 57 0 2 134fdc6fd680 cef96823c800 000000000000
115 115 3 218 57 0 3 723508934dad cef96823c800 000000000000
116 116
117 117 Test format.aggressivemergedeltas
118 118
119 119 $ hg init --config format.generaldelta=1 aggressive
120 120 $ cd aggressive
121 121 $ cat << EOF >> .hg/hgrc
122 122 > [format]
123 123 > generaldelta = 1
124 124 > EOF
125 125 $ touch a b c d e
126 126 $ hg commit -Aqm side1
127 127 $ hg up -q null
128 128 $ touch x y
129 129 $ hg commit -Aqm side2
130 130
131 131 - Verify non-aggressive merge uses p1 (commit 1) as delta parent
132 132 $ hg merge -q 0
133 133 $ hg commit -q -m merge
134 134 $ hg debugindex -m
135 135 rev offset length delta linkrev nodeid p1 p2
136 136 0 0 59 -1 0 8dde941edb6e 000000000000 000000000000
137 137 1 59 61 0 1 315c023f341d 000000000000 000000000000
138 138 2 120 65 1 2 2ab389a983eb 315c023f341d 8dde941edb6e
139 139
140 140 $ hg strip -q -r . --config extensions.strip=
141 141
142 142 - Verify aggressive merge uses p2 (commit 0) as delta parent
143 143 $ hg up -q -C 1
144 144 $ hg merge -q 0
145 145 $ hg commit -q -m merge --config format.aggressivemergedeltas=True
146 146 $ hg debugindex -m
147 147 rev offset length delta linkrev nodeid p1 p2
148 148 0 0 59 -1 0 8dde941edb6e 000000000000 000000000000
149 149 1 59 61 0 1 315c023f341d 000000000000 000000000000
150 150 2 120 62 0 2 2ab389a983eb 315c023f341d 8dde941edb6e
151 151
152 152 Test that strip bundle use bundle2
153 153 $ hg --config extensions.strip= strip .
154 154 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
155 155 saved backup bundle to $TESTTMP/aggressive/.hg/strip-backup/1c5d4dc9a8b8-6c68e60c-backup.hg (glob)
156 156 $ hg debugbundle .hg/strip-backup/*
157 157 Stream params: sortdict([('Compression', 'BZ')])
158 changegroup -- "sortdict([('version', '02')])"
158 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
159 159 1c5d4dc9a8b8d6e1750966d343e94db665e7a1e9
160 160
161 161 $ cd ..
@@ -1,272 +1,272 b''
1 1 #require serve
2 2
3 3 = Test the getbundle() protocol function =
4 4
5 5 Create a test repository:
6 6
7 7 $ hg init repo
8 8 $ cd repo
9 9 $ hg debugbuilddag -n -m '+2 :fork +5 :p1 *fork +6 :p2 /p1 :m1 +3' > /dev/null
10 10 $ hg log -G --template '{node}\n'
11 11 o 10c14a2cc935e1d8c31f9e98587dcf27fb08a6da
12 12 |
13 13 o 4801a72e5d88cb515b0c7e40fae34180f3f837f2
14 14 |
15 15 o 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
16 16 |
17 17 o 8365676dbab05860ce0d9110f2af51368b961bbd
18 18 |\
19 19 | o 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
20 20 | |
21 21 | o 13c0170174366b441dc68e8e33757232fa744458
22 22 | |
23 23 | o 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
24 24 | |
25 25 | o 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
26 26 | |
27 27 | o 928b5f94cdb278bb536eba552de348a4e92ef24d
28 28 | |
29 29 | o f34414c64173e0ecb61b25dc55e116dbbcc89bee
30 30 | |
31 31 | o 8931463777131cd73923e560b760061f2aa8a4bc
32 32 | |
33 33 o | 6621d79f61b23ec74cf4b69464343d9e0980ec8b
34 34 | |
35 35 o | bac16991d12ff45f9dc43c52da1946dfadb83e80
36 36 | |
37 37 o | ff42371d57168345fdf1a3aac66a51f6a45d41d2
38 38 | |
39 39 o | d5f6e1ea452285324836a49d7d3c2a63cfed1d31
40 40 | |
41 41 o | 713346a995c363120712aed1aee7e04afd867638
42 42 |/
43 43 o 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
44 44 |
45 45 o 7704483d56b2a7b5db54dcee7c62378ac629b348
46 46
47 47 $ cd ..
48 48
49 49
50 50 = Test locally =
51 51
52 52 Get everything:
53 53
54 54 $ hg debuggetbundle repo bundle
55 55 $ hg debugbundle bundle
56 56 7704483d56b2a7b5db54dcee7c62378ac629b348
57 57 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
58 58 713346a995c363120712aed1aee7e04afd867638
59 59 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
60 60 ff42371d57168345fdf1a3aac66a51f6a45d41d2
61 61 bac16991d12ff45f9dc43c52da1946dfadb83e80
62 62 6621d79f61b23ec74cf4b69464343d9e0980ec8b
63 63 8931463777131cd73923e560b760061f2aa8a4bc
64 64 f34414c64173e0ecb61b25dc55e116dbbcc89bee
65 65 928b5f94cdb278bb536eba552de348a4e92ef24d
66 66 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
67 67 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
68 68 13c0170174366b441dc68e8e33757232fa744458
69 69 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
70 70 8365676dbab05860ce0d9110f2af51368b961bbd
71 71 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
72 72 4801a72e5d88cb515b0c7e40fae34180f3f837f2
73 73 10c14a2cc935e1d8c31f9e98587dcf27fb08a6da
74 74
75 75 Get part of linear run:
76 76
77 77 $ hg debuggetbundle repo bundle -H 4801a72e5d88cb515b0c7e40fae34180f3f837f2 -C 8365676dbab05860ce0d9110f2af51368b961bbd
78 78 $ hg debugbundle bundle
79 79 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
80 80 4801a72e5d88cb515b0c7e40fae34180f3f837f2
81 81
82 82 Get missing branch and merge:
83 83
84 84 $ hg debuggetbundle repo bundle -H 4801a72e5d88cb515b0c7e40fae34180f3f837f2 -C 13c0170174366b441dc68e8e33757232fa744458
85 85 $ hg debugbundle bundle
86 86 713346a995c363120712aed1aee7e04afd867638
87 87 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
88 88 ff42371d57168345fdf1a3aac66a51f6a45d41d2
89 89 bac16991d12ff45f9dc43c52da1946dfadb83e80
90 90 6621d79f61b23ec74cf4b69464343d9e0980ec8b
91 91 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
92 92 8365676dbab05860ce0d9110f2af51368b961bbd
93 93 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
94 94 4801a72e5d88cb515b0c7e40fae34180f3f837f2
95 95
96 96 Get from only one head:
97 97
98 98 $ hg debuggetbundle repo bundle -H 928b5f94cdb278bb536eba552de348a4e92ef24d -C 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
99 99 $ hg debugbundle bundle
100 100 8931463777131cd73923e560b760061f2aa8a4bc
101 101 f34414c64173e0ecb61b25dc55e116dbbcc89bee
102 102 928b5f94cdb278bb536eba552de348a4e92ef24d
103 103
104 104 Get parts of two branches:
105 105
106 106 $ hg debuggetbundle repo bundle -H 13c0170174366b441dc68e8e33757232fa744458 -C 700b7e19db54103633c4bf4a6a6b6d55f4d50c03 -H bac16991d12ff45f9dc43c52da1946dfadb83e80 -C d5f6e1ea452285324836a49d7d3c2a63cfed1d31
107 107 $ hg debugbundle bundle
108 108 ff42371d57168345fdf1a3aac66a51f6a45d41d2
109 109 bac16991d12ff45f9dc43c52da1946dfadb83e80
110 110 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
111 111 13c0170174366b441dc68e8e33757232fa744458
112 112
113 113 Check that we get all needed file changes:
114 114
115 115 $ hg debugbundle bundle --all
116 116 format: id, p1, p2, cset, delta base, len(delta)
117 117
118 118 changelog
119 119 ff42371d57168345fdf1a3aac66a51f6a45d41d2 d5f6e1ea452285324836a49d7d3c2a63cfed1d31 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 d5f6e1ea452285324836a49d7d3c2a63cfed1d31 99
120 120 bac16991d12ff45f9dc43c52da1946dfadb83e80 ff42371d57168345fdf1a3aac66a51f6a45d41d2 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 ff42371d57168345fdf1a3aac66a51f6a45d41d2 99
121 121 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 700b7e19db54103633c4bf4a6a6b6d55f4d50c03 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 bac16991d12ff45f9dc43c52da1946dfadb83e80 102
122 122 13c0170174366b441dc68e8e33757232fa744458 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 102
123 123
124 124 manifest
125 125 dac7984588fc4eea7acbf39693a9c1b06f5b175d 591f732a3faf1fb903815273f3c199a514a61ccb 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 591f732a3faf1fb903815273f3c199a514a61ccb 113
126 126 0772616e6b48a76afb6c1458e193cbb3dae2e4ff dac7984588fc4eea7acbf39693a9c1b06f5b175d 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 dac7984588fc4eea7acbf39693a9c1b06f5b175d 113
127 127 eb498cd9af6c44108e43041e951ce829e29f6c80 bff2f4817ced57b386caf7c4e3e36a4bc9af7e93 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0772616e6b48a76afb6c1458e193cbb3dae2e4ff 295
128 128 b15709c071ddd2d93188508ba156196ab4f19620 eb498cd9af6c44108e43041e951ce829e29f6c80 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 eb498cd9af6c44108e43041e951ce829e29f6c80 114
129 129
130 130 mf
131 131 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 301ca08d026bb72cb4258a9d211bdf7ca0bcd810 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 301ca08d026bb72cb4258a9d211bdf7ca0bcd810 17
132 132 c7b583de053293870e145f45bd2d61643563fd06 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 18
133 133 266ee3c0302a5a18f1cf96817ac79a51836179e9 edc0f6b8db80d68ae6aff2b19f7e5347ab68fa63 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 c7b583de053293870e145f45bd2d61643563fd06 149
134 134 698c6a36220548cd3903ca7dada27c59aa500c52 266ee3c0302a5a18f1cf96817ac79a51836179e9 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 266ee3c0302a5a18f1cf96817ac79a51836179e9 19
135 135
136 136 nf11
137 137 33fbc651630ffa7ccbebfe4eb91320a873e7291c 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0000000000000000000000000000000000000000 16
138 138
139 139 nf12
140 140 ddce0544363f037e9fb889faca058f52dc01c0a5 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 0000000000000000000000000000000000000000 16
141 141
142 142 nf4
143 143 3c1407305701051cbed9f9cb9a68bdfb5997c235 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 0000000000000000000000000000000000000000 15
144 144
145 145 nf5
146 146 0dbd89c185f53a1727c54cd1ce256482fa23968e 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 0000000000000000000000000000000000000000 15
147 147
148 148 Get branch and merge:
149 149
150 150 $ hg debuggetbundle repo bundle -C 7704483d56b2a7b5db54dcee7c62378ac629b348 -H 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
151 151 $ hg debugbundle bundle
152 152 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
153 153 713346a995c363120712aed1aee7e04afd867638
154 154 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
155 155 ff42371d57168345fdf1a3aac66a51f6a45d41d2
156 156 bac16991d12ff45f9dc43c52da1946dfadb83e80
157 157 6621d79f61b23ec74cf4b69464343d9e0980ec8b
158 158 8931463777131cd73923e560b760061f2aa8a4bc
159 159 f34414c64173e0ecb61b25dc55e116dbbcc89bee
160 160 928b5f94cdb278bb536eba552de348a4e92ef24d
161 161 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
162 162 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
163 163 13c0170174366b441dc68e8e33757232fa744458
164 164 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
165 165 8365676dbab05860ce0d9110f2af51368b961bbd
166 166 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
167 167
168 168 = Test bundle2 =
169 169
170 170 $ hg debuggetbundle repo bundle -t bundle2
171 171 $ hg debugbundle bundle
172 172 Stream params: {}
173 changegroup -- "sortdict([('version', '01')])"
173 changegroup -- "sortdict([('version', '01'), ('nbchanges', '18')])"
174 174 7704483d56b2a7b5db54dcee7c62378ac629b348
175 175 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
176 176 713346a995c363120712aed1aee7e04afd867638
177 177 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
178 178 ff42371d57168345fdf1a3aac66a51f6a45d41d2
179 179 bac16991d12ff45f9dc43c52da1946dfadb83e80
180 180 6621d79f61b23ec74cf4b69464343d9e0980ec8b
181 181 8931463777131cd73923e560b760061f2aa8a4bc
182 182 f34414c64173e0ecb61b25dc55e116dbbcc89bee
183 183 928b5f94cdb278bb536eba552de348a4e92ef24d
184 184 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
185 185 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
186 186 13c0170174366b441dc68e8e33757232fa744458
187 187 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
188 188 8365676dbab05860ce0d9110f2af51368b961bbd
189 189 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
190 190 4801a72e5d88cb515b0c7e40fae34180f3f837f2
191 191 10c14a2cc935e1d8c31f9e98587dcf27fb08a6da
192 192 = Test via HTTP =
193 193
194 194 Get everything:
195 195
196 196 $ hg serve -R repo -p $HGPORT -d --pid-file=hg.pid -E error.log -A access.log
197 197 $ cat hg.pid >> $DAEMON_PIDS
198 198 $ hg debuggetbundle http://localhost:$HGPORT/ bundle
199 199 $ hg debugbundle bundle
200 200 7704483d56b2a7b5db54dcee7c62378ac629b348
201 201 29a4d1f17bd3f0779ca0525bebb1cfb51067c738
202 202 713346a995c363120712aed1aee7e04afd867638
203 203 d5f6e1ea452285324836a49d7d3c2a63cfed1d31
204 204 ff42371d57168345fdf1a3aac66a51f6a45d41d2
205 205 bac16991d12ff45f9dc43c52da1946dfadb83e80
206 206 6621d79f61b23ec74cf4b69464343d9e0980ec8b
207 207 8931463777131cd73923e560b760061f2aa8a4bc
208 208 f34414c64173e0ecb61b25dc55e116dbbcc89bee
209 209 928b5f94cdb278bb536eba552de348a4e92ef24d
210 210 700b7e19db54103633c4bf4a6a6b6d55f4d50c03
211 211 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
212 212 13c0170174366b441dc68e8e33757232fa744458
213 213 5686dbbd9fc46cb806599c878d02fe1cb56b83d3
214 214 8365676dbab05860ce0d9110f2af51368b961bbd
215 215 0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
216 216 4801a72e5d88cb515b0c7e40fae34180f3f837f2
217 217 10c14a2cc935e1d8c31f9e98587dcf27fb08a6da
218 218
219 219 Get parts of two branches:
220 220
221 221 $ hg debuggetbundle http://localhost:$HGPORT/ bundle -H 13c0170174366b441dc68e8e33757232fa744458 -C 700b7e19db54103633c4bf4a6a6b6d55f4d50c03 -H bac16991d12ff45f9dc43c52da1946dfadb83e80 -C d5f6e1ea452285324836a49d7d3c2a63cfed1d31
222 222 $ hg debugbundle bundle
223 223 ff42371d57168345fdf1a3aac66a51f6a45d41d2
224 224 bac16991d12ff45f9dc43c52da1946dfadb83e80
225 225 63476832d8ec6558cf9bbe3cbe0c757e5cf18043
226 226 13c0170174366b441dc68e8e33757232fa744458
227 227
228 228 Check that we get all needed file changes:
229 229
230 230 $ hg debugbundle bundle --all
231 231 format: id, p1, p2, cset, delta base, len(delta)
232 232
233 233 changelog
234 234 ff42371d57168345fdf1a3aac66a51f6a45d41d2 d5f6e1ea452285324836a49d7d3c2a63cfed1d31 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 d5f6e1ea452285324836a49d7d3c2a63cfed1d31 99
235 235 bac16991d12ff45f9dc43c52da1946dfadb83e80 ff42371d57168345fdf1a3aac66a51f6a45d41d2 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 ff42371d57168345fdf1a3aac66a51f6a45d41d2 99
236 236 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 700b7e19db54103633c4bf4a6a6b6d55f4d50c03 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 bac16991d12ff45f9dc43c52da1946dfadb83e80 102
237 237 13c0170174366b441dc68e8e33757232fa744458 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 102
238 238
239 239 manifest
240 240 dac7984588fc4eea7acbf39693a9c1b06f5b175d 591f732a3faf1fb903815273f3c199a514a61ccb 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 591f732a3faf1fb903815273f3c199a514a61ccb 113
241 241 0772616e6b48a76afb6c1458e193cbb3dae2e4ff dac7984588fc4eea7acbf39693a9c1b06f5b175d 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 dac7984588fc4eea7acbf39693a9c1b06f5b175d 113
242 242 eb498cd9af6c44108e43041e951ce829e29f6c80 bff2f4817ced57b386caf7c4e3e36a4bc9af7e93 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0772616e6b48a76afb6c1458e193cbb3dae2e4ff 295
243 243 b15709c071ddd2d93188508ba156196ab4f19620 eb498cd9af6c44108e43041e951ce829e29f6c80 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 eb498cd9af6c44108e43041e951ce829e29f6c80 114
244 244
245 245 mf
246 246 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 301ca08d026bb72cb4258a9d211bdf7ca0bcd810 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 301ca08d026bb72cb4258a9d211bdf7ca0bcd810 17
247 247 c7b583de053293870e145f45bd2d61643563fd06 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 4f73f97080266ab8e0c0561ca8d0da3eaf65b695 18
248 248 266ee3c0302a5a18f1cf96817ac79a51836179e9 edc0f6b8db80d68ae6aff2b19f7e5347ab68fa63 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 c7b583de053293870e145f45bd2d61643563fd06 149
249 249 698c6a36220548cd3903ca7dada27c59aa500c52 266ee3c0302a5a18f1cf96817ac79a51836179e9 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 266ee3c0302a5a18f1cf96817ac79a51836179e9 19
250 250
251 251 nf11
252 252 33fbc651630ffa7ccbebfe4eb91320a873e7291c 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 63476832d8ec6558cf9bbe3cbe0c757e5cf18043 0000000000000000000000000000000000000000 16
253 253
254 254 nf12
255 255 ddce0544363f037e9fb889faca058f52dc01c0a5 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 13c0170174366b441dc68e8e33757232fa744458 0000000000000000000000000000000000000000 16
256 256
257 257 nf4
258 258 3c1407305701051cbed9f9cb9a68bdfb5997c235 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 ff42371d57168345fdf1a3aac66a51f6a45d41d2 0000000000000000000000000000000000000000 15
259 259
260 260 nf5
261 261 0dbd89c185f53a1727c54cd1ce256482fa23968e 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 bac16991d12ff45f9dc43c52da1946dfadb83e80 0000000000000000000000000000000000000000 15
262 262
263 263 Verify we hit the HTTP server:
264 264
265 265 $ cat access.log
266 266 * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
267 267 * - - [*] "GET /?cmd=getbundle HTTP/1.1" 200 - (glob)
268 268 * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
269 269 * - - [*] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:common=700b7e19db54103633c4bf4a6a6b6d55f4d50c03+d5f6e1ea452285324836a49d7d3c2a63cfed1d31&heads=13c0170174366b441dc68e8e33757232fa744458+bac16991d12ff45f9dc43c52da1946dfadb83e80 (glob)
270 270
271 271 $ cat error.log
272 272
@@ -1,2909 +1,2909 b''
1 1 Note for future hackers of patchbomb: this file is a bit heavy on
2 2 wildcards in test expectations due to how many things like hostnames
3 3 tend to make it into outputs. As a result, you may need to perform the
4 4 following regular expression substitutions:
5 5 @$HOSTNAME> -> @*> (glob)
6 6 Mercurial-patchbomb/.* -> Mercurial-patchbomb/* (glob)
7 7 /mixed; boundary="===+[0-9]+==" -> /mixed; boundary="===*== (glob)"
8 8 --===+[0-9]+=+--$ -> --===*=-- (glob)
9 9 --===+[0-9]+=+$ -> --===*= (glob)
10 10
11 11 $ cat > prune-blank-after-boundary.py <<EOF
12 12 > import sys
13 13 > skipblank = False
14 14 > trim = lambda x: x.strip(' \r\n')
15 15 > for l in sys.stdin:
16 16 > if trim(l).endswith('=--') or trim(l).endswith('=='):
17 17 > skipblank = True
18 18 > print l,
19 19 > continue
20 20 > if not trim(l) and skipblank:
21 21 > continue
22 22 > skipblank = False
23 23 > print l,
24 24 > EOF
25 25 $ FILTERBOUNDARY="python `pwd`/prune-blank-after-boundary.py"
26 26 $ echo "[format]" >> $HGRCPATH
27 27 $ echo "usegeneraldelta=yes" >> $HGRCPATH
28 28 $ echo "[extensions]" >> $HGRCPATH
29 29 $ echo "patchbomb=" >> $HGRCPATH
30 30
31 31 Ensure hg email output is sent to stdout
32 32 $ unset PAGER
33 33
34 34 $ hg init t
35 35 $ cd t
36 36 $ echo a > a
37 37 $ hg commit -Ama -d '1 0'
38 38 adding a
39 39
40 40 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -r tip
41 41 this patch series consists of 1 patches.
42 42
43 43
44 44 displaying [PATCH] a ...
45 45 Content-Type: text/plain; charset="us-ascii"
46 46 MIME-Version: 1.0
47 47 Content-Transfer-Encoding: 7bit
48 48 Subject: [PATCH] a
49 49 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
50 50 X-Mercurial-Series-Index: 1
51 51 X-Mercurial-Series-Total: 1
52 52 Message-Id: <8580ff50825a50c8f716.60@*> (glob)
53 53 X-Mercurial-Series-Id: <8580ff50825a50c8f716.60@*> (glob)
54 54 User-Agent: Mercurial-patchbomb/* (glob)
55 55 Date: Thu, 01 Jan 1970 00:01:00 +0000
56 56 From: quux
57 57 To: foo
58 58 Cc: bar
59 59
60 60 # HG changeset patch
61 61 # User test
62 62 # Date 1 0
63 63 # Thu Jan 01 00:00:01 1970 +0000
64 64 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
65 65 # Parent 0000000000000000000000000000000000000000
66 66 a
67 67
68 68 diff -r 000000000000 -r 8580ff50825a a
69 69 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
70 70 +++ b/a Thu Jan 01 00:00:01 1970 +0000
71 71 @@ -0,0 +1,1 @@
72 72 +a
73 73
74 74
75 75 $ hg --config ui.interactive=1 email --confirm -n -f quux -t foo -c bar -r tip<<EOF
76 76 > n
77 77 > EOF
78 78 this patch series consists of 1 patches.
79 79
80 80
81 81 Final summary:
82 82
83 83 From: quux
84 84 To: foo
85 85 Cc: bar
86 86 Subject: [PATCH] a
87 87 a | 1 +
88 88 1 files changed, 1 insertions(+), 0 deletions(-)
89 89
90 90 are you sure you want to send (yn)? n
91 91 abort: patchbomb canceled
92 92 [255]
93 93
94 94 $ hg --config ui.interactive=1 --config patchbomb.confirm=true email -n -f quux -t foo -c bar -r tip<<EOF
95 95 > n
96 96 > EOF
97 97 this patch series consists of 1 patches.
98 98
99 99
100 100 Final summary:
101 101
102 102 From: quux
103 103 To: foo
104 104 Cc: bar
105 105 Subject: [PATCH] a
106 106 a | 1 +
107 107 1 files changed, 1 insertions(+), 0 deletions(-)
108 108
109 109 are you sure you want to send (yn)? n
110 110 abort: patchbomb canceled
111 111 [255]
112 112
113 113
114 114 Test diff.git is respected
115 115 $ hg --config diff.git=True email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -r tip
116 116 this patch series consists of 1 patches.
117 117
118 118
119 119 displaying [PATCH] a ...
120 120 Content-Type: text/plain; charset="us-ascii"
121 121 MIME-Version: 1.0
122 122 Content-Transfer-Encoding: 7bit
123 123 Subject: [PATCH] a
124 124 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
125 125 X-Mercurial-Series-Index: 1
126 126 X-Mercurial-Series-Total: 1
127 127 Message-Id: <8580ff50825a50c8f716.60@*> (glob)
128 128 X-Mercurial-Series-Id: <8580ff50825a50c8f716.60@*> (glob)
129 129 User-Agent: Mercurial-patchbomb/* (glob)
130 130 Date: Thu, 01 Jan 1970 00:01:00 +0000
131 131 From: quux
132 132 To: foo
133 133 Cc: bar
134 134
135 135 # HG changeset patch
136 136 # User test
137 137 # Date 1 0
138 138 # Thu Jan 01 00:00:01 1970 +0000
139 139 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
140 140 # Parent 0000000000000000000000000000000000000000
141 141 a
142 142
143 143 diff --git a/a b/a
144 144 new file mode 100644
145 145 --- /dev/null
146 146 +++ b/a
147 147 @@ -0,0 +1,1 @@
148 148 +a
149 149
150 150
151 151
152 152 Test breaking format changes aren't
153 153 $ hg --config diff.noprefix=True email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -r tip
154 154 this patch series consists of 1 patches.
155 155
156 156
157 157 displaying [PATCH] a ...
158 158 Content-Type: text/plain; charset="us-ascii"
159 159 MIME-Version: 1.0
160 160 Content-Transfer-Encoding: 7bit
161 161 Subject: [PATCH] a
162 162 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
163 163 X-Mercurial-Series-Index: 1
164 164 X-Mercurial-Series-Total: 1
165 165 Message-Id: <8580ff50825a50c8f716.60@*> (glob)
166 166 X-Mercurial-Series-Id: <8580ff50825a50c8f716.60@*> (glob)
167 167 User-Agent: Mercurial-patchbomb/* (glob)
168 168 Date: Thu, 01 Jan 1970 00:01:00 +0000
169 169 From: quux
170 170 To: foo
171 171 Cc: bar
172 172
173 173 # HG changeset patch
174 174 # User test
175 175 # Date 1 0
176 176 # Thu Jan 01 00:00:01 1970 +0000
177 177 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
178 178 # Parent 0000000000000000000000000000000000000000
179 179 a
180 180
181 181 diff -r 000000000000 -r 8580ff50825a a
182 182 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
183 183 +++ b/a Thu Jan 01 00:00:01 1970 +0000
184 184 @@ -0,0 +1,1 @@
185 185 +a
186 186
187 187
188 188 $ echo b > b
189 189 $ hg commit -Amb -d '2 0'
190 190 adding b
191 191
192 192 $ hg email --date '1970-1-1 0:2' -n -f quux -t foo -c bar -s test -r 0:tip
193 193 this patch series consists of 2 patches.
194 194
195 195
196 196 Write the introductory message for the patch series.
197 197
198 198
199 199 displaying [PATCH 0 of 2] test ...
200 200 Content-Type: text/plain; charset="us-ascii"
201 201 MIME-Version: 1.0
202 202 Content-Transfer-Encoding: 7bit
203 203 Subject: [PATCH 0 of 2] test
204 204 Message-Id: <patchbomb.120@*> (glob)
205 205 User-Agent: Mercurial-patchbomb/* (glob)
206 206 Date: Thu, 01 Jan 1970 00:02:00 +0000
207 207 From: quux
208 208 To: foo
209 209 Cc: bar
210 210
211 211
212 212 displaying [PATCH 1 of 2] a ...
213 213 Content-Type: text/plain; charset="us-ascii"
214 214 MIME-Version: 1.0
215 215 Content-Transfer-Encoding: 7bit
216 216 Subject: [PATCH 1 of 2] a
217 217 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
218 218 X-Mercurial-Series-Index: 1
219 219 X-Mercurial-Series-Total: 2
220 220 Message-Id: <8580ff50825a50c8f716.121@*> (glob)
221 221 X-Mercurial-Series-Id: <8580ff50825a50c8f716.121@*> (glob)
222 222 In-Reply-To: <patchbomb.120@*> (glob)
223 223 References: <patchbomb.120@*> (glob)
224 224 User-Agent: Mercurial-patchbomb/* (glob)
225 225 Date: Thu, 01 Jan 1970 00:02:01 +0000
226 226 From: quux
227 227 To: foo
228 228 Cc: bar
229 229
230 230 # HG changeset patch
231 231 # User test
232 232 # Date 1 0
233 233 # Thu Jan 01 00:00:01 1970 +0000
234 234 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
235 235 # Parent 0000000000000000000000000000000000000000
236 236 a
237 237
238 238 diff -r 000000000000 -r 8580ff50825a a
239 239 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
240 240 +++ b/a Thu Jan 01 00:00:01 1970 +0000
241 241 @@ -0,0 +1,1 @@
242 242 +a
243 243
244 244 displaying [PATCH 2 of 2] b ...
245 245 Content-Type: text/plain; charset="us-ascii"
246 246 MIME-Version: 1.0
247 247 Content-Transfer-Encoding: 7bit
248 248 Subject: [PATCH 2 of 2] b
249 249 X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
250 250 X-Mercurial-Series-Index: 2
251 251 X-Mercurial-Series-Total: 2
252 252 Message-Id: <97d72e5f12c7e84f8506.122@*> (glob)
253 253 X-Mercurial-Series-Id: <8580ff50825a50c8f716.121@*> (glob)
254 254 In-Reply-To: <patchbomb.120@*> (glob)
255 255 References: <patchbomb.120@*> (glob)
256 256 User-Agent: Mercurial-patchbomb/* (glob)
257 257 Date: Thu, 01 Jan 1970 00:02:02 +0000
258 258 From: quux
259 259 To: foo
260 260 Cc: bar
261 261
262 262 # HG changeset patch
263 263 # User test
264 264 # Date 2 0
265 265 # Thu Jan 01 00:00:02 1970 +0000
266 266 # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
267 267 # Parent 8580ff50825a50c8f716709acdf8de0deddcd6ab
268 268 b
269 269
270 270 diff -r 8580ff50825a -r 97d72e5f12c7 b
271 271 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
272 272 +++ b/b Thu Jan 01 00:00:02 1970 +0000
273 273 @@ -0,0 +1,1 @@
274 274 +b
275 275
276 276
277 277 .hg/last-email.txt
278 278
279 279 $ cat > editor.sh << '__EOF__'
280 280 > echo "a precious introductory message" > "$1"
281 281 > __EOF__
282 282 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg email -n -t foo -s test -r 0:tip > /dev/null
283 283 $ cat .hg/last-email.txt
284 284 a precious introductory message
285 285
286 286 $ hg email -m test.mbox -f quux -t foo -c bar -s test 0:tip \
287 287 > --config extensions.progress= --config progress.assume-tty=1 \
288 288 > --config progress.delay=0 --config progress.refresh=0 \
289 289 > --config progress.width=60
290 290 this patch series consists of 2 patches.
291 291
292 292
293 293 Write the introductory message for the patch series.
294 294
295 295 \r (no-eol) (esc)
296 296 sending [ ] 0/3\r (no-eol) (esc)
297 297 \r (no-eol) (esc)
298 298 \r (no-eol) (esc)
299 299 sending [==============> ] 1/3\r (no-eol) (esc)
300 300 \r (no-eol) (esc)
301 301 \r (no-eol) (esc)
302 302 sending [=============================> ] 2/3\r (no-eol) (esc)
303 303 \r (esc)
304 304 sending [PATCH 0 of 2] test ...
305 305 sending [PATCH 1 of 2] a ...
306 306 sending [PATCH 2 of 2] b ...
307 307
308 308 $ cd ..
309 309
310 310 $ hg clone -q t t2
311 311 $ cd t2
312 312 $ echo c > c
313 313 $ hg commit -Amc -d '3 0'
314 314 adding c
315 315
316 316 $ cat > description <<EOF
317 317 > a multiline
318 318 >
319 319 > description
320 320 > EOF
321 321
322 322
323 323 test bundle and description:
324 324 $ hg email --date '1970-1-1 0:3' -n -f quux -t foo \
325 325 > -c bar -s test -r tip -b --desc description | $FILTERBOUNDARY
326 326 searching for changes
327 327 1 changesets found
328 328
329 329 displaying test ...
330 330 Content-Type: multipart/mixed; boundary="===*==" (glob)
331 331 MIME-Version: 1.0
332 332 Subject: test
333 333 Message-Id: <patchbomb.180@*> (glob)
334 334 User-Agent: Mercurial-patchbomb/* (glob)
335 335 Date: Thu, 01 Jan 1970 00:03:00 +0000
336 336 From: quux
337 337 To: foo
338 338 Cc: bar
339 339
340 340 --===*= (glob)
341 341 Content-Type: text/plain; charset="us-ascii"
342 342 MIME-Version: 1.0
343 343 Content-Transfer-Encoding: 7bit
344 344
345 345 a multiline
346 346
347 347 description
348 348
349 349 --===*= (glob)
350 350 Content-Type: application/x-mercurial-bundle
351 351 MIME-Version: 1.0
352 352 Content-Disposition: attachment; filename="bundle.hg"
353 353 Content-Transfer-Encoding: base64
354 354
355 SEcyMAAAAA5Db21wcmVzc2lvbj1CWkJaaDkxQVkmU1lCZFwPAAAKf//7nFYSWD1/4H7R09C/I70I
356 Ak0E4peoSIYIgQCgGUQOcLABGY2hqoAAAaBMTTAAAahgTCZoAAAAAMQaqn5GmapojQ00DEGI/VGJ
357 kDAJoGTDUAAyM0QaAEqalPTUaMhoyDIDR6IxAGEGmgAehMRhDRsoyB6TYTC8JyLN+jTGqitRAgRJ
358 b3SRlhd8/+VxlAUqAilLoKPEEyxFQkaEGo+DzItFeNiFAo8NMMweVtvXJFIMhjoKC18DeYwjLKBz
359 wrMcs86qJrctDNJorwBMuLcqvTVWHh1IlsIaaaYSUIP2IZsogT1+pSSZS+bSTJrgfKsO9go/f0HF
360 uW4Yr2vXpxDreOgSIAdK/xC8Yay48SLpxIuqc/BZ6rVZCgG21rr0zhCaEgXOTqNaYEvANvg0B0Qo
361 dgtqAs1FDcZgzYitwJh6ZAG0C4mA7FPrp9b7h0h/A44Xgd+0it1gvF0mFE/CCPwymXS+OisOOCAF
362 mDUDAC1pBvsXckU4UJBCZFwP
355 SEcyMAAAAA5Db21wcmVzc2lvbj1CWkJaaDkxQVkmU1kIqE7KAAAKf//7vFYQWD1/4H7R09C/470I
356 Ak0E4peoSIYIgQCgGUQOcLABGY2hqoTTCYaBqaYAAACaaMAATIwAA1MIYDaQaqn6p+jRop+oJkA2
357 oNqD1PU0PUBoxqaMmjMUepoBoDT1GmQNBKmlTT1GTCNMEAYTQ0NNDI0BoMQHpAZAA8o2pkyNJHfX
358 RRbXoyxKRUlAg41B3lpmMOnr77dEpFKAvEUGEkWuC4wioiMjC2Y2a84EXhsNCFIrbXUGId07PJnS
359 ELAOIpL/gE8R8CUeXuw2NKMtkFoLPkcTSomXtgHSg1IKaCNlWwVU3CpmMYqh5gkFYJKOD4UhVVQ6
360 SiF1DpE8ghWvF1ih+fYgagfYHI96w/QsrRATpYiP7VRbINFrQy2c21mZ7M4pXXrPBypoXAIhtum7
361 aKDJCpUqMDF5dfiDChMfgH9nQ4B60Uvgb4AK9dsbSYc+O3tEyNq9g9gZeA5Je2T82GzjC4DbY4F2
362 0kdrTBwslErFshCgDzeEBwICg13oQaQawQA1WWd3F3JFOFCQCKhOyg==
363 363 --===============*==-- (glob)
364 364
365 365 with a specific bundle type
366 366 (binary part must be different)
367 367
368 368 $ hg email --date '1970-1-1 0:3' -n -f quux -t foo \
369 369 > -c bar -s test -r tip -b --desc description \
370 370 > --config patchbomb.bundletype=gzip-v1 | $FILTERBOUNDARY
371 371 searching for changes
372 372 1 changesets found
373 373
374 374 displaying test ...
375 375 Content-Type: multipart/mixed; boundary="===*==" (glob)
376 376 MIME-Version: 1.0
377 377 Subject: test
378 378 Message-Id: <patchbomb.180@*> (glob)
379 379 User-Agent: Mercurial-patchbomb/* (glob)
380 380 Date: Thu, 01 Jan 1970 00:03:00 +0000
381 381 From: quux
382 382 To: foo
383 383 Cc: bar
384 384
385 385 --===*= (glob)
386 386 Content-Type: text/plain; charset="us-ascii"
387 387 MIME-Version: 1.0
388 388 Content-Transfer-Encoding: 7bit
389 389
390 390 a multiline
391 391
392 392 description
393 393
394 394 --===*= (glob)
395 395 Content-Type: application/x-mercurial-bundle
396 396 MIME-Version: 1.0
397 397 Content-Disposition: attachment; filename="bundle.hg"
398 398 Content-Transfer-Encoding: base64
399 399
400 400 SEcxMEdaeJxjYGBY8V9n/iLGbtFfJZuNk/euDCpWfrRy/vTrevFCx1/4t7J5LdeL0ix0Opx3kwEL
401 401 wKYXKqUJwqnG5sYWSWmmJsaWlqYWaRaWJpaWiWamZpYWRgZGxolJiabmSQbmZqlcQMV6QGwCxGzG
402 402 CgZcySARUyA2A2LGZKiZ3Y+Lu786z4z4MWXmsrAZCsqrl1az5y21PMcjpbThzWeXGT+/nutbmvvz
403 403 zXYS3BoGxdrJDIYmlimJJiZpRokmqYYmaSYWFknmSSkmhqbmliamiZYWxuYmBhbJBgZcUBNZQe5K
404 404 Epm7xF/LT+RLx/a9juFTomaYO/Rgsx4rwBN+IMCUDLOKAQBrsmti
405 405 --===============*==-- (glob)
406 406
407 407 utf-8 patch:
408 408 $ $PYTHON -c 'fp = open("utf", "wb"); fp.write("h\xC3\xB6mma!\n"); fp.close();'
409 409 $ hg commit -A -d '4 0' -m 'utf-8 content'
410 410 adding description
411 411 adding utf
412 412
413 413 no mime encoding for email --test:
414 414 $ hg email --date '1970-1-1 0:4' -f quux -t foo -c bar -r tip -n
415 415 this patch series consists of 1 patches.
416 416
417 417
418 418 displaying [PATCH] utf-8 content ...
419 419 Content-Type: text/plain; charset="us-ascii"
420 420 MIME-Version: 1.0
421 421 Content-Transfer-Encoding: 8bit
422 422 Subject: [PATCH] utf-8 content
423 423 X-Mercurial-Node: 909a00e13e9d78b575aeee23dddbada46d5a143f
424 424 X-Mercurial-Series-Index: 1
425 425 X-Mercurial-Series-Total: 1
426 426 Message-Id: <909a00e13e9d78b575ae.240@*> (glob)
427 427 X-Mercurial-Series-Id: <909a00e13e9d78b575ae.240@*> (glob)
428 428 User-Agent: Mercurial-patchbomb/* (glob)
429 429 Date: Thu, 01 Jan 1970 00:04:00 +0000
430 430 From: quux
431 431 To: foo
432 432 Cc: bar
433 433
434 434 # HG changeset patch
435 435 # User test
436 436 # Date 4 0
437 437 # Thu Jan 01 00:00:04 1970 +0000
438 438 # Node ID 909a00e13e9d78b575aeee23dddbada46d5a143f
439 439 # Parent ff2c9fa2018b15fa74b33363bda9527323e2a99f
440 440 utf-8 content
441 441
442 442 diff -r ff2c9fa2018b -r 909a00e13e9d description
443 443 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
444 444 +++ b/description Thu Jan 01 00:00:04 1970 +0000
445 445 @@ -0,0 +1,3 @@
446 446 +a multiline
447 447 +
448 448 +description
449 449 diff -r ff2c9fa2018b -r 909a00e13e9d utf
450 450 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
451 451 +++ b/utf Thu Jan 01 00:00:04 1970 +0000
452 452 @@ -0,0 +1,1 @@
453 453 +h\xc3\xb6mma! (esc)
454 454
455 455
456 456 mime encoded mbox (base64):
457 457 $ hg email --date '1970-1-1 0:4' -f 'Q <quux>' -t foo -c bar -r tip -m mbox
458 458 this patch series consists of 1 patches.
459 459
460 460
461 461 sending [PATCH] utf-8 content ...
462 462
463 463 $ cat mbox
464 464 From quux ... ... .. ..:..:.. .... (re)
465 465 Content-Type: text/plain; charset="utf-8"
466 466 MIME-Version: 1.0
467 467 Content-Transfer-Encoding: base64
468 468 Subject: [PATCH] utf-8 content
469 469 X-Mercurial-Node: 909a00e13e9d78b575aeee23dddbada46d5a143f
470 470 X-Mercurial-Series-Index: 1
471 471 X-Mercurial-Series-Total: 1
472 472 Message-Id: <909a00e13e9d78b575ae.240@*> (glob)
473 473 X-Mercurial-Series-Id: <909a00e13e9d78b575ae.240@*> (glob)
474 474 User-Agent: Mercurial-patchbomb/* (glob)
475 475 Date: Thu, 01 Jan 1970 00:04:00 +0000
476 476 From: Q <quux>
477 477 To: foo
478 478 Cc: bar
479 479
480 480 IyBIRyBjaGFuZ2VzZXQgcGF0Y2gKIyBVc2VyIHRlc3QKIyBEYXRlIDQgMAojICAgICAgVGh1IEph
481 481 biAwMSAwMDowMDowNCAxOTcwICswMDAwCiMgTm9kZSBJRCA5MDlhMDBlMTNlOWQ3OGI1NzVhZWVl
482 482 MjNkZGRiYWRhNDZkNWExNDNmCiMgUGFyZW50ICBmZjJjOWZhMjAxOGIxNWZhNzRiMzMzNjNiZGE5
483 483 NTI3MzIzZTJhOTlmCnV0Zi04IGNvbnRlbnQKCmRpZmYgLXIgZmYyYzlmYTIwMThiIC1yIDkwOWEw
484 484 MGUxM2U5ZCBkZXNjcmlwdGlvbgotLS0gL2Rldi9udWxsCVRodSBKYW4gMDEgMDA6MDA6MDAgMTk3
485 485 MCArMDAwMAorKysgYi9kZXNjcmlwdGlvbglUaHUgSmFuIDAxIDAwOjAwOjA0IDE5NzAgKzAwMDAK
486 486 QEAgLTAsMCArMSwzIEBACithIG11bHRpbGluZQorCitkZXNjcmlwdGlvbgpkaWZmIC1yIGZmMmM5
487 487 ZmEyMDE4YiAtciA5MDlhMDBlMTNlOWQgdXRmCi0tLSAvZGV2L251bGwJVGh1IEphbiAwMSAwMDow
488 488 MDowMCAxOTcwICswMDAwCisrKyBiL3V0ZglUaHUgSmFuIDAxIDAwOjAwOjA0IDE5NzAgKzAwMDAK
489 489 QEAgLTAsMCArMSwxIEBACitow7ZtbWEhCg==
490 490
491 491
492 492 $ $PYTHON -c 'print open("mbox").read().split("\n\n")[1].decode("base64")'
493 493 # HG changeset patch
494 494 # User test
495 495 # Date 4 0
496 496 # Thu Jan 01 00:00:04 1970 +0000
497 497 # Node ID 909a00e13e9d78b575aeee23dddbada46d5a143f
498 498 # Parent ff2c9fa2018b15fa74b33363bda9527323e2a99f
499 499 utf-8 content
500 500
501 501 diff -r ff2c9fa2018b -r 909a00e13e9d description
502 502 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
503 503 +++ b/description Thu Jan 01 00:00:04 1970 +0000
504 504 @@ -0,0 +1,3 @@
505 505 +a multiline
506 506 +
507 507 +description
508 508 diff -r ff2c9fa2018b -r 909a00e13e9d utf
509 509 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
510 510 +++ b/utf Thu Jan 01 00:00:04 1970 +0000
511 511 @@ -0,0 +1,1 @@
512 512 +h\xc3\xb6mma! (esc)
513 513
514 514 $ rm mbox
515 515
516 516 mime encoded mbox (quoted-printable):
517 517 $ $PYTHON -c 'fp = open("long", "wb"); fp.write("%s\nfoo\n\nbar\n" % ("x" * 1024)); fp.close();'
518 518 $ hg commit -A -d '4 0' -m 'long line'
519 519 adding long
520 520
521 521 no mime encoding for email --test:
522 522 $ hg email --date '1970-1-1 0:4' -f quux -t foo -c bar -r tip -n
523 523 this patch series consists of 1 patches.
524 524
525 525
526 526 displaying [PATCH] long line ...
527 527 Content-Type: text/plain; charset="us-ascii"
528 528 MIME-Version: 1.0
529 529 Content-Transfer-Encoding: quoted-printable
530 530 Subject: [PATCH] long line
531 531 X-Mercurial-Node: a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
532 532 X-Mercurial-Series-Index: 1
533 533 X-Mercurial-Series-Total: 1
534 534 Message-Id: <a2ea8fc83dd8b93cfd86.240@*> (glob)
535 535 X-Mercurial-Series-Id: <a2ea8fc83dd8b93cfd86.240@*> (glob)
536 536 User-Agent: Mercurial-patchbomb/* (glob)
537 537 Date: Thu, 01 Jan 1970 00:04:00 +0000
538 538 From: quux
539 539 To: foo
540 540 Cc: bar
541 541
542 542 # HG changeset patch
543 543 # User test
544 544 # Date 4 0
545 545 # Thu Jan 01 00:00:04 1970 +0000
546 546 # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
547 547 # Parent 909a00e13e9d78b575aeee23dddbada46d5a143f
548 548 long line
549 549
550 550 diff -r 909a00e13e9d -r a2ea8fc83dd8 long
551 551 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
552 552 +++ b/long Thu Jan 01 00:00:04 1970 +0000
553 553 @@ -0,0 +1,4 @@
554 554 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
555 555 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
556 556 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
557 557 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
558 558 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
559 559 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
560 560 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
561 561 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
562 562 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
563 563 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
564 564 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
565 565 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
566 566 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
567 567 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
568 568 +foo
569 569 +
570 570 +bar
571 571
572 572
573 573 mime encoded mbox (quoted-printable):
574 574 $ hg email --date '1970-1-1 0:4' -f quux -t foo -c bar -r tip -m mbox
575 575 this patch series consists of 1 patches.
576 576
577 577
578 578 sending [PATCH] long line ...
579 579 $ cat mbox
580 580 From quux ... ... .. ..:..:.. .... (re)
581 581 Content-Type: text/plain; charset="us-ascii"
582 582 MIME-Version: 1.0
583 583 Content-Transfer-Encoding: quoted-printable
584 584 Subject: [PATCH] long line
585 585 X-Mercurial-Node: a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
586 586 X-Mercurial-Series-Index: 1
587 587 X-Mercurial-Series-Total: 1
588 588 Message-Id: <a2ea8fc83dd8b93cfd86.240@*> (glob)
589 589 X-Mercurial-Series-Id: <a2ea8fc83dd8b93cfd86.240@*> (glob)
590 590 User-Agent: Mercurial-patchbomb/* (glob)
591 591 Date: Thu, 01 Jan 1970 00:04:00 +0000
592 592 From: quux
593 593 To: foo
594 594 Cc: bar
595 595
596 596 # HG changeset patch
597 597 # User test
598 598 # Date 4 0
599 599 # Thu Jan 01 00:00:04 1970 +0000
600 600 # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
601 601 # Parent 909a00e13e9d78b575aeee23dddbada46d5a143f
602 602 long line
603 603
604 604 diff -r 909a00e13e9d -r a2ea8fc83dd8 long
605 605 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
606 606 +++ b/long Thu Jan 01 00:00:04 1970 +0000
607 607 @@ -0,0 +1,4 @@
608 608 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
609 609 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
610 610 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
611 611 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
612 612 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
613 613 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
614 614 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
615 615 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
616 616 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
617 617 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
618 618 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
619 619 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
620 620 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
621 621 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
622 622 +foo
623 623 +
624 624 +bar
625 625
626 626
627 627
628 628 $ rm mbox
629 629
630 630 iso-8859-1 patch:
631 631 $ $PYTHON -c 'fp = open("isolatin", "wb"); fp.write("h\xF6mma!\n"); fp.close();'
632 632 $ hg commit -A -d '5 0' -m 'isolatin 8-bit encoding'
633 633 adding isolatin
634 634
635 635 fake ascii mbox:
636 636 $ hg email --date '1970-1-1 0:5' -f quux -t foo -c bar -r tip -m mbox
637 637 this patch series consists of 1 patches.
638 638
639 639
640 640 sending [PATCH] isolatin 8-bit encoding ...
641 641 $ cat mbox
642 642 From quux ... ... .. ..:..:.. .... (re)
643 643 Content-Type: text/plain; charset="us-ascii"
644 644 MIME-Version: 1.0
645 645 Content-Transfer-Encoding: 8bit
646 646 Subject: [PATCH] isolatin 8-bit encoding
647 647 X-Mercurial-Node: 240fb913fc1b7ff15ddb9f33e73d82bf5277c720
648 648 X-Mercurial-Series-Index: 1
649 649 X-Mercurial-Series-Total: 1
650 650 Message-Id: <240fb913fc1b7ff15ddb.300@*> (glob)
651 651 X-Mercurial-Series-Id: <240fb913fc1b7ff15ddb.300@*> (glob)
652 652 User-Agent: Mercurial-patchbomb/* (glob)
653 653 Date: Thu, 01 Jan 1970 00:05:00 +0000
654 654 From: quux
655 655 To: foo
656 656 Cc: bar
657 657
658 658 # HG changeset patch
659 659 # User test
660 660 # Date 5 0
661 661 # Thu Jan 01 00:00:05 1970 +0000
662 662 # Node ID 240fb913fc1b7ff15ddb9f33e73d82bf5277c720
663 663 # Parent a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
664 664 isolatin 8-bit encoding
665 665
666 666 diff -r a2ea8fc83dd8 -r 240fb913fc1b isolatin
667 667 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
668 668 +++ b/isolatin Thu Jan 01 00:00:05 1970 +0000
669 669 @@ -0,0 +1,1 @@
670 670 +h\xf6mma! (esc)
671 671
672 672
673 673
674 674 test diffstat for single patch:
675 675 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -d -y -r 2
676 676 this patch series consists of 1 patches.
677 677
678 678
679 679 Final summary:
680 680
681 681 From: quux
682 682 To: foo
683 683 Cc: bar
684 684 Subject: [PATCH] test
685 685 c | 1 +
686 686 1 files changed, 1 insertions(+), 0 deletions(-)
687 687
688 688 are you sure you want to send (yn)? y
689 689
690 690 displaying [PATCH] test ...
691 691 Content-Type: text/plain; charset="us-ascii"
692 692 MIME-Version: 1.0
693 693 Content-Transfer-Encoding: 7bit
694 694 Subject: [PATCH] test
695 695 X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
696 696 X-Mercurial-Series-Index: 1
697 697 X-Mercurial-Series-Total: 1
698 698 Message-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
699 699 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
700 700 User-Agent: Mercurial-patchbomb/* (glob)
701 701 Date: Thu, 01 Jan 1970 00:01:00 +0000
702 702 From: quux
703 703 To: foo
704 704 Cc: bar
705 705
706 706 c | 1 +
707 707 1 files changed, 1 insertions(+), 0 deletions(-)
708 708
709 709
710 710 # HG changeset patch
711 711 # User test
712 712 # Date 3 0
713 713 # Thu Jan 01 00:00:03 1970 +0000
714 714 # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
715 715 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
716 716 c
717 717
718 718 diff -r 97d72e5f12c7 -r ff2c9fa2018b c
719 719 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
720 720 +++ b/c Thu Jan 01 00:00:03 1970 +0000
721 721 @@ -0,0 +1,1 @@
722 722 +c
723 723
724 724
725 725 test diffstat for multiple patches:
726 726 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -d -y \
727 727 > -r 0:1
728 728 this patch series consists of 2 patches.
729 729
730 730
731 731 Write the introductory message for the patch series.
732 732
733 733
734 734 Final summary:
735 735
736 736 From: quux
737 737 To: foo
738 738 Cc: bar
739 739 Subject: [PATCH 0 of 2] test
740 740 a | 1 +
741 741 b | 1 +
742 742 2 files changed, 2 insertions(+), 0 deletions(-)
743 743 Subject: [PATCH 1 of 2] a
744 744 a | 1 +
745 745 1 files changed, 1 insertions(+), 0 deletions(-)
746 746 Subject: [PATCH 2 of 2] b
747 747 b | 1 +
748 748 1 files changed, 1 insertions(+), 0 deletions(-)
749 749
750 750 are you sure you want to send (yn)? y
751 751
752 752 displaying [PATCH 0 of 2] test ...
753 753 Content-Type: text/plain; charset="us-ascii"
754 754 MIME-Version: 1.0
755 755 Content-Transfer-Encoding: 7bit
756 756 Subject: [PATCH 0 of 2] test
757 757 Message-Id: <patchbomb.60@*> (glob)
758 758 User-Agent: Mercurial-patchbomb/* (glob)
759 759 Date: Thu, 01 Jan 1970 00:01:00 +0000
760 760 From: quux
761 761 To: foo
762 762 Cc: bar
763 763
764 764
765 765 a | 1 +
766 766 b | 1 +
767 767 2 files changed, 2 insertions(+), 0 deletions(-)
768 768
769 769 displaying [PATCH 1 of 2] a ...
770 770 Content-Type: text/plain; charset="us-ascii"
771 771 MIME-Version: 1.0
772 772 Content-Transfer-Encoding: 7bit
773 773 Subject: [PATCH 1 of 2] a
774 774 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
775 775 X-Mercurial-Series-Index: 1
776 776 X-Mercurial-Series-Total: 2
777 777 Message-Id: <8580ff50825a50c8f716.61@*> (glob)
778 778 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
779 779 In-Reply-To: <patchbomb.60@*> (glob)
780 780 References: <patchbomb.60@*> (glob)
781 781 User-Agent: Mercurial-patchbomb/* (glob)
782 782 Date: Thu, 01 Jan 1970 00:01:01 +0000
783 783 From: quux
784 784 To: foo
785 785 Cc: bar
786 786
787 787 a | 1 +
788 788 1 files changed, 1 insertions(+), 0 deletions(-)
789 789
790 790
791 791 # HG changeset patch
792 792 # User test
793 793 # Date 1 0
794 794 # Thu Jan 01 00:00:01 1970 +0000
795 795 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
796 796 # Parent 0000000000000000000000000000000000000000
797 797 a
798 798
799 799 diff -r 000000000000 -r 8580ff50825a a
800 800 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
801 801 +++ b/a Thu Jan 01 00:00:01 1970 +0000
802 802 @@ -0,0 +1,1 @@
803 803 +a
804 804
805 805 displaying [PATCH 2 of 2] b ...
806 806 Content-Type: text/plain; charset="us-ascii"
807 807 MIME-Version: 1.0
808 808 Content-Transfer-Encoding: 7bit
809 809 Subject: [PATCH 2 of 2] b
810 810 X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
811 811 X-Mercurial-Series-Index: 2
812 812 X-Mercurial-Series-Total: 2
813 813 Message-Id: <97d72e5f12c7e84f8506.62@*> (glob)
814 814 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
815 815 In-Reply-To: <patchbomb.60@*> (glob)
816 816 References: <patchbomb.60@*> (glob)
817 817 User-Agent: Mercurial-patchbomb/* (glob)
818 818 Date: Thu, 01 Jan 1970 00:01:02 +0000
819 819 From: quux
820 820 To: foo
821 821 Cc: bar
822 822
823 823 b | 1 +
824 824 1 files changed, 1 insertions(+), 0 deletions(-)
825 825
826 826
827 827 # HG changeset patch
828 828 # User test
829 829 # Date 2 0
830 830 # Thu Jan 01 00:00:02 1970 +0000
831 831 # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
832 832 # Parent 8580ff50825a50c8f716709acdf8de0deddcd6ab
833 833 b
834 834
835 835 diff -r 8580ff50825a -r 97d72e5f12c7 b
836 836 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
837 837 +++ b/b Thu Jan 01 00:00:02 1970 +0000
838 838 @@ -0,0 +1,1 @@
839 839 +b
840 840
841 841
842 842 test inline for single patch:
843 843 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i -r 2 | $FILTERBOUNDARY
844 844 this patch series consists of 1 patches.
845 845
846 846
847 847 displaying [PATCH] test ...
848 848 Content-Type: multipart/mixed; boundary="===*==" (glob)
849 849 MIME-Version: 1.0
850 850 Subject: [PATCH] test
851 851 X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
852 852 X-Mercurial-Series-Index: 1
853 853 X-Mercurial-Series-Total: 1
854 854 Message-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
855 855 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
856 856 User-Agent: Mercurial-patchbomb/* (glob)
857 857 Date: Thu, 01 Jan 1970 00:01:00 +0000
858 858 From: quux
859 859 To: foo
860 860 Cc: bar
861 861
862 862 --===*= (glob)
863 863 Content-Type: text/x-patch; charset="us-ascii"
864 864 MIME-Version: 1.0
865 865 Content-Transfer-Encoding: 7bit
866 866 Content-Disposition: inline; filename=t2.patch
867 867
868 868 # HG changeset patch
869 869 # User test
870 870 # Date 3 0
871 871 # Thu Jan 01 00:00:03 1970 +0000
872 872 # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
873 873 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
874 874 c
875 875
876 876 diff -r 97d72e5f12c7 -r ff2c9fa2018b c
877 877 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
878 878 +++ b/c Thu Jan 01 00:00:03 1970 +0000
879 879 @@ -0,0 +1,1 @@
880 880 +c
881 881
882 882 --===*=-- (glob)
883 883
884 884
885 885 test inline for single patch (quoted-printable):
886 886 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i -r 4 | $FILTERBOUNDARY
887 887 this patch series consists of 1 patches.
888 888
889 889
890 890 displaying [PATCH] test ...
891 891 Content-Type: multipart/mixed; boundary="===*==" (glob)
892 892 MIME-Version: 1.0
893 893 Subject: [PATCH] test
894 894 X-Mercurial-Node: a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
895 895 X-Mercurial-Series-Index: 1
896 896 X-Mercurial-Series-Total: 1
897 897 Message-Id: <a2ea8fc83dd8b93cfd86.60@*> (glob)
898 898 X-Mercurial-Series-Id: <a2ea8fc83dd8b93cfd86.60@*> (glob)
899 899 User-Agent: Mercurial-patchbomb/* (glob)
900 900 Date: Thu, 01 Jan 1970 00:01:00 +0000
901 901 From: quux
902 902 To: foo
903 903 Cc: bar
904 904
905 905 --===*= (glob)
906 906 Content-Type: text/x-patch; charset="us-ascii"
907 907 MIME-Version: 1.0
908 908 Content-Transfer-Encoding: quoted-printable
909 909 Content-Disposition: inline; filename=t2.patch
910 910
911 911 # HG changeset patch
912 912 # User test
913 913 # Date 4 0
914 914 # Thu Jan 01 00:00:04 1970 +0000
915 915 # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
916 916 # Parent 909a00e13e9d78b575aeee23dddbada46d5a143f
917 917 long line
918 918
919 919 diff -r 909a00e13e9d -r a2ea8fc83dd8 long
920 920 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
921 921 +++ b/long Thu Jan 01 00:00:04 1970 +0000
922 922 @@ -0,0 +1,4 @@
923 923 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
924 924 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
925 925 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
926 926 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
927 927 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
928 928 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
929 929 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
930 930 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
931 931 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
932 932 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
933 933 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
934 934 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
935 935 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
936 936 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
937 937 +foo
938 938 +
939 939 +bar
940 940
941 941 --===*=-- (glob)
942 942
943 943 test inline for multiple patches:
944 944 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i \
945 945 > -r 0:1 -r 4 | $FILTERBOUNDARY
946 946 this patch series consists of 3 patches.
947 947
948 948
949 949 Write the introductory message for the patch series.
950 950
951 951
952 952 displaying [PATCH 0 of 3] test ...
953 953 Content-Type: text/plain; charset="us-ascii"
954 954 MIME-Version: 1.0
955 955 Content-Transfer-Encoding: 7bit
956 956 Subject: [PATCH 0 of 3] test
957 957 Message-Id: <patchbomb.60@*> (glob)
958 958 User-Agent: Mercurial-patchbomb/* (glob)
959 959 Date: Thu, 01 Jan 1970 00:01:00 +0000
960 960 From: quux
961 961 To: foo
962 962 Cc: bar
963 963
964 964
965 965 displaying [PATCH 1 of 3] a ...
966 966 Content-Type: multipart/mixed; boundary="===*==" (glob)
967 967 MIME-Version: 1.0
968 968 Subject: [PATCH 1 of 3] a
969 969 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
970 970 X-Mercurial-Series-Index: 1
971 971 X-Mercurial-Series-Total: 3
972 972 Message-Id: <8580ff50825a50c8f716.61@*> (glob)
973 973 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
974 974 In-Reply-To: <patchbomb.60@*> (glob)
975 975 References: <patchbomb.60@*> (glob)
976 976 User-Agent: Mercurial-patchbomb/* (glob)
977 977 Date: Thu, 01 Jan 1970 00:01:01 +0000
978 978 From: quux
979 979 To: foo
980 980 Cc: bar
981 981
982 982 --===*= (glob)
983 983 Content-Type: text/x-patch; charset="us-ascii"
984 984 MIME-Version: 1.0
985 985 Content-Transfer-Encoding: 7bit
986 986 Content-Disposition: inline; filename=t2-1.patch
987 987
988 988 # HG changeset patch
989 989 # User test
990 990 # Date 1 0
991 991 # Thu Jan 01 00:00:01 1970 +0000
992 992 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
993 993 # Parent 0000000000000000000000000000000000000000
994 994 a
995 995
996 996 diff -r 000000000000 -r 8580ff50825a a
997 997 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
998 998 +++ b/a Thu Jan 01 00:00:01 1970 +0000
999 999 @@ -0,0 +1,1 @@
1000 1000 +a
1001 1001
1002 1002 --===*=-- (glob)
1003 1003 displaying [PATCH 2 of 3] b ...
1004 1004 Content-Type: multipart/mixed; boundary="===*==" (glob)
1005 1005 MIME-Version: 1.0
1006 1006 Subject: [PATCH 2 of 3] b
1007 1007 X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1008 1008 X-Mercurial-Series-Index: 2
1009 1009 X-Mercurial-Series-Total: 3
1010 1010 Message-Id: <97d72e5f12c7e84f8506.62@*> (glob)
1011 1011 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
1012 1012 In-Reply-To: <patchbomb.60@*> (glob)
1013 1013 References: <patchbomb.60@*> (glob)
1014 1014 User-Agent: Mercurial-patchbomb/* (glob)
1015 1015 Date: Thu, 01 Jan 1970 00:01:02 +0000
1016 1016 From: quux
1017 1017 To: foo
1018 1018 Cc: bar
1019 1019
1020 1020 --===*= (glob)
1021 1021 Content-Type: text/x-patch; charset="us-ascii"
1022 1022 MIME-Version: 1.0
1023 1023 Content-Transfer-Encoding: 7bit
1024 1024 Content-Disposition: inline; filename=t2-2.patch
1025 1025
1026 1026 # HG changeset patch
1027 1027 # User test
1028 1028 # Date 2 0
1029 1029 # Thu Jan 01 00:00:02 1970 +0000
1030 1030 # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1031 1031 # Parent 8580ff50825a50c8f716709acdf8de0deddcd6ab
1032 1032 b
1033 1033
1034 1034 diff -r 8580ff50825a -r 97d72e5f12c7 b
1035 1035 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1036 1036 +++ b/b Thu Jan 01 00:00:02 1970 +0000
1037 1037 @@ -0,0 +1,1 @@
1038 1038 +b
1039 1039
1040 1040 --===*=-- (glob)
1041 1041 displaying [PATCH 3 of 3] long line ...
1042 1042 Content-Type: multipart/mixed; boundary="===*==" (glob)
1043 1043 MIME-Version: 1.0
1044 1044 Subject: [PATCH 3 of 3] long line
1045 1045 X-Mercurial-Node: a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
1046 1046 X-Mercurial-Series-Index: 3
1047 1047 X-Mercurial-Series-Total: 3
1048 1048 Message-Id: <a2ea8fc83dd8b93cfd86.63@*> (glob)
1049 1049 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
1050 1050 In-Reply-To: <patchbomb.60@*> (glob)
1051 1051 References: <patchbomb.60@*> (glob)
1052 1052 User-Agent: Mercurial-patchbomb/* (glob)
1053 1053 Date: Thu, 01 Jan 1970 00:01:03 +0000
1054 1054 From: quux
1055 1055 To: foo
1056 1056 Cc: bar
1057 1057
1058 1058 --===*= (glob)
1059 1059 Content-Type: text/x-patch; charset="us-ascii"
1060 1060 MIME-Version: 1.0
1061 1061 Content-Transfer-Encoding: quoted-printable
1062 1062 Content-Disposition: inline; filename=t2-3.patch
1063 1063
1064 1064 # HG changeset patch
1065 1065 # User test
1066 1066 # Date 4 0
1067 1067 # Thu Jan 01 00:00:04 1970 +0000
1068 1068 # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
1069 1069 # Parent 909a00e13e9d78b575aeee23dddbada46d5a143f
1070 1070 long line
1071 1071
1072 1072 diff -r 909a00e13e9d -r a2ea8fc83dd8 long
1073 1073 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1074 1074 +++ b/long Thu Jan 01 00:00:04 1970 +0000
1075 1075 @@ -0,0 +1,4 @@
1076 1076 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1077 1077 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1078 1078 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1079 1079 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1080 1080 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1081 1081 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1082 1082 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1083 1083 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1084 1084 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1085 1085 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1086 1086 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1087 1087 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1088 1088 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1089 1089 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1090 1090 +foo
1091 1091 +
1092 1092 +bar
1093 1093
1094 1094 --===*=-- (glob)
1095 1095
1096 1096 test attach for single patch:
1097 1097 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -a -r 2 | $FILTERBOUNDARY
1098 1098 this patch series consists of 1 patches.
1099 1099
1100 1100
1101 1101 displaying [PATCH] test ...
1102 1102 Content-Type: multipart/mixed; boundary="===*==" (glob)
1103 1103 MIME-Version: 1.0
1104 1104 Subject: [PATCH] test
1105 1105 X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
1106 1106 X-Mercurial-Series-Index: 1
1107 1107 X-Mercurial-Series-Total: 1
1108 1108 Message-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
1109 1109 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
1110 1110 User-Agent: Mercurial-patchbomb/* (glob)
1111 1111 Date: Thu, 01 Jan 1970 00:01:00 +0000
1112 1112 From: quux
1113 1113 To: foo
1114 1114 Cc: bar
1115 1115
1116 1116 --===*= (glob)
1117 1117 Content-Type: text/plain; charset="us-ascii"
1118 1118 MIME-Version: 1.0
1119 1119 Content-Transfer-Encoding: 7bit
1120 1120
1121 1121 Patch subject is complete summary.
1122 1122
1123 1123
1124 1124
1125 1125 --===*= (glob)
1126 1126 Content-Type: text/x-patch; charset="us-ascii"
1127 1127 MIME-Version: 1.0
1128 1128 Content-Transfer-Encoding: 7bit
1129 1129 Content-Disposition: attachment; filename=t2.patch
1130 1130
1131 1131 # HG changeset patch
1132 1132 # User test
1133 1133 # Date 3 0
1134 1134 # Thu Jan 01 00:00:03 1970 +0000
1135 1135 # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
1136 1136 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1137 1137 c
1138 1138
1139 1139 diff -r 97d72e5f12c7 -r ff2c9fa2018b c
1140 1140 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1141 1141 +++ b/c Thu Jan 01 00:00:03 1970 +0000
1142 1142 @@ -0,0 +1,1 @@
1143 1143 +c
1144 1144
1145 1145 --===*=-- (glob)
1146 1146
1147 1147 test attach for single patch (quoted-printable):
1148 1148 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -a -r 4 | $FILTERBOUNDARY
1149 1149 this patch series consists of 1 patches.
1150 1150
1151 1151
1152 1152 displaying [PATCH] test ...
1153 1153 Content-Type: multipart/mixed; boundary="===*==" (glob)
1154 1154 MIME-Version: 1.0
1155 1155 Subject: [PATCH] test
1156 1156 X-Mercurial-Node: a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
1157 1157 X-Mercurial-Series-Index: 1
1158 1158 X-Mercurial-Series-Total: 1
1159 1159 Message-Id: <a2ea8fc83dd8b93cfd86.60@*> (glob)
1160 1160 X-Mercurial-Series-Id: <a2ea8fc83dd8b93cfd86.60@*> (glob)
1161 1161 User-Agent: Mercurial-patchbomb/* (glob)
1162 1162 Date: Thu, 01 Jan 1970 00:01:00 +0000
1163 1163 From: quux
1164 1164 To: foo
1165 1165 Cc: bar
1166 1166
1167 1167 --===*= (glob)
1168 1168 Content-Type: text/plain; charset="us-ascii"
1169 1169 MIME-Version: 1.0
1170 1170 Content-Transfer-Encoding: 7bit
1171 1171
1172 1172 Patch subject is complete summary.
1173 1173
1174 1174
1175 1175
1176 1176 --===*= (glob)
1177 1177 Content-Type: text/x-patch; charset="us-ascii"
1178 1178 MIME-Version: 1.0
1179 1179 Content-Transfer-Encoding: quoted-printable
1180 1180 Content-Disposition: attachment; filename=t2.patch
1181 1181
1182 1182 # HG changeset patch
1183 1183 # User test
1184 1184 # Date 4 0
1185 1185 # Thu Jan 01 00:00:04 1970 +0000
1186 1186 # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
1187 1187 # Parent 909a00e13e9d78b575aeee23dddbada46d5a143f
1188 1188 long line
1189 1189
1190 1190 diff -r 909a00e13e9d -r a2ea8fc83dd8 long
1191 1191 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1192 1192 +++ b/long Thu Jan 01 00:00:04 1970 +0000
1193 1193 @@ -0,0 +1,4 @@
1194 1194 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1195 1195 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1196 1196 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1197 1197 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1198 1198 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1199 1199 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1200 1200 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1201 1201 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1202 1202 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1203 1203 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1204 1204 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1205 1205 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1206 1206 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1207 1207 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1208 1208 +foo
1209 1209 +
1210 1210 +bar
1211 1211
1212 1212 --===*=-- (glob)
1213 1213
1214 1214 test attach and body for single patch:
1215 1215 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -a --body -r 2 | $FILTERBOUNDARY
1216 1216 this patch series consists of 1 patches.
1217 1217
1218 1218
1219 1219 displaying [PATCH] test ...
1220 1220 Content-Type: multipart/mixed; boundary="===*==" (glob)
1221 1221 MIME-Version: 1.0
1222 1222 Subject: [PATCH] test
1223 1223 X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
1224 1224 X-Mercurial-Series-Index: 1
1225 1225 X-Mercurial-Series-Total: 1
1226 1226 Message-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
1227 1227 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
1228 1228 User-Agent: Mercurial-patchbomb/* (glob)
1229 1229 Date: Thu, 01 Jan 1970 00:01:00 +0000
1230 1230 From: quux
1231 1231 To: foo
1232 1232 Cc: bar
1233 1233
1234 1234 --===*= (glob)
1235 1235 Content-Type: text/plain; charset="us-ascii"
1236 1236 MIME-Version: 1.0
1237 1237 Content-Transfer-Encoding: 7bit
1238 1238
1239 1239 # HG changeset patch
1240 1240 # User test
1241 1241 # Date 3 0
1242 1242 # Thu Jan 01 00:00:03 1970 +0000
1243 1243 # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
1244 1244 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1245 1245 c
1246 1246
1247 1247 diff -r 97d72e5f12c7 -r ff2c9fa2018b c
1248 1248 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1249 1249 +++ b/c Thu Jan 01 00:00:03 1970 +0000
1250 1250 @@ -0,0 +1,1 @@
1251 1251 +c
1252 1252
1253 1253 --===*= (glob)
1254 1254 Content-Type: text/x-patch; charset="us-ascii"
1255 1255 MIME-Version: 1.0
1256 1256 Content-Transfer-Encoding: 7bit
1257 1257 Content-Disposition: attachment; filename=t2.patch
1258 1258
1259 1259 # HG changeset patch
1260 1260 # User test
1261 1261 # Date 3 0
1262 1262 # Thu Jan 01 00:00:03 1970 +0000
1263 1263 # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
1264 1264 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1265 1265 c
1266 1266
1267 1267 diff -r 97d72e5f12c7 -r ff2c9fa2018b c
1268 1268 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1269 1269 +++ b/c Thu Jan 01 00:00:03 1970 +0000
1270 1270 @@ -0,0 +1,1 @@
1271 1271 +c
1272 1272
1273 1273 --===*=-- (glob)
1274 1274
1275 1275 test attach for multiple patches:
1276 1276 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -a \
1277 1277 > -r 0:1 -r 4 | $FILTERBOUNDARY
1278 1278 this patch series consists of 3 patches.
1279 1279
1280 1280
1281 1281 Write the introductory message for the patch series.
1282 1282
1283 1283
1284 1284 displaying [PATCH 0 of 3] test ...
1285 1285 Content-Type: text/plain; charset="us-ascii"
1286 1286 MIME-Version: 1.0
1287 1287 Content-Transfer-Encoding: 7bit
1288 1288 Subject: [PATCH 0 of 3] test
1289 1289 Message-Id: <patchbomb.60@*> (glob)
1290 1290 User-Agent: Mercurial-patchbomb/* (glob)
1291 1291 Date: Thu, 01 Jan 1970 00:01:00 +0000
1292 1292 From: quux
1293 1293 To: foo
1294 1294 Cc: bar
1295 1295
1296 1296
1297 1297 displaying [PATCH 1 of 3] a ...
1298 1298 Content-Type: multipart/mixed; boundary="===*==" (glob)
1299 1299 MIME-Version: 1.0
1300 1300 Subject: [PATCH 1 of 3] a
1301 1301 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
1302 1302 X-Mercurial-Series-Index: 1
1303 1303 X-Mercurial-Series-Total: 3
1304 1304 Message-Id: <8580ff50825a50c8f716.61@*> (glob)
1305 1305 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
1306 1306 In-Reply-To: <patchbomb.60@*> (glob)
1307 1307 References: <patchbomb.60@*> (glob)
1308 1308 User-Agent: Mercurial-patchbomb/* (glob)
1309 1309 Date: Thu, 01 Jan 1970 00:01:01 +0000
1310 1310 From: quux
1311 1311 To: foo
1312 1312 Cc: bar
1313 1313
1314 1314 --===*= (glob)
1315 1315 Content-Type: text/plain; charset="us-ascii"
1316 1316 MIME-Version: 1.0
1317 1317 Content-Transfer-Encoding: 7bit
1318 1318
1319 1319 Patch subject is complete summary.
1320 1320
1321 1321
1322 1322
1323 1323 --===*= (glob)
1324 1324 Content-Type: text/x-patch; charset="us-ascii"
1325 1325 MIME-Version: 1.0
1326 1326 Content-Transfer-Encoding: 7bit
1327 1327 Content-Disposition: attachment; filename=t2-1.patch
1328 1328
1329 1329 # HG changeset patch
1330 1330 # User test
1331 1331 # Date 1 0
1332 1332 # Thu Jan 01 00:00:01 1970 +0000
1333 1333 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
1334 1334 # Parent 0000000000000000000000000000000000000000
1335 1335 a
1336 1336
1337 1337 diff -r 000000000000 -r 8580ff50825a a
1338 1338 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1339 1339 +++ b/a Thu Jan 01 00:00:01 1970 +0000
1340 1340 @@ -0,0 +1,1 @@
1341 1341 +a
1342 1342
1343 1343 --===*=-- (glob)
1344 1344 displaying [PATCH 2 of 3] b ...
1345 1345 Content-Type: multipart/mixed; boundary="===*==" (glob)
1346 1346 MIME-Version: 1.0
1347 1347 Subject: [PATCH 2 of 3] b
1348 1348 X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1349 1349 X-Mercurial-Series-Index: 2
1350 1350 X-Mercurial-Series-Total: 3
1351 1351 Message-Id: <97d72e5f12c7e84f8506.62@*> (glob)
1352 1352 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
1353 1353 In-Reply-To: <patchbomb.60@*> (glob)
1354 1354 References: <patchbomb.60@*> (glob)
1355 1355 User-Agent: Mercurial-patchbomb/* (glob)
1356 1356 Date: Thu, 01 Jan 1970 00:01:02 +0000
1357 1357 From: quux
1358 1358 To: foo
1359 1359 Cc: bar
1360 1360
1361 1361 --===*= (glob)
1362 1362 Content-Type: text/plain; charset="us-ascii"
1363 1363 MIME-Version: 1.0
1364 1364 Content-Transfer-Encoding: 7bit
1365 1365
1366 1366 Patch subject is complete summary.
1367 1367
1368 1368
1369 1369
1370 1370 --===*= (glob)
1371 1371 Content-Type: text/x-patch; charset="us-ascii"
1372 1372 MIME-Version: 1.0
1373 1373 Content-Transfer-Encoding: 7bit
1374 1374 Content-Disposition: attachment; filename=t2-2.patch
1375 1375
1376 1376 # HG changeset patch
1377 1377 # User test
1378 1378 # Date 2 0
1379 1379 # Thu Jan 01 00:00:02 1970 +0000
1380 1380 # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1381 1381 # Parent 8580ff50825a50c8f716709acdf8de0deddcd6ab
1382 1382 b
1383 1383
1384 1384 diff -r 8580ff50825a -r 97d72e5f12c7 b
1385 1385 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1386 1386 +++ b/b Thu Jan 01 00:00:02 1970 +0000
1387 1387 @@ -0,0 +1,1 @@
1388 1388 +b
1389 1389
1390 1390 --===*=-- (glob)
1391 1391 displaying [PATCH 3 of 3] long line ...
1392 1392 Content-Type: multipart/mixed; boundary="===*==" (glob)
1393 1393 MIME-Version: 1.0
1394 1394 Subject: [PATCH 3 of 3] long line
1395 1395 X-Mercurial-Node: a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
1396 1396 X-Mercurial-Series-Index: 3
1397 1397 X-Mercurial-Series-Total: 3
1398 1398 Message-Id: <a2ea8fc83dd8b93cfd86.63@*> (glob)
1399 1399 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
1400 1400 In-Reply-To: <patchbomb.60@*> (glob)
1401 1401 References: <patchbomb.60@*> (glob)
1402 1402 User-Agent: Mercurial-patchbomb/* (glob)
1403 1403 Date: Thu, 01 Jan 1970 00:01:03 +0000
1404 1404 From: quux
1405 1405 To: foo
1406 1406 Cc: bar
1407 1407
1408 1408 --===*= (glob)
1409 1409 Content-Type: text/plain; charset="us-ascii"
1410 1410 MIME-Version: 1.0
1411 1411 Content-Transfer-Encoding: 7bit
1412 1412
1413 1413 Patch subject is complete summary.
1414 1414
1415 1415
1416 1416
1417 1417 --===*= (glob)
1418 1418 Content-Type: text/x-patch; charset="us-ascii"
1419 1419 MIME-Version: 1.0
1420 1420 Content-Transfer-Encoding: quoted-printable
1421 1421 Content-Disposition: attachment; filename=t2-3.patch
1422 1422
1423 1423 # HG changeset patch
1424 1424 # User test
1425 1425 # Date 4 0
1426 1426 # Thu Jan 01 00:00:04 1970 +0000
1427 1427 # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
1428 1428 # Parent 909a00e13e9d78b575aeee23dddbada46d5a143f
1429 1429 long line
1430 1430
1431 1431 diff -r 909a00e13e9d -r a2ea8fc83dd8 long
1432 1432 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1433 1433 +++ b/long Thu Jan 01 00:00:04 1970 +0000
1434 1434 @@ -0,0 +1,4 @@
1435 1435 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1436 1436 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1437 1437 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1438 1438 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1439 1439 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1440 1440 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1441 1441 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1442 1442 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1443 1443 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1444 1444 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1445 1445 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1446 1446 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1447 1447 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
1448 1448 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1449 1449 +foo
1450 1450 +
1451 1451 +bar
1452 1452
1453 1453 --===*=-- (glob)
1454 1454
1455 1455 test intro for single patch:
1456 1456 $ hg email --date '1970-1-1 0:1' -n --intro -f quux -t foo -c bar -s test \
1457 1457 > -r 2
1458 1458 this patch series consists of 1 patches.
1459 1459
1460 1460
1461 1461 Write the introductory message for the patch series.
1462 1462
1463 1463
1464 1464 displaying [PATCH 0 of 1] test ...
1465 1465 Content-Type: text/plain; charset="us-ascii"
1466 1466 MIME-Version: 1.0
1467 1467 Content-Transfer-Encoding: 7bit
1468 1468 Subject: [PATCH 0 of 1] test
1469 1469 Message-Id: <patchbomb.60@*> (glob)
1470 1470 User-Agent: Mercurial-patchbomb/* (glob)
1471 1471 Date: Thu, 01 Jan 1970 00:01:00 +0000
1472 1472 From: quux
1473 1473 To: foo
1474 1474 Cc: bar
1475 1475
1476 1476
1477 1477 displaying [PATCH 1 of 1] c ...
1478 1478 Content-Type: text/plain; charset="us-ascii"
1479 1479 MIME-Version: 1.0
1480 1480 Content-Transfer-Encoding: 7bit
1481 1481 Subject: [PATCH 1 of 1] c
1482 1482 X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
1483 1483 X-Mercurial-Series-Index: 1
1484 1484 X-Mercurial-Series-Total: 1
1485 1485 Message-Id: <ff2c9fa2018b15fa74b3.61@*> (glob)
1486 1486 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.61@*> (glob)
1487 1487 In-Reply-To: <patchbomb.60@*> (glob)
1488 1488 References: <patchbomb.60@*> (glob)
1489 1489 User-Agent: Mercurial-patchbomb/* (glob)
1490 1490 Date: Thu, 01 Jan 1970 00:01:01 +0000
1491 1491 From: quux
1492 1492 To: foo
1493 1493 Cc: bar
1494 1494
1495 1495 # HG changeset patch
1496 1496 # User test
1497 1497 # Date 3 0
1498 1498 # Thu Jan 01 00:00:03 1970 +0000
1499 1499 # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
1500 1500 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1501 1501 c
1502 1502
1503 1503 diff -r 97d72e5f12c7 -r ff2c9fa2018b c
1504 1504 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1505 1505 +++ b/c Thu Jan 01 00:00:03 1970 +0000
1506 1506 @@ -0,0 +1,1 @@
1507 1507 +c
1508 1508
1509 1509
1510 1510 test --desc without --intro for a single patch:
1511 1511 $ echo foo > intro.text
1512 1512 $ hg email --date '1970-1-1 0:1' -n --desc intro.text -f quux -t foo -c bar \
1513 1513 > -s test -r 2
1514 1514 this patch series consists of 1 patches.
1515 1515
1516 1516
1517 1517 displaying [PATCH 0 of 1] test ...
1518 1518 Content-Type: text/plain; charset="us-ascii"
1519 1519 MIME-Version: 1.0
1520 1520 Content-Transfer-Encoding: 7bit
1521 1521 Subject: [PATCH 0 of 1] test
1522 1522 Message-Id: <patchbomb.60@*> (glob)
1523 1523 User-Agent: Mercurial-patchbomb/* (glob)
1524 1524 Date: Thu, 01 Jan 1970 00:01:00 +0000
1525 1525 From: quux
1526 1526 To: foo
1527 1527 Cc: bar
1528 1528
1529 1529 foo
1530 1530
1531 1531 displaying [PATCH 1 of 1] c ...
1532 1532 Content-Type: text/plain; charset="us-ascii"
1533 1533 MIME-Version: 1.0
1534 1534 Content-Transfer-Encoding: 7bit
1535 1535 Subject: [PATCH 1 of 1] c
1536 1536 X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
1537 1537 X-Mercurial-Series-Index: 1
1538 1538 X-Mercurial-Series-Total: 1
1539 1539 Message-Id: <ff2c9fa2018b15fa74b3.61@*> (glob)
1540 1540 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.61@*> (glob)
1541 1541 In-Reply-To: <patchbomb.60@*> (glob)
1542 1542 References: <patchbomb.60@*> (glob)
1543 1543 User-Agent: Mercurial-patchbomb/* (glob)
1544 1544 Date: Thu, 01 Jan 1970 00:01:01 +0000
1545 1545 From: quux
1546 1546 To: foo
1547 1547 Cc: bar
1548 1548
1549 1549 # HG changeset patch
1550 1550 # User test
1551 1551 # Date 3 0
1552 1552 # Thu Jan 01 00:00:03 1970 +0000
1553 1553 # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
1554 1554 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1555 1555 c
1556 1556
1557 1557 diff -r 97d72e5f12c7 -r ff2c9fa2018b c
1558 1558 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1559 1559 +++ b/c Thu Jan 01 00:00:03 1970 +0000
1560 1560 @@ -0,0 +1,1 @@
1561 1561 +c
1562 1562
1563 1563
1564 1564 test intro for multiple patches:
1565 1565 $ hg email --date '1970-1-1 0:1' -n --intro -f quux -t foo -c bar -s test \
1566 1566 > -r 0:1
1567 1567 this patch series consists of 2 patches.
1568 1568
1569 1569
1570 1570 Write the introductory message for the patch series.
1571 1571
1572 1572
1573 1573 displaying [PATCH 0 of 2] test ...
1574 1574 Content-Type: text/plain; charset="us-ascii"
1575 1575 MIME-Version: 1.0
1576 1576 Content-Transfer-Encoding: 7bit
1577 1577 Subject: [PATCH 0 of 2] test
1578 1578 Message-Id: <patchbomb.60@*> (glob)
1579 1579 User-Agent: Mercurial-patchbomb/* (glob)
1580 1580 Date: Thu, 01 Jan 1970 00:01:00 +0000
1581 1581 From: quux
1582 1582 To: foo
1583 1583 Cc: bar
1584 1584
1585 1585
1586 1586 displaying [PATCH 1 of 2] a ...
1587 1587 Content-Type: text/plain; charset="us-ascii"
1588 1588 MIME-Version: 1.0
1589 1589 Content-Transfer-Encoding: 7bit
1590 1590 Subject: [PATCH 1 of 2] a
1591 1591 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
1592 1592 X-Mercurial-Series-Index: 1
1593 1593 X-Mercurial-Series-Total: 2
1594 1594 Message-Id: <8580ff50825a50c8f716.61@*> (glob)
1595 1595 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
1596 1596 In-Reply-To: <patchbomb.60@*> (glob)
1597 1597 References: <patchbomb.60@*> (glob)
1598 1598 User-Agent: Mercurial-patchbomb/* (glob)
1599 1599 Date: Thu, 01 Jan 1970 00:01:01 +0000
1600 1600 From: quux
1601 1601 To: foo
1602 1602 Cc: bar
1603 1603
1604 1604 # HG changeset patch
1605 1605 # User test
1606 1606 # Date 1 0
1607 1607 # Thu Jan 01 00:00:01 1970 +0000
1608 1608 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
1609 1609 # Parent 0000000000000000000000000000000000000000
1610 1610 a
1611 1611
1612 1612 diff -r 000000000000 -r 8580ff50825a a
1613 1613 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1614 1614 +++ b/a Thu Jan 01 00:00:01 1970 +0000
1615 1615 @@ -0,0 +1,1 @@
1616 1616 +a
1617 1617
1618 1618 displaying [PATCH 2 of 2] b ...
1619 1619 Content-Type: text/plain; charset="us-ascii"
1620 1620 MIME-Version: 1.0
1621 1621 Content-Transfer-Encoding: 7bit
1622 1622 Subject: [PATCH 2 of 2] b
1623 1623 X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1624 1624 X-Mercurial-Series-Index: 2
1625 1625 X-Mercurial-Series-Total: 2
1626 1626 Message-Id: <97d72e5f12c7e84f8506.62@*> (glob)
1627 1627 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
1628 1628 In-Reply-To: <patchbomb.60@*> (glob)
1629 1629 References: <patchbomb.60@*> (glob)
1630 1630 User-Agent: Mercurial-patchbomb/* (glob)
1631 1631 Date: Thu, 01 Jan 1970 00:01:02 +0000
1632 1632 From: quux
1633 1633 To: foo
1634 1634 Cc: bar
1635 1635
1636 1636 # HG changeset patch
1637 1637 # User test
1638 1638 # Date 2 0
1639 1639 # Thu Jan 01 00:00:02 1970 +0000
1640 1640 # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1641 1641 # Parent 8580ff50825a50c8f716709acdf8de0deddcd6ab
1642 1642 b
1643 1643
1644 1644 diff -r 8580ff50825a -r 97d72e5f12c7 b
1645 1645 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1646 1646 +++ b/b Thu Jan 01 00:00:02 1970 +0000
1647 1647 @@ -0,0 +1,1 @@
1648 1648 +b
1649 1649
1650 1650
1651 1651 test reply-to via config:
1652 1652 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -r 2 \
1653 1653 > --config patchbomb.reply-to='baz@example.com'
1654 1654 this patch series consists of 1 patches.
1655 1655
1656 1656
1657 1657 displaying [PATCH] test ...
1658 1658 Content-Type: text/plain; charset="us-ascii"
1659 1659 MIME-Version: 1.0
1660 1660 Content-Transfer-Encoding: 7bit
1661 1661 Subject: [PATCH] test
1662 1662 X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
1663 1663 X-Mercurial-Series-Index: 1
1664 1664 X-Mercurial-Series-Total: 1
1665 1665 Message-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
1666 1666 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
1667 1667 User-Agent: Mercurial-patchbomb/* (glob)
1668 1668 Date: Thu, 01 Jan 1970 00:01:00 +0000
1669 1669 From: quux
1670 1670 To: foo
1671 1671 Cc: bar
1672 1672 Reply-To: baz@example.com
1673 1673
1674 1674 # HG changeset patch
1675 1675 # User test
1676 1676 # Date 3 0
1677 1677 # Thu Jan 01 00:00:03 1970 +0000
1678 1678 # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
1679 1679 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1680 1680 c
1681 1681
1682 1682 diff -r 97d72e5f12c7 -r ff2c9fa2018b c
1683 1683 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1684 1684 +++ b/c Thu Jan 01 00:00:03 1970 +0000
1685 1685 @@ -0,0 +1,1 @@
1686 1686 +c
1687 1687
1688 1688
1689 1689 test reply-to via command line:
1690 1690 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -r 2 \
1691 1691 > --reply-to baz --reply-to fred
1692 1692 this patch series consists of 1 patches.
1693 1693
1694 1694
1695 1695 displaying [PATCH] test ...
1696 1696 Content-Type: text/plain; charset="us-ascii"
1697 1697 MIME-Version: 1.0
1698 1698 Content-Transfer-Encoding: 7bit
1699 1699 Subject: [PATCH] test
1700 1700 X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
1701 1701 X-Mercurial-Series-Index: 1
1702 1702 X-Mercurial-Series-Total: 1
1703 1703 Message-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
1704 1704 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
1705 1705 User-Agent: Mercurial-patchbomb/* (glob)
1706 1706 Date: Thu, 01 Jan 1970 00:01:00 +0000
1707 1707 From: quux
1708 1708 To: foo
1709 1709 Cc: bar
1710 1710 Reply-To: baz, fred
1711 1711
1712 1712 # HG changeset patch
1713 1713 # User test
1714 1714 # Date 3 0
1715 1715 # Thu Jan 01 00:00:03 1970 +0000
1716 1716 # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
1717 1717 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1718 1718 c
1719 1719
1720 1720 diff -r 97d72e5f12c7 -r ff2c9fa2018b c
1721 1721 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1722 1722 +++ b/c Thu Jan 01 00:00:03 1970 +0000
1723 1723 @@ -0,0 +1,1 @@
1724 1724 +c
1725 1725
1726 1726
1727 1727 tagging csets:
1728 1728 $ hg tag -r0 zero zero.foo
1729 1729 $ hg tag -r1 one one.patch
1730 1730 $ hg tag -r2 two two.diff
1731 1731
1732 1732 test inline for single named patch:
1733 1733 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i \
1734 1734 > -r 2 | $FILTERBOUNDARY
1735 1735 this patch series consists of 1 patches.
1736 1736
1737 1737
1738 1738 displaying [PATCH] test ...
1739 1739 Content-Type: multipart/mixed; boundary="===*==" (glob)
1740 1740 MIME-Version: 1.0
1741 1741 Subject: [PATCH] test
1742 1742 X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
1743 1743 X-Mercurial-Series-Index: 1
1744 1744 X-Mercurial-Series-Total: 1
1745 1745 Message-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
1746 1746 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
1747 1747 User-Agent: Mercurial-patchbomb/* (glob)
1748 1748 Date: Thu, 01 Jan 1970 00:01:00 +0000
1749 1749 From: quux
1750 1750 To: foo
1751 1751 Cc: bar
1752 1752
1753 1753 --===*= (glob)
1754 1754 Content-Type: text/x-patch; charset="us-ascii"
1755 1755 MIME-Version: 1.0
1756 1756 Content-Transfer-Encoding: 7bit
1757 1757 Content-Disposition: inline; filename=two.diff
1758 1758
1759 1759 # HG changeset patch
1760 1760 # User test
1761 1761 # Date 3 0
1762 1762 # Thu Jan 01 00:00:03 1970 +0000
1763 1763 # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
1764 1764 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1765 1765 c
1766 1766
1767 1767 diff -r 97d72e5f12c7 -r ff2c9fa2018b c
1768 1768 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1769 1769 +++ b/c Thu Jan 01 00:00:03 1970 +0000
1770 1770 @@ -0,0 +1,1 @@
1771 1771 +c
1772 1772
1773 1773 --===*=-- (glob)
1774 1774
1775 1775 test inline for multiple named/unnamed patches:
1776 1776 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i \
1777 1777 > -r 0:1 | $FILTERBOUNDARY
1778 1778 this patch series consists of 2 patches.
1779 1779
1780 1780
1781 1781 Write the introductory message for the patch series.
1782 1782
1783 1783
1784 1784 displaying [PATCH 0 of 2] test ...
1785 1785 Content-Type: text/plain; charset="us-ascii"
1786 1786 MIME-Version: 1.0
1787 1787 Content-Transfer-Encoding: 7bit
1788 1788 Subject: [PATCH 0 of 2] test
1789 1789 Message-Id: <patchbomb.60@*> (glob)
1790 1790 User-Agent: Mercurial-patchbomb/* (glob)
1791 1791 Date: Thu, 01 Jan 1970 00:01:00 +0000
1792 1792 From: quux
1793 1793 To: foo
1794 1794 Cc: bar
1795 1795
1796 1796
1797 1797 displaying [PATCH 1 of 2] a ...
1798 1798 Content-Type: multipart/mixed; boundary="===*==" (glob)
1799 1799 MIME-Version: 1.0
1800 1800 Subject: [PATCH 1 of 2] a
1801 1801 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
1802 1802 X-Mercurial-Series-Index: 1
1803 1803 X-Mercurial-Series-Total: 2
1804 1804 Message-Id: <8580ff50825a50c8f716.61@*> (glob)
1805 1805 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
1806 1806 In-Reply-To: <patchbomb.60@*> (glob)
1807 1807 References: <patchbomb.60@*> (glob)
1808 1808 User-Agent: Mercurial-patchbomb/* (glob)
1809 1809 Date: Thu, 01 Jan 1970 00:01:01 +0000
1810 1810 From: quux
1811 1811 To: foo
1812 1812 Cc: bar
1813 1813
1814 1814 --===*= (glob)
1815 1815 Content-Type: text/x-patch; charset="us-ascii"
1816 1816 MIME-Version: 1.0
1817 1817 Content-Transfer-Encoding: 7bit
1818 1818 Content-Disposition: inline; filename=t2-1.patch
1819 1819
1820 1820 # HG changeset patch
1821 1821 # User test
1822 1822 # Date 1 0
1823 1823 # Thu Jan 01 00:00:01 1970 +0000
1824 1824 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
1825 1825 # Parent 0000000000000000000000000000000000000000
1826 1826 a
1827 1827
1828 1828 diff -r 000000000000 -r 8580ff50825a a
1829 1829 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1830 1830 +++ b/a Thu Jan 01 00:00:01 1970 +0000
1831 1831 @@ -0,0 +1,1 @@
1832 1832 +a
1833 1833
1834 1834 --===*=-- (glob)
1835 1835 displaying [PATCH 2 of 2] b ...
1836 1836 Content-Type: multipart/mixed; boundary="===*==" (glob)
1837 1837 MIME-Version: 1.0
1838 1838 Subject: [PATCH 2 of 2] b
1839 1839 X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1840 1840 X-Mercurial-Series-Index: 2
1841 1841 X-Mercurial-Series-Total: 2
1842 1842 Message-Id: <97d72e5f12c7e84f8506.62@*> (glob)
1843 1843 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
1844 1844 In-Reply-To: <patchbomb.60@*> (glob)
1845 1845 References: <patchbomb.60@*> (glob)
1846 1846 User-Agent: Mercurial-patchbomb/* (glob)
1847 1847 Date: Thu, 01 Jan 1970 00:01:02 +0000
1848 1848 From: quux
1849 1849 To: foo
1850 1850 Cc: bar
1851 1851
1852 1852 --===*= (glob)
1853 1853 Content-Type: text/x-patch; charset="us-ascii"
1854 1854 MIME-Version: 1.0
1855 1855 Content-Transfer-Encoding: 7bit
1856 1856 Content-Disposition: inline; filename=one.patch
1857 1857
1858 1858 # HG changeset patch
1859 1859 # User test
1860 1860 # Date 2 0
1861 1861 # Thu Jan 01 00:00:02 1970 +0000
1862 1862 # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1863 1863 # Parent 8580ff50825a50c8f716709acdf8de0deddcd6ab
1864 1864 b
1865 1865
1866 1866 diff -r 8580ff50825a -r 97d72e5f12c7 b
1867 1867 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1868 1868 +++ b/b Thu Jan 01 00:00:02 1970 +0000
1869 1869 @@ -0,0 +1,1 @@
1870 1870 +b
1871 1871
1872 1872 --===*=-- (glob)
1873 1873
1874 1874
1875 1875 test inreplyto:
1876 1876 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar --in-reply-to baz \
1877 1877 > -r tip
1878 1878 this patch series consists of 1 patches.
1879 1879
1880 1880
1881 1881 displaying [PATCH] Added tag two, two.diff for changeset ff2c9fa2018b ...
1882 1882 Content-Type: text/plain; charset="us-ascii"
1883 1883 MIME-Version: 1.0
1884 1884 Content-Transfer-Encoding: 7bit
1885 1885 Subject: [PATCH] Added tag two, two.diff for changeset ff2c9fa2018b
1886 1886 X-Mercurial-Node: 7aead2484924c445ad8ce2613df91f52f9e502ed
1887 1887 X-Mercurial-Series-Index: 1
1888 1888 X-Mercurial-Series-Total: 1
1889 1889 Message-Id: <7aead2484924c445ad8c.60@*> (glob)
1890 1890 X-Mercurial-Series-Id: <7aead2484924c445ad8c.60@*> (glob)
1891 1891 In-Reply-To: <baz>
1892 1892 References: <baz>
1893 1893 User-Agent: Mercurial-patchbomb/* (glob)
1894 1894 Date: Thu, 01 Jan 1970 00:01:00 +0000
1895 1895 From: quux
1896 1896 To: foo
1897 1897 Cc: bar
1898 1898
1899 1899 # HG changeset patch
1900 1900 # User test
1901 1901 # Date 0 0
1902 1902 # Thu Jan 01 00:00:00 1970 +0000
1903 1903 # Node ID 7aead2484924c445ad8ce2613df91f52f9e502ed
1904 1904 # Parent 045ca29b1ea20e4940411e695e20e521f2f0f98e
1905 1905 Added tag two, two.diff for changeset ff2c9fa2018b
1906 1906
1907 1907 diff -r 045ca29b1ea2 -r 7aead2484924 .hgtags
1908 1908 --- a/.hgtags Thu Jan 01 00:00:00 1970 +0000
1909 1909 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
1910 1910 @@ -2,3 +2,5 @@
1911 1911 8580ff50825a50c8f716709acdf8de0deddcd6ab zero.foo
1912 1912 97d72e5f12c7e84f85064aa72e5a297142c36ed9 one
1913 1913 97d72e5f12c7e84f85064aa72e5a297142c36ed9 one.patch
1914 1914 +ff2c9fa2018b15fa74b33363bda9527323e2a99f two
1915 1915 +ff2c9fa2018b15fa74b33363bda9527323e2a99f two.diff
1916 1916
1917 1917 no intro message in non-interactive mode
1918 1918 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar --in-reply-to baz \
1919 1919 > -r 0:1
1920 1920 this patch series consists of 2 patches.
1921 1921
1922 1922 (optional) Subject: [PATCH 0 of 2]
1923 1923
1924 1924 displaying [PATCH 1 of 2] a ...
1925 1925 Content-Type: text/plain; charset="us-ascii"
1926 1926 MIME-Version: 1.0
1927 1927 Content-Transfer-Encoding: 7bit
1928 1928 Subject: [PATCH 1 of 2] a
1929 1929 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
1930 1930 X-Mercurial-Series-Index: 1
1931 1931 X-Mercurial-Series-Total: 2
1932 1932 Message-Id: <8580ff50825a50c8f716.60@*> (glob)
1933 1933 X-Mercurial-Series-Id: <8580ff50825a50c8f716.60@*> (glob)
1934 1934 In-Reply-To: <baz>
1935 1935 References: <baz>
1936 1936 User-Agent: Mercurial-patchbomb/* (glob)
1937 1937 Date: Thu, 01 Jan 1970 00:01:00 +0000
1938 1938 From: quux
1939 1939 To: foo
1940 1940 Cc: bar
1941 1941
1942 1942 # HG changeset patch
1943 1943 # User test
1944 1944 # Date 1 0
1945 1945 # Thu Jan 01 00:00:01 1970 +0000
1946 1946 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
1947 1947 # Parent 0000000000000000000000000000000000000000
1948 1948 a
1949 1949
1950 1950 diff -r 000000000000 -r 8580ff50825a a
1951 1951 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1952 1952 +++ b/a Thu Jan 01 00:00:01 1970 +0000
1953 1953 @@ -0,0 +1,1 @@
1954 1954 +a
1955 1955
1956 1956 displaying [PATCH 2 of 2] b ...
1957 1957 Content-Type: text/plain; charset="us-ascii"
1958 1958 MIME-Version: 1.0
1959 1959 Content-Transfer-Encoding: 7bit
1960 1960 Subject: [PATCH 2 of 2] b
1961 1961 X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1962 1962 X-Mercurial-Series-Index: 2
1963 1963 X-Mercurial-Series-Total: 2
1964 1964 Message-Id: <97d72e5f12c7e84f8506.61@*> (glob)
1965 1965 X-Mercurial-Series-Id: <8580ff50825a50c8f716.60@*> (glob)
1966 1966 In-Reply-To: <baz>
1967 1967 References: <baz>
1968 1968 User-Agent: Mercurial-patchbomb/* (glob)
1969 1969 Date: Thu, 01 Jan 1970 00:01:01 +0000
1970 1970 From: quux
1971 1971 To: foo
1972 1972 Cc: bar
1973 1973
1974 1974 # HG changeset patch
1975 1975 # User test
1976 1976 # Date 2 0
1977 1977 # Thu Jan 01 00:00:02 1970 +0000
1978 1978 # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
1979 1979 # Parent 8580ff50825a50c8f716709acdf8de0deddcd6ab
1980 1980 b
1981 1981
1982 1982 diff -r 8580ff50825a -r 97d72e5f12c7 b
1983 1983 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1984 1984 +++ b/b Thu Jan 01 00:00:02 1970 +0000
1985 1985 @@ -0,0 +1,1 @@
1986 1986 +b
1987 1987
1988 1988
1989 1989
1990 1990
1991 1991 $ hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar --in-reply-to baz \
1992 1992 > -s test -r 0:1
1993 1993 this patch series consists of 2 patches.
1994 1994
1995 1995
1996 1996 Write the introductory message for the patch series.
1997 1997
1998 1998
1999 1999 displaying [PATCH 0 of 2] test ...
2000 2000 Content-Type: text/plain; charset="us-ascii"
2001 2001 MIME-Version: 1.0
2002 2002 Content-Transfer-Encoding: 7bit
2003 2003 Subject: [PATCH 0 of 2] test
2004 2004 Message-Id: <patchbomb.60@*> (glob)
2005 2005 In-Reply-To: <baz>
2006 2006 References: <baz>
2007 2007 User-Agent: Mercurial-patchbomb/* (glob)
2008 2008 Date: Thu, 01 Jan 1970 00:01:00 +0000
2009 2009 From: quux
2010 2010 To: foo
2011 2011 Cc: bar
2012 2012
2013 2013
2014 2014 displaying [PATCH 1 of 2] a ...
2015 2015 Content-Type: text/plain; charset="us-ascii"
2016 2016 MIME-Version: 1.0
2017 2017 Content-Transfer-Encoding: 7bit
2018 2018 Subject: [PATCH 1 of 2] a
2019 2019 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
2020 2020 X-Mercurial-Series-Index: 1
2021 2021 X-Mercurial-Series-Total: 2
2022 2022 Message-Id: <8580ff50825a50c8f716.61@*> (glob)
2023 2023 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
2024 2024 In-Reply-To: <patchbomb.60@*> (glob)
2025 2025 References: <patchbomb.60@*> (glob)
2026 2026 User-Agent: Mercurial-patchbomb/* (glob)
2027 2027 Date: Thu, 01 Jan 1970 00:01:01 +0000
2028 2028 From: quux
2029 2029 To: foo
2030 2030 Cc: bar
2031 2031
2032 2032 # HG changeset patch
2033 2033 # User test
2034 2034 # Date 1 0
2035 2035 # Thu Jan 01 00:00:01 1970 +0000
2036 2036 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
2037 2037 # Parent 0000000000000000000000000000000000000000
2038 2038 a
2039 2039
2040 2040 diff -r 000000000000 -r 8580ff50825a a
2041 2041 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2042 2042 +++ b/a Thu Jan 01 00:00:01 1970 +0000
2043 2043 @@ -0,0 +1,1 @@
2044 2044 +a
2045 2045
2046 2046 displaying [PATCH 2 of 2] b ...
2047 2047 Content-Type: text/plain; charset="us-ascii"
2048 2048 MIME-Version: 1.0
2049 2049 Content-Transfer-Encoding: 7bit
2050 2050 Subject: [PATCH 2 of 2] b
2051 2051 X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
2052 2052 X-Mercurial-Series-Index: 2
2053 2053 X-Mercurial-Series-Total: 2
2054 2054 Message-Id: <97d72e5f12c7e84f8506.62@*> (glob)
2055 2055 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
2056 2056 In-Reply-To: <patchbomb.60@*> (glob)
2057 2057 References: <patchbomb.60@*> (glob)
2058 2058 User-Agent: Mercurial-patchbomb/* (glob)
2059 2059 Date: Thu, 01 Jan 1970 00:01:02 +0000
2060 2060 From: quux
2061 2061 To: foo
2062 2062 Cc: bar
2063 2063
2064 2064 # HG changeset patch
2065 2065 # User test
2066 2066 # Date 2 0
2067 2067 # Thu Jan 01 00:00:02 1970 +0000
2068 2068 # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
2069 2069 # Parent 8580ff50825a50c8f716709acdf8de0deddcd6ab
2070 2070 b
2071 2071
2072 2072 diff -r 8580ff50825a -r 97d72e5f12c7 b
2073 2073 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2074 2074 +++ b/b Thu Jan 01 00:00:02 1970 +0000
2075 2075 @@ -0,0 +1,1 @@
2076 2076 +b
2077 2077
2078 2078
2079 2079 test single flag for single patch (and no warning when not mailing dirty rev):
2080 2080 $ hg up -qr1
2081 2081 $ echo dirt > a
2082 2082 $ hg email --date '1970-1-1 0:1' -n --flag fooFlag -f quux -t foo -c bar -s test \
2083 2083 > -r 2 | $FILTERBOUNDARY
2084 2084 this patch series consists of 1 patches.
2085 2085
2086 2086
2087 2087 displaying [PATCH fooFlag] test ...
2088 2088 Content-Type: text/plain; charset="us-ascii"
2089 2089 MIME-Version: 1.0
2090 2090 Content-Transfer-Encoding: 7bit
2091 2091 Subject: [PATCH fooFlag] test
2092 2092 X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
2093 2093 X-Mercurial-Series-Index: 1
2094 2094 X-Mercurial-Series-Total: 1
2095 2095 Message-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
2096 2096 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
2097 2097 User-Agent: Mercurial-patchbomb/* (glob)
2098 2098 Date: Thu, 01 Jan 1970 00:01:00 +0000
2099 2099 From: quux
2100 2100 To: foo
2101 2101 Cc: bar
2102 2102
2103 2103 # HG changeset patch
2104 2104 # User test
2105 2105 # Date 3 0
2106 2106 # Thu Jan 01 00:00:03 1970 +0000
2107 2107 # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
2108 2108 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
2109 2109 c
2110 2110
2111 2111 diff -r 97d72e5f12c7 -r ff2c9fa2018b c
2112 2112 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2113 2113 +++ b/c Thu Jan 01 00:00:03 1970 +0000
2114 2114 @@ -0,0 +1,1 @@
2115 2115 +c
2116 2116
2117 2117
2118 2118 test single flag for multiple patches (and warning when mailing dirty rev):
2119 2119 $ hg email --date '1970-1-1 0:1' -n --flag fooFlag -f quux -t foo -c bar -s test \
2120 2120 > -r 0:1
2121 2121 warning: working directory has uncommitted changes
2122 2122 this patch series consists of 2 patches.
2123 2123
2124 2124
2125 2125 Write the introductory message for the patch series.
2126 2126
2127 2127
2128 2128 displaying [PATCH 0 of 2 fooFlag] test ...
2129 2129 Content-Type: text/plain; charset="us-ascii"
2130 2130 MIME-Version: 1.0
2131 2131 Content-Transfer-Encoding: 7bit
2132 2132 Subject: [PATCH 0 of 2 fooFlag] test
2133 2133 Message-Id: <patchbomb.60@*> (glob)
2134 2134 User-Agent: Mercurial-patchbomb/* (glob)
2135 2135 Date: Thu, 01 Jan 1970 00:01:00 +0000
2136 2136 From: quux
2137 2137 To: foo
2138 2138 Cc: bar
2139 2139
2140 2140
2141 2141 displaying [PATCH 1 of 2 fooFlag] a ...
2142 2142 Content-Type: text/plain; charset="us-ascii"
2143 2143 MIME-Version: 1.0
2144 2144 Content-Transfer-Encoding: 7bit
2145 2145 Subject: [PATCH 1 of 2 fooFlag] a
2146 2146 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
2147 2147 X-Mercurial-Series-Index: 1
2148 2148 X-Mercurial-Series-Total: 2
2149 2149 Message-Id: <8580ff50825a50c8f716.61@*> (glob)
2150 2150 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
2151 2151 In-Reply-To: <patchbomb.60@*> (glob)
2152 2152 References: <patchbomb.60@*> (glob)
2153 2153 User-Agent: Mercurial-patchbomb/* (glob)
2154 2154 Date: Thu, 01 Jan 1970 00:01:01 +0000
2155 2155 From: quux
2156 2156 To: foo
2157 2157 Cc: bar
2158 2158
2159 2159 # HG changeset patch
2160 2160 # User test
2161 2161 # Date 1 0
2162 2162 # Thu Jan 01 00:00:01 1970 +0000
2163 2163 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
2164 2164 # Parent 0000000000000000000000000000000000000000
2165 2165 a
2166 2166
2167 2167 diff -r 000000000000 -r 8580ff50825a a
2168 2168 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2169 2169 +++ b/a Thu Jan 01 00:00:01 1970 +0000
2170 2170 @@ -0,0 +1,1 @@
2171 2171 +a
2172 2172
2173 2173 displaying [PATCH 2 of 2 fooFlag] b ...
2174 2174 Content-Type: text/plain; charset="us-ascii"
2175 2175 MIME-Version: 1.0
2176 2176 Content-Transfer-Encoding: 7bit
2177 2177 Subject: [PATCH 2 of 2 fooFlag] b
2178 2178 X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
2179 2179 X-Mercurial-Series-Index: 2
2180 2180 X-Mercurial-Series-Total: 2
2181 2181 Message-Id: <97d72e5f12c7e84f8506.62@*> (glob)
2182 2182 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
2183 2183 In-Reply-To: <patchbomb.60@*> (glob)
2184 2184 References: <patchbomb.60@*> (glob)
2185 2185 User-Agent: Mercurial-patchbomb/* (glob)
2186 2186 Date: Thu, 01 Jan 1970 00:01:02 +0000
2187 2187 From: quux
2188 2188 To: foo
2189 2189 Cc: bar
2190 2190
2191 2191 # HG changeset patch
2192 2192 # User test
2193 2193 # Date 2 0
2194 2194 # Thu Jan 01 00:00:02 1970 +0000
2195 2195 # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
2196 2196 # Parent 8580ff50825a50c8f716709acdf8de0deddcd6ab
2197 2197 b
2198 2198
2199 2199 diff -r 8580ff50825a -r 97d72e5f12c7 b
2200 2200 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2201 2201 +++ b/b Thu Jan 01 00:00:02 1970 +0000
2202 2202 @@ -0,0 +1,1 @@
2203 2203 +b
2204 2204
2205 2205 $ hg revert --no-b a
2206 2206 $ hg up -q
2207 2207
2208 2208 test multiple flags for single patch:
2209 2209 $ hg email --date '1970-1-1 0:1' -n --flag fooFlag --flag barFlag -f quux -t foo \
2210 2210 > -c bar -s test -r 2
2211 2211 this patch series consists of 1 patches.
2212 2212
2213 2213
2214 2214 displaying [PATCH fooFlag barFlag] test ...
2215 2215 Content-Type: text/plain; charset="us-ascii"
2216 2216 MIME-Version: 1.0
2217 2217 Content-Transfer-Encoding: 7bit
2218 2218 Subject: [PATCH fooFlag barFlag] test
2219 2219 X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
2220 2220 X-Mercurial-Series-Index: 1
2221 2221 X-Mercurial-Series-Total: 1
2222 2222 Message-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
2223 2223 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.60@*> (glob)
2224 2224 User-Agent: Mercurial-patchbomb/* (glob)
2225 2225 Date: Thu, 01 Jan 1970 00:01:00 +0000
2226 2226 From: quux
2227 2227 To: foo
2228 2228 Cc: bar
2229 2229
2230 2230 # HG changeset patch
2231 2231 # User test
2232 2232 # Date 3 0
2233 2233 # Thu Jan 01 00:00:03 1970 +0000
2234 2234 # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
2235 2235 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
2236 2236 c
2237 2237
2238 2238 diff -r 97d72e5f12c7 -r ff2c9fa2018b c
2239 2239 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2240 2240 +++ b/c Thu Jan 01 00:00:03 1970 +0000
2241 2241 @@ -0,0 +1,1 @@
2242 2242 +c
2243 2243
2244 2244
2245 2245 test multiple flags for multiple patches:
2246 2246 $ hg email --date '1970-1-1 0:1' -n --flag fooFlag --flag barFlag -f quux -t foo \
2247 2247 > -c bar -s test -r 0:1
2248 2248 this patch series consists of 2 patches.
2249 2249
2250 2250
2251 2251 Write the introductory message for the patch series.
2252 2252
2253 2253
2254 2254 displaying [PATCH 0 of 2 fooFlag barFlag] test ...
2255 2255 Content-Type: text/plain; charset="us-ascii"
2256 2256 MIME-Version: 1.0
2257 2257 Content-Transfer-Encoding: 7bit
2258 2258 Subject: [PATCH 0 of 2 fooFlag barFlag] test
2259 2259 Message-Id: <patchbomb.60@*> (glob)
2260 2260 User-Agent: Mercurial-patchbomb/* (glob)
2261 2261 Date: Thu, 01 Jan 1970 00:01:00 +0000
2262 2262 From: quux
2263 2263 To: foo
2264 2264 Cc: bar
2265 2265
2266 2266
2267 2267 displaying [PATCH 1 of 2 fooFlag barFlag] a ...
2268 2268 Content-Type: text/plain; charset="us-ascii"
2269 2269 MIME-Version: 1.0
2270 2270 Content-Transfer-Encoding: 7bit
2271 2271 Subject: [PATCH 1 of 2 fooFlag barFlag] a
2272 2272 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
2273 2273 X-Mercurial-Series-Index: 1
2274 2274 X-Mercurial-Series-Total: 2
2275 2275 Message-Id: <8580ff50825a50c8f716.61@*> (glob)
2276 2276 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
2277 2277 In-Reply-To: <patchbomb.60@*> (glob)
2278 2278 References: <patchbomb.60@*> (glob)
2279 2279 User-Agent: Mercurial-patchbomb/* (glob)
2280 2280 Date: Thu, 01 Jan 1970 00:01:01 +0000
2281 2281 From: quux
2282 2282 To: foo
2283 2283 Cc: bar
2284 2284
2285 2285 # HG changeset patch
2286 2286 # User test
2287 2287 # Date 1 0
2288 2288 # Thu Jan 01 00:00:01 1970 +0000
2289 2289 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
2290 2290 # Parent 0000000000000000000000000000000000000000
2291 2291 a
2292 2292
2293 2293 diff -r 000000000000 -r 8580ff50825a a
2294 2294 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2295 2295 +++ b/a Thu Jan 01 00:00:01 1970 +0000
2296 2296 @@ -0,0 +1,1 @@
2297 2297 +a
2298 2298
2299 2299 displaying [PATCH 2 of 2 fooFlag barFlag] b ...
2300 2300 Content-Type: text/plain; charset="us-ascii"
2301 2301 MIME-Version: 1.0
2302 2302 Content-Transfer-Encoding: 7bit
2303 2303 Subject: [PATCH 2 of 2 fooFlag barFlag] b
2304 2304 X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
2305 2305 X-Mercurial-Series-Index: 2
2306 2306 X-Mercurial-Series-Total: 2
2307 2307 Message-Id: <97d72e5f12c7e84f8506.62@*> (glob)
2308 2308 X-Mercurial-Series-Id: <8580ff50825a50c8f716.61@*> (glob)
2309 2309 In-Reply-To: <patchbomb.60@*> (glob)
2310 2310 References: <patchbomb.60@*> (glob)
2311 2311 User-Agent: Mercurial-patchbomb/* (glob)
2312 2312 Date: Thu, 01 Jan 1970 00:01:02 +0000
2313 2313 From: quux
2314 2314 To: foo
2315 2315 Cc: bar
2316 2316
2317 2317 # HG changeset patch
2318 2318 # User test
2319 2319 # Date 2 0
2320 2320 # Thu Jan 01 00:00:02 1970 +0000
2321 2321 # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
2322 2322 # Parent 8580ff50825a50c8f716709acdf8de0deddcd6ab
2323 2323 b
2324 2324
2325 2325 diff -r 8580ff50825a -r 97d72e5f12c7 b
2326 2326 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2327 2327 +++ b/b Thu Jan 01 00:00:02 1970 +0000
2328 2328 @@ -0,0 +1,1 @@
2329 2329 +b
2330 2330
2331 2331
2332 2332 test multi-address parsing:
2333 2333 $ hg email --date '1980-1-1 0:1' -m tmp.mbox -f quux -t 'spam<spam><eggs>' \
2334 2334 > -t toast -c 'foo,bar@example.com' -c '"A, B <>" <a@example.com>' -s test -r 0 \
2335 2335 > --config email.bcc='"Quux, A." <quux>'
2336 2336 this patch series consists of 1 patches.
2337 2337
2338 2338
2339 2339 sending [PATCH] test ...
2340 2340 $ cat < tmp.mbox
2341 2341 From quux ... ... .. ..:..:.. .... (re)
2342 2342 Content-Type: text/plain; charset="us-ascii"
2343 2343 MIME-Version: 1.0
2344 2344 Content-Transfer-Encoding: 7bit
2345 2345 Subject: [PATCH] test
2346 2346 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
2347 2347 X-Mercurial-Series-Index: 1
2348 2348 X-Mercurial-Series-Total: 1
2349 2349 Message-Id: <8580ff50825a50c8f716.315532860@*> (glob)
2350 2350 X-Mercurial-Series-Id: <8580ff50825a50c8f716.315532860@*> (glob)
2351 2351 User-Agent: Mercurial-patchbomb/* (glob)
2352 2352 Date: Tue, 01 Jan 1980 00:01:00 +0000
2353 2353 From: quux
2354 2354 To: spam <spam>, eggs, toast
2355 2355 Cc: foo, bar@example.com, "A, B <>" <a@example.com>
2356 2356 Bcc: "Quux, A." <quux>
2357 2357
2358 2358 # HG changeset patch
2359 2359 # User test
2360 2360 # Date 1 0
2361 2361 # Thu Jan 01 00:00:01 1970 +0000
2362 2362 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
2363 2363 # Parent 0000000000000000000000000000000000000000
2364 2364 a
2365 2365
2366 2366 diff -r 000000000000 -r 8580ff50825a a
2367 2367 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2368 2368 +++ b/a Thu Jan 01 00:00:01 1970 +0000
2369 2369 @@ -0,0 +1,1 @@
2370 2370 +a
2371 2371
2372 2372
2373 2373
2374 2374 test multi-byte domain parsing:
2375 2375 $ UUML=`$PYTHON -c 'import sys; sys.stdout.write("\374")'`
2376 2376 $ HGENCODING=iso-8859-1
2377 2377 $ export HGENCODING
2378 2378 $ hg email --date '1980-1-1 0:1' -m tmp.mbox -f quux -t "bar@${UUML}nicode.com" -s test -r 0
2379 2379 this patch series consists of 1 patches.
2380 2380
2381 2381 Cc:
2382 2382
2383 2383 sending [PATCH] test ...
2384 2384
2385 2385 $ cat tmp.mbox
2386 2386 From quux ... ... .. ..:..:.. .... (re)
2387 2387 Content-Type: text/plain; charset="us-ascii"
2388 2388 MIME-Version: 1.0
2389 2389 Content-Transfer-Encoding: 7bit
2390 2390 Subject: [PATCH] test
2391 2391 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
2392 2392 X-Mercurial-Series-Index: 1
2393 2393 X-Mercurial-Series-Total: 1
2394 2394 Message-Id: <8580ff50825a50c8f716.315532860@*> (glob)
2395 2395 X-Mercurial-Series-Id: <8580ff50825a50c8f716.315532860@*> (glob)
2396 2396 User-Agent: Mercurial-patchbomb/* (glob)
2397 2397 Date: Tue, 01 Jan 1980 00:01:00 +0000
2398 2398 From: quux
2399 2399 To: bar@xn--nicode-2ya.com
2400 2400
2401 2401 # HG changeset patch
2402 2402 # User test
2403 2403 # Date 1 0
2404 2404 # Thu Jan 01 00:00:01 1970 +0000
2405 2405 # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
2406 2406 # Parent 0000000000000000000000000000000000000000
2407 2407 a
2408 2408
2409 2409 diff -r 000000000000 -r 8580ff50825a a
2410 2410 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2411 2411 +++ b/a Thu Jan 01 00:00:01 1970 +0000
2412 2412 @@ -0,0 +1,1 @@
2413 2413 +a
2414 2414
2415 2415
2416 2416
2417 2417 test outgoing:
2418 2418 $ hg up 1
2419 2419 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
2420 2420
2421 2421 $ hg branch test
2422 2422 marked working directory as branch test
2423 2423 (branches are permanent and global, did you want a bookmark?)
2424 2424
2425 2425 $ echo d > d
2426 2426 $ hg add d
2427 2427 $ hg ci -md -d '4 0'
2428 2428 $ echo d >> d
2429 2429 $ hg ci -mdd -d '5 0'
2430 2430 $ hg log -G --template "{rev}:{node|short} {desc|firstline}\n"
2431 2431 @ 10:3b6f1ec9dde9 dd
2432 2432 |
2433 2433 o 9:2f9fa9b998c5 d
2434 2434 |
2435 2435 | o 8:7aead2484924 Added tag two, two.diff for changeset ff2c9fa2018b
2436 2436 | |
2437 2437 | o 7:045ca29b1ea2 Added tag one, one.patch for changeset 97d72e5f12c7
2438 2438 | |
2439 2439 | o 6:5d5ef15dfe5e Added tag zero, zero.foo for changeset 8580ff50825a
2440 2440 | |
2441 2441 | o 5:240fb913fc1b isolatin 8-bit encoding
2442 2442 | |
2443 2443 | o 4:a2ea8fc83dd8 long line
2444 2444 | |
2445 2445 | o 3:909a00e13e9d utf-8 content
2446 2446 | |
2447 2447 | o 2:ff2c9fa2018b c
2448 2448 |/
2449 2449 o 1:97d72e5f12c7 b
2450 2450 |
2451 2451 o 0:8580ff50825a a
2452 2452
2453 2453 $ hg phase --force --secret -r 10
2454 2454 $ hg email --date '1980-1-1 0:1' -n -t foo -s test -o ../t -r 'rev(10) or rev(6)'
2455 2455 comparing with ../t
2456 2456 From [test]: test
2457 2457 this patch series consists of 6 patches.
2458 2458
2459 2459
2460 2460 Write the introductory message for the patch series.
2461 2461
2462 2462 Cc:
2463 2463
2464 2464 displaying [PATCH 0 of 6] test ...
2465 2465 Content-Type: text/plain; charset="us-ascii"
2466 2466 MIME-Version: 1.0
2467 2467 Content-Transfer-Encoding: 7bit
2468 2468 Subject: [PATCH 0 of 6] test
2469 2469 Message-Id: <patchbomb.315532860@*> (glob)
2470 2470 User-Agent: Mercurial-patchbomb/* (glob)
2471 2471 Date: Tue, 01 Jan 1980 00:01:00 +0000
2472 2472 From: test
2473 2473 To: foo
2474 2474
2475 2475
2476 2476 displaying [PATCH 1 of 6] c ...
2477 2477 Content-Type: text/plain; charset="us-ascii"
2478 2478 MIME-Version: 1.0
2479 2479 Content-Transfer-Encoding: 7bit
2480 2480 Subject: [PATCH 1 of 6] c
2481 2481 X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
2482 2482 X-Mercurial-Series-Index: 1
2483 2483 X-Mercurial-Series-Total: 6
2484 2484 Message-Id: <ff2c9fa2018b15fa74b3.315532861@*> (glob)
2485 2485 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.315532861@*> (glob)
2486 2486 In-Reply-To: <patchbomb.315532860@*> (glob)
2487 2487 References: <patchbomb.315532860@*> (glob)
2488 2488 User-Agent: Mercurial-patchbomb/* (glob)
2489 2489 Date: Tue, 01 Jan 1980 00:01:01 +0000
2490 2490 From: test
2491 2491 To: foo
2492 2492
2493 2493 # HG changeset patch
2494 2494 # User test
2495 2495 # Date 3 0
2496 2496 # Thu Jan 01 00:00:03 1970 +0000
2497 2497 # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
2498 2498 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
2499 2499 c
2500 2500
2501 2501 diff -r 97d72e5f12c7 -r ff2c9fa2018b c
2502 2502 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2503 2503 +++ b/c Thu Jan 01 00:00:03 1970 +0000
2504 2504 @@ -0,0 +1,1 @@
2505 2505 +c
2506 2506
2507 2507 displaying [PATCH 2 of 6] utf-8 content ...
2508 2508 Content-Type: text/plain; charset="us-ascii"
2509 2509 MIME-Version: 1.0
2510 2510 Content-Transfer-Encoding: 8bit
2511 2511 Subject: [PATCH 2 of 6] utf-8 content
2512 2512 X-Mercurial-Node: 909a00e13e9d78b575aeee23dddbada46d5a143f
2513 2513 X-Mercurial-Series-Index: 2
2514 2514 X-Mercurial-Series-Total: 6
2515 2515 Message-Id: <909a00e13e9d78b575ae.315532862@*> (glob)
2516 2516 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.315532861@*> (glob)
2517 2517 In-Reply-To: <patchbomb.315532860@*> (glob)
2518 2518 References: <patchbomb.315532860@*> (glob)
2519 2519 User-Agent: Mercurial-patchbomb/* (glob)
2520 2520 Date: Tue, 01 Jan 1980 00:01:02 +0000
2521 2521 From: test
2522 2522 To: foo
2523 2523
2524 2524 # HG changeset patch
2525 2525 # User test
2526 2526 # Date 4 0
2527 2527 # Thu Jan 01 00:00:04 1970 +0000
2528 2528 # Node ID 909a00e13e9d78b575aeee23dddbada46d5a143f
2529 2529 # Parent ff2c9fa2018b15fa74b33363bda9527323e2a99f
2530 2530 utf-8 content
2531 2531
2532 2532 diff -r ff2c9fa2018b -r 909a00e13e9d description
2533 2533 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2534 2534 +++ b/description Thu Jan 01 00:00:04 1970 +0000
2535 2535 @@ -0,0 +1,3 @@
2536 2536 +a multiline
2537 2537 +
2538 2538 +description
2539 2539 diff -r ff2c9fa2018b -r 909a00e13e9d utf
2540 2540 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2541 2541 +++ b/utf Thu Jan 01 00:00:04 1970 +0000
2542 2542 @@ -0,0 +1,1 @@
2543 2543 +h\xc3\xb6mma! (esc)
2544 2544
2545 2545 displaying [PATCH 3 of 6] long line ...
2546 2546 Content-Type: text/plain; charset="us-ascii"
2547 2547 MIME-Version: 1.0
2548 2548 Content-Transfer-Encoding: quoted-printable
2549 2549 Subject: [PATCH 3 of 6] long line
2550 2550 X-Mercurial-Node: a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
2551 2551 X-Mercurial-Series-Index: 3
2552 2552 X-Mercurial-Series-Total: 6
2553 2553 Message-Id: <a2ea8fc83dd8b93cfd86.315532863@*> (glob)
2554 2554 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.315532861@*> (glob)
2555 2555 In-Reply-To: <patchbomb.315532860@*> (glob)
2556 2556 References: <patchbomb.315532860@*> (glob)
2557 2557 User-Agent: Mercurial-patchbomb/* (glob)
2558 2558 Date: Tue, 01 Jan 1980 00:01:03 +0000
2559 2559 From: test
2560 2560 To: foo
2561 2561
2562 2562 # HG changeset patch
2563 2563 # User test
2564 2564 # Date 4 0
2565 2565 # Thu Jan 01 00:00:04 1970 +0000
2566 2566 # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
2567 2567 # Parent 909a00e13e9d78b575aeee23dddbada46d5a143f
2568 2568 long line
2569 2569
2570 2570 diff -r 909a00e13e9d -r a2ea8fc83dd8 long
2571 2571 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2572 2572 +++ b/long Thu Jan 01 00:00:04 1970 +0000
2573 2573 @@ -0,0 +1,4 @@
2574 2574 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
2575 2575 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
2576 2576 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
2577 2577 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
2578 2578 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
2579 2579 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
2580 2580 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
2581 2581 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
2582 2582 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
2583 2583 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
2584 2584 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
2585 2585 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
2586 2586 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
2587 2587 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2588 2588 +foo
2589 2589 +
2590 2590 +bar
2591 2591
2592 2592 displaying [PATCH 4 of 6] isolatin 8-bit encoding ...
2593 2593 Content-Type: text/plain; charset="us-ascii"
2594 2594 MIME-Version: 1.0
2595 2595 Content-Transfer-Encoding: 8bit
2596 2596 Subject: [PATCH 4 of 6] isolatin 8-bit encoding
2597 2597 X-Mercurial-Node: 240fb913fc1b7ff15ddb9f33e73d82bf5277c720
2598 2598 X-Mercurial-Series-Index: 4
2599 2599 X-Mercurial-Series-Total: 6
2600 2600 Message-Id: <240fb913fc1b7ff15ddb.315532864@*> (glob)
2601 2601 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.315532861@*> (glob)
2602 2602 In-Reply-To: <patchbomb.315532860@*> (glob)
2603 2603 References: <patchbomb.315532860@*> (glob)
2604 2604 User-Agent: Mercurial-patchbomb/* (glob)
2605 2605 Date: Tue, 01 Jan 1980 00:01:04 +0000
2606 2606 From: test
2607 2607 To: foo
2608 2608
2609 2609 # HG changeset patch
2610 2610 # User test
2611 2611 # Date 5 0
2612 2612 # Thu Jan 01 00:00:05 1970 +0000
2613 2613 # Node ID 240fb913fc1b7ff15ddb9f33e73d82bf5277c720
2614 2614 # Parent a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
2615 2615 isolatin 8-bit encoding
2616 2616
2617 2617 diff -r a2ea8fc83dd8 -r 240fb913fc1b isolatin
2618 2618 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2619 2619 +++ b/isolatin Thu Jan 01 00:00:05 1970 +0000
2620 2620 @@ -0,0 +1,1 @@
2621 2621 +h\xf6mma! (esc)
2622 2622
2623 2623 displaying [PATCH 5 of 6] Added tag zero, zero.foo for changeset 8580ff50825a ...
2624 2624 Content-Type: text/plain; charset="us-ascii"
2625 2625 MIME-Version: 1.0
2626 2626 Content-Transfer-Encoding: 7bit
2627 2627 Subject: [PATCH 5 of 6] Added tag zero, zero.foo for changeset 8580ff50825a
2628 2628 X-Mercurial-Node: 5d5ef15dfe5e7bd3a4ee154b5fff76c7945ec433
2629 2629 X-Mercurial-Series-Index: 5
2630 2630 X-Mercurial-Series-Total: 6
2631 2631 Message-Id: <5d5ef15dfe5e7bd3a4ee.315532865@*> (glob)
2632 2632 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.315532861@*> (glob)
2633 2633 In-Reply-To: <patchbomb.315532860@*> (glob)
2634 2634 References: <patchbomb.315532860@*> (glob)
2635 2635 User-Agent: Mercurial-patchbomb/* (glob)
2636 2636 Date: Tue, 01 Jan 1980 00:01:05 +0000
2637 2637 From: test
2638 2638 To: foo
2639 2639
2640 2640 # HG changeset patch
2641 2641 # User test
2642 2642 # Date 0 0
2643 2643 # Thu Jan 01 00:00:00 1970 +0000
2644 2644 # Node ID 5d5ef15dfe5e7bd3a4ee154b5fff76c7945ec433
2645 2645 # Parent 240fb913fc1b7ff15ddb9f33e73d82bf5277c720
2646 2646 Added tag zero, zero.foo for changeset 8580ff50825a
2647 2647
2648 2648 diff -r 240fb913fc1b -r 5d5ef15dfe5e .hgtags
2649 2649 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2650 2650 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
2651 2651 @@ -0,0 +1,2 @@
2652 2652 +8580ff50825a50c8f716709acdf8de0deddcd6ab zero
2653 2653 +8580ff50825a50c8f716709acdf8de0deddcd6ab zero.foo
2654 2654
2655 2655 displaying [PATCH 6 of 6] d ...
2656 2656 Content-Type: text/plain; charset="us-ascii"
2657 2657 MIME-Version: 1.0
2658 2658 Content-Transfer-Encoding: 7bit
2659 2659 Subject: [PATCH 6 of 6] d
2660 2660 X-Mercurial-Node: 2f9fa9b998c5fe3ac2bd9a2b14bfcbeecbc7c268
2661 2661 X-Mercurial-Series-Index: 6
2662 2662 X-Mercurial-Series-Total: 6
2663 2663 Message-Id: <2f9fa9b998c5fe3ac2bd.315532866@*> (glob)
2664 2664 X-Mercurial-Series-Id: <ff2c9fa2018b15fa74b3.315532861@*> (glob)
2665 2665 In-Reply-To: <patchbomb.315532860@*> (glob)
2666 2666 References: <patchbomb.315532860@*> (glob)
2667 2667 User-Agent: Mercurial-patchbomb/* (glob)
2668 2668 Date: Tue, 01 Jan 1980 00:01:06 +0000
2669 2669 From: test
2670 2670 To: foo
2671 2671
2672 2672 # HG changeset patch
2673 2673 # User test
2674 2674 # Date 4 0
2675 2675 # Thu Jan 01 00:00:04 1970 +0000
2676 2676 # Branch test
2677 2677 # Node ID 2f9fa9b998c5fe3ac2bd9a2b14bfcbeecbc7c268
2678 2678 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
2679 2679 d
2680 2680
2681 2681 diff -r 97d72e5f12c7 -r 2f9fa9b998c5 d
2682 2682 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2683 2683 +++ b/d Thu Jan 01 00:00:04 1970 +0000
2684 2684 @@ -0,0 +1,1 @@
2685 2685 +d
2686 2686
2687 2687
2688 2688 Don't prompt for a CC header.
2689 2689
2690 2690 $ echo "[email]" >> $HGRCPATH
2691 2691 $ echo "cc=" >> $HGRCPATH
2692 2692
2693 2693 dest#branch URIs:
2694 2694 $ hg email --date '1980-1-1 0:1' -n -t foo -s test -o ../t#test
2695 2695 comparing with ../t
2696 2696 From [test]: test
2697 2697 this patch series consists of 1 patches.
2698 2698
2699 2699
2700 2700 displaying [PATCH] test ...
2701 2701 Content-Type: text/plain; charset="us-ascii"
2702 2702 MIME-Version: 1.0
2703 2703 Content-Transfer-Encoding: 7bit
2704 2704 Subject: [PATCH] test
2705 2705 X-Mercurial-Node: 2f9fa9b998c5fe3ac2bd9a2b14bfcbeecbc7c268
2706 2706 X-Mercurial-Series-Index: 1
2707 2707 X-Mercurial-Series-Total: 1
2708 2708 Message-Id: <2f9fa9b998c5fe3ac2bd.315532860@*> (glob)
2709 2709 X-Mercurial-Series-Id: <2f9fa9b998c5fe3ac2bd.315532860@*> (glob)
2710 2710 User-Agent: Mercurial-patchbomb/* (glob)
2711 2711 Date: Tue, 01 Jan 1980 00:01:00 +0000
2712 2712 From: test
2713 2713 To: foo
2714 2714
2715 2715 # HG changeset patch
2716 2716 # User test
2717 2717 # Date 4 0
2718 2718 # Thu Jan 01 00:00:04 1970 +0000
2719 2719 # Branch test
2720 2720 # Node ID 2f9fa9b998c5fe3ac2bd9a2b14bfcbeecbc7c268
2721 2721 # Parent 97d72e5f12c7e84f85064aa72e5a297142c36ed9
2722 2722 d
2723 2723
2724 2724 diff -r 97d72e5f12c7 -r 2f9fa9b998c5 d
2725 2725 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2726 2726 +++ b/d Thu Jan 01 00:00:04 1970 +0000
2727 2727 @@ -0,0 +1,1 @@
2728 2728 +d
2729 2729
2730 2730
2731 2731 Set up a fake sendmail program
2732 2732
2733 2733 $ cat > pretendmail.sh << 'EOF'
2734 2734 > #!/bin/sh
2735 2735 > echo "$@"
2736 2736 > cat
2737 2737 > EOF
2738 2738 $ chmod +x pretendmail.sh
2739 2739
2740 2740 $ echo '[email]' >> $HGRCPATH
2741 2741 $ echo "method=`pwd`/pretendmail.sh" >> $HGRCPATH
2742 2742
2743 2743 Test introduction configuration
2744 2744 =================================
2745 2745
2746 2746 $ echo '[patchbomb]' >> $HGRCPATH
2747 2747
2748 2748 "auto" setting
2749 2749 ----------------
2750 2750
2751 2751 $ echo 'intro=auto' >> $HGRCPATH
2752 2752
2753 2753 single rev
2754 2754
2755 2755 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '10' | grep "Write the introductory message for the patch series."
2756 2756 [1]
2757 2757
2758 2758 single rev + flag
2759 2759
2760 2760 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '10' --intro | grep "Write the introductory message for the patch series."
2761 2761 Write the introductory message for the patch series.
2762 2762
2763 2763
2764 2764 Multi rev
2765 2765
2766 2766 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '9::' | grep "Write the introductory message for the patch series."
2767 2767 Write the introductory message for the patch series.
2768 2768
2769 2769 "never" setting
2770 2770 -----------------
2771 2771
2772 2772 $ echo 'intro=never' >> $HGRCPATH
2773 2773
2774 2774 single rev
2775 2775
2776 2776 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '10' | grep "Write the introductory message for the patch series."
2777 2777 [1]
2778 2778
2779 2779 single rev + flag
2780 2780
2781 2781 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '10' --intro | grep "Write the introductory message for the patch series."
2782 2782 Write the introductory message for the patch series.
2783 2783
2784 2784
2785 2785 Multi rev
2786 2786
2787 2787 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '9::' | grep "Write the introductory message for the patch series."
2788 2788 [1]
2789 2789
2790 2790 Multi rev + flag
2791 2791
2792 2792 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '9::' --intro | grep "Write the introductory message for the patch series."
2793 2793 Write the introductory message for the patch series.
2794 2794
2795 2795 "always" setting
2796 2796 -----------------
2797 2797
2798 2798 $ echo 'intro=always' >> $HGRCPATH
2799 2799
2800 2800 single rev
2801 2801
2802 2802 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '10' | grep "Write the introductory message for the patch series."
2803 2803 Write the introductory message for the patch series.
2804 2804
2805 2805 single rev + flag
2806 2806
2807 2807 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '10' --intro | grep "Write the introductory message for the patch series."
2808 2808 Write the introductory message for the patch series.
2809 2809
2810 2810
2811 2811 Multi rev
2812 2812
2813 2813 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '9::' | grep "Write the introductory message for the patch series."
2814 2814 Write the introductory message for the patch series.
2815 2815
2816 2816 Multi rev + flag
2817 2817
2818 2818 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '9::' --intro | grep "Write the introductory message for the patch series."
2819 2819 Write the introductory message for the patch series.
2820 2820
2821 2821 bad value setting
2822 2822 -----------------
2823 2823
2824 2824 $ echo 'intro=mpmwearaclownnose' >> $HGRCPATH
2825 2825
2826 2826 single rev
2827 2827
2828 2828 $ hg email --date '1980-1-1 0:1' -v -t foo -s test -r '10'
2829 2829 From [test]: test
2830 2830 this patch series consists of 1 patches.
2831 2831
2832 2832 warning: invalid patchbomb.intro value "mpmwearaclownnose"
2833 2833 (should be one of always, never, auto)
2834 2834 -f test foo
2835 2835 Content-Type: text/plain; charset="us-ascii"
2836 2836 MIME-Version: 1.0
2837 2837 Content-Transfer-Encoding: 7bit
2838 2838 Subject: [PATCH] test
2839 2839 X-Mercurial-Node: 3b6f1ec9dde933a40a115a7990f8b320477231af
2840 2840 X-Mercurial-Series-Index: 1
2841 2841 X-Mercurial-Series-Total: 1
2842 2842 Message-Id: <3b6f1ec9dde933a40a11*> (glob)
2843 2843 X-Mercurial-Series-Id: <3b6f1ec9dde933a40a11.*> (glob)
2844 2844 User-Agent: Mercurial-patchbomb/* (glob)
2845 2845 Date: Tue, 01 Jan 1980 00:01:00 +0000
2846 2846 From: test
2847 2847 To: foo
2848 2848
2849 2849 # HG changeset patch
2850 2850 # User test
2851 2851 # Date 5 0
2852 2852 # Thu Jan 01 00:00:05 1970 +0000
2853 2853 # Branch test
2854 2854 # Node ID 3b6f1ec9dde933a40a115a7990f8b320477231af
2855 2855 # Parent 2f9fa9b998c5fe3ac2bd9a2b14bfcbeecbc7c268
2856 2856 dd
2857 2857
2858 2858 diff -r 2f9fa9b998c5 -r 3b6f1ec9dde9 d
2859 2859 --- a/d Thu Jan 01 00:00:04 1970 +0000
2860 2860 +++ b/d Thu Jan 01 00:00:05 1970 +0000
2861 2861 @@ -1,1 +1,2 @@
2862 2862 d
2863 2863 +d
2864 2864
2865 2865 sending [PATCH] test ...
2866 2866 sending mail: $TESTTMP/t2/pretendmail.sh -f test foo
2867 2867
2868 2868 Test pull url header
2869 2869 =================================
2870 2870
2871 2871 basic version
2872 2872
2873 2873 $ echo 'intro=auto' >> $HGRCPATH
2874 2874 $ echo "publicurl=$TESTTMP/t2" >> $HGRCPATH
2875 2875 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '10' | grep '^#'
2876 2876 abort: public url $TESTTMP/t2 is missing 3b6f1ec9dde9
2877 2877 (use 'hg push $TESTTMP/t2 -r 3b6f1ec9dde9')
2878 2878 [1]
2879 2879
2880 2880 public missing
2881 2881
2882 2882 $ echo 'publicurl=$TESTTMP/missing' >> $HGRCPATH
2883 2883 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '10'
2884 2884 unable to access public repo: $TESTTMP/missing
2885 2885 abort: repository $TESTTMP/missing not found!
2886 2886 [255]
2887 2887
2888 2888 node missing at public
2889 2889
2890 2890 $ hg clone -r '9' . ../t3
2891 2891 adding changesets
2892 2892 adding manifests
2893 2893 adding file changes
2894 2894 added 3 changesets with 3 changes to 3 files
2895 2895 updating to branch test
2896 2896 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
2897 2897 $ echo 'publicurl=$TESTTMP/t3' >> $HGRCPATH
2898 2898 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '10'
2899 2899 abort: public url $TESTTMP/t3 is missing 3b6f1ec9dde9
2900 2900 (use 'hg push $TESTTMP/t3 -r 3b6f1ec9dde9')
2901 2901 [255]
2902 2902
2903 2903 multiple heads are missing at public
2904 2904
2905 2905 $ hg email --date '1980-1-1 0:1' -t foo -s test -r '2+10'
2906 2906 abort: public "$TESTTMP/t3" is missing ff2c9fa2018b and 1 others
2907 2907 (use 'hg push $TESTTMP/t3 -r ff2c9fa2018b -r 3b6f1ec9dde9')
2908 2908 [255]
2909 2909
@@ -1,359 +1,359 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [format]
3 3 > usegeneraldelta=yes
4 4 > [extensions]
5 5 > rebase=
6 6 >
7 7 > [phases]
8 8 > publish=False
9 9 >
10 10 > [alias]
11 11 > tglog = log -G --template "{rev}:{phase} '{desc}' {branches} {bookmarks}\n"
12 12 > EOF
13 13
14 14 $ hg init a
15 15 $ cd a
16 16 $ echo c1 >common
17 17 $ hg add common
18 18 $ hg ci -m C1
19 19
20 20 $ echo c2 >>common
21 21 $ hg ci -m C2
22 22
23 23 $ echo c3 >>common
24 24 $ hg ci -m C3
25 25
26 26 $ hg up -q -C 1
27 27
28 28 $ echo l1 >>extra
29 29 $ hg add extra
30 30 $ hg ci -m L1
31 31 created new head
32 32
33 33 $ sed -e 's/c2/l2/' common > common.new
34 34 $ mv common.new common
35 35 $ hg ci -m L2
36 36
37 37 $ echo l3 >> extra2
38 38 $ hg add extra2
39 39 $ hg ci -m L3
40 40 $ hg bookmark mybook
41 41
42 42 $ hg phase --force --secret 4
43 43
44 44 $ hg tglog
45 45 @ 5:secret 'L3' mybook
46 46 |
47 47 o 4:secret 'L2'
48 48 |
49 49 o 3:draft 'L1'
50 50 |
51 51 | o 2:draft 'C3'
52 52 |/
53 53 o 1:draft 'C2'
54 54 |
55 55 o 0:draft 'C1'
56 56
57 57 Try to call --continue:
58 58
59 59 $ hg rebase --continue
60 60 abort: no rebase in progress
61 61 [255]
62 62
63 63 Conflicting rebase:
64 64
65 65 $ hg rebase -s 3 -d 2
66 66 rebasing 3:3163e20567cc "L1"
67 67 rebasing 4:46f0b057b5c0 "L2"
68 68 merging common
69 69 warning: conflicts while merging common! (edit, then use 'hg resolve --mark')
70 70 unresolved conflicts (see hg resolve, then hg rebase --continue)
71 71 [1]
72 72
73 73 Try to continue without solving the conflict:
74 74
75 75 $ hg rebase --continue
76 76 already rebased 3:3163e20567cc "L1" as 3e046f2ecedb
77 77 rebasing 4:46f0b057b5c0 "L2"
78 78 abort: unresolved merge conflicts (see "hg help resolve")
79 79 [255]
80 80
81 81 Conclude rebase:
82 82
83 83 $ echo 'resolved merge' >common
84 84 $ hg resolve -m common
85 85 (no more unresolved files)
86 86 continue: hg rebase --continue
87 87 $ hg rebase --continue
88 88 already rebased 3:3163e20567cc "L1" as 3e046f2ecedb
89 89 rebasing 4:46f0b057b5c0 "L2"
90 90 rebasing 5:8029388f38dc "L3" (mybook)
91 91 saved backup bundle to $TESTTMP/a/.hg/strip-backup/3163e20567cc-5ca4656e-backup.hg (glob)
92 92
93 93 $ hg tglog
94 94 @ 5:secret 'L3' mybook
95 95 |
96 96 o 4:secret 'L2'
97 97 |
98 98 o 3:draft 'L1'
99 99 |
100 100 o 2:draft 'C3'
101 101 |
102 102 o 1:draft 'C2'
103 103 |
104 104 o 0:draft 'C1'
105 105
106 106 Check correctness:
107 107
108 108 $ hg cat -r 0 common
109 109 c1
110 110
111 111 $ hg cat -r 1 common
112 112 c1
113 113 c2
114 114
115 115 $ hg cat -r 2 common
116 116 c1
117 117 c2
118 118 c3
119 119
120 120 $ hg cat -r 3 common
121 121 c1
122 122 c2
123 123 c3
124 124
125 125 $ hg cat -r 4 common
126 126 resolved merge
127 127
128 128 $ hg cat -r 5 common
129 129 resolved merge
130 130
131 131 Bookmark stays active after --continue
132 132 $ hg bookmarks
133 133 * mybook 5:d67b21408fc0
134 134
135 135 $ cd ..
136 136
137 137 Check that the right ancestors is used while rebasing a merge (issue4041)
138 138
139 139 $ hg clone "$TESTDIR/bundles/issue4041.hg" issue4041
140 140 requesting all changes
141 141 adding changesets
142 142 adding manifests
143 143 adding file changes
144 144 added 11 changesets with 8 changes to 3 files (+1 heads)
145 145 updating to branch default
146 146 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
147 147 $ cd issue4041
148 148 $ hg log -G
149 149 o changeset: 10:2f2496ddf49d
150 150 |\ branch: f1
151 151 | | tag: tip
152 152 | | parent: 7:4c9fbe56a16f
153 153 | | parent: 9:e31216eec445
154 154 | | user: szhang
155 155 | | date: Thu Sep 05 12:59:39 2013 -0400
156 156 | | summary: merge
157 157 | |
158 158 | o changeset: 9:e31216eec445
159 159 | | branch: f1
160 160 | | user: szhang
161 161 | | date: Thu Sep 05 12:59:10 2013 -0400
162 162 | | summary: more changes to f1
163 163 | |
164 164 | o changeset: 8:8e4e2c1a07ae
165 165 | |\ branch: f1
166 166 | | | parent: 2:4bc80088dc6b
167 167 | | | parent: 6:400110238667
168 168 | | | user: szhang
169 169 | | | date: Thu Sep 05 12:57:59 2013 -0400
170 170 | | | summary: bad merge
171 171 | | |
172 172 o | | changeset: 7:4c9fbe56a16f
173 173 |/ / branch: f1
174 174 | | parent: 2:4bc80088dc6b
175 175 | | user: szhang
176 176 | | date: Thu Sep 05 12:54:00 2013 -0400
177 177 | | summary: changed f1
178 178 | |
179 179 | o changeset: 6:400110238667
180 180 | | branch: f2
181 181 | | parent: 4:12e8ec6bb010
182 182 | | user: szhang
183 183 | | date: Tue Sep 03 13:58:02 2013 -0400
184 184 | | summary: changed f2 on f2
185 185 | |
186 186 | | @ changeset: 5:d79e2059b5c0
187 187 | | | parent: 3:8a951942e016
188 188 | | | user: szhang
189 189 | | | date: Tue Sep 03 13:57:39 2013 -0400
190 190 | | | summary: changed f2 on default
191 191 | | |
192 192 | o | changeset: 4:12e8ec6bb010
193 193 | |/ branch: f2
194 194 | | user: szhang
195 195 | | date: Tue Sep 03 13:57:18 2013 -0400
196 196 | | summary: created f2 branch
197 197 | |
198 198 | o changeset: 3:8a951942e016
199 199 | | parent: 0:24797d4f68de
200 200 | | user: szhang
201 201 | | date: Tue Sep 03 13:57:11 2013 -0400
202 202 | | summary: added f2.txt
203 203 | |
204 204 o | changeset: 2:4bc80088dc6b
205 205 | | branch: f1
206 206 | | user: szhang
207 207 | | date: Tue Sep 03 13:56:20 2013 -0400
208 208 | | summary: added f1.txt
209 209 | |
210 210 o | changeset: 1:ef53c9e6b608
211 211 |/ branch: f1
212 212 | user: szhang
213 213 | date: Tue Sep 03 13:55:26 2013 -0400
214 214 | summary: created f1 branch
215 215 |
216 216 o changeset: 0:24797d4f68de
217 217 user: szhang
218 218 date: Tue Sep 03 13:55:08 2013 -0400
219 219 summary: added default.txt
220 220
221 221 $ hg rebase -s9 -d2 --debug # use debug to really check merge base used
222 222 rebase onto 2 starting from e31216eec445
223 223 ignoring null merge rebase of 3
224 224 ignoring null merge rebase of 4
225 225 ignoring null merge rebase of 6
226 226 ignoring null merge rebase of 8
227 227 rebasing 9:e31216eec445 "more changes to f1"
228 228 future parents are 2 and -1
229 229 rebase status stored
230 230 update to 2:4bc80088dc6b
231 231 resolving manifests
232 232 branchmerge: False, force: True, partial: False
233 233 ancestor: d79e2059b5c0+, local: d79e2059b5c0+, remote: 4bc80088dc6b
234 234 f2.txt: other deleted -> r
235 235 removing f2.txt
236 236 f1.txt: remote created -> g
237 237 getting f1.txt
238 238 merge against 9:e31216eec445
239 239 detach base 8:8e4e2c1a07ae
240 240 searching for copies back to rev 3
241 241 resolving manifests
242 242 branchmerge: True, force: True, partial: False
243 243 ancestor: 8e4e2c1a07ae, local: 4bc80088dc6b+, remote: e31216eec445
244 244 f1.txt: remote is newer -> g
245 245 getting f1.txt
246 246 committing files:
247 247 f1.txt
248 248 committing manifest
249 249 committing changelog
250 250 rebased as 19c888675e13
251 251 rebasing 10:2f2496ddf49d "merge" (tip)
252 252 future parents are 11 and 7
253 253 rebase status stored
254 254 already in target
255 255 merge against 10:2f2496ddf49d
256 256 detach base 9:e31216eec445
257 257 searching for copies back to rev 3
258 258 resolving manifests
259 259 branchmerge: True, force: True, partial: False
260 260 ancestor: e31216eec445, local: 19c888675e13+, remote: 2f2496ddf49d
261 261 f1.txt: remote is newer -> g
262 262 getting f1.txt
263 263 committing files:
264 264 f1.txt
265 265 committing manifest
266 266 committing changelog
267 267 rebased as 2a7f09cac94c
268 268 rebase merging completed
269 269 update back to initial working directory parent
270 270 resolving manifests
271 271 branchmerge: False, force: False, partial: False
272 272 ancestor: 2a7f09cac94c, local: 2a7f09cac94c+, remote: d79e2059b5c0
273 273 f1.txt: other deleted -> r
274 274 removing f1.txt
275 275 f2.txt: remote created -> g
276 276 getting f2.txt
277 277 2 changesets found
278 278 list of changesets:
279 279 e31216eec445e44352c5f01588856059466a24c9
280 280 2f2496ddf49d69b5ef23ad8cf9fb2e0e4faf0ac2
281 281 bundle2-output-bundle: "HG20", (1 params) 1 parts total
282 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
282 bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
283 283 saved backup bundle to $TESTTMP/issue4041/.hg/strip-backup/e31216eec445-15f7a814-backup.hg (glob)
284 284 3 changesets found
285 285 list of changesets:
286 286 4c9fbe56a16f30c0d5dcc40ec1a97bbe3325209c
287 287 19c888675e133ab5dff84516926a65672eaf04d9
288 288 2a7f09cac94c7f4b73ebd5cd1a62d3b2e8e336bf
289 289 bundle2-output-bundle: "HG20", 1 parts total
290 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
290 bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
291 291 adding branch
292 292 bundle2-input-bundle: with-transaction
293 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
293 bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
294 294 adding changesets
295 295 add changeset 4c9fbe56a16f
296 296 add changeset 19c888675e13
297 297 add changeset 2a7f09cac94c
298 298 adding manifests
299 299 adding file changes
300 300 adding f1.txt revisions
301 301 added 2 changesets with 2 changes to 1 files
302 302 bundle2-input-part: total payload size 1713
303 303 bundle2-input-bundle: 0 parts total
304 304 invalid branchheads cache (served): tip differs
305 305 rebase completed
306 306 updating the branch cache
307 307 truncating cache/rbc-revs-v1 to 72
308 308
309 309 Test minimization of merge conflicts
310 310 $ hg up -q null
311 311 $ echo a > a
312 312 $ hg add a
313 313 $ hg commit -q -m 'a'
314 314 $ echo b >> a
315 315 $ hg commit -q -m 'ab'
316 316 $ hg bookmark ab
317 317 $ hg up -q '.^'
318 318 $ echo b >> a
319 319 $ echo c >> a
320 320 $ hg commit -q -m 'abc'
321 321 $ hg rebase -s 7bc217434fc1 -d ab --keep
322 322 rebasing 13:7bc217434fc1 "abc" (tip)
323 323 merging a
324 324 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
325 325 unresolved conflicts (see hg resolve, then hg rebase --continue)
326 326 [1]
327 327 $ hg diff
328 328 diff -r 328e4ab1f7cc a
329 329 --- a/a Thu Jan 01 00:00:00 1970 +0000
330 330 +++ b/a * (glob)
331 331 @@ -1,2 +1,6 @@
332 332 a
333 333 b
334 334 +<<<<<<< dest: 328e4ab1f7cc ab - test: ab
335 335 +=======
336 336 +c
337 337 +>>>>>>> source: 7bc217434fc1 - test: abc
338 338 $ hg rebase --abort
339 339 rebase aborted
340 340 $ hg up -q -C 7bc217434fc1
341 341 $ hg rebase -s . -d ab --keep -t internal:merge3
342 342 rebasing 13:7bc217434fc1 "abc" (tip)
343 343 merging a
344 344 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
345 345 unresolved conflicts (see hg resolve, then hg rebase --continue)
346 346 [1]
347 347 $ hg diff
348 348 diff -r 328e4ab1f7cc a
349 349 --- a/a Thu Jan 01 00:00:00 1970 +0000
350 350 +++ b/a * (glob)
351 351 @@ -1,2 +1,8 @@
352 352 a
353 353 +<<<<<<< dest: 328e4ab1f7cc ab - test: ab
354 354 b
355 355 +||||||| base
356 356 +=======
357 357 +b
358 358 +c
359 359 +>>>>>>> source: 7bc217434fc1 - test: abc
@@ -1,1624 +1,1624 b''
1 1 $ cat <<EOF >> $HGRCPATH
2 2 > [extensions]
3 3 > mq =
4 4 > shelve =
5 5 > [defaults]
6 6 > diff = --nodates --git
7 7 > qnew = --date '0 0'
8 8 > [shelve]
9 9 > maxbackups = 2
10 10 > EOF
11 11
12 12 $ hg init repo
13 13 $ cd repo
14 14 $ mkdir a b
15 15 $ echo a > a/a
16 16 $ echo b > b/b
17 17 $ echo c > c
18 18 $ echo d > d
19 19 $ echo x > x
20 20 $ hg addremove -q
21 21
22 22 shelve has a help message
23 23 $ hg shelve -h
24 24 hg shelve [OPTION]... [FILE]...
25 25
26 26 save and set aside changes from the working directory
27 27
28 28 Shelving takes files that "hg status" reports as not clean, saves the
29 29 modifications to a bundle (a shelved change), and reverts the files so
30 30 that their state in the working directory becomes clean.
31 31
32 32 To restore these changes to the working directory, using "hg unshelve";
33 33 this will work even if you switch to a different commit.
34 34
35 35 When no files are specified, "hg shelve" saves all not-clean files. If
36 36 specific files or directories are named, only changes to those files are
37 37 shelved.
38 38
39 39 In bare shelve(when no files are specified, without interactive, include
40 40 and exclude option), shelving remembers information if the working
41 41 directory was on newly created branch, in other words working directory
42 42 was on different branch than its first parent. In this situation
43 43 unshelving restores branch information to the working directory.
44 44
45 45 Each shelved change has a name that makes it easier to find later. The
46 46 name of a shelved change defaults to being based on the active bookmark,
47 47 or if there is no active bookmark, the current named branch. To specify a
48 48 different name, use "--name".
49 49
50 50 To see a list of existing shelved changes, use the "--list" option. For
51 51 each shelved change, this will print its name, age, and description; use "
52 52 --patch" or "--stat" for more details.
53 53
54 54 To delete specific shelved changes, use "--delete". To delete all shelved
55 55 changes, use "--cleanup".
56 56
57 57 (use "hg help -e shelve" to show help for the shelve extension)
58 58
59 59 options ([+] can be repeated):
60 60
61 61 -A --addremove mark new/missing files as added/removed before
62 62 shelving
63 63 -u --unknown store unknown files in the shelve
64 64 --cleanup delete all shelved changes
65 65 --date DATE shelve with the specified commit date
66 66 -d --delete delete the named shelved change(s)
67 67 -e --edit invoke editor on commit messages
68 68 -l --list list current shelves
69 69 -m --message TEXT use text as shelve message
70 70 -n --name NAME use the given name for the shelved commit
71 71 -p --patch show patch
72 72 -i --interactive interactive mode, only works while creating a shelve
73 73 --stat output diffstat-style summary of changes
74 74 -I --include PATTERN [+] include names matching the given patterns
75 75 -X --exclude PATTERN [+] exclude names matching the given patterns
76 76 --mq operate on patch repository
77 77
78 78 (some details hidden, use --verbose to show complete help)
79 79
80 80 shelving in an empty repo should be possible
81 81 (this tests also that editor is not invoked, if '--edit' is not
82 82 specified)
83 83
84 84 $ HGEDITOR=cat hg shelve
85 85 shelved as default
86 86 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
87 87
88 88 $ hg unshelve
89 89 unshelving change 'default'
90 90
91 91 $ hg commit -q -m 'initial commit'
92 92
93 93 $ hg shelve
94 94 nothing changed
95 95 [1]
96 96
97 97 make sure shelve files were backed up
98 98
99 99 $ ls .hg/shelve-backup
100 100 default.hg
101 101 default.patch
102 102
103 103 create an mq patch - shelving should work fine with a patch applied
104 104
105 105 $ echo n > n
106 106 $ hg add n
107 107 $ hg commit n -m second
108 108 $ hg qnew second.patch
109 109
110 110 shelve a change that we will delete later
111 111
112 112 $ echo a >> a/a
113 113 $ hg shelve
114 114 shelved as default
115 115 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
116 116
117 117 set up some more complex changes to shelve
118 118
119 119 $ echo a >> a/a
120 120 $ hg mv b b.rename
121 121 moving b/b to b.rename/b (glob)
122 122 $ hg cp c c.copy
123 123 $ hg status -C
124 124 M a/a
125 125 A b.rename/b
126 126 b/b
127 127 A c.copy
128 128 c
129 129 R b/b
130 130
131 131 prevent some foot-shooting
132 132
133 133 $ hg shelve -n foo/bar
134 134 abort: shelved change names may not contain slashes
135 135 [255]
136 136 $ hg shelve -n .baz
137 137 abort: shelved change names may not start with '.'
138 138 [255]
139 139
140 140 the common case - no options or filenames
141 141
142 142 $ hg shelve
143 143 shelved as default-01
144 144 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
145 145 $ hg status -C
146 146
147 147 ensure that our shelved changes exist
148 148
149 149 $ hg shelve -l
150 150 default-01 (*)* changes to: [mq]: second.patch (glob)
151 151 default (*)* changes to: [mq]: second.patch (glob)
152 152
153 153 $ hg shelve -l -p default
154 154 default (*)* changes to: [mq]: second.patch (glob)
155 155
156 156 diff --git a/a/a b/a/a
157 157 --- a/a/a
158 158 +++ b/a/a
159 159 @@ -1,1 +1,2 @@
160 160 a
161 161 +a
162 162
163 163 $ hg shelve --list --addremove
164 164 abort: options '--list' and '--addremove' may not be used together
165 165 [255]
166 166
167 167 delete our older shelved change
168 168
169 169 $ hg shelve -d default
170 170 $ hg qfinish -a -q
171 171
172 172 ensure shelve backups aren't overwritten
173 173
174 174 $ ls .hg/shelve-backup/
175 175 default-1.hg
176 176 default-1.patch
177 177 default.hg
178 178 default.patch
179 179
180 180 local edits should not prevent a shelved change from applying
181 181
182 182 $ printf "z\na\n" > a/a
183 183 $ hg unshelve --keep
184 184 unshelving change 'default-01'
185 185 temporarily committing pending changes (restore with 'hg unshelve --abort')
186 186 rebasing shelved changes
187 187 rebasing 4:32c69314e062 "changes to: [mq]: second.patch" (tip)
188 188 merging a/a
189 189
190 190 $ hg revert --all -q
191 191 $ rm a/a.orig b.rename/b c.copy
192 192
193 193 apply it and make sure our state is as expected
194 194
195 195 (this also tests that same timestamp prevents backups from being
196 196 removed, even though there are more than 'maxbackups' backups)
197 197
198 198 $ f -t .hg/shelve-backup/default.hg
199 199 .hg/shelve-backup/default.hg: file
200 200 $ touch -t 200001010000 .hg/shelve-backup/default.hg
201 201 $ f -t .hg/shelve-backup/default-1.hg
202 202 .hg/shelve-backup/default-1.hg: file
203 203 $ touch -t 200001010000 .hg/shelve-backup/default-1.hg
204 204
205 205 $ hg unshelve
206 206 unshelving change 'default-01'
207 207 $ hg status -C
208 208 M a/a
209 209 A b.rename/b
210 210 b/b
211 211 A c.copy
212 212 c
213 213 R b/b
214 214 $ hg shelve -l
215 215
216 216 (both of default.hg and default-1.hg should be still kept, because it
217 217 is difficult to decide actual order of them from same timestamp)
218 218
219 219 $ ls .hg/shelve-backup/
220 220 default-01.hg
221 221 default-01.patch
222 222 default-1.hg
223 223 default-1.patch
224 224 default.hg
225 225 default.patch
226 226
227 227 $ hg unshelve
228 228 abort: no shelved changes to apply!
229 229 [255]
230 230 $ hg unshelve foo
231 231 abort: shelved change 'foo' not found
232 232 [255]
233 233
234 234 named shelves, specific filenames, and "commit messages" should all work
235 235 (this tests also that editor is invoked, if '--edit' is specified)
236 236
237 237 $ hg status -C
238 238 M a/a
239 239 A b.rename/b
240 240 b/b
241 241 A c.copy
242 242 c
243 243 R b/b
244 244 $ HGEDITOR=cat hg shelve -q -n wibble -m wat -e a
245 245 wat
246 246
247 247
248 248 HG: Enter commit message. Lines beginning with 'HG:' are removed.
249 249 HG: Leave message empty to abort commit.
250 250 HG: --
251 251 HG: user: shelve@localhost
252 252 HG: branch 'default'
253 253 HG: changed a/a
254 254
255 255 expect "a" to no longer be present, but status otherwise unchanged
256 256
257 257 $ hg status -C
258 258 A b.rename/b
259 259 b/b
260 260 A c.copy
261 261 c
262 262 R b/b
263 263 $ hg shelve -l --stat
264 264 wibble (*) wat (glob)
265 265 a/a | 1 +
266 266 1 files changed, 1 insertions(+), 0 deletions(-)
267 267
268 268 and now "a/a" should reappear
269 269
270 270 $ cd a
271 271 $ hg unshelve -q wibble
272 272 $ cd ..
273 273 $ hg status -C
274 274 M a/a
275 275 A b.rename/b
276 276 b/b
277 277 A c.copy
278 278 c
279 279 R b/b
280 280
281 281 ensure old shelve backups are being deleted automatically
282 282
283 283 $ ls .hg/shelve-backup/
284 284 default-01.hg
285 285 default-01.patch
286 286 wibble.hg
287 287 wibble.patch
288 288
289 289 cause unshelving to result in a merge with 'a' conflicting
290 290
291 291 $ hg shelve -q
292 292 $ echo c>>a/a
293 293 $ hg commit -m second
294 294 $ hg tip --template '{files}\n'
295 295 a/a
296 296
297 297 add an unrelated change that should be preserved
298 298
299 299 $ mkdir foo
300 300 $ echo foo > foo/foo
301 301 $ hg add foo/foo
302 302
303 303 force a conflicted merge to occur
304 304
305 305 $ hg unshelve
306 306 unshelving change 'default'
307 307 temporarily committing pending changes (restore with 'hg unshelve --abort')
308 308 rebasing shelved changes
309 309 rebasing 5:32c69314e062 "changes to: [mq]: second.patch" (tip)
310 310 merging a/a
311 311 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
312 312 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
313 313 [1]
314 314
315 315 ensure that we have a merge with unresolved conflicts
316 316
317 317 $ hg heads -q --template '{rev}\n'
318 318 5
319 319 4
320 320 $ hg parents -q --template '{rev}\n'
321 321 4
322 322 5
323 323 $ hg status
324 324 M a/a
325 325 M b.rename/b
326 326 M c.copy
327 327 R b/b
328 328 ? a/a.orig
329 329 $ hg diff
330 330 diff --git a/a/a b/a/a
331 331 --- a/a/a
332 332 +++ b/a/a
333 333 @@ -1,2 +1,6 @@
334 334 a
335 335 +<<<<<<< dest: * - shelve: pending changes temporary commit (glob)
336 336 c
337 337 +=======
338 338 +a
339 339 +>>>>>>> source: 32c69314e062 - shelve: changes to: [mq]: second.patch
340 340 diff --git a/b/b b/b.rename/b
341 341 rename from b/b
342 342 rename to b.rename/b
343 343 diff --git a/c b/c.copy
344 344 copy from c
345 345 copy to c.copy
346 346 $ hg resolve -l
347 347 U a/a
348 348
349 349 $ hg shelve
350 350 abort: unshelve already in progress
351 351 (use 'hg unshelve --continue' or 'hg unshelve --abort')
352 352 [255]
353 353
354 354 abort the unshelve and be happy
355 355
356 356 $ hg status
357 357 M a/a
358 358 M b.rename/b
359 359 M c.copy
360 360 R b/b
361 361 ? a/a.orig
362 362 $ hg unshelve -a
363 363 rebase aborted
364 364 unshelve of 'default' aborted
365 365 $ hg heads -q
366 366 3:2e69b451d1ea
367 367 $ hg parents
368 368 changeset: 3:2e69b451d1ea
369 369 tag: tip
370 370 user: test
371 371 date: Thu Jan 01 00:00:00 1970 +0000
372 372 summary: second
373 373
374 374 $ hg resolve -l
375 375 $ hg status
376 376 A foo/foo
377 377 ? a/a.orig
378 378
379 379 try to continue with no unshelve underway
380 380
381 381 $ hg unshelve -c
382 382 abort: no unshelve in progress
383 383 [255]
384 384 $ hg status
385 385 A foo/foo
386 386 ? a/a.orig
387 387
388 388 redo the unshelve to get a conflict
389 389
390 390 $ hg unshelve -q
391 391 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
392 392 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
393 393 [1]
394 394
395 395 attempt to continue
396 396
397 397 $ hg unshelve -c
398 398 abort: unresolved conflicts, can't continue
399 399 (see 'hg resolve', then 'hg unshelve --continue')
400 400 [255]
401 401
402 402 $ hg revert -r . a/a
403 403 $ hg resolve -m a/a
404 404 (no more unresolved files)
405 405 continue: hg unshelve --continue
406 406
407 407 $ hg commit -m 'commit while unshelve in progress'
408 408 abort: unshelve already in progress
409 409 (use 'hg unshelve --continue' or 'hg unshelve --abort')
410 410 [255]
411 411
412 412 $ hg graft --continue
413 413 abort: no graft in progress
414 414 (continue: hg unshelve --continue)
415 415 [255]
416 416 $ hg unshelve -c
417 417 rebasing 5:32c69314e062 "changes to: [mq]: second.patch" (tip)
418 418 unshelve of 'default' complete
419 419
420 420 ensure the repo is as we hope
421 421
422 422 $ hg parents
423 423 changeset: 3:2e69b451d1ea
424 424 tag: tip
425 425 user: test
426 426 date: Thu Jan 01 00:00:00 1970 +0000
427 427 summary: second
428 428
429 429 $ hg heads -q
430 430 3:2e69b451d1ea
431 431
432 432 $ hg status -C
433 433 A b.rename/b
434 434 b/b
435 435 A c.copy
436 436 c
437 437 A foo/foo
438 438 R b/b
439 439 ? a/a.orig
440 440
441 441 there should be no shelves left
442 442
443 443 $ hg shelve -l
444 444
445 445 #if execbit
446 446
447 447 ensure that metadata-only changes are shelved
448 448
449 449 $ chmod +x a/a
450 450 $ hg shelve -q -n execbit a/a
451 451 $ hg status a/a
452 452 $ hg unshelve -q execbit
453 453 $ hg status a/a
454 454 M a/a
455 455 $ hg revert a/a
456 456
457 457 #endif
458 458
459 459 #if symlink
460 460
461 461 $ rm a/a
462 462 $ ln -s foo a/a
463 463 $ hg shelve -q -n symlink a/a
464 464 $ hg status a/a
465 465 $ hg unshelve -q symlink
466 466 $ hg status a/a
467 467 M a/a
468 468 $ hg revert a/a
469 469
470 470 #endif
471 471
472 472 set up another conflict between a commit and a shelved change
473 473
474 474 $ hg revert -q -C -a
475 475 $ rm a/a.orig b.rename/b c.copy
476 476 $ echo a >> a/a
477 477 $ hg shelve -q
478 478 $ echo x >> a/a
479 479 $ hg ci -m 'create conflict'
480 480 $ hg add foo/foo
481 481
482 482 if we resolve a conflict while unshelving, the unshelve should succeed
483 483
484 484 $ hg unshelve --tool :merge-other --keep
485 485 unshelving change 'default'
486 486 temporarily committing pending changes (restore with 'hg unshelve --abort')
487 487 rebasing shelved changes
488 488 rebasing 6:2f694dd83a13 "changes to: second" (tip)
489 489 merging a/a
490 490 $ hg parents -q
491 491 4:33f7f61e6c5e
492 492 $ hg shelve -l
493 493 default (*)* changes to: second (glob)
494 494 $ hg status
495 495 M a/a
496 496 A foo/foo
497 497 $ cat a/a
498 498 a
499 499 c
500 500 a
501 501 $ cat > a/a << EOF
502 502 > a
503 503 > c
504 504 > x
505 505 > EOF
506 506
507 507 $ HGMERGE=true hg unshelve
508 508 unshelving change 'default'
509 509 temporarily committing pending changes (restore with 'hg unshelve --abort')
510 510 rebasing shelved changes
511 511 rebasing 6:2f694dd83a13 "changes to: second" (tip)
512 512 merging a/a
513 513 note: rebase of 6:2f694dd83a13 created no changes to commit
514 514 $ hg parents -q
515 515 4:33f7f61e6c5e
516 516 $ hg shelve -l
517 517 $ hg status
518 518 A foo/foo
519 519 $ cat a/a
520 520 a
521 521 c
522 522 x
523 523
524 524 test keep and cleanup
525 525
526 526 $ hg shelve
527 527 shelved as default
528 528 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
529 529 $ hg shelve --list
530 530 default (*)* changes to: create conflict (glob)
531 531 $ hg unshelve -k
532 532 unshelving change 'default'
533 533 $ hg shelve --list
534 534 default (*)* changes to: create conflict (glob)
535 535 $ hg shelve --cleanup
536 536 $ hg shelve --list
537 537
538 538 $ hg shelve --cleanup --delete
539 539 abort: options '--cleanup' and '--delete' may not be used together
540 540 [255]
541 541 $ hg shelve --cleanup --patch
542 542 abort: options '--cleanup' and '--patch' may not be used together
543 543 [255]
544 544 $ hg shelve --cleanup --message MESSAGE
545 545 abort: options '--cleanup' and '--message' may not be used together
546 546 [255]
547 547
548 548 test bookmarks
549 549
550 550 $ hg bookmark test
551 551 $ hg bookmark
552 552 * test 4:33f7f61e6c5e
553 553 $ hg shelve
554 554 shelved as test
555 555 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
556 556 $ hg bookmark
557 557 * test 4:33f7f61e6c5e
558 558 $ hg unshelve
559 559 unshelving change 'test'
560 560 $ hg bookmark
561 561 * test 4:33f7f61e6c5e
562 562
563 563 shelve should still work even if mq is disabled
564 564
565 565 $ hg --config extensions.mq=! shelve
566 566 shelved as test
567 567 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
568 568 $ hg --config extensions.mq=! shelve --list
569 569 test (*)* changes to: create conflict (glob)
570 570 $ hg bookmark
571 571 * test 4:33f7f61e6c5e
572 572 $ hg --config extensions.mq=! unshelve
573 573 unshelving change 'test'
574 574 $ hg bookmark
575 575 * test 4:33f7f61e6c5e
576 576
577 577 shelve should leave dirstate clean (issue4055)
578 578
579 579 $ cd ..
580 580 $ hg init shelverebase
581 581 $ cd shelverebase
582 582 $ printf 'x\ny\n' > x
583 583 $ echo z > z
584 584 $ hg commit -Aqm xy
585 585 $ echo z >> x
586 586 $ hg commit -Aqm z
587 587 $ hg up 0
588 588 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
589 589 $ printf 'a\nx\ny\nz\n' > x
590 590 $ hg commit -Aqm xyz
591 591 $ echo c >> z
592 592 $ hg shelve
593 593 shelved as default
594 594 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
595 595 $ hg rebase -d 1 --config extensions.rebase=
596 596 rebasing 2:323bfa07f744 "xyz" (tip)
597 597 merging x
598 598 saved backup bundle to $TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-78114325-backup.hg (glob)
599 599 $ hg unshelve
600 600 unshelving change 'default'
601 601 rebasing shelved changes
602 602 rebasing 4:82a0d7d6ba61 "changes to: xyz" (tip)
603 603 $ hg status
604 604 M z
605 605
606 606 $ cd ..
607 607
608 608 shelve should only unshelve pending changes (issue4068)
609 609
610 610 $ hg init onlypendingchanges
611 611 $ cd onlypendingchanges
612 612 $ touch a
613 613 $ hg ci -Aqm a
614 614 $ touch b
615 615 $ hg ci -Aqm b
616 616 $ hg up -q 0
617 617 $ touch c
618 618 $ hg ci -Aqm c
619 619
620 620 $ touch d
621 621 $ hg add d
622 622 $ hg shelve
623 623 shelved as default
624 624 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
625 625 $ hg up -q 1
626 626 $ hg unshelve
627 627 unshelving change 'default'
628 628 rebasing shelved changes
629 629 rebasing 3:958bcbd1776e "changes to: c" (tip)
630 630 $ hg status
631 631 A d
632 632
633 633 unshelve should work on an ancestor of the original commit
634 634
635 635 $ hg shelve
636 636 shelved as default
637 637 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
638 638 $ hg up 0
639 639 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
640 640 $ hg unshelve
641 641 unshelving change 'default'
642 642 rebasing shelved changes
643 643 rebasing 3:013284d9655e "changes to: b" (tip)
644 644 $ hg status
645 645 A d
646 646
647 647 test bug 4073 we need to enable obsolete markers for it
648 648
649 649 $ cat >> $HGRCPATH << EOF
650 650 > [experimental]
651 651 > evolution=createmarkers
652 652 > EOF
653 653 $ hg shelve
654 654 shelved as default
655 655 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
656 656 $ hg debugobsolete `hg --debug id -i -r 1`
657 657 $ hg unshelve
658 658 unshelving change 'default'
659 659
660 660 unshelve should leave unknown files alone (issue4113)
661 661
662 662 $ echo e > e
663 663 $ hg shelve
664 664 shelved as default
665 665 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
666 666 $ hg status
667 667 ? e
668 668 $ hg unshelve
669 669 unshelving change 'default'
670 670 $ hg status
671 671 A d
672 672 ? e
673 673 $ cat e
674 674 e
675 675
676 676 unshelve should keep a copy of unknown files
677 677
678 678 $ hg add e
679 679 $ hg shelve
680 680 shelved as default
681 681 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
682 682 $ echo z > e
683 683 $ hg unshelve
684 684 unshelving change 'default'
685 685 $ cat e
686 686 e
687 687 $ cat e.orig
688 688 z
689 689
690 690
691 691 unshelve and conflicts with tracked and untracked files
692 692
693 693 preparing:
694 694
695 695 $ rm *.orig
696 696 $ hg ci -qm 'commit stuff'
697 697 $ hg phase -p null:
698 698
699 699 no other changes - no merge:
700 700
701 701 $ echo f > f
702 702 $ hg add f
703 703 $ hg shelve
704 704 shelved as default
705 705 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
706 706 $ echo g > f
707 707 $ hg unshelve
708 708 unshelving change 'default'
709 709 $ hg st
710 710 A f
711 711 ? f.orig
712 712 $ cat f
713 713 f
714 714 $ cat f.orig
715 715 g
716 716
717 717 other uncommitted changes - merge:
718 718
719 719 $ hg st
720 720 A f
721 721 ? f.orig
722 722 $ hg shelve
723 723 shelved as default
724 724 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
725 725 $ hg log -G --template '{rev} {desc|firstline} {author}' -R bundle://.hg/shelved/default.hg -r 'bundle()'
726 726 o 4 changes to: commit stuff shelve@localhost
727 727 |
728 728 ~
729 729 $ hg log -G --template '{rev} {desc|firstline} {author}'
730 730 @ 3 commit stuff test
731 731 |
732 732 | o 2 c test
733 733 |/
734 734 o 0 a test
735 735
736 736 $ mv f.orig f
737 737 $ echo 1 > a
738 738 $ hg unshelve --date '1073741824 0'
739 739 unshelving change 'default'
740 740 temporarily committing pending changes (restore with 'hg unshelve --abort')
741 741 rebasing shelved changes
742 742 rebasing 5:81152db69da7 "changes to: commit stuff" (tip)
743 743 merging f
744 744 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
745 745 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
746 746 [1]
747 747 $ hg log -G --template '{rev} {desc|firstline} {author} {date|isodate}'
748 748 @ 5 changes to: commit stuff shelve@localhost 1970-01-01 00:00 +0000
749 749 |
750 750 | @ 4 pending changes temporary commit shelve@localhost 2004-01-10 13:37 +0000
751 751 |/
752 752 o 3 commit stuff test 1970-01-01 00:00 +0000
753 753 |
754 754 | o 2 c test 1970-01-01 00:00 +0000
755 755 |/
756 756 o 0 a test 1970-01-01 00:00 +0000
757 757
758 758 $ hg st
759 759 M f
760 760 ? f.orig
761 761 $ cat f
762 762 <<<<<<< dest: 5f6b880e719b - shelve: pending changes temporary commit
763 763 g
764 764 =======
765 765 f
766 766 >>>>>>> source: 81152db69da7 - shelve: changes to: commit stuff
767 767 $ cat f.orig
768 768 g
769 769 $ hg unshelve --abort -t false
770 770 tool option will be ignored
771 771 rebase aborted
772 772 unshelve of 'default' aborted
773 773 $ hg st
774 774 M a
775 775 ? f.orig
776 776 $ cat f.orig
777 777 g
778 778 $ hg unshelve
779 779 unshelving change 'default'
780 780 temporarily committing pending changes (restore with 'hg unshelve --abort')
781 781 rebasing shelved changes
782 782 rebasing 5:81152db69da7 "changes to: commit stuff" (tip)
783 783 $ hg st
784 784 M a
785 785 A f
786 786 ? f.orig
787 787
788 788 other committed changes - merge:
789 789
790 790 $ hg shelve f
791 791 shelved as default
792 792 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
793 793 $ hg ci a -m 'intermediate other change'
794 794 $ mv f.orig f
795 795 $ hg unshelve
796 796 unshelving change 'default'
797 797 rebasing shelved changes
798 798 rebasing 5:81152db69da7 "changes to: commit stuff" (tip)
799 799 merging f
800 800 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
801 801 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
802 802 [1]
803 803 $ hg st
804 804 M f
805 805 ? f.orig
806 806 $ cat f
807 807 <<<<<<< dest: * - test: intermediate other change (glob)
808 808 g
809 809 =======
810 810 f
811 811 >>>>>>> source: 81152db69da7 - shelve: changes to: commit stuff
812 812 $ cat f.orig
813 813 g
814 814 $ hg unshelve --abort
815 815 rebase aborted
816 816 unshelve of 'default' aborted
817 817 $ hg st
818 818 ? f.orig
819 819 $ cat f.orig
820 820 g
821 821 $ hg shelve --delete default
822 822
823 823 Recreate some conflict again
824 824
825 825 $ cd ../repo
826 826 $ hg up -C -r 3
827 827 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
828 828 (leaving bookmark test)
829 829 $ echo y >> a/a
830 830 $ hg shelve
831 831 shelved as default
832 832 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
833 833 $ hg up test
834 834 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
835 835 (activating bookmark test)
836 836 $ hg bookmark
837 837 * test 4:33f7f61e6c5e
838 838 $ hg unshelve
839 839 unshelving change 'default'
840 840 rebasing shelved changes
841 841 rebasing 5:e42a7da90865 "changes to: second" (tip)
842 842 merging a/a
843 843 warning: conflicts while merging a/a! (edit, then use 'hg resolve --mark')
844 844 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
845 845 [1]
846 846 $ hg bookmark
847 847 test 4:33f7f61e6c5e
848 848
849 849 Test that resolving all conflicts in one direction (so that the rebase
850 850 is a no-op), works (issue4398)
851 851
852 852 $ hg revert -a -r .
853 853 reverting a/a (glob)
854 854 $ hg resolve -m a/a
855 855 (no more unresolved files)
856 856 continue: hg unshelve --continue
857 857 $ hg unshelve -c
858 858 rebasing 5:e42a7da90865 "changes to: second" (tip)
859 859 note: rebase of 5:e42a7da90865 created no changes to commit
860 860 unshelve of 'default' complete
861 861 $ hg bookmark
862 862 * test 4:33f7f61e6c5e
863 863 $ hg diff
864 864 $ hg status
865 865 ? a/a.orig
866 866 ? foo/foo
867 867 $ hg summary
868 868 parent: 4:33f7f61e6c5e tip
869 869 create conflict
870 870 branch: default
871 871 bookmarks: *test
872 872 commit: 2 unknown (clean)
873 873 update: (current)
874 874 phases: 5 draft
875 875
876 876 $ hg shelve --delete --stat
877 877 abort: options '--delete' and '--stat' may not be used together
878 878 [255]
879 879 $ hg shelve --delete --name NAME
880 880 abort: options '--delete' and '--name' may not be used together
881 881 [255]
882 882
883 883 Test interactive shelve
884 884 $ cat <<EOF >> $HGRCPATH
885 885 > [ui]
886 886 > interactive = true
887 887 > EOF
888 888 $ echo 'a' >> a/b
889 889 $ cat a/a >> a/b
890 890 $ echo 'x' >> a/b
891 891 $ mv a/b a/a
892 892 $ echo 'a' >> foo/foo
893 893 $ hg st
894 894 M a/a
895 895 ? a/a.orig
896 896 ? foo/foo
897 897 $ cat a/a
898 898 a
899 899 a
900 900 c
901 901 x
902 902 x
903 903 $ cat foo/foo
904 904 foo
905 905 a
906 906 $ hg shelve --interactive --config ui.interactive=false
907 907 abort: running non-interactively
908 908 [255]
909 909 $ hg shelve --interactive << EOF
910 910 > y
911 911 > y
912 912 > n
913 913 > EOF
914 914 diff --git a/a/a b/a/a
915 915 2 hunks, 2 lines changed
916 916 examine changes to 'a/a'? [Ynesfdaq?] y
917 917
918 918 @@ -1,3 +1,4 @@
919 919 +a
920 920 a
921 921 c
922 922 x
923 923 record change 1/2 to 'a/a'? [Ynesfdaq?] y
924 924
925 925 @@ -1,3 +2,4 @@
926 926 a
927 927 c
928 928 x
929 929 +x
930 930 record change 2/2 to 'a/a'? [Ynesfdaq?] n
931 931
932 932 shelved as test
933 933 merging a/a
934 934 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
935 935 $ cat a/a
936 936 a
937 937 c
938 938 x
939 939 x
940 940 $ cat foo/foo
941 941 foo
942 942 a
943 943 $ hg st
944 944 M a/a
945 945 ? foo/foo
946 946 $ hg bookmark
947 947 * test 4:33f7f61e6c5e
948 948 $ hg unshelve
949 949 unshelving change 'test'
950 950 temporarily committing pending changes (restore with 'hg unshelve --abort')
951 951 rebasing shelved changes
952 952 rebasing 6:96a1354f65f6 "changes to: create conflict" (tip)
953 953 merging a/a
954 954 $ hg bookmark
955 955 * test 4:33f7f61e6c5e
956 956 $ cat a/a
957 957 a
958 958 a
959 959 c
960 960 x
961 961 x
962 962
963 963 shelve --patch and shelve --stat should work with a single valid shelfname
964 964
965 965 $ hg up --clean .
966 966 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
967 967 (leaving bookmark test)
968 968 $ hg shelve --list
969 969 $ echo 'patch a' > shelf-patch-a
970 970 $ hg add shelf-patch-a
971 971 $ hg shelve
972 972 shelved as default
973 973 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
974 974 $ echo 'patch b' > shelf-patch-b
975 975 $ hg add shelf-patch-b
976 976 $ hg shelve
977 977 shelved as default-01
978 978 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
979 979 $ hg shelve --patch default default-01
980 980 abort: --patch expects a single shelf
981 981 [255]
982 982 $ hg shelve --stat default default-01
983 983 abort: --stat expects a single shelf
984 984 [255]
985 985 $ hg shelve --patch default
986 986 default (*)* changes to: create conflict (glob)
987 987
988 988 diff --git a/shelf-patch-a b/shelf-patch-a
989 989 new file mode 100644
990 990 --- /dev/null
991 991 +++ b/shelf-patch-a
992 992 @@ -0,0 +1,1 @@
993 993 +patch a
994 994 $ hg shelve --stat default
995 995 default (*)* changes to: create conflict (glob)
996 996 shelf-patch-a | 1 +
997 997 1 files changed, 1 insertions(+), 0 deletions(-)
998 998 $ hg shelve --patch nonexistentshelf
999 999 abort: cannot find shelf nonexistentshelf
1000 1000 [255]
1001 1001 $ hg shelve --stat nonexistentshelf
1002 1002 abort: cannot find shelf nonexistentshelf
1003 1003 [255]
1004 1004
1005 1005 $ cd ..
1006 1006
1007 1007 Shelve from general delta repo uses bundle2 on disk
1008 1008 --------------------------------------------------
1009 1009
1010 1010 no general delta
1011 1011
1012 1012 $ hg clone --pull repo bundle1 --config format.usegeneraldelta=0
1013 1013 requesting all changes
1014 1014 adding changesets
1015 1015 adding manifests
1016 1016 adding file changes
1017 1017 added 5 changesets with 8 changes to 6 files
1018 1018 updating to branch default
1019 1019 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1020 1020 $ cd bundle1
1021 1021 $ echo babar > jungle
1022 1022 $ hg add jungle
1023 1023 $ hg shelve
1024 1024 shelved as default
1025 1025 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1026 1026 $ hg debugbundle .hg/shelved/*.hg
1027 1027 45993d65fe9dc3c6d8764b9c3b07fa831ee7d92d
1028 1028 $ cd ..
1029 1029
1030 1030 with general delta
1031 1031
1032 1032 $ hg clone --pull repo bundle2 --config format.usegeneraldelta=1
1033 1033 requesting all changes
1034 1034 adding changesets
1035 1035 adding manifests
1036 1036 adding file changes
1037 1037 added 5 changesets with 8 changes to 6 files
1038 1038 updating to branch default
1039 1039 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1040 1040 $ cd bundle2
1041 1041 $ echo babar > jungle
1042 1042 $ hg add jungle
1043 1043 $ hg shelve
1044 1044 shelved as default
1045 1045 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1046 1046 $ hg debugbundle .hg/shelved/*.hg
1047 1047 Stream params: sortdict([('Compression', 'BZ')])
1048 changegroup -- "sortdict([('version', '02')])"
1048 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
1049 1049 45993d65fe9dc3c6d8764b9c3b07fa831ee7d92d
1050 1050 $ cd ..
1051 1051
1052 1052 Test visibility of in-memory changes inside transaction to external hook
1053 1053 ------------------------------------------------------------------------
1054 1054
1055 1055 $ cd repo
1056 1056
1057 1057 $ echo xxxx >> x
1058 1058 $ hg commit -m "#5: changes to invoke rebase"
1059 1059
1060 1060 $ cat > $TESTTMP/checkvisibility.sh <<EOF
1061 1061 > echo "==== \$1:"
1062 1062 > hg parents --template "VISIBLE {rev}:{node|short}\n"
1063 1063 > # test that pending changes are hidden
1064 1064 > unset HG_PENDING
1065 1065 > hg parents --template "ACTUAL {rev}:{node|short}\n"
1066 1066 > echo "===="
1067 1067 > EOF
1068 1068
1069 1069 $ cat >> .hg/hgrc <<EOF
1070 1070 > [defaults]
1071 1071 > # to fix hash id of temporary revisions
1072 1072 > unshelve = --date '0 0'
1073 1073 > EOF
1074 1074
1075 1075 "hg unshelve" at REV5 implies steps below:
1076 1076
1077 1077 (1) commit changes in the working directory (REV6)
1078 1078 (2) unbundle shelved revision (REV7)
1079 1079 (3) rebase: merge REV7 into REV6 (REV6 => REV6, REV7)
1080 1080 (4) rebase: commit merged revision (REV8)
1081 1081 (5) rebase: update to REV6 (REV8 => REV6)
1082 1082 (6) update to REV5 (REV6 => REV5)
1083 1083 (7) abort transaction
1084 1084
1085 1085 == test visibility to external preupdate hook
1086 1086
1087 1087 $ cat >> .hg/hgrc <<EOF
1088 1088 > [hooks]
1089 1089 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
1090 1090 > EOF
1091 1091
1092 1092 $ echo nnnn >> n
1093 1093
1094 1094 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1095 1095 ==== before-unshelving:
1096 1096 VISIBLE 5:703117a2acfb
1097 1097 ACTUAL 5:703117a2acfb
1098 1098 ====
1099 1099
1100 1100 $ hg unshelve --keep default
1101 1101 temporarily committing pending changes (restore with 'hg unshelve --abort')
1102 1102 rebasing shelved changes
1103 1103 rebasing 7:206bf5d4f922 "changes to: create conflict" (tip)
1104 1104 ==== preupdate:
1105 1105 VISIBLE 6:66b86db80ee4
1106 1106 ACTUAL 5:703117a2acfb
1107 1107 ====
1108 1108 ==== preupdate:
1109 1109 VISIBLE 8:a0e04704317e
1110 1110 ACTUAL 5:703117a2acfb
1111 1111 ====
1112 1112 ==== preupdate:
1113 1113 VISIBLE 6:66b86db80ee4
1114 1114 ACTUAL 5:703117a2acfb
1115 1115 ====
1116 1116
1117 1117 $ cat >> .hg/hgrc <<EOF
1118 1118 > [hooks]
1119 1119 > preupdate.visibility =
1120 1120 > EOF
1121 1121
1122 1122 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1123 1123 ==== after-unshelving:
1124 1124 VISIBLE 5:703117a2acfb
1125 1125 ACTUAL 5:703117a2acfb
1126 1126 ====
1127 1127
1128 1128 == test visibility to external update hook
1129 1129
1130 1130 $ hg update -q -C 5
1131 1131
1132 1132 $ cat >> .hg/hgrc <<EOF
1133 1133 > [hooks]
1134 1134 > update.visibility = sh $TESTTMP/checkvisibility.sh update
1135 1135 > EOF
1136 1136
1137 1137 $ echo nnnn >> n
1138 1138
1139 1139 $ sh $TESTTMP/checkvisibility.sh before-unshelving
1140 1140 ==== before-unshelving:
1141 1141 VISIBLE 5:703117a2acfb
1142 1142 ACTUAL 5:703117a2acfb
1143 1143 ====
1144 1144
1145 1145 $ hg unshelve --keep default
1146 1146 temporarily committing pending changes (restore with 'hg unshelve --abort')
1147 1147 rebasing shelved changes
1148 1148 rebasing 7:206bf5d4f922 "changes to: create conflict" (tip)
1149 1149 ==== update:
1150 1150 VISIBLE 6:66b86db80ee4
1151 1151 VISIBLE 7:206bf5d4f922
1152 1152 ACTUAL 5:703117a2acfb
1153 1153 ====
1154 1154 ==== update:
1155 1155 VISIBLE 6:66b86db80ee4
1156 1156 ACTUAL 5:703117a2acfb
1157 1157 ====
1158 1158 ==== update:
1159 1159 VISIBLE 5:703117a2acfb
1160 1160 ACTUAL 5:703117a2acfb
1161 1161 ====
1162 1162
1163 1163 $ cat >> .hg/hgrc <<EOF
1164 1164 > [hooks]
1165 1165 > update.visibility =
1166 1166 > EOF
1167 1167
1168 1168 $ sh $TESTTMP/checkvisibility.sh after-unshelving
1169 1169 ==== after-unshelving:
1170 1170 VISIBLE 5:703117a2acfb
1171 1171 ACTUAL 5:703117a2acfb
1172 1172 ====
1173 1173
1174 1174 $ cd ..
1175 1175
1176 1176 test .orig files go where the user wants them to
1177 1177 ---------------------------------------------------------------
1178 1178 $ hg init salvage
1179 1179 $ cd salvage
1180 1180 $ echo 'content' > root
1181 1181 $ hg commit -A -m 'root' -q
1182 1182 $ echo '' > root
1183 1183 $ hg shelve -q
1184 1184 $ echo 'contADDent' > root
1185 1185 $ hg unshelve -q --config 'ui.origbackuppath=.hg/origbackups'
1186 1186 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1187 1187 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1188 1188 [1]
1189 1189 $ ls .hg/origbackups
1190 1190 root.orig
1191 1191 $ rm -rf .hg/origbackups
1192 1192
1193 1193 test Abort unshelve always gets user out of the unshelved state
1194 1194 ---------------------------------------------------------------
1195 1195 Wreak havoc on the unshelve process
1196 1196 $ rm .hg/unshelverebasestate
1197 1197 $ hg unshelve --abort
1198 1198 unshelve of 'default' aborted
1199 1199 abort: (No such file or directory|The system cannot find the file specified) (re)
1200 1200 [255]
1201 1201 Can the user leave the current state?
1202 1202 $ hg up -C .
1203 1203 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1204 1204
1205 1205 Try again but with a corrupted shelve state file
1206 1206 $ hg strip -r 2 -r 1 -q
1207 1207 $ hg up -r 0 -q
1208 1208 $ echo '' > root
1209 1209 $ hg shelve -q
1210 1210 $ echo 'contADDent' > root
1211 1211 $ hg unshelve -q
1212 1212 warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
1213 1213 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1214 1214 [1]
1215 1215 $ sed 's/ae8c668541e8/123456789012/' .hg/shelvedstate > ../corrupt-shelvedstate
1216 1216 $ mv ../corrupt-shelvedstate .hg/histedit-state
1217 1217 $ hg unshelve --abort 2>&1 | grep 'rebase aborted'
1218 1218 rebase aborted
1219 1219 $ hg up -C .
1220 1220 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1221 1221
1222 1222 $ cd ..
1223 1223
1224 1224 Keep active bookmark while (un)shelving even on shared repo (issue4940)
1225 1225 -----------------------------------------------------------------------
1226 1226
1227 1227 $ cat <<EOF >> $HGRCPATH
1228 1228 > [extensions]
1229 1229 > share =
1230 1230 > EOF
1231 1231
1232 1232 $ hg bookmarks -R repo
1233 1233 test 4:33f7f61e6c5e
1234 1234 $ hg share -B repo share
1235 1235 updating working directory
1236 1236 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1237 1237 $ cd share
1238 1238
1239 1239 $ hg bookmarks
1240 1240 test 4:33f7f61e6c5e
1241 1241 $ hg bookmarks foo
1242 1242 $ hg bookmarks
1243 1243 * foo 5:703117a2acfb
1244 1244 test 4:33f7f61e6c5e
1245 1245 $ echo x >> x
1246 1246 $ hg shelve
1247 1247 shelved as foo
1248 1248 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1249 1249 $ hg bookmarks
1250 1250 * foo 5:703117a2acfb
1251 1251 test 4:33f7f61e6c5e
1252 1252
1253 1253 $ hg unshelve
1254 1254 unshelving change 'foo'
1255 1255 $ hg bookmarks
1256 1256 * foo 5:703117a2acfb
1257 1257 test 4:33f7f61e6c5e
1258 1258
1259 1259 $ cd ..
1260 1260
1261 1261 Shelve and unshelve unknown files. For the purposes of unshelve, a shelved
1262 1262 unknown file is the same as a shelved added file, except that it will be in
1263 1263 unknown state after unshelve if and only if it was either absent or unknown
1264 1264 before the unshelve operation.
1265 1265
1266 1266 $ hg init unknowns
1267 1267 $ cd unknowns
1268 1268
1269 1269 The simplest case is if I simply have an unknown file that I shelve and unshelve
1270 1270
1271 1271 $ echo unknown > unknown
1272 1272 $ hg status
1273 1273 ? unknown
1274 1274 $ hg shelve --unknown
1275 1275 shelved as default
1276 1276 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1277 1277 $ hg status
1278 1278 $ hg unshelve
1279 1279 unshelving change 'default'
1280 1280 $ hg status
1281 1281 ? unknown
1282 1282 $ rm unknown
1283 1283
1284 1284 If I shelve, add the file, and unshelve, does it stay added?
1285 1285
1286 1286 $ echo unknown > unknown
1287 1287 $ hg shelve -u
1288 1288 shelved as default
1289 1289 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1290 1290 $ hg status
1291 1291 $ touch unknown
1292 1292 $ hg add unknown
1293 1293 $ hg status
1294 1294 A unknown
1295 1295 $ hg unshelve
1296 1296 unshelving change 'default'
1297 1297 temporarily committing pending changes (restore with 'hg unshelve --abort')
1298 1298 rebasing shelved changes
1299 1299 rebasing 1:098df96e7410 "(changes in empty repository)" (tip)
1300 1300 merging unknown
1301 1301 $ hg status
1302 1302 A unknown
1303 1303 $ hg forget unknown
1304 1304 $ rm unknown
1305 1305
1306 1306 And if I shelve, commit, then unshelve, does it become modified?
1307 1307
1308 1308 $ echo unknown > unknown
1309 1309 $ hg shelve -u
1310 1310 shelved as default
1311 1311 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1312 1312 $ hg status
1313 1313 $ touch unknown
1314 1314 $ hg add unknown
1315 1315 $ hg commit -qm "Add unknown"
1316 1316 $ hg status
1317 1317 $ hg unshelve
1318 1318 unshelving change 'default'
1319 1319 rebasing shelved changes
1320 1320 rebasing 1:098df96e7410 "(changes in empty repository)" (tip)
1321 1321 merging unknown
1322 1322 $ hg status
1323 1323 M unknown
1324 1324 $ hg remove --force unknown
1325 1325 $ hg commit -qm "Remove unknown"
1326 1326
1327 1327 $ cd ..
1328 1328
1329 1329 We expects that non-bare shelve keeps newly created branch in
1330 1330 working directory.
1331 1331
1332 1332 $ hg init shelve-preserve-new-branch
1333 1333 $ cd shelve-preserve-new-branch
1334 1334 $ echo "a" >> a
1335 1335 $ hg add a
1336 1336 $ echo "b" >> b
1337 1337 $ hg add b
1338 1338 $ hg commit -m "ab"
1339 1339 $ echo "aa" >> a
1340 1340 $ echo "bb" >> b
1341 1341 $ hg branch new-branch
1342 1342 marked working directory as branch new-branch
1343 1343 (branches are permanent and global, did you want a bookmark?)
1344 1344 $ hg status
1345 1345 M a
1346 1346 M b
1347 1347 $ hg branch
1348 1348 new-branch
1349 1349 $ hg shelve a
1350 1350 shelved as default
1351 1351 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1352 1352 $ hg branch
1353 1353 new-branch
1354 1354 $ hg status
1355 1355 M b
1356 1356 $ touch "c" >> c
1357 1357 $ hg add c
1358 1358 $ hg status
1359 1359 M b
1360 1360 A c
1361 1361 $ hg shelve --exclude c
1362 1362 shelved as default-01
1363 1363 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1364 1364 $ hg branch
1365 1365 new-branch
1366 1366 $ hg status
1367 1367 A c
1368 1368 $ hg shelve --include c
1369 1369 shelved as default-02
1370 1370 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1371 1371 $ hg branch
1372 1372 new-branch
1373 1373 $ hg status
1374 1374 $ echo "d" >> d
1375 1375 $ hg add d
1376 1376 $ hg status
1377 1377 A d
1378 1378
1379 1379 We expect that bare-shelve will not keep branch in current working directory.
1380 1380
1381 1381 $ hg shelve
1382 1382 shelved as default-03
1383 1383 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1384 1384 $ hg branch
1385 1385 default
1386 1386
1387 1387 When i shelve commit on newly created branch i expect
1388 1388 that after unshelve newly created branch will be preserved.
1389 1389
1390 1390 $ hg init shelve_on_new_branch_simple
1391 1391 $ cd shelve_on_new_branch_simple
1392 1392 $ echo "aaa" >> a
1393 1393 $ hg commit -A -m "a"
1394 1394 adding a
1395 1395 $ hg branch
1396 1396 default
1397 1397 $ hg branch test
1398 1398 marked working directory as branch test
1399 1399 (branches are permanent and global, did you want a bookmark?)
1400 1400 $ echo "bbb" >> a
1401 1401 $ hg status
1402 1402 M a
1403 1403 $ hg shelve
1404 1404 shelved as default
1405 1405 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1406 1406 $ hg branch
1407 1407 default
1408 1408 $ echo "bbb" >> b
1409 1409 $ hg status
1410 1410 ? b
1411 1411 $ hg unshelve
1412 1412 unshelving change 'default'
1413 1413 marked working directory as branch test
1414 1414 $ hg status
1415 1415 M a
1416 1416 ? b
1417 1417 $ hg branch
1418 1418 test
1419 1419
1420 1420 When i shelve commit on newly created branch, make
1421 1421 some changes, unshelve it and running into merge
1422 1422 conflicts i expect that after fixing them and
1423 1423 running unshelve --continue newly created branch
1424 1424 will be preserved.
1425 1425
1426 1426 $ hg init shelve_on_new_branch_conflict
1427 1427 $ cd shelve_on_new_branch_conflict
1428 1428 $ echo "aaa" >> a
1429 1429 $ hg commit -A -m "a"
1430 1430 adding a
1431 1431 $ hg branch
1432 1432 default
1433 1433 $ hg branch test
1434 1434 marked working directory as branch test
1435 1435 (branches are permanent and global, did you want a bookmark?)
1436 1436 $ echo "bbb" >> a
1437 1437 $ hg status
1438 1438 M a
1439 1439 $ hg shelve
1440 1440 shelved as default
1441 1441 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1442 1442 $ hg branch
1443 1443 default
1444 1444 $ echo "ccc" >> a
1445 1445 $ hg status
1446 1446 M a
1447 1447 $ hg unshelve
1448 1448 unshelving change 'default'
1449 1449 temporarily committing pending changes (restore with 'hg unshelve --abort')
1450 1450 rebasing shelved changes
1451 1451 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1452 1452 merging a
1453 1453 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
1454 1454 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1455 1455 [1]
1456 1456 $ echo "aaabbbccc" > a
1457 1457 $ rm a.orig
1458 1458 $ hg resolve --mark a
1459 1459 (no more unresolved files)
1460 1460 continue: hg unshelve --continue
1461 1461 $ hg unshelve --continue
1462 1462 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1463 1463 marked working directory as branch test
1464 1464 unshelve of 'default' complete
1465 1465 $ cat a
1466 1466 aaabbbccc
1467 1467 $ hg status
1468 1468 M a
1469 1469 $ hg branch
1470 1470 test
1471 1471 $ hg commit -m "test-commit"
1472 1472
1473 1473 When i shelve on test branch, update to default branch
1474 1474 and unshelve i expect that it will not preserve previous
1475 1475 test branch.
1476 1476
1477 1477 $ echo "xxx" > b
1478 1478 $ hg add b
1479 1479 $ hg shelve
1480 1480 shelved as test
1481 1481 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1482 1482 $ hg update -r default
1483 1483 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1484 1484 $ hg unshelve
1485 1485 unshelving change 'test'
1486 1486 rebasing shelved changes
1487 1487 rebasing 2:357525f34729 "changes to: test-commit" (tip)
1488 1488 $ hg status
1489 1489 A b
1490 1490 $ hg branch
1491 1491 default
1492 1492
1493 1493 When i unshelve resulting in merge conflicts and makes saved
1494 1494 file shelvedstate looks like in previous versions in
1495 1495 mercurial(without restore branch information in 7th line) i
1496 1496 expect that after resolving conflicts and succesfully
1497 1497 running 'shelve --continue' the branch information won't be
1498 1498 restored and branch will be unchanged.
1499 1499
1500 1500 shelve on new branch, conflict with previous shelvedstate
1501 1501
1502 1502 $ hg init conflict
1503 1503 $ cd conflict
1504 1504 $ echo "aaa" >> a
1505 1505 $ hg commit -A -m "a"
1506 1506 adding a
1507 1507 $ hg branch
1508 1508 default
1509 1509 $ hg branch test
1510 1510 marked working directory as branch test
1511 1511 (branches are permanent and global, did you want a bookmark?)
1512 1512 $ echo "bbb" >> a
1513 1513 $ hg status
1514 1514 M a
1515 1515 $ hg shelve
1516 1516 shelved as default
1517 1517 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1518 1518 $ hg branch
1519 1519 default
1520 1520 $ echo "ccc" >> a
1521 1521 $ hg status
1522 1522 M a
1523 1523 $ hg unshelve
1524 1524 unshelving change 'default'
1525 1525 temporarily committing pending changes (restore with 'hg unshelve --abort')
1526 1526 rebasing shelved changes
1527 1527 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1528 1528 merging a
1529 1529 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
1530 1530 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1531 1531 [1]
1532 1532
1533 1533 Removing restore branch information from shelvedstate file(making it looks like
1534 1534 in previous versions) and running unshelve --continue
1535 1535
1536 1536 $ head -n 6 < .hg/shelvedstate > .hg/shelvedstate_oldformat
1537 1537 $ rm .hg/shelvedstate
1538 1538 $ mv .hg/shelvedstate_oldformat .hg/shelvedstate
1539 1539
1540 1540 $ echo "aaabbbccc" > a
1541 1541 $ rm a.orig
1542 1542 $ hg resolve --mark a
1543 1543 (no more unresolved files)
1544 1544 continue: hg unshelve --continue
1545 1545 $ hg unshelve --continue
1546 1546 rebasing 2:425c97ef07f3 "changes to: a" (tip)
1547 1547 unshelve of 'default' complete
1548 1548 $ cat a
1549 1549 aaabbbccc
1550 1550 $ hg status
1551 1551 M a
1552 1552 $ hg branch
1553 1553 default
1554 1554
1555 1555 On non bare shelve the branch information shouldn't be restored
1556 1556
1557 1557 $ hg init bare_shelve_on_new_branch
1558 1558 $ cd bare_shelve_on_new_branch
1559 1559 $ echo "aaa" >> a
1560 1560 $ hg commit -A -m "a"
1561 1561 adding a
1562 1562 $ hg branch
1563 1563 default
1564 1564 $ hg branch test
1565 1565 marked working directory as branch test
1566 1566 (branches are permanent and global, did you want a bookmark?)
1567 1567 $ echo "bbb" >> a
1568 1568 $ hg status
1569 1569 M a
1570 1570 $ hg shelve a
1571 1571 shelved as default
1572 1572 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1573 1573 $ hg branch
1574 1574 test
1575 1575 $ hg branch default
1576 1576 marked working directory as branch default
1577 1577 (branches are permanent and global, did you want a bookmark?)
1578 1578 $ echo "bbb" >> b
1579 1579 $ hg status
1580 1580 ? b
1581 1581 $ hg unshelve
1582 1582 unshelving change 'default'
1583 1583 $ hg status
1584 1584 M a
1585 1585 ? b
1586 1586 $ hg branch
1587 1587 default
1588 1588 $ cd ..
1589 1589
1590 1590 Prepare unshleve with a corrupted shelvedstate
1591 1591 $ hg init r1 && cd r1
1592 1592 $ echo text1 > file && hg add file
1593 1593 $ hg shelve
1594 1594 shelved as default
1595 1595 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1596 1596 $ echo text2 > file && hg ci -Am text1
1597 1597 adding file
1598 1598 $ hg unshelve
1599 1599 unshelving change 'default'
1600 1600 rebasing shelved changes
1601 1601 rebasing 1:396ea74229f9 "(changes in empty repository)" (tip)
1602 1602 merging file
1603 1603 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
1604 1604 unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
1605 1605 [1]
1606 1606 $ echo somethingsomething > .hg/shelvedstate
1607 1607
1608 1608 Unshelve --continue fails with appropriate message if shelvedstate is corrupted
1609 1609 $ hg unshelve --continue
1610 1610 abort: corrupted shelved state file
1611 1611 (please run hg unshelve --abort to abort unshelve operation)
1612 1612 [255]
1613 1613
1614 1614 Unshelve --abort works with a corrupted shelvedstate
1615 1615 $ hg unshelve --abort
1616 1616 could not read shelved state file, your working copy may be in an unexpected state
1617 1617 please update to some commit
1618 1618
1619 1619 Unshelve --abort fails with appropriate message if there's no unshelve in
1620 1620 progress
1621 1621 $ hg unshelve --abort
1622 1622 abort: no unshelve in progress
1623 1623 [255]
1624 1624 $ cd ..
@@ -1,898 +1,898 b''
1 1 $ echo "[format]" >> $HGRCPATH
2 2 $ echo "usegeneraldelta=yes" >> $HGRCPATH
3 3 $ echo "[extensions]" >> $HGRCPATH
4 4 $ echo "strip=" >> $HGRCPATH
5 5
6 6 $ restore() {
7 7 > hg unbundle -q .hg/strip-backup/*
8 8 > rm .hg/strip-backup/*
9 9 > }
10 10 $ teststrip() {
11 11 > hg up -C $1
12 12 > echo % before update $1, strip $2
13 13 > hg parents
14 14 > hg --traceback strip $2
15 15 > echo % after update $1, strip $2
16 16 > hg parents
17 17 > restore
18 18 > }
19 19
20 20 $ hg init test
21 21 $ cd test
22 22
23 23 $ echo foo > bar
24 24 $ hg ci -Ama
25 25 adding bar
26 26
27 27 $ echo more >> bar
28 28 $ hg ci -Amb
29 29
30 30 $ echo blah >> bar
31 31 $ hg ci -Amc
32 32
33 33 $ hg up 1
34 34 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
35 35 $ echo blah >> bar
36 36 $ hg ci -Amd
37 37 created new head
38 38
39 39 $ echo final >> bar
40 40 $ hg ci -Ame
41 41
42 42 $ hg log
43 43 changeset: 4:443431ffac4f
44 44 tag: tip
45 45 user: test
46 46 date: Thu Jan 01 00:00:00 1970 +0000
47 47 summary: e
48 48
49 49 changeset: 3:65bd5f99a4a3
50 50 parent: 1:ef3a871183d7
51 51 user: test
52 52 date: Thu Jan 01 00:00:00 1970 +0000
53 53 summary: d
54 54
55 55 changeset: 2:264128213d29
56 56 user: test
57 57 date: Thu Jan 01 00:00:00 1970 +0000
58 58 summary: c
59 59
60 60 changeset: 1:ef3a871183d7
61 61 user: test
62 62 date: Thu Jan 01 00:00:00 1970 +0000
63 63 summary: b
64 64
65 65 changeset: 0:9ab35a2d17cb
66 66 user: test
67 67 date: Thu Jan 01 00:00:00 1970 +0000
68 68 summary: a
69 69
70 70
71 71 $ teststrip 4 4
72 72 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
73 73 % before update 4, strip 4
74 74 changeset: 4:443431ffac4f
75 75 tag: tip
76 76 user: test
77 77 date: Thu Jan 01 00:00:00 1970 +0000
78 78 summary: e
79 79
80 80 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
81 81 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
82 82 % after update 4, strip 4
83 83 changeset: 3:65bd5f99a4a3
84 84 tag: tip
85 85 parent: 1:ef3a871183d7
86 86 user: test
87 87 date: Thu Jan 01 00:00:00 1970 +0000
88 88 summary: d
89 89
90 90 $ teststrip 4 3
91 91 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 92 % before update 4, strip 3
93 93 changeset: 4:443431ffac4f
94 94 tag: tip
95 95 user: test
96 96 date: Thu Jan 01 00:00:00 1970 +0000
97 97 summary: e
98 98
99 99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 100 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
101 101 % after update 4, strip 3
102 102 changeset: 1:ef3a871183d7
103 103 user: test
104 104 date: Thu Jan 01 00:00:00 1970 +0000
105 105 summary: b
106 106
107 107 $ teststrip 1 4
108 108 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 109 % before update 1, strip 4
110 110 changeset: 1:ef3a871183d7
111 111 user: test
112 112 date: Thu Jan 01 00:00:00 1970 +0000
113 113 summary: b
114 114
115 115 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
116 116 % after update 1, strip 4
117 117 changeset: 1:ef3a871183d7
118 118 user: test
119 119 date: Thu Jan 01 00:00:00 1970 +0000
120 120 summary: b
121 121
122 122 $ teststrip 4 2
123 123 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
124 124 % before update 4, strip 2
125 125 changeset: 4:443431ffac4f
126 126 tag: tip
127 127 user: test
128 128 date: Thu Jan 01 00:00:00 1970 +0000
129 129 summary: e
130 130
131 131 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
132 132 % after update 4, strip 2
133 133 changeset: 3:443431ffac4f
134 134 tag: tip
135 135 user: test
136 136 date: Thu Jan 01 00:00:00 1970 +0000
137 137 summary: e
138 138
139 139 $ teststrip 4 1
140 140 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 141 % before update 4, strip 1
142 142 changeset: 4:264128213d29
143 143 tag: tip
144 144 parent: 1:ef3a871183d7
145 145 user: test
146 146 date: Thu Jan 01 00:00:00 1970 +0000
147 147 summary: c
148 148
149 149 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
150 150 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
151 151 % after update 4, strip 1
152 152 changeset: 0:9ab35a2d17cb
153 153 tag: tip
154 154 user: test
155 155 date: Thu Jan 01 00:00:00 1970 +0000
156 156 summary: a
157 157
158 158 $ teststrip null 4
159 159 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
160 160 % before update null, strip 4
161 161 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
162 162 % after update null, strip 4
163 163
164 164 $ hg log
165 165 changeset: 4:264128213d29
166 166 tag: tip
167 167 parent: 1:ef3a871183d7
168 168 user: test
169 169 date: Thu Jan 01 00:00:00 1970 +0000
170 170 summary: c
171 171
172 172 changeset: 3:443431ffac4f
173 173 user: test
174 174 date: Thu Jan 01 00:00:00 1970 +0000
175 175 summary: e
176 176
177 177 changeset: 2:65bd5f99a4a3
178 178 user: test
179 179 date: Thu Jan 01 00:00:00 1970 +0000
180 180 summary: d
181 181
182 182 changeset: 1:ef3a871183d7
183 183 user: test
184 184 date: Thu Jan 01 00:00:00 1970 +0000
185 185 summary: b
186 186
187 187 changeset: 0:9ab35a2d17cb
188 188 user: test
189 189 date: Thu Jan 01 00:00:00 1970 +0000
190 190 summary: a
191 191
192 192 $ hg up -C 4
193 193 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
194 194 $ hg parents
195 195 changeset: 4:264128213d29
196 196 tag: tip
197 197 parent: 1:ef3a871183d7
198 198 user: test
199 199 date: Thu Jan 01 00:00:00 1970 +0000
200 200 summary: c
201 201
202 202
203 203 $ hg --traceback strip 4
204 204 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
205 205 saved backup bundle to $TESTTMP/test/.hg/strip-backup/264128213d29-0b39d6bf-backup.hg (glob)
206 206 $ hg parents
207 207 changeset: 1:ef3a871183d7
208 208 user: test
209 209 date: Thu Jan 01 00:00:00 1970 +0000
210 210 summary: b
211 211
212 212 $ hg debugbundle .hg/strip-backup/*
213 213 Stream params: sortdict([('Compression', 'BZ')])
214 changegroup -- "sortdict([('version', '02')])"
214 changegroup -- "sortdict([('version', '02'), ('nbchanges', '1')])"
215 215 264128213d290d868c54642d13aeaa3675551a78
216 216 $ hg pull .hg/strip-backup/*
217 217 pulling from .hg/strip-backup/264128213d29-0b39d6bf-backup.hg
218 218 searching for changes
219 219 adding changesets
220 220 adding manifests
221 221 adding file changes
222 222 added 1 changesets with 0 changes to 0 files (+1 heads)
223 223 (run 'hg heads' to see heads, 'hg merge' to merge)
224 224 $ rm .hg/strip-backup/*
225 225 $ hg log --graph
226 226 o changeset: 4:264128213d29
227 227 | tag: tip
228 228 | parent: 1:ef3a871183d7
229 229 | user: test
230 230 | date: Thu Jan 01 00:00:00 1970 +0000
231 231 | summary: c
232 232 |
233 233 | o changeset: 3:443431ffac4f
234 234 | | user: test
235 235 | | date: Thu Jan 01 00:00:00 1970 +0000
236 236 | | summary: e
237 237 | |
238 238 | o changeset: 2:65bd5f99a4a3
239 239 |/ user: test
240 240 | date: Thu Jan 01 00:00:00 1970 +0000
241 241 | summary: d
242 242 |
243 243 @ changeset: 1:ef3a871183d7
244 244 | user: test
245 245 | date: Thu Jan 01 00:00:00 1970 +0000
246 246 | summary: b
247 247 |
248 248 o changeset: 0:9ab35a2d17cb
249 249 user: test
250 250 date: Thu Jan 01 00:00:00 1970 +0000
251 251 summary: a
252 252
253 253 $ hg up -C 2
254 254 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
255 255 $ hg merge 4
256 256 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
257 257 (branch merge, don't forget to commit)
258 258
259 259 before strip of merge parent
260 260
261 261 $ hg parents
262 262 changeset: 2:65bd5f99a4a3
263 263 user: test
264 264 date: Thu Jan 01 00:00:00 1970 +0000
265 265 summary: d
266 266
267 267 changeset: 4:264128213d29
268 268 tag: tip
269 269 parent: 1:ef3a871183d7
270 270 user: test
271 271 date: Thu Jan 01 00:00:00 1970 +0000
272 272 summary: c
273 273
274 274 $ hg strip 4
275 275 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
276 276 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
277 277
278 278 after strip of merge parent
279 279
280 280 $ hg parents
281 281 changeset: 1:ef3a871183d7
282 282 user: test
283 283 date: Thu Jan 01 00:00:00 1970 +0000
284 284 summary: b
285 285
286 286 $ restore
287 287
288 288 $ hg up
289 289 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
290 290 1 other heads for branch "default"
291 291 $ hg log -G
292 292 @ changeset: 4:264128213d29
293 293 | tag: tip
294 294 | parent: 1:ef3a871183d7
295 295 | user: test
296 296 | date: Thu Jan 01 00:00:00 1970 +0000
297 297 | summary: c
298 298 |
299 299 | o changeset: 3:443431ffac4f
300 300 | | user: test
301 301 | | date: Thu Jan 01 00:00:00 1970 +0000
302 302 | | summary: e
303 303 | |
304 304 | o changeset: 2:65bd5f99a4a3
305 305 |/ user: test
306 306 | date: Thu Jan 01 00:00:00 1970 +0000
307 307 | summary: d
308 308 |
309 309 o changeset: 1:ef3a871183d7
310 310 | user: test
311 311 | date: Thu Jan 01 00:00:00 1970 +0000
312 312 | summary: b
313 313 |
314 314 o changeset: 0:9ab35a2d17cb
315 315 user: test
316 316 date: Thu Jan 01 00:00:00 1970 +0000
317 317 summary: a
318 318
319 319
320 320 2 is parent of 3, only one strip should happen
321 321
322 322 $ hg strip "roots(2)" 3
323 323 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
324 324 $ hg log -G
325 325 @ changeset: 2:264128213d29
326 326 | tag: tip
327 327 | user: test
328 328 | date: Thu Jan 01 00:00:00 1970 +0000
329 329 | summary: c
330 330 |
331 331 o changeset: 1:ef3a871183d7
332 332 | user: test
333 333 | date: Thu Jan 01 00:00:00 1970 +0000
334 334 | summary: b
335 335 |
336 336 o changeset: 0:9ab35a2d17cb
337 337 user: test
338 338 date: Thu Jan 01 00:00:00 1970 +0000
339 339 summary: a
340 340
341 341 $ restore
342 342 $ hg log -G
343 343 o changeset: 4:443431ffac4f
344 344 | tag: tip
345 345 | user: test
346 346 | date: Thu Jan 01 00:00:00 1970 +0000
347 347 | summary: e
348 348 |
349 349 o changeset: 3:65bd5f99a4a3
350 350 | parent: 1:ef3a871183d7
351 351 | user: test
352 352 | date: Thu Jan 01 00:00:00 1970 +0000
353 353 | summary: d
354 354 |
355 355 | @ changeset: 2:264128213d29
356 356 |/ user: test
357 357 | date: Thu Jan 01 00:00:00 1970 +0000
358 358 | summary: c
359 359 |
360 360 o changeset: 1:ef3a871183d7
361 361 | user: test
362 362 | date: Thu Jan 01 00:00:00 1970 +0000
363 363 | summary: b
364 364 |
365 365 o changeset: 0:9ab35a2d17cb
366 366 user: test
367 367 date: Thu Jan 01 00:00:00 1970 +0000
368 368 summary: a
369 369
370 370
371 371 2 different branches: 2 strips
372 372
373 373 $ hg strip 2 4
374 374 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
375 375 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
376 376 $ hg log -G
377 377 o changeset: 2:65bd5f99a4a3
378 378 | tag: tip
379 379 | user: test
380 380 | date: Thu Jan 01 00:00:00 1970 +0000
381 381 | summary: d
382 382 |
383 383 @ changeset: 1:ef3a871183d7
384 384 | user: test
385 385 | date: Thu Jan 01 00:00:00 1970 +0000
386 386 | summary: b
387 387 |
388 388 o changeset: 0:9ab35a2d17cb
389 389 user: test
390 390 date: Thu Jan 01 00:00:00 1970 +0000
391 391 summary: a
392 392
393 393 $ restore
394 394
395 395 2 different branches and a common ancestor: 1 strip
396 396
397 397 $ hg strip 1 "2|4"
398 398 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
399 399 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
400 400 $ restore
401 401
402 402 verify fncache is kept up-to-date
403 403
404 404 $ touch a
405 405 $ hg ci -qAm a
406 406 $ cat .hg/store/fncache | sort
407 407 data/a.i
408 408 data/bar.i
409 409 $ hg strip tip
410 410 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
411 411 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
412 412 $ cat .hg/store/fncache
413 413 data/bar.i
414 414
415 415 stripping an empty revset
416 416
417 417 $ hg strip "1 and not 1"
418 418 abort: empty revision set
419 419 [255]
420 420
421 421 remove branchy history for qimport tests
422 422
423 423 $ hg strip 3
424 424 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
425 425
426 426
427 427 strip of applied mq should cleanup status file
428 428
429 429 $ echo "mq=" >> $HGRCPATH
430 430 $ hg up -C 3
431 431 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
432 432 $ echo fooagain >> bar
433 433 $ hg ci -mf
434 434 $ hg qimport -r tip:2
435 435
436 436 applied patches before strip
437 437
438 438 $ hg qapplied
439 439 d
440 440 e
441 441 f
442 442
443 443 stripping revision in queue
444 444
445 445 $ hg strip 3
446 446 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
447 447 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
448 448
449 449 applied patches after stripping rev in queue
450 450
451 451 $ hg qapplied
452 452 d
453 453
454 454 stripping ancestor of queue
455 455
456 456 $ hg strip 1
457 457 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
458 458 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
459 459
460 460 applied patches after stripping ancestor of queue
461 461
462 462 $ hg qapplied
463 463
464 464 Verify strip protects against stripping wc parent when there are uncommitted mods
465 465
466 466 $ echo b > b
467 467 $ echo bb > bar
468 468 $ hg add b
469 469 $ hg ci -m 'b'
470 470 $ hg log --graph
471 471 @ changeset: 1:76dcf9fab855
472 472 | tag: tip
473 473 | user: test
474 474 | date: Thu Jan 01 00:00:00 1970 +0000
475 475 | summary: b
476 476 |
477 477 o changeset: 0:9ab35a2d17cb
478 478 user: test
479 479 date: Thu Jan 01 00:00:00 1970 +0000
480 480 summary: a
481 481
482 482 $ hg up 0
483 483 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
484 484 $ echo c > bar
485 485 $ hg up -t false
486 486 merging bar
487 487 merging bar failed!
488 488 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
489 489 use 'hg resolve' to retry unresolved file merges
490 490 [1]
491 491 $ hg sum
492 492 parent: 1:76dcf9fab855 tip
493 493 b
494 494 branch: default
495 495 commit: 1 modified, 1 unknown, 1 unresolved
496 496 update: (current)
497 497 phases: 2 draft
498 498 mq: 3 unapplied
499 499
500 500 $ echo c > b
501 501 $ hg strip tip
502 502 abort: local changes found
503 503 [255]
504 504 $ hg strip tip --keep
505 505 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
506 506 $ hg log --graph
507 507 @ changeset: 0:9ab35a2d17cb
508 508 tag: tip
509 509 user: test
510 510 date: Thu Jan 01 00:00:00 1970 +0000
511 511 summary: a
512 512
513 513 $ hg status
514 514 M bar
515 515 ? b
516 516 ? bar.orig
517 517
518 518 $ rm bar.orig
519 519 $ hg sum
520 520 parent: 0:9ab35a2d17cb tip
521 521 a
522 522 branch: default
523 523 commit: 1 modified, 1 unknown
524 524 update: (current)
525 525 phases: 1 draft
526 526 mq: 3 unapplied
527 527
528 528 Strip adds, removes, modifies with --keep
529 529
530 530 $ touch b
531 531 $ hg add b
532 532 $ hg commit -mb
533 533 $ touch c
534 534
535 535 ... with a clean working dir
536 536
537 537 $ hg add c
538 538 $ hg rm bar
539 539 $ hg commit -mc
540 540 $ hg status
541 541 $ hg strip --keep tip
542 542 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
543 543 $ hg status
544 544 ! bar
545 545 ? c
546 546
547 547 ... with a dirty working dir
548 548
549 549 $ hg add c
550 550 $ hg rm bar
551 551 $ hg commit -mc
552 552 $ hg status
553 553 $ echo b > b
554 554 $ echo d > d
555 555 $ hg strip --keep tip
556 556 saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
557 557 $ hg status
558 558 M b
559 559 ! bar
560 560 ? c
561 561 ? d
562 562
563 563 ... after updating the dirstate
564 564 $ hg add c
565 565 $ hg commit -mc
566 566 $ hg rm c
567 567 $ hg commit -mc
568 568 $ hg strip --keep '.^' -q
569 569 $ cd ..
570 570
571 571 stripping many nodes on a complex graph (issue3299)
572 572
573 573 $ hg init issue3299
574 574 $ cd issue3299
575 575 $ hg debugbuilddag '@a.:a@b.:b.:x<a@a.:a<b@b.:b<a@a.:a'
576 576 $ hg strip 'not ancestors(x)'
577 577 saved backup bundle to $TESTTMP/issue3299/.hg/strip-backup/*-backup.hg (glob)
578 578
579 579 test hg strip -B bookmark
580 580
581 581 $ cd ..
582 582 $ hg init bookmarks
583 583 $ cd bookmarks
584 584 $ hg debugbuilddag '..<2.*1/2:m<2+3:c<m+3:a<2.:b<m+2:d<2.:e<m+1:f'
585 585 $ hg bookmark -r 'a' 'todelete'
586 586 $ hg bookmark -r 'b' 'B'
587 587 $ hg bookmark -r 'b' 'nostrip'
588 588 $ hg bookmark -r 'c' 'delete'
589 589 $ hg bookmark -r 'd' 'multipledelete1'
590 590 $ hg bookmark -r 'e' 'multipledelete2'
591 591 $ hg bookmark -r 'f' 'singlenode1'
592 592 $ hg bookmark -r 'f' 'singlenode2'
593 593 $ hg up -C todelete
594 594 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
595 595 (activating bookmark todelete)
596 596 $ hg strip -B nostrip
597 597 bookmark 'nostrip' deleted
598 598 abort: empty revision set
599 599 [255]
600 600 $ hg strip -B todelete
601 601 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
602 602 saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
603 603 bookmark 'todelete' deleted
604 604 $ hg id -ir dcbb326fdec2
605 605 abort: unknown revision 'dcbb326fdec2'!
606 606 [255]
607 607 $ hg id -ir d62d843c9a01
608 608 d62d843c9a01
609 609 $ hg bookmarks
610 610 B 9:ff43616e5d0f
611 611 delete 6:2702dd0c91e7
612 612 multipledelete1 11:e46a4836065c
613 613 multipledelete2 12:b4594d867745
614 614 singlenode1 13:43227190fef8
615 615 singlenode2 13:43227190fef8
616 616 $ hg strip -B multipledelete1 -B multipledelete2
617 617 saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/e46a4836065c-89ec65c2-backup.hg (glob)
618 618 bookmark 'multipledelete1' deleted
619 619 bookmark 'multipledelete2' deleted
620 620 $ hg id -ir e46a4836065c
621 621 abort: unknown revision 'e46a4836065c'!
622 622 [255]
623 623 $ hg id -ir b4594d867745
624 624 abort: unknown revision 'b4594d867745'!
625 625 [255]
626 626 $ hg strip -B singlenode1 -B singlenode2
627 627 saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/43227190fef8-8da858f2-backup.hg (glob)
628 628 bookmark 'singlenode1' deleted
629 629 bookmark 'singlenode2' deleted
630 630 $ hg id -ir 43227190fef8
631 631 abort: unknown revision '43227190fef8'!
632 632 [255]
633 633 $ hg strip -B unknownbookmark
634 634 abort: bookmark 'unknownbookmark' not found
635 635 [255]
636 636 $ hg strip -B unknownbookmark1 -B unknownbookmark2
637 637 abort: bookmark 'unknownbookmark1,unknownbookmark2' not found
638 638 [255]
639 639 $ hg strip -B delete -B unknownbookmark
640 640 abort: bookmark 'unknownbookmark' not found
641 641 [255]
642 642 $ hg strip -B delete
643 643 saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
644 644 bookmark 'delete' deleted
645 645 $ hg id -ir 6:2702dd0c91e7
646 646 abort: unknown revision '2702dd0c91e7'!
647 647 [255]
648 648 $ hg update B
649 649 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
650 650 (activating bookmark B)
651 651 $ echo a > a
652 652 $ hg add a
653 653 $ hg strip -B B
654 654 abort: local changes found
655 655 [255]
656 656 $ hg bookmarks
657 657 * B 6:ff43616e5d0f
658 658
659 659 Make sure no one adds back a -b option:
660 660
661 661 $ hg strip -b tip
662 662 hg strip: option -b not recognized
663 663 hg strip [-k] [-f] [-B bookmark] [-r] REV...
664 664
665 665 strip changesets and all their descendants from the repository
666 666
667 667 (use "hg help -e strip" to show help for the strip extension)
668 668
669 669 options ([+] can be repeated):
670 670
671 671 -r --rev REV [+] strip specified revision (optional, can specify
672 672 revisions without this option)
673 673 -f --force force removal of changesets, discard uncommitted
674 674 changes (no backup)
675 675 --no-backup no backups
676 676 -k --keep do not modify working directory during strip
677 677 -B --bookmark VALUE [+] remove revs only reachable from given bookmark
678 678 --mq operate on patch repository
679 679
680 680 (use "hg strip -h" to show more help)
681 681 [255]
682 682
683 683 $ cd ..
684 684
685 685 Verify bundles don't get overwritten:
686 686
687 687 $ hg init doublebundle
688 688 $ cd doublebundle
689 689 $ touch a
690 690 $ hg commit -Aqm a
691 691 $ touch b
692 692 $ hg commit -Aqm b
693 693 $ hg strip -r 0
694 694 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
695 695 saved backup bundle to $TESTTMP/doublebundle/.hg/strip-backup/3903775176ed-e68910bd-backup.hg (glob)
696 696 $ ls .hg/strip-backup
697 697 3903775176ed-e68910bd-backup.hg
698 698 $ hg pull -q -r 3903775176ed .hg/strip-backup/3903775176ed-e68910bd-backup.hg
699 699 $ hg strip -r 0
700 700 saved backup bundle to $TESTTMP/doublebundle/.hg/strip-backup/3903775176ed-54390173-backup.hg (glob)
701 701 $ ls .hg/strip-backup
702 702 3903775176ed-54390173-backup.hg
703 703 3903775176ed-e68910bd-backup.hg
704 704 $ cd ..
705 705
706 706 Test that we only bundle the stripped changesets (issue4736)
707 707 ------------------------------------------------------------
708 708
709 709 initialization (previous repo is empty anyway)
710 710
711 711 $ hg init issue4736
712 712 $ cd issue4736
713 713 $ echo a > a
714 714 $ hg add a
715 715 $ hg commit -m commitA
716 716 $ echo b > b
717 717 $ hg add b
718 718 $ hg commit -m commitB
719 719 $ echo c > c
720 720 $ hg add c
721 721 $ hg commit -m commitC
722 722 $ hg up 'desc(commitB)'
723 723 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
724 724 $ echo d > d
725 725 $ hg add d
726 726 $ hg commit -m commitD
727 727 created new head
728 728 $ hg up 'desc(commitC)'
729 729 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
730 730 $ hg merge 'desc(commitD)'
731 731 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
732 732 (branch merge, don't forget to commit)
733 733 $ hg ci -m 'mergeCD'
734 734 $ hg log -G
735 735 @ changeset: 4:d8db9d137221
736 736 |\ tag: tip
737 737 | | parent: 2:5c51d8d6557d
738 738 | | parent: 3:6625a5168474
739 739 | | user: test
740 740 | | date: Thu Jan 01 00:00:00 1970 +0000
741 741 | | summary: mergeCD
742 742 | |
743 743 | o changeset: 3:6625a5168474
744 744 | | parent: 1:eca11cf91c71
745 745 | | user: test
746 746 | | date: Thu Jan 01 00:00:00 1970 +0000
747 747 | | summary: commitD
748 748 | |
749 749 o | changeset: 2:5c51d8d6557d
750 750 |/ user: test
751 751 | date: Thu Jan 01 00:00:00 1970 +0000
752 752 | summary: commitC
753 753 |
754 754 o changeset: 1:eca11cf91c71
755 755 | user: test
756 756 | date: Thu Jan 01 00:00:00 1970 +0000
757 757 | summary: commitB
758 758 |
759 759 o changeset: 0:105141ef12d0
760 760 user: test
761 761 date: Thu Jan 01 00:00:00 1970 +0000
762 762 summary: commitA
763 763
764 764
765 765 Check bundle behavior:
766 766
767 767 $ hg bundle -r 'desc(mergeCD)' --base 'desc(commitC)' ../issue4736.hg
768 768 2 changesets found
769 769 $ hg log -r 'bundle()' -R ../issue4736.hg
770 770 changeset: 3:6625a5168474
771 771 parent: 1:eca11cf91c71
772 772 user: test
773 773 date: Thu Jan 01 00:00:00 1970 +0000
774 774 summary: commitD
775 775
776 776 changeset: 4:d8db9d137221
777 777 tag: tip
778 778 parent: 2:5c51d8d6557d
779 779 parent: 3:6625a5168474
780 780 user: test
781 781 date: Thu Jan 01 00:00:00 1970 +0000
782 782 summary: mergeCD
783 783
784 784
785 785 check strip behavior
786 786
787 787 $ hg --config extensions.strip= strip 'desc(commitD)' --debug
788 788 resolving manifests
789 789 branchmerge: False, force: True, partial: False
790 790 ancestor: d8db9d137221+, local: d8db9d137221+, remote: eca11cf91c71
791 791 c: other deleted -> r
792 792 removing c
793 793 d: other deleted -> r
794 794 removing d
795 795 starting 4 threads for background file closing (?)
796 796 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
797 797 2 changesets found
798 798 list of changesets:
799 799 6625a516847449b6f0fa3737b9ba56e9f0f3032c
800 800 d8db9d1372214336d2b5570f20ee468d2c72fa8b
801 801 bundle2-output-bundle: "HG20", (1 params) 1 parts total
802 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
802 bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
803 803 saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/6625a5168474-345bb43d-backup.hg (glob)
804 804 invalid branchheads cache (served): tip differs
805 805 truncating cache/rbc-revs-v1 to 24
806 806 $ hg log -G
807 807 o changeset: 2:5c51d8d6557d
808 808 | tag: tip
809 809 | user: test
810 810 | date: Thu Jan 01 00:00:00 1970 +0000
811 811 | summary: commitC
812 812 |
813 813 @ changeset: 1:eca11cf91c71
814 814 | user: test
815 815 | date: Thu Jan 01 00:00:00 1970 +0000
816 816 | summary: commitB
817 817 |
818 818 o changeset: 0:105141ef12d0
819 819 user: test
820 820 date: Thu Jan 01 00:00:00 1970 +0000
821 821 summary: commitA
822 822
823 823
824 824 strip backup content
825 825
826 826 $ hg log -r 'bundle()' -R .hg/strip-backup/6625a5168474-*-backup.hg
827 827 changeset: 3:6625a5168474
828 828 parent: 1:eca11cf91c71
829 829 user: test
830 830 date: Thu Jan 01 00:00:00 1970 +0000
831 831 summary: commitD
832 832
833 833 changeset: 4:d8db9d137221
834 834 tag: tip
835 835 parent: 2:5c51d8d6557d
836 836 parent: 3:6625a5168474
837 837 user: test
838 838 date: Thu Jan 01 00:00:00 1970 +0000
839 839 summary: mergeCD
840 840
841 841 Check that the phase cache is properly invalidated after a strip with bookmark.
842 842
843 843 $ cat > ../stripstalephasecache.py << EOF
844 844 > from mercurial import extensions, localrepo
845 845 > def transactioncallback(orig, repo, desc, *args, **kwargs):
846 846 > def test(transaction):
847 847 > # observe cache inconsistency
848 848 > try:
849 849 > [repo.changelog.node(r) for r in repo.revs("not public()")]
850 850 > except IndexError:
851 851 > repo.ui.status("Index error!\n")
852 852 > transaction = orig(repo, desc, *args, **kwargs)
853 853 > # warm up the phase cache
854 854 > list(repo.revs("not public()"))
855 855 > if desc != 'strip':
856 856 > transaction.addpostclose("phase invalidation test", test)
857 857 > return transaction
858 858 > def extsetup(ui):
859 859 > extensions.wrapfunction(localrepo.localrepository, "transaction",
860 860 > transactioncallback)
861 861 > EOF
862 862 $ hg up -C 2
863 863 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
864 864 $ echo k > k
865 865 $ hg add k
866 866 $ hg commit -m commitK
867 867 $ echo l > l
868 868 $ hg add l
869 869 $ hg commit -m commitL
870 870 $ hg book -r tip blah
871 871 $ hg strip ".^" --config extensions.crash=$TESTTMP/stripstalephasecache.py
872 872 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
873 873 saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/8f0b4384875c-4fa10deb-backup.hg (glob)
874 874 $ hg up -C 1
875 875 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
876 876
877 877 Error during post-close callback of the strip transaction
878 878 (They should be gracefully handled and reported)
879 879
880 880 $ cat > ../crashstrip.py << EOF
881 881 > from mercurial import error
882 882 > def reposetup(ui, repo):
883 883 > class crashstriprepo(repo.__class__):
884 884 > def transaction(self, desc, *args, **kwargs):
885 885 > tr = super(crashstriprepo, self).transaction(self, desc, *args, **kwargs)
886 886 > if desc == 'strip':
887 887 > def crash(tra): raise error.Abort('boom')
888 888 > tr.addpostclose('crash', crash)
889 889 > return tr
890 890 > repo.__class__ = crashstriprepo
891 891 > EOF
892 892 $ hg strip tip --config extensions.crash=$TESTTMP/crashstrip.py
893 893 saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/5c51d8d6557d-70daef06-backup.hg (glob)
894 894 strip failed, full bundle stored in '$TESTTMP/issue4736/.hg/strip-backup/5c51d8d6557d-70daef06-backup.hg' (glob)
895 895 abort: boom
896 896 [255]
897 897
898 898
General Comments 0
You need to be logged in to leave comments. Login now