##// END OF EJS Templates
obsolete: reports the number of local changeset obsoleted when unbundling...
marmoute -
r33249:53b3a196 default
parent child Browse files
Show More
@@ -1,1848 +1,1850 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 phases,
162 162 pushkey,
163 163 pycompat,
164 scmutil,
164 165 tags,
165 166 url,
166 167 util,
167 168 )
168 169
169 170 urlerr = util.urlerr
170 171 urlreq = util.urlreq
171 172
172 173 _pack = struct.pack
173 174 _unpack = struct.unpack
174 175
175 176 _fstreamparamsize = '>i'
176 177 _fpartheadersize = '>i'
177 178 _fparttypesize = '>B'
178 179 _fpartid = '>I'
179 180 _fpayloadsize = '>i'
180 181 _fpartparamcount = '>BB'
181 182
182 183 _fphasesentry = '>i20s'
183 184
184 185 preferedchunksize = 4096
185 186
186 187 _parttypeforbidden = re.compile('[^a-zA-Z0-9_:-]')
187 188
188 189 def outdebug(ui, message):
189 190 """debug regarding output stream (bundling)"""
190 191 if ui.configbool('devel', 'bundle2.debug'):
191 192 ui.debug('bundle2-output: %s\n' % message)
192 193
193 194 def indebug(ui, message):
194 195 """debug on input stream (unbundling)"""
195 196 if ui.configbool('devel', 'bundle2.debug'):
196 197 ui.debug('bundle2-input: %s\n' % message)
197 198
198 199 def validateparttype(parttype):
199 200 """raise ValueError if a parttype contains invalid character"""
200 201 if _parttypeforbidden.search(parttype):
201 202 raise ValueError(parttype)
202 203
203 204 def _makefpartparamsizes(nbparams):
204 205 """return a struct format to read part parameter sizes
205 206
206 207 The number parameters is variable so we need to build that format
207 208 dynamically.
208 209 """
209 210 return '>'+('BB'*nbparams)
210 211
211 212 parthandlermapping = {}
212 213
213 214 def parthandler(parttype, params=()):
214 215 """decorator that register a function as a bundle2 part handler
215 216
216 217 eg::
217 218
218 219 @parthandler('myparttype', ('mandatory', 'param', 'handled'))
219 220 def myparttypehandler(...):
220 221 '''process a part of type "my part".'''
221 222 ...
222 223 """
223 224 validateparttype(parttype)
224 225 def _decorator(func):
225 226 lparttype = parttype.lower() # enforce lower case matching.
226 227 assert lparttype not in parthandlermapping
227 228 parthandlermapping[lparttype] = func
228 229 func.params = frozenset(params)
229 230 return func
230 231 return _decorator
231 232
232 233 class unbundlerecords(object):
233 234 """keep record of what happens during and unbundle
234 235
235 236 New records are added using `records.add('cat', obj)`. Where 'cat' is a
236 237 category of record and obj is an arbitrary object.
237 238
238 239 `records['cat']` will return all entries of this category 'cat'.
239 240
240 241 Iterating on the object itself will yield `('category', obj)` tuples
241 242 for all entries.
242 243
243 244 All iterations happens in chronological order.
244 245 """
245 246
246 247 def __init__(self):
247 248 self._categories = {}
248 249 self._sequences = []
249 250 self._replies = {}
250 251
251 252 def add(self, category, entry, inreplyto=None):
252 253 """add a new record of a given category.
253 254
254 255 The entry can then be retrieved in the list returned by
255 256 self['category']."""
256 257 self._categories.setdefault(category, []).append(entry)
257 258 self._sequences.append((category, entry))
258 259 if inreplyto is not None:
259 260 self.getreplies(inreplyto).add(category, entry)
260 261
261 262 def getreplies(self, partid):
262 263 """get the records that are replies to a specific part"""
263 264 return self._replies.setdefault(partid, unbundlerecords())
264 265
265 266 def __getitem__(self, cat):
266 267 return tuple(self._categories.get(cat, ()))
267 268
268 269 def __iter__(self):
269 270 return iter(self._sequences)
270 271
271 272 def __len__(self):
272 273 return len(self._sequences)
273 274
274 275 def __nonzero__(self):
275 276 return bool(self._sequences)
276 277
277 278 __bool__ = __nonzero__
278 279
279 280 class bundleoperation(object):
280 281 """an object that represents a single bundling process
281 282
282 283 Its purpose is to carry unbundle-related objects and states.
283 284
284 285 A new object should be created at the beginning of each bundle processing.
285 286 The object is to be returned by the processing function.
286 287
287 288 The object has very little content now it will ultimately contain:
288 289 * an access to the repo the bundle is applied to,
289 290 * a ui object,
290 291 * a way to retrieve a transaction to add changes to the repo,
291 292 * a way to record the result of processing each part,
292 293 * a way to construct a bundle response when applicable.
293 294 """
294 295
295 296 def __init__(self, repo, transactiongetter, captureoutput=True):
296 297 self.repo = repo
297 298 self.ui = repo.ui
298 299 self.records = unbundlerecords()
299 300 self.gettransaction = transactiongetter
300 301 self.reply = None
301 302 self.captureoutput = captureoutput
302 303
303 304 class TransactionUnavailable(RuntimeError):
304 305 pass
305 306
306 307 def _notransaction():
307 308 """default method to get a transaction while processing a bundle
308 309
309 310 Raise an exception to highlight the fact that no transaction was expected
310 311 to be created"""
311 312 raise TransactionUnavailable()
312 313
313 314 def applybundle(repo, unbundler, tr, source=None, url=None, **kwargs):
314 315 # transform me into unbundler.apply() as soon as the freeze is lifted
315 316 if isinstance(unbundler, unbundle20):
316 317 tr.hookargs['bundle2'] = '1'
317 318 if source is not None and 'source' not in tr.hookargs:
318 319 tr.hookargs['source'] = source
319 320 if url is not None and 'url' not in tr.hookargs:
320 321 tr.hookargs['url'] = url
321 322 return processbundle(repo, unbundler, lambda: tr)
322 323 else:
323 324 # the transactiongetter won't be used, but we might as well set it
324 325 op = bundleoperation(repo, lambda: tr)
325 326 _processchangegroup(op, unbundler, tr, source, url, **kwargs)
326 327 return op
327 328
328 329 def processbundle(repo, unbundler, transactiongetter=None, op=None):
329 330 """This function process a bundle, apply effect to/from a repo
330 331
331 332 It iterates over each part then searches for and uses the proper handling
332 333 code to process the part. Parts are processed in order.
333 334
334 335 Unknown Mandatory part will abort the process.
335 336
336 337 It is temporarily possible to provide a prebuilt bundleoperation to the
337 338 function. This is used to ensure output is properly propagated in case of
338 339 an error during the unbundling. This output capturing part will likely be
339 340 reworked and this ability will probably go away in the process.
340 341 """
341 342 if op is None:
342 343 if transactiongetter is None:
343 344 transactiongetter = _notransaction
344 345 op = bundleoperation(repo, transactiongetter)
345 346 # todo:
346 347 # - replace this is a init function soon.
347 348 # - exception catching
348 349 unbundler.params
349 350 if repo.ui.debugflag:
350 351 msg = ['bundle2-input-bundle:']
351 352 if unbundler.params:
352 353 msg.append(' %i params' % len(unbundler.params))
353 354 if op.gettransaction is None or op.gettransaction is _notransaction:
354 355 msg.append(' no-transaction')
355 356 else:
356 357 msg.append(' with-transaction')
357 358 msg.append('\n')
358 359 repo.ui.debug(''.join(msg))
359 360 iterparts = enumerate(unbundler.iterparts())
360 361 part = None
361 362 nbpart = 0
362 363 try:
363 364 for nbpart, part in iterparts:
364 365 _processpart(op, part)
365 366 except Exception as exc:
366 367 # Any exceptions seeking to the end of the bundle at this point are
367 368 # almost certainly related to the underlying stream being bad.
368 369 # And, chances are that the exception we're handling is related to
369 370 # getting in that bad state. So, we swallow the seeking error and
370 371 # re-raise the original error.
371 372 seekerror = False
372 373 try:
373 374 for nbpart, part in iterparts:
374 375 # consume the bundle content
375 376 part.seek(0, 2)
376 377 except Exception:
377 378 seekerror = True
378 379
379 380 # Small hack to let caller code distinguish exceptions from bundle2
380 381 # processing from processing the old format. This is mostly
381 382 # needed to handle different return codes to unbundle according to the
382 383 # type of bundle. We should probably clean up or drop this return code
383 384 # craziness in a future version.
384 385 exc.duringunbundle2 = True
385 386 salvaged = []
386 387 replycaps = None
387 388 if op.reply is not None:
388 389 salvaged = op.reply.salvageoutput()
389 390 replycaps = op.reply.capabilities
390 391 exc._replycaps = replycaps
391 392 exc._bundle2salvagedoutput = salvaged
392 393
393 394 # Re-raising from a variable loses the original stack. So only use
394 395 # that form if we need to.
395 396 if seekerror:
396 397 raise exc
397 398 else:
398 399 raise
399 400 finally:
400 401 repo.ui.debug('bundle2-input-bundle: %i parts total\n' % nbpart)
401 402
402 403 return op
403 404
404 405 def _processchangegroup(op, cg, tr, source, url, **kwargs):
405 406 ret, addednodes = cg.apply(op.repo, tr, source, url, **kwargs)
406 407 op.records.add('changegroup', {
407 408 'return': ret,
408 409 'addednodes': addednodes,
409 410 })
410 411 return ret
411 412
412 413 def _processpart(op, part):
413 414 """process a single part from a bundle
414 415
415 416 The part is guaranteed to have been fully consumed when the function exits
416 417 (even if an exception is raised)."""
417 418 status = 'unknown' # used by debug output
418 419 hardabort = False
419 420 try:
420 421 try:
421 422 handler = parthandlermapping.get(part.type)
422 423 if handler is None:
423 424 status = 'unsupported-type'
424 425 raise error.BundleUnknownFeatureError(parttype=part.type)
425 426 indebug(op.ui, 'found a handler for part %r' % part.type)
426 427 unknownparams = part.mandatorykeys - handler.params
427 428 if unknownparams:
428 429 unknownparams = list(unknownparams)
429 430 unknownparams.sort()
430 431 status = 'unsupported-params (%s)' % unknownparams
431 432 raise error.BundleUnknownFeatureError(parttype=part.type,
432 433 params=unknownparams)
433 434 status = 'supported'
434 435 except error.BundleUnknownFeatureError as exc:
435 436 if part.mandatory: # mandatory parts
436 437 raise
437 438 indebug(op.ui, 'ignoring unsupported advisory part %s' % exc)
438 439 return # skip to part processing
439 440 finally:
440 441 if op.ui.debugflag:
441 442 msg = ['bundle2-input-part: "%s"' % part.type]
442 443 if not part.mandatory:
443 444 msg.append(' (advisory)')
444 445 nbmp = len(part.mandatorykeys)
445 446 nbap = len(part.params) - nbmp
446 447 if nbmp or nbap:
447 448 msg.append(' (params:')
448 449 if nbmp:
449 450 msg.append(' %i mandatory' % nbmp)
450 451 if nbap:
451 452 msg.append(' %i advisory' % nbmp)
452 453 msg.append(')')
453 454 msg.append(' %s\n' % status)
454 455 op.ui.debug(''.join(msg))
455 456
456 457 # handler is called outside the above try block so that we don't
457 458 # risk catching KeyErrors from anything other than the
458 459 # parthandlermapping lookup (any KeyError raised by handler()
459 460 # itself represents a defect of a different variety).
460 461 output = None
461 462 if op.captureoutput and op.reply is not None:
462 463 op.ui.pushbuffer(error=True, subproc=True)
463 464 output = ''
464 465 try:
465 466 handler(op, part)
466 467 finally:
467 468 if output is not None:
468 469 output = op.ui.popbuffer()
469 470 if output:
470 471 outpart = op.reply.newpart('output', data=output,
471 472 mandatory=False)
472 473 outpart.addparam('in-reply-to', str(part.id), mandatory=False)
473 474 # If exiting or interrupted, do not attempt to seek the stream in the
474 475 # finally block below. This makes abort faster.
475 476 except (SystemExit, KeyboardInterrupt):
476 477 hardabort = True
477 478 raise
478 479 finally:
479 480 # consume the part content to not corrupt the stream.
480 481 if not hardabort:
481 482 part.seek(0, 2)
482 483
483 484
484 485 def decodecaps(blob):
485 486 """decode a bundle2 caps bytes blob into a dictionary
486 487
487 488 The blob is a list of capabilities (one per line)
488 489 Capabilities may have values using a line of the form::
489 490
490 491 capability=value1,value2,value3
491 492
492 493 The values are always a list."""
493 494 caps = {}
494 495 for line in blob.splitlines():
495 496 if not line:
496 497 continue
497 498 if '=' not in line:
498 499 key, vals = line, ()
499 500 else:
500 501 key, vals = line.split('=', 1)
501 502 vals = vals.split(',')
502 503 key = urlreq.unquote(key)
503 504 vals = [urlreq.unquote(v) for v in vals]
504 505 caps[key] = vals
505 506 return caps
506 507
507 508 def encodecaps(caps):
508 509 """encode a bundle2 caps dictionary into a bytes blob"""
509 510 chunks = []
510 511 for ca in sorted(caps):
511 512 vals = caps[ca]
512 513 ca = urlreq.quote(ca)
513 514 vals = [urlreq.quote(v) for v in vals]
514 515 if vals:
515 516 ca = "%s=%s" % (ca, ','.join(vals))
516 517 chunks.append(ca)
517 518 return '\n'.join(chunks)
518 519
519 520 bundletypes = {
520 521 "": ("", 'UN'), # only when using unbundle on ssh and old http servers
521 522 # since the unification ssh accepts a header but there
522 523 # is no capability signaling it.
523 524 "HG20": (), # special-cased below
524 525 "HG10UN": ("HG10UN", 'UN'),
525 526 "HG10BZ": ("HG10", 'BZ'),
526 527 "HG10GZ": ("HG10GZ", 'GZ'),
527 528 }
528 529
529 530 # hgweb uses this list to communicate its preferred type
530 531 bundlepriority = ['HG10GZ', 'HG10BZ', 'HG10UN']
531 532
532 533 class bundle20(object):
533 534 """represent an outgoing bundle2 container
534 535
535 536 Use the `addparam` method to add stream level parameter. and `newpart` to
536 537 populate it. Then call `getchunks` to retrieve all the binary chunks of
537 538 data that compose the bundle2 container."""
538 539
539 540 _magicstring = 'HG20'
540 541
541 542 def __init__(self, ui, capabilities=()):
542 543 self.ui = ui
543 544 self._params = []
544 545 self._parts = []
545 546 self.capabilities = dict(capabilities)
546 547 self._compengine = util.compengines.forbundletype('UN')
547 548 self._compopts = None
548 549
549 550 def setcompression(self, alg, compopts=None):
550 551 """setup core part compression to <alg>"""
551 552 if alg in (None, 'UN'):
552 553 return
553 554 assert not any(n.lower() == 'compression' for n, v in self._params)
554 555 self.addparam('Compression', alg)
555 556 self._compengine = util.compengines.forbundletype(alg)
556 557 self._compopts = compopts
557 558
558 559 @property
559 560 def nbparts(self):
560 561 """total number of parts added to the bundler"""
561 562 return len(self._parts)
562 563
563 564 # methods used to defines the bundle2 content
564 565 def addparam(self, name, value=None):
565 566 """add a stream level parameter"""
566 567 if not name:
567 568 raise ValueError('empty parameter name')
568 569 if name[0] not in string.letters:
569 570 raise ValueError('non letter first character: %r' % name)
570 571 self._params.append((name, value))
571 572
572 573 def addpart(self, part):
573 574 """add a new part to the bundle2 container
574 575
575 576 Parts contains the actual applicative payload."""
576 577 assert part.id is None
577 578 part.id = len(self._parts) # very cheap counter
578 579 self._parts.append(part)
579 580
580 581 def newpart(self, typeid, *args, **kwargs):
581 582 """create a new part and add it to the containers
582 583
583 584 As the part is directly added to the containers. For now, this means
584 585 that any failure to properly initialize the part after calling
585 586 ``newpart`` should result in a failure of the whole bundling process.
586 587
587 588 You can still fall back to manually create and add if you need better
588 589 control."""
589 590 part = bundlepart(typeid, *args, **kwargs)
590 591 self.addpart(part)
591 592 return part
592 593
593 594 # methods used to generate the bundle2 stream
594 595 def getchunks(self):
595 596 if self.ui.debugflag:
596 597 msg = ['bundle2-output-bundle: "%s",' % self._magicstring]
597 598 if self._params:
598 599 msg.append(' (%i params)' % len(self._params))
599 600 msg.append(' %i parts total\n' % len(self._parts))
600 601 self.ui.debug(''.join(msg))
601 602 outdebug(self.ui, 'start emission of %s stream' % self._magicstring)
602 603 yield self._magicstring
603 604 param = self._paramchunk()
604 605 outdebug(self.ui, 'bundle parameter: %s' % param)
605 606 yield _pack(_fstreamparamsize, len(param))
606 607 if param:
607 608 yield param
608 609 for chunk in self._compengine.compressstream(self._getcorechunk(),
609 610 self._compopts):
610 611 yield chunk
611 612
612 613 def _paramchunk(self):
613 614 """return a encoded version of all stream parameters"""
614 615 blocks = []
615 616 for par, value in self._params:
616 617 par = urlreq.quote(par)
617 618 if value is not None:
618 619 value = urlreq.quote(value)
619 620 par = '%s=%s' % (par, value)
620 621 blocks.append(par)
621 622 return ' '.join(blocks)
622 623
623 624 def _getcorechunk(self):
624 625 """yield chunk for the core part of the bundle
625 626
626 627 (all but headers and parameters)"""
627 628 outdebug(self.ui, 'start of parts')
628 629 for part in self._parts:
629 630 outdebug(self.ui, 'bundle part: "%s"' % part.type)
630 631 for chunk in part.getchunks(ui=self.ui):
631 632 yield chunk
632 633 outdebug(self.ui, 'end of bundle')
633 634 yield _pack(_fpartheadersize, 0)
634 635
635 636
636 637 def salvageoutput(self):
637 638 """return a list with a copy of all output parts in the bundle
638 639
639 640 This is meant to be used during error handling to make sure we preserve
640 641 server output"""
641 642 salvaged = []
642 643 for part in self._parts:
643 644 if part.type.startswith('output'):
644 645 salvaged.append(part.copy())
645 646 return salvaged
646 647
647 648
648 649 class unpackermixin(object):
649 650 """A mixin to extract bytes and struct data from a stream"""
650 651
651 652 def __init__(self, fp):
652 653 self._fp = fp
653 654
654 655 def _unpack(self, format):
655 656 """unpack this struct format from the stream
656 657
657 658 This method is meant for internal usage by the bundle2 protocol only.
658 659 They directly manipulate the low level stream including bundle2 level
659 660 instruction.
660 661
661 662 Do not use it to implement higher-level logic or methods."""
662 663 data = self._readexact(struct.calcsize(format))
663 664 return _unpack(format, data)
664 665
665 666 def _readexact(self, size):
666 667 """read exactly <size> bytes from the stream
667 668
668 669 This method is meant for internal usage by the bundle2 protocol only.
669 670 They directly manipulate the low level stream including bundle2 level
670 671 instruction.
671 672
672 673 Do not use it to implement higher-level logic or methods."""
673 674 return changegroup.readexactly(self._fp, size)
674 675
675 676 def getunbundler(ui, fp, magicstring=None):
676 677 """return a valid unbundler object for a given magicstring"""
677 678 if magicstring is None:
678 679 magicstring = changegroup.readexactly(fp, 4)
679 680 magic, version = magicstring[0:2], magicstring[2:4]
680 681 if magic != 'HG':
681 682 ui.debug(
682 683 "error: invalid magic: %r (version %r), should be 'HG'\n"
683 684 % (magic, version))
684 685 raise error.Abort(_('not a Mercurial bundle'))
685 686 unbundlerclass = formatmap.get(version)
686 687 if unbundlerclass is None:
687 688 raise error.Abort(_('unknown bundle version %s') % version)
688 689 unbundler = unbundlerclass(ui, fp)
689 690 indebug(ui, 'start processing of %s stream' % magicstring)
690 691 return unbundler
691 692
692 693 class unbundle20(unpackermixin):
693 694 """interpret a bundle2 stream
694 695
695 696 This class is fed with a binary stream and yields parts through its
696 697 `iterparts` methods."""
697 698
698 699 _magicstring = 'HG20'
699 700
700 701 def __init__(self, ui, fp):
701 702 """If header is specified, we do not read it out of the stream."""
702 703 self.ui = ui
703 704 self._compengine = util.compengines.forbundletype('UN')
704 705 self._compressed = None
705 706 super(unbundle20, self).__init__(fp)
706 707
707 708 @util.propertycache
708 709 def params(self):
709 710 """dictionary of stream level parameters"""
710 711 indebug(self.ui, 'reading bundle2 stream parameters')
711 712 params = {}
712 713 paramssize = self._unpack(_fstreamparamsize)[0]
713 714 if paramssize < 0:
714 715 raise error.BundleValueError('negative bundle param size: %i'
715 716 % paramssize)
716 717 if paramssize:
717 718 params = self._readexact(paramssize)
718 719 params = self._processallparams(params)
719 720 return params
720 721
721 722 def _processallparams(self, paramsblock):
722 723 """"""
723 724 params = util.sortdict()
724 725 for p in paramsblock.split(' '):
725 726 p = p.split('=', 1)
726 727 p = [urlreq.unquote(i) for i in p]
727 728 if len(p) < 2:
728 729 p.append(None)
729 730 self._processparam(*p)
730 731 params[p[0]] = p[1]
731 732 return params
732 733
733 734
734 735 def _processparam(self, name, value):
735 736 """process a parameter, applying its effect if needed
736 737
737 738 Parameter starting with a lower case letter are advisory and will be
738 739 ignored when unknown. Those starting with an upper case letter are
739 740 mandatory and will this function will raise a KeyError when unknown.
740 741
741 742 Note: no option are currently supported. Any input will be either
742 743 ignored or failing.
743 744 """
744 745 if not name:
745 746 raise ValueError('empty parameter name')
746 747 if name[0] not in string.letters:
747 748 raise ValueError('non letter first character: %r' % name)
748 749 try:
749 750 handler = b2streamparamsmap[name.lower()]
750 751 except KeyError:
751 752 if name[0].islower():
752 753 indebug(self.ui, "ignoring unknown parameter %r" % name)
753 754 else:
754 755 raise error.BundleUnknownFeatureError(params=(name,))
755 756 else:
756 757 handler(self, name, value)
757 758
758 759 def _forwardchunks(self):
759 760 """utility to transfer a bundle2 as binary
760 761
761 762 This is made necessary by the fact the 'getbundle' command over 'ssh'
762 763 have no way to know then the reply end, relying on the bundle to be
763 764 interpreted to know its end. This is terrible and we are sorry, but we
764 765 needed to move forward to get general delta enabled.
765 766 """
766 767 yield self._magicstring
767 768 assert 'params' not in vars(self)
768 769 paramssize = self._unpack(_fstreamparamsize)[0]
769 770 if paramssize < 0:
770 771 raise error.BundleValueError('negative bundle param size: %i'
771 772 % paramssize)
772 773 yield _pack(_fstreamparamsize, paramssize)
773 774 if paramssize:
774 775 params = self._readexact(paramssize)
775 776 self._processallparams(params)
776 777 yield params
777 778 assert self._compengine.bundletype == 'UN'
778 779 # From there, payload might need to be decompressed
779 780 self._fp = self._compengine.decompressorreader(self._fp)
780 781 emptycount = 0
781 782 while emptycount < 2:
782 783 # so we can brainlessly loop
783 784 assert _fpartheadersize == _fpayloadsize
784 785 size = self._unpack(_fpartheadersize)[0]
785 786 yield _pack(_fpartheadersize, size)
786 787 if size:
787 788 emptycount = 0
788 789 else:
789 790 emptycount += 1
790 791 continue
791 792 if size == flaginterrupt:
792 793 continue
793 794 elif size < 0:
794 795 raise error.BundleValueError('negative chunk size: %i')
795 796 yield self._readexact(size)
796 797
797 798
798 799 def iterparts(self):
799 800 """yield all parts contained in the stream"""
800 801 # make sure param have been loaded
801 802 self.params
802 803 # From there, payload need to be decompressed
803 804 self._fp = self._compengine.decompressorreader(self._fp)
804 805 indebug(self.ui, 'start extraction of bundle2 parts')
805 806 headerblock = self._readpartheader()
806 807 while headerblock is not None:
807 808 part = unbundlepart(self.ui, headerblock, self._fp)
808 809 yield part
809 810 part.seek(0, 2)
810 811 headerblock = self._readpartheader()
811 812 indebug(self.ui, 'end of bundle2 stream')
812 813
813 814 def _readpartheader(self):
814 815 """reads a part header size and return the bytes blob
815 816
816 817 returns None if empty"""
817 818 headersize = self._unpack(_fpartheadersize)[0]
818 819 if headersize < 0:
819 820 raise error.BundleValueError('negative part header size: %i'
820 821 % headersize)
821 822 indebug(self.ui, 'part header size: %i' % headersize)
822 823 if headersize:
823 824 return self._readexact(headersize)
824 825 return None
825 826
826 827 def compressed(self):
827 828 self.params # load params
828 829 return self._compressed
829 830
830 831 def close(self):
831 832 """close underlying file"""
832 833 if util.safehasattr(self._fp, 'close'):
833 834 return self._fp.close()
834 835
835 836 formatmap = {'20': unbundle20}
836 837
837 838 b2streamparamsmap = {}
838 839
839 840 def b2streamparamhandler(name):
840 841 """register a handler for a stream level parameter"""
841 842 def decorator(func):
842 843 assert name not in formatmap
843 844 b2streamparamsmap[name] = func
844 845 return func
845 846 return decorator
846 847
847 848 @b2streamparamhandler('compression')
848 849 def processcompression(unbundler, param, value):
849 850 """read compression parameter and install payload decompression"""
850 851 if value not in util.compengines.supportedbundletypes:
851 852 raise error.BundleUnknownFeatureError(params=(param,),
852 853 values=(value,))
853 854 unbundler._compengine = util.compengines.forbundletype(value)
854 855 if value is not None:
855 856 unbundler._compressed = True
856 857
857 858 class bundlepart(object):
858 859 """A bundle2 part contains application level payload
859 860
860 861 The part `type` is used to route the part to the application level
861 862 handler.
862 863
863 864 The part payload is contained in ``part.data``. It could be raw bytes or a
864 865 generator of byte chunks.
865 866
866 867 You can add parameters to the part using the ``addparam`` method.
867 868 Parameters can be either mandatory (default) or advisory. Remote side
868 869 should be able to safely ignore the advisory ones.
869 870
870 871 Both data and parameters cannot be modified after the generation has begun.
871 872 """
872 873
873 874 def __init__(self, parttype, mandatoryparams=(), advisoryparams=(),
874 875 data='', mandatory=True):
875 876 validateparttype(parttype)
876 877 self.id = None
877 878 self.type = parttype
878 879 self._data = data
879 880 self._mandatoryparams = list(mandatoryparams)
880 881 self._advisoryparams = list(advisoryparams)
881 882 # checking for duplicated entries
882 883 self._seenparams = set()
883 884 for pname, __ in self._mandatoryparams + self._advisoryparams:
884 885 if pname in self._seenparams:
885 886 raise error.ProgrammingError('duplicated params: %s' % pname)
886 887 self._seenparams.add(pname)
887 888 # status of the part's generation:
888 889 # - None: not started,
889 890 # - False: currently generated,
890 891 # - True: generation done.
891 892 self._generated = None
892 893 self.mandatory = mandatory
893 894
894 895 def __repr__(self):
895 896 cls = "%s.%s" % (self.__class__.__module__, self.__class__.__name__)
896 897 return ('<%s object at %x; id: %s; type: %s; mandatory: %s>'
897 898 % (cls, id(self), self.id, self.type, self.mandatory))
898 899
899 900 def copy(self):
900 901 """return a copy of the part
901 902
902 903 The new part have the very same content but no partid assigned yet.
903 904 Parts with generated data cannot be copied."""
904 905 assert not util.safehasattr(self.data, 'next')
905 906 return self.__class__(self.type, self._mandatoryparams,
906 907 self._advisoryparams, self._data, self.mandatory)
907 908
908 909 # methods used to defines the part content
909 910 @property
910 911 def data(self):
911 912 return self._data
912 913
913 914 @data.setter
914 915 def data(self, data):
915 916 if self._generated is not None:
916 917 raise error.ReadOnlyPartError('part is being generated')
917 918 self._data = data
918 919
919 920 @property
920 921 def mandatoryparams(self):
921 922 # make it an immutable tuple to force people through ``addparam``
922 923 return tuple(self._mandatoryparams)
923 924
924 925 @property
925 926 def advisoryparams(self):
926 927 # make it an immutable tuple to force people through ``addparam``
927 928 return tuple(self._advisoryparams)
928 929
929 930 def addparam(self, name, value='', mandatory=True):
930 931 """add a parameter to the part
931 932
932 933 If 'mandatory' is set to True, the remote handler must claim support
933 934 for this parameter or the unbundling will be aborted.
934 935
935 936 The 'name' and 'value' cannot exceed 255 bytes each.
936 937 """
937 938 if self._generated is not None:
938 939 raise error.ReadOnlyPartError('part is being generated')
939 940 if name in self._seenparams:
940 941 raise ValueError('duplicated params: %s' % name)
941 942 self._seenparams.add(name)
942 943 params = self._advisoryparams
943 944 if mandatory:
944 945 params = self._mandatoryparams
945 946 params.append((name, value))
946 947
947 948 # methods used to generates the bundle2 stream
948 949 def getchunks(self, ui):
949 950 if self._generated is not None:
950 951 raise error.ProgrammingError('part can only be consumed once')
951 952 self._generated = False
952 953
953 954 if ui.debugflag:
954 955 msg = ['bundle2-output-part: "%s"' % self.type]
955 956 if not self.mandatory:
956 957 msg.append(' (advisory)')
957 958 nbmp = len(self.mandatoryparams)
958 959 nbap = len(self.advisoryparams)
959 960 if nbmp or nbap:
960 961 msg.append(' (params:')
961 962 if nbmp:
962 963 msg.append(' %i mandatory' % nbmp)
963 964 if nbap:
964 965 msg.append(' %i advisory' % nbmp)
965 966 msg.append(')')
966 967 if not self.data:
967 968 msg.append(' empty payload')
968 969 elif util.safehasattr(self.data, 'next'):
969 970 msg.append(' streamed payload')
970 971 else:
971 972 msg.append(' %i bytes payload' % len(self.data))
972 973 msg.append('\n')
973 974 ui.debug(''.join(msg))
974 975
975 976 #### header
976 977 if self.mandatory:
977 978 parttype = self.type.upper()
978 979 else:
979 980 parttype = self.type.lower()
980 981 outdebug(ui, 'part %s: "%s"' % (self.id, parttype))
981 982 ## parttype
982 983 header = [_pack(_fparttypesize, len(parttype)),
983 984 parttype, _pack(_fpartid, self.id),
984 985 ]
985 986 ## parameters
986 987 # count
987 988 manpar = self.mandatoryparams
988 989 advpar = self.advisoryparams
989 990 header.append(_pack(_fpartparamcount, len(manpar), len(advpar)))
990 991 # size
991 992 parsizes = []
992 993 for key, value in manpar:
993 994 parsizes.append(len(key))
994 995 parsizes.append(len(value))
995 996 for key, value in advpar:
996 997 parsizes.append(len(key))
997 998 parsizes.append(len(value))
998 999 paramsizes = _pack(_makefpartparamsizes(len(parsizes) / 2), *parsizes)
999 1000 header.append(paramsizes)
1000 1001 # key, value
1001 1002 for key, value in manpar:
1002 1003 header.append(key)
1003 1004 header.append(value)
1004 1005 for key, value in advpar:
1005 1006 header.append(key)
1006 1007 header.append(value)
1007 1008 ## finalize header
1008 1009 headerchunk = ''.join(header)
1009 1010 outdebug(ui, 'header chunk size: %i' % len(headerchunk))
1010 1011 yield _pack(_fpartheadersize, len(headerchunk))
1011 1012 yield headerchunk
1012 1013 ## payload
1013 1014 try:
1014 1015 for chunk in self._payloadchunks():
1015 1016 outdebug(ui, 'payload chunk size: %i' % len(chunk))
1016 1017 yield _pack(_fpayloadsize, len(chunk))
1017 1018 yield chunk
1018 1019 except GeneratorExit:
1019 1020 # GeneratorExit means that nobody is listening for our
1020 1021 # results anyway, so just bail quickly rather than trying
1021 1022 # to produce an error part.
1022 1023 ui.debug('bundle2-generatorexit\n')
1023 1024 raise
1024 1025 except BaseException as exc:
1025 1026 # backup exception data for later
1026 1027 ui.debug('bundle2-input-stream-interrupt: encoding exception %s'
1027 1028 % exc)
1028 1029 tb = sys.exc_info()[2]
1029 1030 msg = 'unexpected error: %s' % exc
1030 1031 interpart = bundlepart('error:abort', [('message', msg)],
1031 1032 mandatory=False)
1032 1033 interpart.id = 0
1033 1034 yield _pack(_fpayloadsize, -1)
1034 1035 for chunk in interpart.getchunks(ui=ui):
1035 1036 yield chunk
1036 1037 outdebug(ui, 'closing payload chunk')
1037 1038 # abort current part payload
1038 1039 yield _pack(_fpayloadsize, 0)
1039 1040 pycompat.raisewithtb(exc, tb)
1040 1041 # end of payload
1041 1042 outdebug(ui, 'closing payload chunk')
1042 1043 yield _pack(_fpayloadsize, 0)
1043 1044 self._generated = True
1044 1045
1045 1046 def _payloadchunks(self):
1046 1047 """yield chunks of a the part payload
1047 1048
1048 1049 Exists to handle the different methods to provide data to a part."""
1049 1050 # we only support fixed size data now.
1050 1051 # This will be improved in the future.
1051 1052 if util.safehasattr(self.data, 'next'):
1052 1053 buff = util.chunkbuffer(self.data)
1053 1054 chunk = buff.read(preferedchunksize)
1054 1055 while chunk:
1055 1056 yield chunk
1056 1057 chunk = buff.read(preferedchunksize)
1057 1058 elif len(self.data):
1058 1059 yield self.data
1059 1060
1060 1061
1061 1062 flaginterrupt = -1
1062 1063
1063 1064 class interrupthandler(unpackermixin):
1064 1065 """read one part and process it with restricted capability
1065 1066
1066 1067 This allows to transmit exception raised on the producer size during part
1067 1068 iteration while the consumer is reading a part.
1068 1069
1069 1070 Part processed in this manner only have access to a ui object,"""
1070 1071
1071 1072 def __init__(self, ui, fp):
1072 1073 super(interrupthandler, self).__init__(fp)
1073 1074 self.ui = ui
1074 1075
1075 1076 def _readpartheader(self):
1076 1077 """reads a part header size and return the bytes blob
1077 1078
1078 1079 returns None if empty"""
1079 1080 headersize = self._unpack(_fpartheadersize)[0]
1080 1081 if headersize < 0:
1081 1082 raise error.BundleValueError('negative part header size: %i'
1082 1083 % headersize)
1083 1084 indebug(self.ui, 'part header size: %i\n' % headersize)
1084 1085 if headersize:
1085 1086 return self._readexact(headersize)
1086 1087 return None
1087 1088
1088 1089 def __call__(self):
1089 1090
1090 1091 self.ui.debug('bundle2-input-stream-interrupt:'
1091 1092 ' opening out of band context\n')
1092 1093 indebug(self.ui, 'bundle2 stream interruption, looking for a part.')
1093 1094 headerblock = self._readpartheader()
1094 1095 if headerblock is None:
1095 1096 indebug(self.ui, 'no part found during interruption.')
1096 1097 return
1097 1098 part = unbundlepart(self.ui, headerblock, self._fp)
1098 1099 op = interruptoperation(self.ui)
1099 1100 _processpart(op, part)
1100 1101 self.ui.debug('bundle2-input-stream-interrupt:'
1101 1102 ' closing out of band context\n')
1102 1103
1103 1104 class interruptoperation(object):
1104 1105 """A limited operation to be use by part handler during interruption
1105 1106
1106 1107 It only have access to an ui object.
1107 1108 """
1108 1109
1109 1110 def __init__(self, ui):
1110 1111 self.ui = ui
1111 1112 self.reply = None
1112 1113 self.captureoutput = False
1113 1114
1114 1115 @property
1115 1116 def repo(self):
1116 1117 raise error.ProgrammingError('no repo access from stream interruption')
1117 1118
1118 1119 def gettransaction(self):
1119 1120 raise TransactionUnavailable('no repo access from stream interruption')
1120 1121
1121 1122 class unbundlepart(unpackermixin):
1122 1123 """a bundle part read from a bundle"""
1123 1124
1124 1125 def __init__(self, ui, header, fp):
1125 1126 super(unbundlepart, self).__init__(fp)
1126 1127 self._seekable = (util.safehasattr(fp, 'seek') and
1127 1128 util.safehasattr(fp, 'tell'))
1128 1129 self.ui = ui
1129 1130 # unbundle state attr
1130 1131 self._headerdata = header
1131 1132 self._headeroffset = 0
1132 1133 self._initialized = False
1133 1134 self.consumed = False
1134 1135 # part data
1135 1136 self.id = None
1136 1137 self.type = None
1137 1138 self.mandatoryparams = None
1138 1139 self.advisoryparams = None
1139 1140 self.params = None
1140 1141 self.mandatorykeys = ()
1141 1142 self._payloadstream = None
1142 1143 self._readheader()
1143 1144 self._mandatory = None
1144 1145 self._chunkindex = [] #(payload, file) position tuples for chunk starts
1145 1146 self._pos = 0
1146 1147
1147 1148 def _fromheader(self, size):
1148 1149 """return the next <size> byte from the header"""
1149 1150 offset = self._headeroffset
1150 1151 data = self._headerdata[offset:(offset + size)]
1151 1152 self._headeroffset = offset + size
1152 1153 return data
1153 1154
1154 1155 def _unpackheader(self, format):
1155 1156 """read given format from header
1156 1157
1157 1158 This automatically compute the size of the format to read."""
1158 1159 data = self._fromheader(struct.calcsize(format))
1159 1160 return _unpack(format, data)
1160 1161
1161 1162 def _initparams(self, mandatoryparams, advisoryparams):
1162 1163 """internal function to setup all logic related parameters"""
1163 1164 # make it read only to prevent people touching it by mistake.
1164 1165 self.mandatoryparams = tuple(mandatoryparams)
1165 1166 self.advisoryparams = tuple(advisoryparams)
1166 1167 # user friendly UI
1167 1168 self.params = util.sortdict(self.mandatoryparams)
1168 1169 self.params.update(self.advisoryparams)
1169 1170 self.mandatorykeys = frozenset(p[0] for p in mandatoryparams)
1170 1171
1171 1172 def _payloadchunks(self, chunknum=0):
1172 1173 '''seek to specified chunk and start yielding data'''
1173 1174 if len(self._chunkindex) == 0:
1174 1175 assert chunknum == 0, 'Must start with chunk 0'
1175 1176 self._chunkindex.append((0, self._tellfp()))
1176 1177 else:
1177 1178 assert chunknum < len(self._chunkindex), \
1178 1179 'Unknown chunk %d' % chunknum
1179 1180 self._seekfp(self._chunkindex[chunknum][1])
1180 1181
1181 1182 pos = self._chunkindex[chunknum][0]
1182 1183 payloadsize = self._unpack(_fpayloadsize)[0]
1183 1184 indebug(self.ui, 'payload chunk size: %i' % payloadsize)
1184 1185 while payloadsize:
1185 1186 if payloadsize == flaginterrupt:
1186 1187 # interruption detection, the handler will now read a
1187 1188 # single part and process it.
1188 1189 interrupthandler(self.ui, self._fp)()
1189 1190 elif payloadsize < 0:
1190 1191 msg = 'negative payload chunk size: %i' % payloadsize
1191 1192 raise error.BundleValueError(msg)
1192 1193 else:
1193 1194 result = self._readexact(payloadsize)
1194 1195 chunknum += 1
1195 1196 pos += payloadsize
1196 1197 if chunknum == len(self._chunkindex):
1197 1198 self._chunkindex.append((pos, self._tellfp()))
1198 1199 yield result
1199 1200 payloadsize = self._unpack(_fpayloadsize)[0]
1200 1201 indebug(self.ui, 'payload chunk size: %i' % payloadsize)
1201 1202
1202 1203 def _findchunk(self, pos):
1203 1204 '''for a given payload position, return a chunk number and offset'''
1204 1205 for chunk, (ppos, fpos) in enumerate(self._chunkindex):
1205 1206 if ppos == pos:
1206 1207 return chunk, 0
1207 1208 elif ppos > pos:
1208 1209 return chunk - 1, pos - self._chunkindex[chunk - 1][0]
1209 1210 raise ValueError('Unknown chunk')
1210 1211
1211 1212 def _readheader(self):
1212 1213 """read the header and setup the object"""
1213 1214 typesize = self._unpackheader(_fparttypesize)[0]
1214 1215 self.type = self._fromheader(typesize)
1215 1216 indebug(self.ui, 'part type: "%s"' % self.type)
1216 1217 self.id = self._unpackheader(_fpartid)[0]
1217 1218 indebug(self.ui, 'part id: "%s"' % self.id)
1218 1219 # extract mandatory bit from type
1219 1220 self.mandatory = (self.type != self.type.lower())
1220 1221 self.type = self.type.lower()
1221 1222 ## reading parameters
1222 1223 # param count
1223 1224 mancount, advcount = self._unpackheader(_fpartparamcount)
1224 1225 indebug(self.ui, 'part parameters: %i' % (mancount + advcount))
1225 1226 # param size
1226 1227 fparamsizes = _makefpartparamsizes(mancount + advcount)
1227 1228 paramsizes = self._unpackheader(fparamsizes)
1228 1229 # make it a list of couple again
1229 1230 paramsizes = zip(paramsizes[::2], paramsizes[1::2])
1230 1231 # split mandatory from advisory
1231 1232 mansizes = paramsizes[:mancount]
1232 1233 advsizes = paramsizes[mancount:]
1233 1234 # retrieve param value
1234 1235 manparams = []
1235 1236 for key, value in mansizes:
1236 1237 manparams.append((self._fromheader(key), self._fromheader(value)))
1237 1238 advparams = []
1238 1239 for key, value in advsizes:
1239 1240 advparams.append((self._fromheader(key), self._fromheader(value)))
1240 1241 self._initparams(manparams, advparams)
1241 1242 ## part payload
1242 1243 self._payloadstream = util.chunkbuffer(self._payloadchunks())
1243 1244 # we read the data, tell it
1244 1245 self._initialized = True
1245 1246
1246 1247 def read(self, size=None):
1247 1248 """read payload data"""
1248 1249 if not self._initialized:
1249 1250 self._readheader()
1250 1251 if size is None:
1251 1252 data = self._payloadstream.read()
1252 1253 else:
1253 1254 data = self._payloadstream.read(size)
1254 1255 self._pos += len(data)
1255 1256 if size is None or len(data) < size:
1256 1257 if not self.consumed and self._pos:
1257 1258 self.ui.debug('bundle2-input-part: total payload size %i\n'
1258 1259 % self._pos)
1259 1260 self.consumed = True
1260 1261 return data
1261 1262
1262 1263 def tell(self):
1263 1264 return self._pos
1264 1265
1265 1266 def seek(self, offset, whence=0):
1266 1267 if whence == 0:
1267 1268 newpos = offset
1268 1269 elif whence == 1:
1269 1270 newpos = self._pos + offset
1270 1271 elif whence == 2:
1271 1272 if not self.consumed:
1272 1273 self.read()
1273 1274 newpos = self._chunkindex[-1][0] - offset
1274 1275 else:
1275 1276 raise ValueError('Unknown whence value: %r' % (whence,))
1276 1277
1277 1278 if newpos > self._chunkindex[-1][0] and not self.consumed:
1278 1279 self.read()
1279 1280 if not 0 <= newpos <= self._chunkindex[-1][0]:
1280 1281 raise ValueError('Offset out of range')
1281 1282
1282 1283 if self._pos != newpos:
1283 1284 chunk, internaloffset = self._findchunk(newpos)
1284 1285 self._payloadstream = util.chunkbuffer(self._payloadchunks(chunk))
1285 1286 adjust = self.read(internaloffset)
1286 1287 if len(adjust) != internaloffset:
1287 1288 raise error.Abort(_('Seek failed\n'))
1288 1289 self._pos = newpos
1289 1290
1290 1291 def _seekfp(self, offset, whence=0):
1291 1292 """move the underlying file pointer
1292 1293
1293 1294 This method is meant for internal usage by the bundle2 protocol only.
1294 1295 They directly manipulate the low level stream including bundle2 level
1295 1296 instruction.
1296 1297
1297 1298 Do not use it to implement higher-level logic or methods."""
1298 1299 if self._seekable:
1299 1300 return self._fp.seek(offset, whence)
1300 1301 else:
1301 1302 raise NotImplementedError(_('File pointer is not seekable'))
1302 1303
1303 1304 def _tellfp(self):
1304 1305 """return the file offset, or None if file is not seekable
1305 1306
1306 1307 This method is meant for internal usage by the bundle2 protocol only.
1307 1308 They directly manipulate the low level stream including bundle2 level
1308 1309 instruction.
1309 1310
1310 1311 Do not use it to implement higher-level logic or methods."""
1311 1312 if self._seekable:
1312 1313 try:
1313 1314 return self._fp.tell()
1314 1315 except IOError as e:
1315 1316 if e.errno == errno.ESPIPE:
1316 1317 self._seekable = False
1317 1318 else:
1318 1319 raise
1319 1320 return None
1320 1321
1321 1322 # These are only the static capabilities.
1322 1323 # Check the 'getrepocaps' function for the rest.
1323 1324 capabilities = {'HG20': (),
1324 1325 'error': ('abort', 'unsupportedcontent', 'pushraced',
1325 1326 'pushkey'),
1326 1327 'listkeys': (),
1327 1328 'pushkey': (),
1328 1329 'digests': tuple(sorted(util.DIGESTS.keys())),
1329 1330 'remote-changegroup': ('http', 'https'),
1330 1331 'hgtagsfnodes': (),
1331 1332 }
1332 1333
1333 1334 def getrepocaps(repo, allowpushback=False):
1334 1335 """return the bundle2 capabilities for a given repo
1335 1336
1336 1337 Exists to allow extensions (like evolution) to mutate the capabilities.
1337 1338 """
1338 1339 caps = capabilities.copy()
1339 1340 caps['changegroup'] = tuple(sorted(
1340 1341 changegroup.supportedincomingversions(repo)))
1341 1342 if obsolete.isenabled(repo, obsolete.exchangeopt):
1342 1343 supportedformat = tuple('V%i' % v for v in obsolete.formats)
1343 1344 caps['obsmarkers'] = supportedformat
1344 1345 if allowpushback:
1345 1346 caps['pushback'] = ()
1346 1347 cpmode = repo.ui.config('server', 'concurrent-push-mode')
1347 1348 if cpmode == 'check-related':
1348 1349 caps['checkheads'] = ('related',)
1349 1350 return caps
1350 1351
1351 1352 def bundle2caps(remote):
1352 1353 """return the bundle capabilities of a peer as dict"""
1353 1354 raw = remote.capable('bundle2')
1354 1355 if not raw and raw != '':
1355 1356 return {}
1356 1357 capsblob = urlreq.unquote(remote.capable('bundle2'))
1357 1358 return decodecaps(capsblob)
1358 1359
1359 1360 def obsmarkersversion(caps):
1360 1361 """extract the list of supported obsmarkers versions from a bundle2caps dict
1361 1362 """
1362 1363 obscaps = caps.get('obsmarkers', ())
1363 1364 return [int(c[1:]) for c in obscaps if c.startswith('V')]
1364 1365
1365 1366 def writenewbundle(ui, repo, source, filename, bundletype, outgoing, opts,
1366 1367 vfs=None, compression=None, compopts=None):
1367 1368 if bundletype.startswith('HG10'):
1368 1369 cg = changegroup.getchangegroup(repo, source, outgoing, version='01')
1369 1370 return writebundle(ui, cg, filename, bundletype, vfs=vfs,
1370 1371 compression=compression, compopts=compopts)
1371 1372 elif not bundletype.startswith('HG20'):
1372 1373 raise error.ProgrammingError('unknown bundle type: %s' % bundletype)
1373 1374
1374 1375 caps = {}
1375 1376 if 'obsolescence' in opts:
1376 1377 caps['obsmarkers'] = ('V1',)
1377 1378 bundle = bundle20(ui, caps)
1378 1379 bundle.setcompression(compression, compopts)
1379 1380 _addpartsfromopts(ui, repo, bundle, source, outgoing, opts)
1380 1381 chunkiter = bundle.getchunks()
1381 1382
1382 1383 return changegroup.writechunks(ui, chunkiter, filename, vfs=vfs)
1383 1384
1384 1385 def _addpartsfromopts(ui, repo, bundler, source, outgoing, opts):
1385 1386 # We should eventually reconcile this logic with the one behind
1386 1387 # 'exchange.getbundle2partsgenerator'.
1387 1388 #
1388 1389 # The type of input from 'getbundle' and 'writenewbundle' are a bit
1389 1390 # different right now. So we keep them separated for now for the sake of
1390 1391 # simplicity.
1391 1392
1392 1393 # we always want a changegroup in such bundle
1393 1394 cgversion = opts.get('cg.version')
1394 1395 if cgversion is None:
1395 1396 cgversion = changegroup.safeversion(repo)
1396 1397 cg = changegroup.getchangegroup(repo, source, outgoing,
1397 1398 version=cgversion)
1398 1399 part = bundler.newpart('changegroup', data=cg.getchunks())
1399 1400 part.addparam('version', cg.version)
1400 1401 if 'clcount' in cg.extras:
1401 1402 part.addparam('nbchanges', str(cg.extras['clcount']),
1402 1403 mandatory=False)
1403 1404
1404 1405 addparttagsfnodescache(repo, bundler, outgoing)
1405 1406
1406 1407 if opts.get('obsolescence', False):
1407 1408 obsmarkers = repo.obsstore.relevantmarkers(outgoing.missing)
1408 1409 buildobsmarkerspart(bundler, obsmarkers)
1409 1410
1410 1411 if opts.get('phases', False):
1411 1412 headsbyphase = phases.subsetphaseheads(repo, outgoing.missing)
1412 1413 phasedata = []
1413 1414 for phase in phases.allphases:
1414 1415 for head in headsbyphase[phase]:
1415 1416 phasedata.append(_pack(_fphasesentry, phase, head))
1416 1417 bundler.newpart('phase-heads', data=''.join(phasedata))
1417 1418
1418 1419 def addparttagsfnodescache(repo, bundler, outgoing):
1419 1420 # we include the tags fnode cache for the bundle changeset
1420 1421 # (as an optional parts)
1421 1422 cache = tags.hgtagsfnodescache(repo.unfiltered())
1422 1423 chunks = []
1423 1424
1424 1425 # .hgtags fnodes are only relevant for head changesets. While we could
1425 1426 # transfer values for all known nodes, there will likely be little to
1426 1427 # no benefit.
1427 1428 #
1428 1429 # We don't bother using a generator to produce output data because
1429 1430 # a) we only have 40 bytes per head and even esoteric numbers of heads
1430 1431 # consume little memory (1M heads is 40MB) b) we don't want to send the
1431 1432 # part if we don't have entries and knowing if we have entries requires
1432 1433 # cache lookups.
1433 1434 for node in outgoing.missingheads:
1434 1435 # Don't compute missing, as this may slow down serving.
1435 1436 fnode = cache.getfnode(node, computemissing=False)
1436 1437 if fnode is not None:
1437 1438 chunks.extend([node, fnode])
1438 1439
1439 1440 if chunks:
1440 1441 bundler.newpart('hgtagsfnodes', data=''.join(chunks))
1441 1442
1442 1443 def buildobsmarkerspart(bundler, markers):
1443 1444 """add an obsmarker part to the bundler with <markers>
1444 1445
1445 1446 No part is created if markers is empty.
1446 1447 Raises ValueError if the bundler doesn't support any known obsmarker format.
1447 1448 """
1448 1449 if not markers:
1449 1450 return None
1450 1451
1451 1452 remoteversions = obsmarkersversion(bundler.capabilities)
1452 1453 version = obsolete.commonversion(remoteversions)
1453 1454 if version is None:
1454 1455 raise ValueError('bundler does not support common obsmarker format')
1455 1456 stream = obsolete.encodemarkers(markers, True, version=version)
1456 1457 return bundler.newpart('obsmarkers', data=stream)
1457 1458
1458 1459 def writebundle(ui, cg, filename, bundletype, vfs=None, compression=None,
1459 1460 compopts=None):
1460 1461 """Write a bundle file and return its filename.
1461 1462
1462 1463 Existing files will not be overwritten.
1463 1464 If no filename is specified, a temporary file is created.
1464 1465 bz2 compression can be turned off.
1465 1466 The bundle file will be deleted in case of errors.
1466 1467 """
1467 1468
1468 1469 if bundletype == "HG20":
1469 1470 bundle = bundle20(ui)
1470 1471 bundle.setcompression(compression, compopts)
1471 1472 part = bundle.newpart('changegroup', data=cg.getchunks())
1472 1473 part.addparam('version', cg.version)
1473 1474 if 'clcount' in cg.extras:
1474 1475 part.addparam('nbchanges', str(cg.extras['clcount']),
1475 1476 mandatory=False)
1476 1477 chunkiter = bundle.getchunks()
1477 1478 else:
1478 1479 # compression argument is only for the bundle2 case
1479 1480 assert compression is None
1480 1481 if cg.version != '01':
1481 1482 raise error.Abort(_('old bundle types only supports v1 '
1482 1483 'changegroups'))
1483 1484 header, comp = bundletypes[bundletype]
1484 1485 if comp not in util.compengines.supportedbundletypes:
1485 1486 raise error.Abort(_('unknown stream compression type: %s')
1486 1487 % comp)
1487 1488 compengine = util.compengines.forbundletype(comp)
1488 1489 def chunkiter():
1489 1490 yield header
1490 1491 for chunk in compengine.compressstream(cg.getchunks(), compopts):
1491 1492 yield chunk
1492 1493 chunkiter = chunkiter()
1493 1494
1494 1495 # parse the changegroup data, otherwise we will block
1495 1496 # in case of sshrepo because we don't know the end of the stream
1496 1497 return changegroup.writechunks(ui, chunkiter, filename, vfs=vfs)
1497 1498
1498 1499 def combinechangegroupresults(op):
1499 1500 """logic to combine 0 or more addchangegroup results into one"""
1500 1501 results = [r.get('return', 0)
1501 1502 for r in op.records['changegroup']]
1502 1503 changedheads = 0
1503 1504 result = 1
1504 1505 for ret in results:
1505 1506 # If any changegroup result is 0, return 0
1506 1507 if ret == 0:
1507 1508 result = 0
1508 1509 break
1509 1510 if ret < -1:
1510 1511 changedheads += ret + 1
1511 1512 elif ret > 1:
1512 1513 changedheads += ret - 1
1513 1514 if changedheads > 0:
1514 1515 result = 1 + changedheads
1515 1516 elif changedheads < 0:
1516 1517 result = -1 + changedheads
1517 1518 return result
1518 1519
1519 1520 @parthandler('changegroup', ('version', 'nbchanges', 'treemanifest'))
1520 1521 def handlechangegroup(op, inpart):
1521 1522 """apply a changegroup part on the repo
1522 1523
1523 1524 This is a very early implementation that will massive rework before being
1524 1525 inflicted to any end-user.
1525 1526 """
1526 1527 tr = op.gettransaction()
1527 1528 unpackerversion = inpart.params.get('version', '01')
1528 1529 # We should raise an appropriate exception here
1529 1530 cg = changegroup.getunbundler(unpackerversion, inpart, None)
1530 1531 # the source and url passed here are overwritten by the one contained in
1531 1532 # the transaction.hookargs argument. So 'bundle2' is a placeholder
1532 1533 nbchangesets = None
1533 1534 if 'nbchanges' in inpart.params:
1534 1535 nbchangesets = int(inpart.params.get('nbchanges'))
1535 1536 if ('treemanifest' in inpart.params and
1536 1537 'treemanifest' not in op.repo.requirements):
1537 1538 if len(op.repo.changelog) != 0:
1538 1539 raise error.Abort(_(
1539 1540 "bundle contains tree manifests, but local repo is "
1540 1541 "non-empty and does not use tree manifests"))
1541 1542 op.repo.requirements.add('treemanifest')
1542 1543 op.repo._applyopenerreqs()
1543 1544 op.repo._writerequirements()
1544 1545 ret = _processchangegroup(op, cg, tr, 'bundle2', 'bundle2',
1545 1546 expectedtotal=nbchangesets)
1546 1547 if op.reply is not None:
1547 1548 # This is definitely not the final form of this
1548 1549 # return. But one need to start somewhere.
1549 1550 part = op.reply.newpart('reply:changegroup', mandatory=False)
1550 1551 part.addparam('in-reply-to', str(inpart.id), mandatory=False)
1551 1552 part.addparam('return', '%i' % ret, mandatory=False)
1552 1553 assert not inpart.read()
1553 1554
1554 1555 _remotechangegroupparams = tuple(['url', 'size', 'digests'] +
1555 1556 ['digest:%s' % k for k in util.DIGESTS.keys()])
1556 1557 @parthandler('remote-changegroup', _remotechangegroupparams)
1557 1558 def handleremotechangegroup(op, inpart):
1558 1559 """apply a bundle10 on the repo, given an url and validation information
1559 1560
1560 1561 All the information about the remote bundle to import are given as
1561 1562 parameters. The parameters include:
1562 1563 - url: the url to the bundle10.
1563 1564 - size: the bundle10 file size. It is used to validate what was
1564 1565 retrieved by the client matches the server knowledge about the bundle.
1565 1566 - digests: a space separated list of the digest types provided as
1566 1567 parameters.
1567 1568 - digest:<digest-type>: the hexadecimal representation of the digest with
1568 1569 that name. Like the size, it is used to validate what was retrieved by
1569 1570 the client matches what the server knows about the bundle.
1570 1571
1571 1572 When multiple digest types are given, all of them are checked.
1572 1573 """
1573 1574 try:
1574 1575 raw_url = inpart.params['url']
1575 1576 except KeyError:
1576 1577 raise error.Abort(_('remote-changegroup: missing "%s" param') % 'url')
1577 1578 parsed_url = util.url(raw_url)
1578 1579 if parsed_url.scheme not in capabilities['remote-changegroup']:
1579 1580 raise error.Abort(_('remote-changegroup does not support %s urls') %
1580 1581 parsed_url.scheme)
1581 1582
1582 1583 try:
1583 1584 size = int(inpart.params['size'])
1584 1585 except ValueError:
1585 1586 raise error.Abort(_('remote-changegroup: invalid value for param "%s"')
1586 1587 % 'size')
1587 1588 except KeyError:
1588 1589 raise error.Abort(_('remote-changegroup: missing "%s" param') % 'size')
1589 1590
1590 1591 digests = {}
1591 1592 for typ in inpart.params.get('digests', '').split():
1592 1593 param = 'digest:%s' % typ
1593 1594 try:
1594 1595 value = inpart.params[param]
1595 1596 except KeyError:
1596 1597 raise error.Abort(_('remote-changegroup: missing "%s" param') %
1597 1598 param)
1598 1599 digests[typ] = value
1599 1600
1600 1601 real_part = util.digestchecker(url.open(op.ui, raw_url), size, digests)
1601 1602
1602 1603 tr = op.gettransaction()
1603 1604 from . import exchange
1604 1605 cg = exchange.readbundle(op.repo.ui, real_part, raw_url)
1605 1606 if not isinstance(cg, changegroup.cg1unpacker):
1606 1607 raise error.Abort(_('%s: not a bundle version 1.0') %
1607 1608 util.hidepassword(raw_url))
1608 1609 ret = _processchangegroup(op, cg, tr, 'bundle2', 'bundle2')
1609 1610 if op.reply is not None:
1610 1611 # This is definitely not the final form of this
1611 1612 # return. But one need to start somewhere.
1612 1613 part = op.reply.newpart('reply:changegroup')
1613 1614 part.addparam('in-reply-to', str(inpart.id), mandatory=False)
1614 1615 part.addparam('return', '%i' % ret, mandatory=False)
1615 1616 try:
1616 1617 real_part.validate()
1617 1618 except error.Abort as e:
1618 1619 raise error.Abort(_('bundle at %s is corrupted:\n%s') %
1619 1620 (util.hidepassword(raw_url), str(e)))
1620 1621 assert not inpart.read()
1621 1622
1622 1623 @parthandler('reply:changegroup', ('return', 'in-reply-to'))
1623 1624 def handlereplychangegroup(op, inpart):
1624 1625 ret = int(inpart.params['return'])
1625 1626 replyto = int(inpart.params['in-reply-to'])
1626 1627 op.records.add('changegroup', {'return': ret}, replyto)
1627 1628
1628 1629 @parthandler('check:heads')
1629 1630 def handlecheckheads(op, inpart):
1630 1631 """check that head of the repo did not change
1631 1632
1632 1633 This is used to detect a push race when using unbundle.
1633 1634 This replaces the "heads" argument of unbundle."""
1634 1635 h = inpart.read(20)
1635 1636 heads = []
1636 1637 while len(h) == 20:
1637 1638 heads.append(h)
1638 1639 h = inpart.read(20)
1639 1640 assert not h
1640 1641 # Trigger a transaction so that we are guaranteed to have the lock now.
1641 1642 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1642 1643 op.gettransaction()
1643 1644 if sorted(heads) != sorted(op.repo.heads()):
1644 1645 raise error.PushRaced('repository changed while pushing - '
1645 1646 'please try again')
1646 1647
1647 1648 @parthandler('check:updated-heads')
1648 1649 def handlecheckupdatedheads(op, inpart):
1649 1650 """check for race on the heads touched by a push
1650 1651
1651 1652 This is similar to 'check:heads' but focus on the heads actually updated
1652 1653 during the push. If other activities happen on unrelated heads, it is
1653 1654 ignored.
1654 1655
1655 1656 This allow server with high traffic to avoid push contention as long as
1656 1657 unrelated parts of the graph are involved."""
1657 1658 h = inpart.read(20)
1658 1659 heads = []
1659 1660 while len(h) == 20:
1660 1661 heads.append(h)
1661 1662 h = inpart.read(20)
1662 1663 assert not h
1663 1664 # trigger a transaction so that we are guaranteed to have the lock now.
1664 1665 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1665 1666 op.gettransaction()
1666 1667
1667 1668 currentheads = set()
1668 1669 for ls in op.repo.branchmap().itervalues():
1669 1670 currentheads.update(ls)
1670 1671
1671 1672 for h in heads:
1672 1673 if h not in currentheads:
1673 1674 raise error.PushRaced('repository changed while pushing - '
1674 1675 'please try again')
1675 1676
1676 1677 @parthandler('output')
1677 1678 def handleoutput(op, inpart):
1678 1679 """forward output captured on the server to the client"""
1679 1680 for line in inpart.read().splitlines():
1680 1681 op.ui.status(_('remote: %s\n') % line)
1681 1682
1682 1683 @parthandler('replycaps')
1683 1684 def handlereplycaps(op, inpart):
1684 1685 """Notify that a reply bundle should be created
1685 1686
1686 1687 The payload contains the capabilities information for the reply"""
1687 1688 caps = decodecaps(inpart.read())
1688 1689 if op.reply is None:
1689 1690 op.reply = bundle20(op.ui, caps)
1690 1691
1691 1692 class AbortFromPart(error.Abort):
1692 1693 """Sub-class of Abort that denotes an error from a bundle2 part."""
1693 1694
1694 1695 @parthandler('error:abort', ('message', 'hint'))
1695 1696 def handleerrorabort(op, inpart):
1696 1697 """Used to transmit abort error over the wire"""
1697 1698 raise AbortFromPart(inpart.params['message'],
1698 1699 hint=inpart.params.get('hint'))
1699 1700
1700 1701 @parthandler('error:pushkey', ('namespace', 'key', 'new', 'old', 'ret',
1701 1702 'in-reply-to'))
1702 1703 def handleerrorpushkey(op, inpart):
1703 1704 """Used to transmit failure of a mandatory pushkey over the wire"""
1704 1705 kwargs = {}
1705 1706 for name in ('namespace', 'key', 'new', 'old', 'ret'):
1706 1707 value = inpart.params.get(name)
1707 1708 if value is not None:
1708 1709 kwargs[name] = value
1709 1710 raise error.PushkeyFailed(inpart.params['in-reply-to'], **kwargs)
1710 1711
1711 1712 @parthandler('error:unsupportedcontent', ('parttype', 'params'))
1712 1713 def handleerrorunsupportedcontent(op, inpart):
1713 1714 """Used to transmit unknown content error over the wire"""
1714 1715 kwargs = {}
1715 1716 parttype = inpart.params.get('parttype')
1716 1717 if parttype is not None:
1717 1718 kwargs['parttype'] = parttype
1718 1719 params = inpart.params.get('params')
1719 1720 if params is not None:
1720 1721 kwargs['params'] = params.split('\0')
1721 1722
1722 1723 raise error.BundleUnknownFeatureError(**kwargs)
1723 1724
1724 1725 @parthandler('error:pushraced', ('message',))
1725 1726 def handleerrorpushraced(op, inpart):
1726 1727 """Used to transmit push race error over the wire"""
1727 1728 raise error.ResponseError(_('push failed:'), inpart.params['message'])
1728 1729
1729 1730 @parthandler('listkeys', ('namespace',))
1730 1731 def handlelistkeys(op, inpart):
1731 1732 """retrieve pushkey namespace content stored in a bundle2"""
1732 1733 namespace = inpart.params['namespace']
1733 1734 r = pushkey.decodekeys(inpart.read())
1734 1735 op.records.add('listkeys', (namespace, r))
1735 1736
1736 1737 @parthandler('pushkey', ('namespace', 'key', 'old', 'new'))
1737 1738 def handlepushkey(op, inpart):
1738 1739 """process a pushkey request"""
1739 1740 dec = pushkey.decode
1740 1741 namespace = dec(inpart.params['namespace'])
1741 1742 key = dec(inpart.params['key'])
1742 1743 old = dec(inpart.params['old'])
1743 1744 new = dec(inpart.params['new'])
1744 1745 # Grab the transaction to ensure that we have the lock before performing the
1745 1746 # pushkey.
1746 1747 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1747 1748 op.gettransaction()
1748 1749 ret = op.repo.pushkey(namespace, key, old, new)
1749 1750 record = {'namespace': namespace,
1750 1751 'key': key,
1751 1752 'old': old,
1752 1753 'new': new}
1753 1754 op.records.add('pushkey', record)
1754 1755 if op.reply is not None:
1755 1756 rpart = op.reply.newpart('reply:pushkey')
1756 1757 rpart.addparam('in-reply-to', str(inpart.id), mandatory=False)
1757 1758 rpart.addparam('return', '%i' % ret, mandatory=False)
1758 1759 if inpart.mandatory and not ret:
1759 1760 kwargs = {}
1760 1761 for key in ('namespace', 'key', 'new', 'old', 'ret'):
1761 1762 if key in inpart.params:
1762 1763 kwargs[key] = inpart.params[key]
1763 1764 raise error.PushkeyFailed(partid=str(inpart.id), **kwargs)
1764 1765
1765 1766 def _readphaseheads(inpart):
1766 1767 headsbyphase = [[] for i in phases.allphases]
1767 1768 entrysize = struct.calcsize(_fphasesentry)
1768 1769 while True:
1769 1770 entry = inpart.read(entrysize)
1770 1771 if len(entry) < entrysize:
1771 1772 if entry:
1772 1773 raise error.Abort(_('bad phase-heads bundle part'))
1773 1774 break
1774 1775 phase, node = struct.unpack(_fphasesentry, entry)
1775 1776 headsbyphase[phase].append(node)
1776 1777 return headsbyphase
1777 1778
1778 1779 @parthandler('phase-heads')
1779 1780 def handlephases(op, inpart):
1780 1781 """apply phases from bundle part to repo"""
1781 1782 headsbyphase = _readphaseheads(inpart)
1782 1783 addednodes = []
1783 1784 for entry in op.records['changegroup']:
1784 1785 addednodes.extend(entry['addednodes'])
1785 1786 phases.updatephases(op.repo.unfiltered(), op.gettransaction(), headsbyphase,
1786 1787 addednodes)
1787 1788
1788 1789 @parthandler('reply:pushkey', ('return', 'in-reply-to'))
1789 1790 def handlepushkeyreply(op, inpart):
1790 1791 """retrieve the result of a pushkey request"""
1791 1792 ret = int(inpart.params['return'])
1792 1793 partid = int(inpart.params['in-reply-to'])
1793 1794 op.records.add('pushkey', {'return': ret}, partid)
1794 1795
1795 1796 @parthandler('obsmarkers')
1796 1797 def handleobsmarker(op, inpart):
1797 1798 """add a stream of obsmarkers to the repo"""
1798 1799 tr = op.gettransaction()
1799 1800 markerdata = inpart.read()
1800 1801 if op.ui.config('experimental', 'obsmarkers-exchange-debug', False):
1801 1802 op.ui.write(('obsmarker-exchange: %i bytes received\n')
1802 1803 % len(markerdata))
1803 1804 # The mergemarkers call will crash if marker creation is not enabled.
1804 1805 # we want to avoid this if the part is advisory.
1805 1806 if not inpart.mandatory and op.repo.obsstore.readonly:
1806 1807 op.repo.ui.debug('ignoring obsolescence markers, feature not enabled')
1807 1808 return
1808 1809 new = op.repo.obsstore.mergemarkers(tr, markerdata)
1809 1810 op.repo.invalidatevolatilesets()
1810 1811 if new:
1811 1812 op.repo.ui.status(_('%i new obsolescence markers\n') % new)
1812 1813 op.records.add('obsmarkers', {'new': new})
1814 scmutil.registersummarycallback(op.repo, tr)
1813 1815 if op.reply is not None:
1814 1816 rpart = op.reply.newpart('reply:obsmarkers')
1815 1817 rpart.addparam('in-reply-to', str(inpart.id), mandatory=False)
1816 1818 rpart.addparam('new', '%i' % new, mandatory=False)
1817 1819
1818 1820
1819 1821 @parthandler('reply:obsmarkers', ('new', 'in-reply-to'))
1820 1822 def handleobsmarkerreply(op, inpart):
1821 1823 """retrieve the result of a pushkey request"""
1822 1824 ret = int(inpart.params['new'])
1823 1825 partid = int(inpart.params['in-reply-to'])
1824 1826 op.records.add('obsmarkers', {'new': ret}, partid)
1825 1827
1826 1828 @parthandler('hgtagsfnodes')
1827 1829 def handlehgtagsfnodes(op, inpart):
1828 1830 """Applies .hgtags fnodes cache entries to the local repo.
1829 1831
1830 1832 Payload is pairs of 20 byte changeset nodes and filenodes.
1831 1833 """
1832 1834 # Grab the transaction so we ensure that we have the lock at this point.
1833 1835 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1834 1836 op.gettransaction()
1835 1837 cache = tags.hgtagsfnodescache(op.repo.unfiltered())
1836 1838
1837 1839 count = 0
1838 1840 while True:
1839 1841 node = inpart.read(20)
1840 1842 fnode = inpart.read(20)
1841 1843 if len(node) < 20 or len(fnode) < 20:
1842 1844 op.ui.debug('ignoring incomplete received .hgtags fnodes data\n')
1843 1845 break
1844 1846 cache.setfnode(node, fnode)
1845 1847 count += 1
1846 1848
1847 1849 cache.write()
1848 1850 op.ui.debug('applied %i hgtags fnodes cache entries\n' % count)
@@ -1,491 +1,517 b''
1 1 # obsutil.py - utility functions for obsolescence
2 2 #
3 3 # Copyright 2017 Boris Feld <boris.feld@octobus.net>
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 from . import (
11 phases,
12 )
13
10 14 class marker(object):
11 15 """Wrap obsolete marker raw data"""
12 16
13 17 def __init__(self, repo, data):
14 18 # the repo argument will be used to create changectx in later version
15 19 self._repo = repo
16 20 self._data = data
17 21 self._decodedmeta = None
18 22
19 23 def __hash__(self):
20 24 return hash(self._data)
21 25
22 26 def __eq__(self, other):
23 27 if type(other) != type(self):
24 28 return False
25 29 return self._data == other._data
26 30
27 31 def precnode(self):
28 32 """Precursor changeset node identifier"""
29 33 return self._data[0]
30 34
31 35 def succnodes(self):
32 36 """List of successor changesets node identifiers"""
33 37 return self._data[1]
34 38
35 39 def parentnodes(self):
36 40 """Parents of the precursors (None if not recorded)"""
37 41 return self._data[5]
38 42
39 43 def metadata(self):
40 44 """Decoded metadata dictionary"""
41 45 return dict(self._data[3])
42 46
43 47 def date(self):
44 48 """Creation date as (unixtime, offset)"""
45 49 return self._data[4]
46 50
47 51 def flags(self):
48 52 """The flags field of the marker"""
49 53 return self._data[2]
50 54
51 55 def getmarkers(repo, nodes=None, exclusive=False):
52 56 """returns markers known in a repository
53 57
54 58 If <nodes> is specified, only markers "relevant" to those nodes are are
55 59 returned"""
56 60 if nodes is None:
57 61 rawmarkers = repo.obsstore
58 62 elif exclusive:
59 63 rawmarkers = exclusivemarkers(repo, nodes)
60 64 else:
61 65 rawmarkers = repo.obsstore.relevantmarkers(nodes)
62 66
63 67 for markerdata in rawmarkers:
64 68 yield marker(repo, markerdata)
65 69
66 70 def closestpredecessors(repo, nodeid):
67 71 """yield the list of next predecessors pointing on visible changectx nodes
68 72
69 73 This function respect the repoview filtering, filtered revision will be
70 74 considered missing.
71 75 """
72 76
73 77 precursors = repo.obsstore.precursors
74 78 stack = [nodeid]
75 79 seen = set(stack)
76 80
77 81 while stack:
78 82 current = stack.pop()
79 83 currentpreccs = precursors.get(current, ())
80 84
81 85 for prec in currentpreccs:
82 86 precnodeid = prec[0]
83 87
84 88 # Basic cycle protection
85 89 if precnodeid in seen:
86 90 continue
87 91 seen.add(precnodeid)
88 92
89 93 if precnodeid in repo:
90 94 yield precnodeid
91 95 else:
92 96 stack.append(precnodeid)
93 97
94 98 def allprecursors(obsstore, nodes, ignoreflags=0):
95 99 """Yield node for every precursors of <nodes>.
96 100
97 101 Some precursors may be unknown locally.
98 102
99 103 This is a linear yield unsuited to detecting folded changesets. It includes
100 104 initial nodes too."""
101 105
102 106 remaining = set(nodes)
103 107 seen = set(remaining)
104 108 while remaining:
105 109 current = remaining.pop()
106 110 yield current
107 111 for mark in obsstore.precursors.get(current, ()):
108 112 # ignore marker flagged with specified flag
109 113 if mark[2] & ignoreflags:
110 114 continue
111 115 suc = mark[0]
112 116 if suc not in seen:
113 117 seen.add(suc)
114 118 remaining.add(suc)
115 119
116 120 def allsuccessors(obsstore, nodes, ignoreflags=0):
117 121 """Yield node for every successor of <nodes>.
118 122
119 123 Some successors may be unknown locally.
120 124
121 125 This is a linear yield unsuited to detecting split changesets. It includes
122 126 initial nodes too."""
123 127 remaining = set(nodes)
124 128 seen = set(remaining)
125 129 while remaining:
126 130 current = remaining.pop()
127 131 yield current
128 132 for mark in obsstore.successors.get(current, ()):
129 133 # ignore marker flagged with specified flag
130 134 if mark[2] & ignoreflags:
131 135 continue
132 136 for suc in mark[1]:
133 137 if suc not in seen:
134 138 seen.add(suc)
135 139 remaining.add(suc)
136 140
137 141 def _filterprunes(markers):
138 142 """return a set with no prune markers"""
139 143 return set(m for m in markers if m[1])
140 144
141 145 def exclusivemarkers(repo, nodes):
142 146 """set of markers relevant to "nodes" but no other locally-known nodes
143 147
144 148 This function compute the set of markers "exclusive" to a locally-known
145 149 node. This means we walk the markers starting from <nodes> until we reach a
146 150 locally-known precursors outside of <nodes>. Element of <nodes> with
147 151 locally-known successors outside of <nodes> are ignored (since their
148 152 precursors markers are also relevant to these successors).
149 153
150 154 For example:
151 155
152 156 # (A0 rewritten as A1)
153 157 #
154 158 # A0 <-1- A1 # Marker "1" is exclusive to A1
155 159
156 160 or
157 161
158 162 # (A0 rewritten as AX; AX rewritten as A1; AX is unkown locally)
159 163 #
160 164 # <-1- A0 <-2- AX <-3- A1 # Marker "2,3" are exclusive to A1
161 165
162 166 or
163 167
164 168 # (A0 has unknown precursors, A0 rewritten as A1 and A2 (divergence))
165 169 #
166 170 # <-2- A1 # Marker "2" is exclusive to A0,A1
167 171 # /
168 172 # <-1- A0
169 173 # \
170 174 # <-3- A2 # Marker "3" is exclusive to A0,A2
171 175 #
172 176 # in addition:
173 177 #
174 178 # Markers "2,3" are exclusive to A1,A2
175 179 # Markers "1,2,3" are exclusive to A0,A1,A2
176 180
177 181 See test/test-obsolete-bundle-strip.t for more examples.
178 182
179 183 An example usage is strip. When stripping a changeset, we also want to
180 184 strip the markers exclusive to this changeset. Otherwise we would have
181 185 "dangling"" obsolescence markers from its precursors: Obsolescence markers
182 186 marking a node as obsolete without any successors available locally.
183 187
184 188 As for relevant markers, the prune markers for children will be followed.
185 189 Of course, they will only be followed if the pruned children is
186 190 locally-known. Since the prune markers are relevant to the pruned node.
187 191 However, while prune markers are considered relevant to the parent of the
188 192 pruned changesets, prune markers for locally-known changeset (with no
189 193 successors) are considered exclusive to the pruned nodes. This allows
190 194 to strip the prune markers (with the rest of the exclusive chain) alongside
191 195 the pruned changesets.
192 196 """
193 197 # running on a filtered repository would be dangerous as markers could be
194 198 # reported as exclusive when they are relevant for other filtered nodes.
195 199 unfi = repo.unfiltered()
196 200
197 201 # shortcut to various useful item
198 202 nm = unfi.changelog.nodemap
199 203 precursorsmarkers = unfi.obsstore.precursors
200 204 successormarkers = unfi.obsstore.successors
201 205 childrenmarkers = unfi.obsstore.children
202 206
203 207 # exclusive markers (return of the function)
204 208 exclmarkers = set()
205 209 # we need fast membership testing
206 210 nodes = set(nodes)
207 211 # looking for head in the obshistory
208 212 #
209 213 # XXX we are ignoring all issues in regard with cycle for now.
210 214 stack = [n for n in nodes if not _filterprunes(successormarkers.get(n, ()))]
211 215 stack.sort()
212 216 # nodes already stacked
213 217 seennodes = set(stack)
214 218 while stack:
215 219 current = stack.pop()
216 220 # fetch precursors markers
217 221 markers = list(precursorsmarkers.get(current, ()))
218 222 # extend the list with prune markers
219 223 for mark in successormarkers.get(current, ()):
220 224 if not mark[1]:
221 225 markers.append(mark)
222 226 # and markers from children (looking for prune)
223 227 for mark in childrenmarkers.get(current, ()):
224 228 if not mark[1]:
225 229 markers.append(mark)
226 230 # traverse the markers
227 231 for mark in markers:
228 232 if mark in exclmarkers:
229 233 # markers already selected
230 234 continue
231 235
232 236 # If the markers is about the current node, select it
233 237 #
234 238 # (this delay the addition of markers from children)
235 239 if mark[1] or mark[0] == current:
236 240 exclmarkers.add(mark)
237 241
238 242 # should we keep traversing through the precursors?
239 243 prec = mark[0]
240 244
241 245 # nodes in the stack or already processed
242 246 if prec in seennodes:
243 247 continue
244 248
245 249 # is this a locally known node ?
246 250 known = prec in nm
247 251 # if locally-known and not in the <nodes> set the traversal
248 252 # stop here.
249 253 if known and prec not in nodes:
250 254 continue
251 255
252 256 # do not keep going if there are unselected markers pointing to this
253 257 # nodes. If we end up traversing these unselected markers later the
254 258 # node will be taken care of at that point.
255 259 precmarkers = _filterprunes(successormarkers.get(prec))
256 260 if precmarkers.issubset(exclmarkers):
257 261 seennodes.add(prec)
258 262 stack.append(prec)
259 263
260 264 return exclmarkers
261 265
262 266 def foreground(repo, nodes):
263 267 """return all nodes in the "foreground" of other node
264 268
265 269 The foreground of a revision is anything reachable using parent -> children
266 270 or precursor -> successor relation. It is very similar to "descendant" but
267 271 augmented with obsolescence information.
268 272
269 273 Beware that possible obsolescence cycle may result if complex situation.
270 274 """
271 275 repo = repo.unfiltered()
272 276 foreground = set(repo.set('%ln::', nodes))
273 277 if repo.obsstore:
274 278 # We only need this complicated logic if there is obsolescence
275 279 # XXX will probably deserve an optimised revset.
276 280 nm = repo.changelog.nodemap
277 281 plen = -1
278 282 # compute the whole set of successors or descendants
279 283 while len(foreground) != plen:
280 284 plen = len(foreground)
281 285 succs = set(c.node() for c in foreground)
282 286 mutable = [c.node() for c in foreground if c.mutable()]
283 287 succs.update(allsuccessors(repo.obsstore, mutable))
284 288 known = (n for n in succs if n in nm)
285 289 foreground = set(repo.set('%ln::', known))
286 290 return set(c.node() for c in foreground)
287 291
292 def getobsoleted(repo, tr):
293 """return the set of pre-existing revisions obsoleted by a transaction"""
294 torev = repo.unfiltered().changelog.nodemap.get
295 phase = repo._phasecache.phase
296 succsmarkers = repo.obsstore.successors.get
297 public = phases.public
298 addedmarkers = tr.changes.get('obsmarkers')
299 addedrevs = tr.changes.get('revs')
300 seenrevs = set(addedrevs)
301 obsoleted = set()
302 for mark in addedmarkers:
303 node = mark[0]
304 rev = torev(node)
305 if rev is None or rev in seenrevs:
306 continue
307 seenrevs.add(rev)
308 if phase(repo, rev) == public:
309 continue
310 if set(succsmarkers(node)).issubset(addedmarkers):
311 obsoleted.add(rev)
312 return obsoleted
313
288 314 def successorssets(repo, initialnode, cache=None):
289 315 """Return set of all latest successors of initial nodes
290 316
291 317 The successors set of a changeset A are the group of revisions that succeed
292 318 A. It succeeds A as a consistent whole, each revision being only a partial
293 319 replacement. The successors set contains non-obsolete changesets only.
294 320
295 321 This function returns the full list of successor sets which is why it
296 322 returns a list of tuples and not just a single tuple. Each tuple is a valid
297 323 successors set. Note that (A,) may be a valid successors set for changeset A
298 324 (see below).
299 325
300 326 In most cases, a changeset A will have a single element (e.g. the changeset
301 327 A is replaced by A') in its successors set. Though, it is also common for a
302 328 changeset A to have no elements in its successor set (e.g. the changeset
303 329 has been pruned). Therefore, the returned list of successors sets will be
304 330 [(A',)] or [], respectively.
305 331
306 332 When a changeset A is split into A' and B', however, it will result in a
307 333 successors set containing more than a single element, i.e. [(A',B')].
308 334 Divergent changesets will result in multiple successors sets, i.e. [(A',),
309 335 (A'')].
310 336
311 337 If a changeset A is not obsolete, then it will conceptually have no
312 338 successors set. To distinguish this from a pruned changeset, the successor
313 339 set will contain itself only, i.e. [(A,)].
314 340
315 341 Finally, successors unknown locally are considered to be pruned (obsoleted
316 342 without any successors).
317 343
318 344 The optional `cache` parameter is a dictionary that may contain precomputed
319 345 successors sets. It is meant to reuse the computation of a previous call to
320 346 `successorssets` when multiple calls are made at the same time. The cache
321 347 dictionary is updated in place. The caller is responsible for its life
322 348 span. Code that makes multiple calls to `successorssets` *must* use this
323 349 cache mechanism or suffer terrible performance.
324 350 """
325 351
326 352 succmarkers = repo.obsstore.successors
327 353
328 354 # Stack of nodes we search successors sets for
329 355 toproceed = [initialnode]
330 356 # set version of above list for fast loop detection
331 357 # element added to "toproceed" must be added here
332 358 stackedset = set(toproceed)
333 359 if cache is None:
334 360 cache = {}
335 361
336 362 # This while loop is the flattened version of a recursive search for
337 363 # successors sets
338 364 #
339 365 # def successorssets(x):
340 366 # successors = directsuccessors(x)
341 367 # ss = [[]]
342 368 # for succ in directsuccessors(x):
343 369 # # product as in itertools cartesian product
344 370 # ss = product(ss, successorssets(succ))
345 371 # return ss
346 372 #
347 373 # But we can not use plain recursive calls here:
348 374 # - that would blow the python call stack
349 375 # - obsolescence markers may have cycles, we need to handle them.
350 376 #
351 377 # The `toproceed` list act as our call stack. Every node we search
352 378 # successors set for are stacked there.
353 379 #
354 380 # The `stackedset` is set version of this stack used to check if a node is
355 381 # already stacked. This check is used to detect cycles and prevent infinite
356 382 # loop.
357 383 #
358 384 # successors set of all nodes are stored in the `cache` dictionary.
359 385 #
360 386 # After this while loop ends we use the cache to return the successors sets
361 387 # for the node requested by the caller.
362 388 while toproceed:
363 389 # Every iteration tries to compute the successors sets of the topmost
364 390 # node of the stack: CURRENT.
365 391 #
366 392 # There are four possible outcomes:
367 393 #
368 394 # 1) We already know the successors sets of CURRENT:
369 395 # -> mission accomplished, pop it from the stack.
370 396 # 2) Node is not obsolete:
371 397 # -> the node is its own successors sets. Add it to the cache.
372 398 # 3) We do not know successors set of direct successors of CURRENT:
373 399 # -> We add those successors to the stack.
374 400 # 4) We know successors sets of all direct successors of CURRENT:
375 401 # -> We can compute CURRENT successors set and add it to the
376 402 # cache.
377 403 #
378 404 current = toproceed[-1]
379 405 if current in cache:
380 406 # case (1): We already know the successors sets
381 407 stackedset.remove(toproceed.pop())
382 408 elif current not in succmarkers:
383 409 # case (2): The node is not obsolete.
384 410 if current in repo:
385 411 # We have a valid last successors.
386 412 cache[current] = [(current,)]
387 413 else:
388 414 # Final obsolete version is unknown locally.
389 415 # Do not count that as a valid successors
390 416 cache[current] = []
391 417 else:
392 418 # cases (3) and (4)
393 419 #
394 420 # We proceed in two phases. Phase 1 aims to distinguish case (3)
395 421 # from case (4):
396 422 #
397 423 # For each direct successors of CURRENT, we check whether its
398 424 # successors sets are known. If they are not, we stack the
399 425 # unknown node and proceed to the next iteration of the while
400 426 # loop. (case 3)
401 427 #
402 428 # During this step, we may detect obsolescence cycles: a node
403 429 # with unknown successors sets but already in the call stack.
404 430 # In such a situation, we arbitrary set the successors sets of
405 431 # the node to nothing (node pruned) to break the cycle.
406 432 #
407 433 # If no break was encountered we proceed to phase 2.
408 434 #
409 435 # Phase 2 computes successors sets of CURRENT (case 4); see details
410 436 # in phase 2 itself.
411 437 #
412 438 # Note the two levels of iteration in each phase.
413 439 # - The first one handles obsolescence markers using CURRENT as
414 440 # precursor (successors markers of CURRENT).
415 441 #
416 442 # Having multiple entry here means divergence.
417 443 #
418 444 # - The second one handles successors defined in each marker.
419 445 #
420 446 # Having none means pruned node, multiple successors means split,
421 447 # single successors are standard replacement.
422 448 #
423 449 for mark in sorted(succmarkers[current]):
424 450 for suc in mark[1]:
425 451 if suc not in cache:
426 452 if suc in stackedset:
427 453 # cycle breaking
428 454 cache[suc] = []
429 455 else:
430 456 # case (3) If we have not computed successors sets
431 457 # of one of those successors we add it to the
432 458 # `toproceed` stack and stop all work for this
433 459 # iteration.
434 460 toproceed.append(suc)
435 461 stackedset.add(suc)
436 462 break
437 463 else:
438 464 continue
439 465 break
440 466 else:
441 467 # case (4): we know all successors sets of all direct
442 468 # successors
443 469 #
444 470 # Successors set contributed by each marker depends on the
445 471 # successors sets of all its "successors" node.
446 472 #
447 473 # Each different marker is a divergence in the obsolescence
448 474 # history. It contributes successors sets distinct from other
449 475 # markers.
450 476 #
451 477 # Within a marker, a successor may have divergent successors
452 478 # sets. In such a case, the marker will contribute multiple
453 479 # divergent successors sets. If multiple successors have
454 480 # divergent successors sets, a Cartesian product is used.
455 481 #
456 482 # At the end we post-process successors sets to remove
457 483 # duplicated entry and successors set that are strict subset of
458 484 # another one.
459 485 succssets = []
460 486 for mark in sorted(succmarkers[current]):
461 487 # successors sets contributed by this marker
462 488 markss = [[]]
463 489 for suc in mark[1]:
464 490 # cardinal product with previous successors
465 491 productresult = []
466 492 for prefix in markss:
467 493 for suffix in cache[suc]:
468 494 newss = list(prefix)
469 495 for part in suffix:
470 496 # do not duplicated entry in successors set
471 497 # first entry wins.
472 498 if part not in newss:
473 499 newss.append(part)
474 500 productresult.append(newss)
475 501 markss = productresult
476 502 succssets.extend(markss)
477 503 # remove duplicated and subset
478 504 seen = []
479 505 final = []
480 506 candidate = sorted(((set(s), s) for s in succssets if s),
481 507 key=lambda x: len(x[1]), reverse=True)
482 508 for setversion, listversion in candidate:
483 509 for seenset in seen:
484 510 if setversion.issubset(seenset):
485 511 break
486 512 else:
487 513 final.append(listversion)
488 514 seen.append(setversion)
489 515 final.reverse() # put small successors set first
490 516 cache[current] = final
491 517 return cache[initialnode]
@@ -1,1061 +1,1076 b''
1 1 # scmutil.py - Mercurial core utility functions
2 2 #
3 3 # Copyright 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 errno
11 11 import glob
12 12 import hashlib
13 13 import os
14 14 import re
15 15 import socket
16 import weakref
16 17
17 18 from .i18n import _
18 19 from .node import (
19 20 hex,
20 21 nullid,
21 22 wdirid,
22 23 wdirrev,
23 24 )
24 25
26 from .i18n import _
25 27 from . import (
26 28 encoding,
27 29 error,
28 30 match as matchmod,
29 31 obsolete,
32 obsutil,
30 33 pathutil,
31 34 phases,
32 35 pycompat,
33 36 revsetlang,
34 37 similar,
35 38 util,
36 39 )
37 40
38 41 if pycompat.osname == 'nt':
39 42 from . import scmwindows as scmplatform
40 43 else:
41 44 from . import scmposix as scmplatform
42 45
43 46 termsize = scmplatform.termsize
44 47
45 48 class status(tuple):
46 49 '''Named tuple with a list of files per status. The 'deleted', 'unknown'
47 50 and 'ignored' properties are only relevant to the working copy.
48 51 '''
49 52
50 53 __slots__ = ()
51 54
52 55 def __new__(cls, modified, added, removed, deleted, unknown, ignored,
53 56 clean):
54 57 return tuple.__new__(cls, (modified, added, removed, deleted, unknown,
55 58 ignored, clean))
56 59
57 60 @property
58 61 def modified(self):
59 62 '''files that have been modified'''
60 63 return self[0]
61 64
62 65 @property
63 66 def added(self):
64 67 '''files that have been added'''
65 68 return self[1]
66 69
67 70 @property
68 71 def removed(self):
69 72 '''files that have been removed'''
70 73 return self[2]
71 74
72 75 @property
73 76 def deleted(self):
74 77 '''files that are in the dirstate, but have been deleted from the
75 78 working copy (aka "missing")
76 79 '''
77 80 return self[3]
78 81
79 82 @property
80 83 def unknown(self):
81 84 '''files not in the dirstate that are not ignored'''
82 85 return self[4]
83 86
84 87 @property
85 88 def ignored(self):
86 89 '''files not in the dirstate that are ignored (by _dirignore())'''
87 90 return self[5]
88 91
89 92 @property
90 93 def clean(self):
91 94 '''files that have not been modified'''
92 95 return self[6]
93 96
94 97 def __repr__(self, *args, **kwargs):
95 98 return (('<status modified=%r, added=%r, removed=%r, deleted=%r, '
96 99 'unknown=%r, ignored=%r, clean=%r>') % self)
97 100
98 101 def itersubrepos(ctx1, ctx2):
99 102 """find subrepos in ctx1 or ctx2"""
100 103 # Create a (subpath, ctx) mapping where we prefer subpaths from
101 104 # ctx1. The subpaths from ctx2 are important when the .hgsub file
102 105 # has been modified (in ctx2) but not yet committed (in ctx1).
103 106 subpaths = dict.fromkeys(ctx2.substate, ctx2)
104 107 subpaths.update(dict.fromkeys(ctx1.substate, ctx1))
105 108
106 109 missing = set()
107 110
108 111 for subpath in ctx2.substate:
109 112 if subpath not in ctx1.substate:
110 113 del subpaths[subpath]
111 114 missing.add(subpath)
112 115
113 116 for subpath, ctx in sorted(subpaths.iteritems()):
114 117 yield subpath, ctx.sub(subpath)
115 118
116 119 # Yield an empty subrepo based on ctx1 for anything only in ctx2. That way,
117 120 # status and diff will have an accurate result when it does
118 121 # 'sub.{status|diff}(rev2)'. Otherwise, the ctx2 subrepo is compared
119 122 # against itself.
120 123 for subpath in missing:
121 124 yield subpath, ctx2.nullsub(subpath, ctx1)
122 125
123 126 def nochangesfound(ui, repo, excluded=None):
124 127 '''Report no changes for push/pull, excluded is None or a list of
125 128 nodes excluded from the push/pull.
126 129 '''
127 130 secretlist = []
128 131 if excluded:
129 132 for n in excluded:
130 133 ctx = repo[n]
131 134 if ctx.phase() >= phases.secret and not ctx.extinct():
132 135 secretlist.append(n)
133 136
134 137 if secretlist:
135 138 ui.status(_("no changes found (ignored %d secret changesets)\n")
136 139 % len(secretlist))
137 140 else:
138 141 ui.status(_("no changes found\n"))
139 142
140 143 def callcatch(ui, func):
141 144 """call func() with global exception handling
142 145
143 146 return func() if no exception happens. otherwise do some error handling
144 147 and return an exit code accordingly. does not handle all exceptions.
145 148 """
146 149 try:
147 150 try:
148 151 return func()
149 152 except: # re-raises
150 153 ui.traceback()
151 154 raise
152 155 # Global exception handling, alphabetically
153 156 # Mercurial-specific first, followed by built-in and library exceptions
154 157 except error.LockHeld as inst:
155 158 if inst.errno == errno.ETIMEDOUT:
156 159 reason = _('timed out waiting for lock held by %r') % inst.locker
157 160 else:
158 161 reason = _('lock held by %r') % inst.locker
159 162 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
160 163 if not inst.locker:
161 164 ui.warn(_("(lock might be very busy)\n"))
162 165 except error.LockUnavailable as inst:
163 166 ui.warn(_("abort: could not lock %s: %s\n") %
164 167 (inst.desc or inst.filename, inst.strerror))
165 168 except error.OutOfBandError as inst:
166 169 if inst.args:
167 170 msg = _("abort: remote error:\n")
168 171 else:
169 172 msg = _("abort: remote error\n")
170 173 ui.warn(msg)
171 174 if inst.args:
172 175 ui.warn(''.join(inst.args))
173 176 if inst.hint:
174 177 ui.warn('(%s)\n' % inst.hint)
175 178 except error.RepoError as inst:
176 179 ui.warn(_("abort: %s!\n") % inst)
177 180 if inst.hint:
178 181 ui.warn(_("(%s)\n") % inst.hint)
179 182 except error.ResponseError as inst:
180 183 ui.warn(_("abort: %s") % inst.args[0])
181 184 if not isinstance(inst.args[1], basestring):
182 185 ui.warn(" %r\n" % (inst.args[1],))
183 186 elif not inst.args[1]:
184 187 ui.warn(_(" empty string\n"))
185 188 else:
186 189 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
187 190 except error.CensoredNodeError as inst:
188 191 ui.warn(_("abort: file censored %s!\n") % inst)
189 192 except error.RevlogError as inst:
190 193 ui.warn(_("abort: %s!\n") % inst)
191 194 except error.InterventionRequired as inst:
192 195 ui.warn("%s\n" % inst)
193 196 if inst.hint:
194 197 ui.warn(_("(%s)\n") % inst.hint)
195 198 return 1
196 199 except error.WdirUnsupported:
197 200 ui.warn(_("abort: working directory revision cannot be specified\n"))
198 201 except error.Abort as inst:
199 202 ui.warn(_("abort: %s\n") % inst)
200 203 if inst.hint:
201 204 ui.warn(_("(%s)\n") % inst.hint)
202 205 except ImportError as inst:
203 206 ui.warn(_("abort: %s!\n") % inst)
204 207 m = str(inst).split()[-1]
205 208 if m in "mpatch bdiff".split():
206 209 ui.warn(_("(did you forget to compile extensions?)\n"))
207 210 elif m in "zlib".split():
208 211 ui.warn(_("(is your Python install correct?)\n"))
209 212 except IOError as inst:
210 213 if util.safehasattr(inst, "code"):
211 214 ui.warn(_("abort: %s\n") % inst)
212 215 elif util.safehasattr(inst, "reason"):
213 216 try: # usually it is in the form (errno, strerror)
214 217 reason = inst.reason.args[1]
215 218 except (AttributeError, IndexError):
216 219 # it might be anything, for example a string
217 220 reason = inst.reason
218 221 if isinstance(reason, unicode):
219 222 # SSLError of Python 2.7.9 contains a unicode
220 223 reason = encoding.unitolocal(reason)
221 224 ui.warn(_("abort: error: %s\n") % reason)
222 225 elif (util.safehasattr(inst, "args")
223 226 and inst.args and inst.args[0] == errno.EPIPE):
224 227 pass
225 228 elif getattr(inst, "strerror", None):
226 229 if getattr(inst, "filename", None):
227 230 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
228 231 else:
229 232 ui.warn(_("abort: %s\n") % inst.strerror)
230 233 else:
231 234 raise
232 235 except OSError as inst:
233 236 if getattr(inst, "filename", None) is not None:
234 237 ui.warn(_("abort: %s: '%s'\n") % (inst.strerror, inst.filename))
235 238 else:
236 239 ui.warn(_("abort: %s\n") % inst.strerror)
237 240 except MemoryError:
238 241 ui.warn(_("abort: out of memory\n"))
239 242 except SystemExit as inst:
240 243 # Commands shouldn't sys.exit directly, but give a return code.
241 244 # Just in case catch this and and pass exit code to caller.
242 245 return inst.code
243 246 except socket.error as inst:
244 247 ui.warn(_("abort: %s\n") % inst.args[-1])
245 248
246 249 return -1
247 250
248 251 def checknewlabel(repo, lbl, kind):
249 252 # Do not use the "kind" parameter in ui output.
250 253 # It makes strings difficult to translate.
251 254 if lbl in ['tip', '.', 'null']:
252 255 raise error.Abort(_("the name '%s' is reserved") % lbl)
253 256 for c in (':', '\0', '\n', '\r'):
254 257 if c in lbl:
255 258 raise error.Abort(_("%r cannot be used in a name") % c)
256 259 try:
257 260 int(lbl)
258 261 raise error.Abort(_("cannot use an integer as a name"))
259 262 except ValueError:
260 263 pass
261 264
262 265 def checkfilename(f):
263 266 '''Check that the filename f is an acceptable filename for a tracked file'''
264 267 if '\r' in f or '\n' in f:
265 268 raise error.Abort(_("'\\n' and '\\r' disallowed in filenames: %r") % f)
266 269
267 270 def checkportable(ui, f):
268 271 '''Check if filename f is portable and warn or abort depending on config'''
269 272 checkfilename(f)
270 273 abort, warn = checkportabilityalert(ui)
271 274 if abort or warn:
272 275 msg = util.checkwinfilename(f)
273 276 if msg:
274 277 msg = "%s: %r" % (msg, f)
275 278 if abort:
276 279 raise error.Abort(msg)
277 280 ui.warn(_("warning: %s\n") % msg)
278 281
279 282 def checkportabilityalert(ui):
280 283 '''check if the user's config requests nothing, a warning, or abort for
281 284 non-portable filenames'''
282 285 val = ui.config('ui', 'portablefilenames', 'warn')
283 286 lval = val.lower()
284 287 bval = util.parsebool(val)
285 288 abort = pycompat.osname == 'nt' or lval == 'abort'
286 289 warn = bval or lval == 'warn'
287 290 if bval is None and not (warn or abort or lval == 'ignore'):
288 291 raise error.ConfigError(
289 292 _("ui.portablefilenames value is invalid ('%s')") % val)
290 293 return abort, warn
291 294
292 295 class casecollisionauditor(object):
293 296 def __init__(self, ui, abort, dirstate):
294 297 self._ui = ui
295 298 self._abort = abort
296 299 allfiles = '\0'.join(dirstate._map)
297 300 self._loweredfiles = set(encoding.lower(allfiles).split('\0'))
298 301 self._dirstate = dirstate
299 302 # The purpose of _newfiles is so that we don't complain about
300 303 # case collisions if someone were to call this object with the
301 304 # same filename twice.
302 305 self._newfiles = set()
303 306
304 307 def __call__(self, f):
305 308 if f in self._newfiles:
306 309 return
307 310 fl = encoding.lower(f)
308 311 if fl in self._loweredfiles and f not in self._dirstate:
309 312 msg = _('possible case-folding collision for %s') % f
310 313 if self._abort:
311 314 raise error.Abort(msg)
312 315 self._ui.warn(_("warning: %s\n") % msg)
313 316 self._loweredfiles.add(fl)
314 317 self._newfiles.add(f)
315 318
316 319 def filteredhash(repo, maxrev):
317 320 """build hash of filtered revisions in the current repoview.
318 321
319 322 Multiple caches perform up-to-date validation by checking that the
320 323 tiprev and tipnode stored in the cache file match the current repository.
321 324 However, this is not sufficient for validating repoviews because the set
322 325 of revisions in the view may change without the repository tiprev and
323 326 tipnode changing.
324 327
325 328 This function hashes all the revs filtered from the view and returns
326 329 that SHA-1 digest.
327 330 """
328 331 cl = repo.changelog
329 332 if not cl.filteredrevs:
330 333 return None
331 334 key = None
332 335 revs = sorted(r for r in cl.filteredrevs if r <= maxrev)
333 336 if revs:
334 337 s = hashlib.sha1()
335 338 for rev in revs:
336 339 s.update('%d;' % rev)
337 340 key = s.digest()
338 341 return key
339 342
340 343 def walkrepos(path, followsym=False, seen_dirs=None, recurse=False):
341 344 '''yield every hg repository under path, always recursively.
342 345 The recurse flag will only control recursion into repo working dirs'''
343 346 def errhandler(err):
344 347 if err.filename == path:
345 348 raise err
346 349 samestat = getattr(os.path, 'samestat', None)
347 350 if followsym and samestat is not None:
348 351 def adddir(dirlst, dirname):
349 352 match = False
350 353 dirstat = os.stat(dirname)
351 354 for lstdirstat in dirlst:
352 355 if samestat(dirstat, lstdirstat):
353 356 match = True
354 357 break
355 358 if not match:
356 359 dirlst.append(dirstat)
357 360 return not match
358 361 else:
359 362 followsym = False
360 363
361 364 if (seen_dirs is None) and followsym:
362 365 seen_dirs = []
363 366 adddir(seen_dirs, path)
364 367 for root, dirs, files in os.walk(path, topdown=True, onerror=errhandler):
365 368 dirs.sort()
366 369 if '.hg' in dirs:
367 370 yield root # found a repository
368 371 qroot = os.path.join(root, '.hg', 'patches')
369 372 if os.path.isdir(os.path.join(qroot, '.hg')):
370 373 yield qroot # we have a patch queue repo here
371 374 if recurse:
372 375 # avoid recursing inside the .hg directory
373 376 dirs.remove('.hg')
374 377 else:
375 378 dirs[:] = [] # don't descend further
376 379 elif followsym:
377 380 newdirs = []
378 381 for d in dirs:
379 382 fname = os.path.join(root, d)
380 383 if adddir(seen_dirs, fname):
381 384 if os.path.islink(fname):
382 385 for hgname in walkrepos(fname, True, seen_dirs):
383 386 yield hgname
384 387 else:
385 388 newdirs.append(d)
386 389 dirs[:] = newdirs
387 390
388 391 def binnode(ctx):
389 392 """Return binary node id for a given basectx"""
390 393 node = ctx.node()
391 394 if node is None:
392 395 return wdirid
393 396 return node
394 397
395 398 def intrev(ctx):
396 399 """Return integer for a given basectx that can be used in comparison or
397 400 arithmetic operation"""
398 401 rev = ctx.rev()
399 402 if rev is None:
400 403 return wdirrev
401 404 return rev
402 405
403 406 def revsingle(repo, revspec, default='.'):
404 407 if not revspec and revspec != 0:
405 408 return repo[default]
406 409
407 410 l = revrange(repo, [revspec])
408 411 if not l:
409 412 raise error.Abort(_('empty revision set'))
410 413 return repo[l.last()]
411 414
412 415 def _pairspec(revspec):
413 416 tree = revsetlang.parse(revspec)
414 417 return tree and tree[0] in ('range', 'rangepre', 'rangepost', 'rangeall')
415 418
416 419 def revpair(repo, revs):
417 420 if not revs:
418 421 return repo.dirstate.p1(), None
419 422
420 423 l = revrange(repo, revs)
421 424
422 425 if not l:
423 426 first = second = None
424 427 elif l.isascending():
425 428 first = l.min()
426 429 second = l.max()
427 430 elif l.isdescending():
428 431 first = l.max()
429 432 second = l.min()
430 433 else:
431 434 first = l.first()
432 435 second = l.last()
433 436
434 437 if first is None:
435 438 raise error.Abort(_('empty revision range'))
436 439 if (first == second and len(revs) >= 2
437 440 and not all(revrange(repo, [r]) for r in revs)):
438 441 raise error.Abort(_('empty revision on one side of range'))
439 442
440 443 # if top-level is range expression, the result must always be a pair
441 444 if first == second and len(revs) == 1 and not _pairspec(revs[0]):
442 445 return repo.lookup(first), None
443 446
444 447 return repo.lookup(first), repo.lookup(second)
445 448
446 449 def revrange(repo, specs):
447 450 """Execute 1 to many revsets and return the union.
448 451
449 452 This is the preferred mechanism for executing revsets using user-specified
450 453 config options, such as revset aliases.
451 454
452 455 The revsets specified by ``specs`` will be executed via a chained ``OR``
453 456 expression. If ``specs`` is empty, an empty result is returned.
454 457
455 458 ``specs`` can contain integers, in which case they are assumed to be
456 459 revision numbers.
457 460
458 461 It is assumed the revsets are already formatted. If you have arguments
459 462 that need to be expanded in the revset, call ``revsetlang.formatspec()``
460 463 and pass the result as an element of ``specs``.
461 464
462 465 Specifying a single revset is allowed.
463 466
464 467 Returns a ``revset.abstractsmartset`` which is a list-like interface over
465 468 integer revisions.
466 469 """
467 470 allspecs = []
468 471 for spec in specs:
469 472 if isinstance(spec, int):
470 473 spec = revsetlang.formatspec('rev(%d)', spec)
471 474 allspecs.append(spec)
472 475 return repo.anyrevs(allspecs, user=True)
473 476
474 477 def meaningfulparents(repo, ctx):
475 478 """Return list of meaningful (or all if debug) parentrevs for rev.
476 479
477 480 For merges (two non-nullrev revisions) both parents are meaningful.
478 481 Otherwise the first parent revision is considered meaningful if it
479 482 is not the preceding revision.
480 483 """
481 484 parents = ctx.parents()
482 485 if len(parents) > 1:
483 486 return parents
484 487 if repo.ui.debugflag:
485 488 return [parents[0], repo['null']]
486 489 if parents[0].rev() >= intrev(ctx) - 1:
487 490 return []
488 491 return parents
489 492
490 493 def expandpats(pats):
491 494 '''Expand bare globs when running on windows.
492 495 On posix we assume it already has already been done by sh.'''
493 496 if not util.expandglobs:
494 497 return list(pats)
495 498 ret = []
496 499 for kindpat in pats:
497 500 kind, pat = matchmod._patsplit(kindpat, None)
498 501 if kind is None:
499 502 try:
500 503 globbed = glob.glob(pat)
501 504 except re.error:
502 505 globbed = [pat]
503 506 if globbed:
504 507 ret.extend(globbed)
505 508 continue
506 509 ret.append(kindpat)
507 510 return ret
508 511
509 512 def matchandpats(ctx, pats=(), opts=None, globbed=False, default='relpath',
510 513 badfn=None):
511 514 '''Return a matcher and the patterns that were used.
512 515 The matcher will warn about bad matches, unless an alternate badfn callback
513 516 is provided.'''
514 517 if pats == ("",):
515 518 pats = []
516 519 if opts is None:
517 520 opts = {}
518 521 if not globbed and default == 'relpath':
519 522 pats = expandpats(pats or [])
520 523
521 524 def bad(f, msg):
522 525 ctx.repo().ui.warn("%s: %s\n" % (m.rel(f), msg))
523 526
524 527 if badfn is None:
525 528 badfn = bad
526 529
527 530 m = ctx.match(pats, opts.get('include'), opts.get('exclude'),
528 531 default, listsubrepos=opts.get('subrepos'), badfn=badfn)
529 532
530 533 if m.always():
531 534 pats = []
532 535 return m, pats
533 536
534 537 def match(ctx, pats=(), opts=None, globbed=False, default='relpath',
535 538 badfn=None):
536 539 '''Return a matcher that will warn about bad matches.'''
537 540 return matchandpats(ctx, pats, opts, globbed, default, badfn=badfn)[0]
538 541
539 542 def matchall(repo):
540 543 '''Return a matcher that will efficiently match everything.'''
541 544 return matchmod.always(repo.root, repo.getcwd())
542 545
543 546 def matchfiles(repo, files, badfn=None):
544 547 '''Return a matcher that will efficiently match exactly these files.'''
545 548 return matchmod.exact(repo.root, repo.getcwd(), files, badfn=badfn)
546 549
547 550 def origpath(ui, repo, filepath):
548 551 '''customize where .orig files are created
549 552
550 553 Fetch user defined path from config file: [ui] origbackuppath = <path>
551 554 Fall back to default (filepath) if not specified
552 555 '''
553 556 origbackuppath = ui.config('ui', 'origbackuppath', None)
554 557 if origbackuppath is None:
555 558 return filepath + ".orig"
556 559
557 560 filepathfromroot = os.path.relpath(filepath, start=repo.root)
558 561 fullorigpath = repo.wjoin(origbackuppath, filepathfromroot)
559 562
560 563 origbackupdir = repo.vfs.dirname(fullorigpath)
561 564 if not repo.vfs.exists(origbackupdir):
562 565 ui.note(_('creating directory: %s\n') % origbackupdir)
563 566 util.makedirs(origbackupdir)
564 567
565 568 return fullorigpath + ".orig"
566 569
567 570 def cleanupnodes(repo, mapping, operation):
568 571 """do common cleanups when old nodes are replaced by new nodes
569 572
570 573 That includes writing obsmarkers or stripping nodes, and moving bookmarks.
571 574 (we might also want to move working directory parent in the future)
572 575
573 576 mapping is {oldnode: [newnode]} or a iterable of nodes if they do not have
574 577 replacements. operation is a string, like "rebase".
575 578 """
576 579 if not util.safehasattr(mapping, 'items'):
577 580 mapping = {n: () for n in mapping}
578 581
579 582 with repo.transaction('cleanup') as tr:
580 583 # Move bookmarks
581 584 bmarks = repo._bookmarks
582 585 bmarkchanged = False
583 586 for oldnode, newnodes in mapping.items():
584 587 oldbmarks = repo.nodebookmarks(oldnode)
585 588 if not oldbmarks:
586 589 continue
587 590 bmarkchanged = True
588 591 if len(newnodes) > 1:
589 592 heads = list(repo.set('heads(%ln)', newnodes))
590 593 if len(heads) != 1:
591 594 raise error.ProgrammingError(
592 595 'cannot figure out bookmark movement')
593 596 newnode = heads[0].node()
594 597 elif len(newnodes) == 0:
595 598 # move bookmark backwards
596 599 roots = list(repo.set('max((::%n) - %ln)', oldnode,
597 600 list(mapping)))
598 601 if roots:
599 602 newnode = roots[0].node()
600 603 else:
601 604 newnode = nullid
602 605 else:
603 606 newnode = newnodes[0]
604 607 repo.ui.debug('moving bookmarks %r from %s to %s\n' %
605 608 (oldbmarks, hex(oldnode), hex(newnode)))
606 609 for name in oldbmarks:
607 610 bmarks[name] = newnode
608 611 if bmarkchanged:
609 612 bmarks.recordchange(tr)
610 613
611 614 # Obsolete or strip nodes
612 615 if obsolete.isenabled(repo, obsolete.createmarkersopt):
613 616 # If a node is already obsoleted, and we want to obsolete it
614 617 # without a successor, skip that obssolete request since it's
615 618 # unnecessary. That's the "if s or not isobs(n)" check below.
616 619 # Also sort the node in topology order, that might be useful for
617 620 # some obsstore logic.
618 621 # NOTE: the filtering and sorting might belong to createmarkers.
619 622 isobs = repo.obsstore.successors.__contains__
620 623 sortfunc = lambda ns: repo.changelog.rev(ns[0])
621 624 rels = [(repo[n], (repo[m] for m in s))
622 625 for n, s in sorted(mapping.items(), key=sortfunc)
623 626 if s or not isobs(n)]
624 627 obsolete.createmarkers(repo, rels, operation=operation)
625 628 else:
626 629 from . import repair # avoid import cycle
627 630 repair.delayedstrip(repo.ui, repo, list(mapping), operation)
628 631
629 632 def addremove(repo, matcher, prefix, opts=None, dry_run=None, similarity=None):
630 633 if opts is None:
631 634 opts = {}
632 635 m = matcher
633 636 if dry_run is None:
634 637 dry_run = opts.get('dry_run')
635 638 if similarity is None:
636 639 similarity = float(opts.get('similarity') or 0)
637 640
638 641 ret = 0
639 642 join = lambda f: os.path.join(prefix, f)
640 643
641 644 wctx = repo[None]
642 645 for subpath in sorted(wctx.substate):
643 646 submatch = matchmod.subdirmatcher(subpath, m)
644 647 if opts.get('subrepos') or m.exact(subpath) or any(submatch.files()):
645 648 sub = wctx.sub(subpath)
646 649 try:
647 650 if sub.addremove(submatch, prefix, opts, dry_run, similarity):
648 651 ret = 1
649 652 except error.LookupError:
650 653 repo.ui.status(_("skipping missing subrepository: %s\n")
651 654 % join(subpath))
652 655
653 656 rejected = []
654 657 def badfn(f, msg):
655 658 if f in m.files():
656 659 m.bad(f, msg)
657 660 rejected.append(f)
658 661
659 662 badmatch = matchmod.badmatch(m, badfn)
660 663 added, unknown, deleted, removed, forgotten = _interestingfiles(repo,
661 664 badmatch)
662 665
663 666 unknownset = set(unknown + forgotten)
664 667 toprint = unknownset.copy()
665 668 toprint.update(deleted)
666 669 for abs in sorted(toprint):
667 670 if repo.ui.verbose or not m.exact(abs):
668 671 if abs in unknownset:
669 672 status = _('adding %s\n') % m.uipath(abs)
670 673 else:
671 674 status = _('removing %s\n') % m.uipath(abs)
672 675 repo.ui.status(status)
673 676
674 677 renames = _findrenames(repo, m, added + unknown, removed + deleted,
675 678 similarity)
676 679
677 680 if not dry_run:
678 681 _markchanges(repo, unknown + forgotten, deleted, renames)
679 682
680 683 for f in rejected:
681 684 if f in m.files():
682 685 return 1
683 686 return ret
684 687
685 688 def marktouched(repo, files, similarity=0.0):
686 689 '''Assert that files have somehow been operated upon. files are relative to
687 690 the repo root.'''
688 691 m = matchfiles(repo, files, badfn=lambda x, y: rejected.append(x))
689 692 rejected = []
690 693
691 694 added, unknown, deleted, removed, forgotten = _interestingfiles(repo, m)
692 695
693 696 if repo.ui.verbose:
694 697 unknownset = set(unknown + forgotten)
695 698 toprint = unknownset.copy()
696 699 toprint.update(deleted)
697 700 for abs in sorted(toprint):
698 701 if abs in unknownset:
699 702 status = _('adding %s\n') % abs
700 703 else:
701 704 status = _('removing %s\n') % abs
702 705 repo.ui.status(status)
703 706
704 707 renames = _findrenames(repo, m, added + unknown, removed + deleted,
705 708 similarity)
706 709
707 710 _markchanges(repo, unknown + forgotten, deleted, renames)
708 711
709 712 for f in rejected:
710 713 if f in m.files():
711 714 return 1
712 715 return 0
713 716
714 717 def _interestingfiles(repo, matcher):
715 718 '''Walk dirstate with matcher, looking for files that addremove would care
716 719 about.
717 720
718 721 This is different from dirstate.status because it doesn't care about
719 722 whether files are modified or clean.'''
720 723 added, unknown, deleted, removed, forgotten = [], [], [], [], []
721 724 audit_path = pathutil.pathauditor(repo.root)
722 725
723 726 ctx = repo[None]
724 727 dirstate = repo.dirstate
725 728 walkresults = dirstate.walk(matcher, sorted(ctx.substate), True, False,
726 729 full=False)
727 730 for abs, st in walkresults.iteritems():
728 731 dstate = dirstate[abs]
729 732 if dstate == '?' and audit_path.check(abs):
730 733 unknown.append(abs)
731 734 elif dstate != 'r' and not st:
732 735 deleted.append(abs)
733 736 elif dstate == 'r' and st:
734 737 forgotten.append(abs)
735 738 # for finding renames
736 739 elif dstate == 'r' and not st:
737 740 removed.append(abs)
738 741 elif dstate == 'a':
739 742 added.append(abs)
740 743
741 744 return added, unknown, deleted, removed, forgotten
742 745
743 746 def _findrenames(repo, matcher, added, removed, similarity):
744 747 '''Find renames from removed files to added ones.'''
745 748 renames = {}
746 749 if similarity > 0:
747 750 for old, new, score in similar.findrenames(repo, added, removed,
748 751 similarity):
749 752 if (repo.ui.verbose or not matcher.exact(old)
750 753 or not matcher.exact(new)):
751 754 repo.ui.status(_('recording removal of %s as rename to %s '
752 755 '(%d%% similar)\n') %
753 756 (matcher.rel(old), matcher.rel(new),
754 757 score * 100))
755 758 renames[new] = old
756 759 return renames
757 760
758 761 def _markchanges(repo, unknown, deleted, renames):
759 762 '''Marks the files in unknown as added, the files in deleted as removed,
760 763 and the files in renames as copied.'''
761 764 wctx = repo[None]
762 765 with repo.wlock():
763 766 wctx.forget(deleted)
764 767 wctx.add(unknown)
765 768 for new, old in renames.iteritems():
766 769 wctx.copy(old, new)
767 770
768 771 def dirstatecopy(ui, repo, wctx, src, dst, dryrun=False, cwd=None):
769 772 """Update the dirstate to reflect the intent of copying src to dst. For
770 773 different reasons it might not end with dst being marked as copied from src.
771 774 """
772 775 origsrc = repo.dirstate.copied(src) or src
773 776 if dst == origsrc: # copying back a copy?
774 777 if repo.dirstate[dst] not in 'mn' and not dryrun:
775 778 repo.dirstate.normallookup(dst)
776 779 else:
777 780 if repo.dirstate[origsrc] == 'a' and origsrc == src:
778 781 if not ui.quiet:
779 782 ui.warn(_("%s has not been committed yet, so no copy "
780 783 "data will be stored for %s.\n")
781 784 % (repo.pathto(origsrc, cwd), repo.pathto(dst, cwd)))
782 785 if repo.dirstate[dst] in '?r' and not dryrun:
783 786 wctx.add([dst])
784 787 elif not dryrun:
785 788 wctx.copy(origsrc, dst)
786 789
787 790 def readrequires(opener, supported):
788 791 '''Reads and parses .hg/requires and checks if all entries found
789 792 are in the list of supported features.'''
790 793 requirements = set(opener.read("requires").splitlines())
791 794 missings = []
792 795 for r in requirements:
793 796 if r not in supported:
794 797 if not r or not r[0].isalnum():
795 798 raise error.RequirementError(_(".hg/requires file is corrupt"))
796 799 missings.append(r)
797 800 missings.sort()
798 801 if missings:
799 802 raise error.RequirementError(
800 803 _("repository requires features unknown to this Mercurial: %s")
801 804 % " ".join(missings),
802 805 hint=_("see https://mercurial-scm.org/wiki/MissingRequirement"
803 806 " for more information"))
804 807 return requirements
805 808
806 809 def writerequires(opener, requirements):
807 810 with opener('requires', 'w') as fp:
808 811 for r in sorted(requirements):
809 812 fp.write("%s\n" % r)
810 813
811 814 class filecachesubentry(object):
812 815 def __init__(self, path, stat):
813 816 self.path = path
814 817 self.cachestat = None
815 818 self._cacheable = None
816 819
817 820 if stat:
818 821 self.cachestat = filecachesubentry.stat(self.path)
819 822
820 823 if self.cachestat:
821 824 self._cacheable = self.cachestat.cacheable()
822 825 else:
823 826 # None means we don't know yet
824 827 self._cacheable = None
825 828
826 829 def refresh(self):
827 830 if self.cacheable():
828 831 self.cachestat = filecachesubentry.stat(self.path)
829 832
830 833 def cacheable(self):
831 834 if self._cacheable is not None:
832 835 return self._cacheable
833 836
834 837 # we don't know yet, assume it is for now
835 838 return True
836 839
837 840 def changed(self):
838 841 # no point in going further if we can't cache it
839 842 if not self.cacheable():
840 843 return True
841 844
842 845 newstat = filecachesubentry.stat(self.path)
843 846
844 847 # we may not know if it's cacheable yet, check again now
845 848 if newstat and self._cacheable is None:
846 849 self._cacheable = newstat.cacheable()
847 850
848 851 # check again
849 852 if not self._cacheable:
850 853 return True
851 854
852 855 if self.cachestat != newstat:
853 856 self.cachestat = newstat
854 857 return True
855 858 else:
856 859 return False
857 860
858 861 @staticmethod
859 862 def stat(path):
860 863 try:
861 864 return util.cachestat(path)
862 865 except OSError as e:
863 866 if e.errno != errno.ENOENT:
864 867 raise
865 868
866 869 class filecacheentry(object):
867 870 def __init__(self, paths, stat=True):
868 871 self._entries = []
869 872 for path in paths:
870 873 self._entries.append(filecachesubentry(path, stat))
871 874
872 875 def changed(self):
873 876 '''true if any entry has changed'''
874 877 for entry in self._entries:
875 878 if entry.changed():
876 879 return True
877 880 return False
878 881
879 882 def refresh(self):
880 883 for entry in self._entries:
881 884 entry.refresh()
882 885
883 886 class filecache(object):
884 887 '''A property like decorator that tracks files under .hg/ for updates.
885 888
886 889 Records stat info when called in _filecache.
887 890
888 891 On subsequent calls, compares old stat info with new info, and recreates the
889 892 object when any of the files changes, updating the new stat info in
890 893 _filecache.
891 894
892 895 Mercurial either atomic renames or appends for files under .hg,
893 896 so to ensure the cache is reliable we need the filesystem to be able
894 897 to tell us if a file has been replaced. If it can't, we fallback to
895 898 recreating the object on every call (essentially the same behavior as
896 899 propertycache).
897 900
898 901 '''
899 902 def __init__(self, *paths):
900 903 self.paths = paths
901 904
902 905 def join(self, obj, fname):
903 906 """Used to compute the runtime path of a cached file.
904 907
905 908 Users should subclass filecache and provide their own version of this
906 909 function to call the appropriate join function on 'obj' (an instance
907 910 of the class that its member function was decorated).
908 911 """
909 912 raise NotImplementedError
910 913
911 914 def __call__(self, func):
912 915 self.func = func
913 916 self.name = func.__name__.encode('ascii')
914 917 return self
915 918
916 919 def __get__(self, obj, type=None):
917 920 # if accessed on the class, return the descriptor itself.
918 921 if obj is None:
919 922 return self
920 923 # do we need to check if the file changed?
921 924 if self.name in obj.__dict__:
922 925 assert self.name in obj._filecache, self.name
923 926 return obj.__dict__[self.name]
924 927
925 928 entry = obj._filecache.get(self.name)
926 929
927 930 if entry:
928 931 if entry.changed():
929 932 entry.obj = self.func(obj)
930 933 else:
931 934 paths = [self.join(obj, path) for path in self.paths]
932 935
933 936 # We stat -before- creating the object so our cache doesn't lie if
934 937 # a writer modified between the time we read and stat
935 938 entry = filecacheentry(paths, True)
936 939 entry.obj = self.func(obj)
937 940
938 941 obj._filecache[self.name] = entry
939 942
940 943 obj.__dict__[self.name] = entry.obj
941 944 return entry.obj
942 945
943 946 def __set__(self, obj, value):
944 947 if self.name not in obj._filecache:
945 948 # we add an entry for the missing value because X in __dict__
946 949 # implies X in _filecache
947 950 paths = [self.join(obj, path) for path in self.paths]
948 951 ce = filecacheentry(paths, False)
949 952 obj._filecache[self.name] = ce
950 953 else:
951 954 ce = obj._filecache[self.name]
952 955
953 956 ce.obj = value # update cached copy
954 957 obj.__dict__[self.name] = value # update copy returned by obj.x
955 958
956 959 def __delete__(self, obj):
957 960 try:
958 961 del obj.__dict__[self.name]
959 962 except KeyError:
960 963 raise AttributeError(self.name)
961 964
962 965 def _locksub(repo, lock, envvar, cmd, environ=None, *args, **kwargs):
963 966 if lock is None:
964 967 raise error.LockInheritanceContractViolation(
965 968 'lock can only be inherited while held')
966 969 if environ is None:
967 970 environ = {}
968 971 with lock.inherit() as locker:
969 972 environ[envvar] = locker
970 973 return repo.ui.system(cmd, environ=environ, *args, **kwargs)
971 974
972 975 def wlocksub(repo, cmd, *args, **kwargs):
973 976 """run cmd as a subprocess that allows inheriting repo's wlock
974 977
975 978 This can only be called while the wlock is held. This takes all the
976 979 arguments that ui.system does, and returns the exit code of the
977 980 subprocess."""
978 981 return _locksub(repo, repo.currentwlock(), 'HG_WLOCK_LOCKER', cmd, *args,
979 982 **kwargs)
980 983
981 984 def gdinitconfig(ui):
982 985 """helper function to know if a repo should be created as general delta
983 986 """
984 987 # experimental config: format.generaldelta
985 988 return (ui.configbool('format', 'generaldelta')
986 989 or ui.configbool('format', 'usegeneraldelta'))
987 990
988 991 def gddeltaconfig(ui):
989 992 """helper function to know if incoming delta should be optimised
990 993 """
991 994 # experimental config: format.generaldelta
992 995 return ui.configbool('format', 'generaldelta')
993 996
994 997 class simplekeyvaluefile(object):
995 998 """A simple file with key=value lines
996 999
997 1000 Keys must be alphanumerics and start with a letter, values must not
998 1001 contain '\n' characters"""
999 1002 firstlinekey = '__firstline'
1000 1003
1001 1004 def __init__(self, vfs, path, keys=None):
1002 1005 self.vfs = vfs
1003 1006 self.path = path
1004 1007
1005 1008 def read(self, firstlinenonkeyval=False):
1006 1009 """Read the contents of a simple key-value file
1007 1010
1008 1011 'firstlinenonkeyval' indicates whether the first line of file should
1009 1012 be treated as a key-value pair or reuturned fully under the
1010 1013 __firstline key."""
1011 1014 lines = self.vfs.readlines(self.path)
1012 1015 d = {}
1013 1016 if firstlinenonkeyval:
1014 1017 if not lines:
1015 1018 e = _("empty simplekeyvalue file")
1016 1019 raise error.CorruptedState(e)
1017 1020 # we don't want to include '\n' in the __firstline
1018 1021 d[self.firstlinekey] = lines[0][:-1]
1019 1022 del lines[0]
1020 1023
1021 1024 try:
1022 1025 # the 'if line.strip()' part prevents us from failing on empty
1023 1026 # lines which only contain '\n' therefore are not skipped
1024 1027 # by 'if line'
1025 1028 updatedict = dict(line[:-1].split('=', 1) for line in lines
1026 1029 if line.strip())
1027 1030 if self.firstlinekey in updatedict:
1028 1031 e = _("%r can't be used as a key")
1029 1032 raise error.CorruptedState(e % self.firstlinekey)
1030 1033 d.update(updatedict)
1031 1034 except ValueError as e:
1032 1035 raise error.CorruptedState(str(e))
1033 1036 return d
1034 1037
1035 1038 def write(self, data, firstline=None):
1036 1039 """Write key=>value mapping to a file
1037 1040 data is a dict. Keys must be alphanumerical and start with a letter.
1038 1041 Values must not contain newline characters.
1039 1042
1040 1043 If 'firstline' is not None, it is written to file before
1041 1044 everything else, as it is, not in a key=value form"""
1042 1045 lines = []
1043 1046 if firstline is not None:
1044 1047 lines.append('%s\n' % firstline)
1045 1048
1046 1049 for k, v in data.items():
1047 1050 if k == self.firstlinekey:
1048 1051 e = "key name '%s' is reserved" % self.firstlinekey
1049 1052 raise error.ProgrammingError(e)
1050 1053 if not k[0].isalpha():
1051 1054 e = "keys must start with a letter in a key-value file"
1052 1055 raise error.ProgrammingError(e)
1053 1056 if not k.isalnum():
1054 1057 e = "invalid key name in a simple key-value file"
1055 1058 raise error.ProgrammingError(e)
1056 1059 if '\n' in v:
1057 1060 e = "invalid value in a simple key-value file"
1058 1061 raise error.ProgrammingError(e)
1059 1062 lines.append("%s=%s\n" % (k, v))
1060 1063 with self.vfs(self.path, mode='wb', atomictemp=True) as fp:
1061 1064 fp.write(''.join(lines))
1065
1066 def registersummarycallback(repo, otr):
1067 """register a callback to issue a summary after the transaction is closed
1068 """
1069 reporef = weakref.ref(repo)
1070 def reportsummary(tr):
1071 """the actual callback reporting the summary"""
1072 repo = reporef()
1073 obsoleted = obsutil.getobsoleted(repo, tr)
1074 if obsoleted:
1075 repo.ui.status(_('obsoleted %i changesets\n') % len(obsoleted))
1076 otr.addpostclose('00-txnreport', reportsummary)
@@ -1,881 +1,882 b''
1 1 #require serve
2 2
3 3 $ cat << EOF >> $HGRCPATH
4 4 > [ui]
5 5 > logtemplate={rev}:{node|short} {desc|firstline}
6 6 > [phases]
7 7 > publish=False
8 8 > [experimental]
9 9 > evolution=createmarkers,exchange
10 10 > EOF
11 11
12 12 initialize
13 13
14 14 $ hg init a
15 15 $ cd a
16 16 $ echo 'test' > test
17 17 $ hg commit -Am'test'
18 18 adding test
19 19
20 20 set bookmarks
21 21
22 22 $ hg bookmark X
23 23 $ hg bookmark Y
24 24 $ hg bookmark Z
25 25
26 26 import bookmark by name
27 27
28 28 $ hg init ../b
29 29 $ cd ../b
30 30 $ hg book Y
31 31 $ hg book
32 32 * Y -1:000000000000
33 33 $ hg pull ../a
34 34 pulling from ../a
35 35 requesting all changes
36 36 adding changesets
37 37 adding manifests
38 38 adding file changes
39 39 added 1 changesets with 1 changes to 1 files
40 40 adding remote bookmark X
41 41 updating bookmark Y
42 42 adding remote bookmark Z
43 43 (run 'hg update' to get a working copy)
44 44 $ hg bookmarks
45 45 X 0:4e3505fd9583
46 46 * Y 0:4e3505fd9583
47 47 Z 0:4e3505fd9583
48 48 $ hg debugpushkey ../a namespaces
49 49 bookmarks
50 50 namespaces
51 51 obsolete
52 52 phases
53 53 $ hg debugpushkey ../a bookmarks
54 54 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
55 55 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
56 56 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
57 57
58 58 delete the bookmark to re-pull it
59 59
60 60 $ hg book -d X
61 61 $ hg pull -B X ../a
62 62 pulling from ../a
63 63 no changes found
64 64 adding remote bookmark X
65 65
66 66 finally no-op pull
67 67
68 68 $ hg pull -B X ../a
69 69 pulling from ../a
70 70 no changes found
71 71 $ hg bookmark
72 72 X 0:4e3505fd9583
73 73 * Y 0:4e3505fd9583
74 74 Z 0:4e3505fd9583
75 75
76 76 export bookmark by name
77 77
78 78 $ hg bookmark W
79 79 $ hg bookmark foo
80 80 $ hg bookmark foobar
81 81 $ hg push -B W ../a
82 82 pushing to ../a
83 83 searching for changes
84 84 no changes found
85 85 exporting bookmark W
86 86 [1]
87 87 $ hg -R ../a bookmarks
88 88 W -1:000000000000
89 89 X 0:4e3505fd9583
90 90 Y 0:4e3505fd9583
91 91 * Z 0:4e3505fd9583
92 92
93 93 delete a remote bookmark
94 94
95 95 $ hg book -d W
96 96 $ hg push -B W ../a
97 97 pushing to ../a
98 98 searching for changes
99 99 no changes found
100 100 deleting remote bookmark W
101 101 [1]
102 102
103 103 export the active bookmark
104 104
105 105 $ hg bookmark V
106 106 $ hg push -B . ../a
107 107 pushing to ../a
108 108 searching for changes
109 109 no changes found
110 110 exporting bookmark V
111 111 [1]
112 112
113 113 exporting the active bookmark with 'push -B .'
114 114 demand that one of the bookmarks is activated
115 115
116 116 $ hg update -r default
117 117 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
118 118 (leaving bookmark V)
119 119 $ hg push -B . ../a
120 120 abort: no active bookmark
121 121 [255]
122 122 $ hg update -r V
123 123 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
124 124 (activating bookmark V)
125 125
126 126 delete the bookmark
127 127
128 128 $ hg book -d V
129 129 $ hg push -B V ../a
130 130 pushing to ../a
131 131 searching for changes
132 132 no changes found
133 133 deleting remote bookmark V
134 134 [1]
135 135 $ hg up foobar
136 136 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
137 137 (activating bookmark foobar)
138 138
139 139 push/pull name that doesn't exist
140 140
141 141 $ hg push -B badname ../a
142 142 pushing to ../a
143 143 searching for changes
144 144 bookmark badname does not exist on the local or remote repository!
145 145 no changes found
146 146 [2]
147 147 $ hg pull -B anotherbadname ../a
148 148 pulling from ../a
149 149 abort: remote bookmark anotherbadname not found!
150 150 [255]
151 151
152 152 divergent bookmarks
153 153
154 154 $ cd ../a
155 155 $ echo c1 > f1
156 156 $ hg ci -Am1
157 157 adding f1
158 158 $ hg book -f @
159 159 $ hg book -f X
160 160 $ hg book
161 161 @ 1:0d2164f0ce0d
162 162 * X 1:0d2164f0ce0d
163 163 Y 0:4e3505fd9583
164 164 Z 1:0d2164f0ce0d
165 165
166 166 $ cd ../b
167 167 $ hg up
168 168 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
169 169 updating bookmark foobar
170 170 $ echo c2 > f2
171 171 $ hg ci -Am2
172 172 adding f2
173 173 $ hg book -if @
174 174 $ hg book -if X
175 175 $ hg book
176 176 @ 1:9b140be10808
177 177 X 1:9b140be10808
178 178 Y 0:4e3505fd9583
179 179 Z 0:4e3505fd9583
180 180 foo -1:000000000000
181 181 * foobar 1:9b140be10808
182 182
183 183 $ hg pull --config paths.foo=../a foo
184 184 pulling from $TESTTMP/a (glob)
185 185 searching for changes
186 186 adding changesets
187 187 adding manifests
188 188 adding file changes
189 189 added 1 changesets with 1 changes to 1 files (+1 heads)
190 190 divergent bookmark @ stored as @foo
191 191 divergent bookmark X stored as X@foo
192 192 updating bookmark Z
193 193 (run 'hg heads' to see heads, 'hg merge' to merge)
194 194 $ hg book
195 195 @ 1:9b140be10808
196 196 @foo 2:0d2164f0ce0d
197 197 X 1:9b140be10808
198 198 X@foo 2:0d2164f0ce0d
199 199 Y 0:4e3505fd9583
200 200 Z 2:0d2164f0ce0d
201 201 foo -1:000000000000
202 202 * foobar 1:9b140be10808
203 203
204 204 (test that too many divergence of bookmark)
205 205
206 206 $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
207 207 $ hg pull ../a
208 208 pulling from ../a
209 209 searching for changes
210 210 no changes found
211 211 warning: failed to assign numbered name to divergent bookmark X
212 212 divergent bookmark @ stored as @1
213 213 $ hg bookmarks | grep '^ X' | grep -v ':000000000000'
214 214 X 1:9b140be10808
215 215 X@foo 2:0d2164f0ce0d
216 216
217 217 (test that remotely diverged bookmarks are reused if they aren't changed)
218 218
219 219 $ hg bookmarks | grep '^ @'
220 220 @ 1:9b140be10808
221 221 @1 2:0d2164f0ce0d
222 222 @foo 2:0d2164f0ce0d
223 223 $ hg pull ../a
224 224 pulling from ../a
225 225 searching for changes
226 226 no changes found
227 227 warning: failed to assign numbered name to divergent bookmark X
228 228 divergent bookmark @ stored as @1
229 229 $ hg bookmarks | grep '^ @'
230 230 @ 1:9b140be10808
231 231 @1 2:0d2164f0ce0d
232 232 @foo 2:0d2164f0ce0d
233 233
234 234 $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
235 235 $ hg bookmarks -d "@1"
236 236
237 237 $ hg push -f ../a
238 238 pushing to ../a
239 239 searching for changes
240 240 adding changesets
241 241 adding manifests
242 242 adding file changes
243 243 added 1 changesets with 1 changes to 1 files (+1 heads)
244 244 $ hg -R ../a book
245 245 @ 1:0d2164f0ce0d
246 246 * X 1:0d2164f0ce0d
247 247 Y 0:4e3505fd9583
248 248 Z 1:0d2164f0ce0d
249 249
250 250 explicit pull should overwrite the local version (issue4439)
251 251
252 252 $ hg update -r X
253 253 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
254 254 (activating bookmark X)
255 255 $ hg pull --config paths.foo=../a foo -B .
256 256 pulling from $TESTTMP/a (glob)
257 257 no changes found
258 258 divergent bookmark @ stored as @foo
259 259 importing bookmark X
260 260
261 261 reinstall state for further testing:
262 262
263 263 $ hg book -fr 9b140be10808 X
264 264
265 265 revsets should not ignore divergent bookmarks
266 266
267 267 $ hg bookmark -fr 1 Z
268 268 $ hg log -r 'bookmark()' --template '{rev}:{node|short} {bookmarks}\n'
269 269 0:4e3505fd9583 Y
270 270 1:9b140be10808 @ X Z foobar
271 271 2:0d2164f0ce0d @foo X@foo
272 272 $ hg log -r 'bookmark("X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
273 273 2:0d2164f0ce0d @foo X@foo
274 274 $ hg log -r 'bookmark("re:X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
275 275 2:0d2164f0ce0d @foo X@foo
276 276
277 277 update a remote bookmark from a non-head to a head
278 278
279 279 $ hg up -q Y
280 280 $ echo c3 > f2
281 281 $ hg ci -Am3
282 282 adding f2
283 283 created new head
284 284 $ hg push ../a
285 285 pushing to ../a
286 286 searching for changes
287 287 adding changesets
288 288 adding manifests
289 289 adding file changes
290 290 added 1 changesets with 1 changes to 1 files (+1 heads)
291 291 updating bookmark Y
292 292 $ hg -R ../a book
293 293 @ 1:0d2164f0ce0d
294 294 * X 1:0d2164f0ce0d
295 295 Y 3:f6fc62dde3c0
296 296 Z 1:0d2164f0ce0d
297 297
298 298 update a bookmark in the middle of a client pulling changes
299 299
300 300 $ cd ..
301 301 $ hg clone -q a pull-race
302 302
303 303 We want to use http because it is stateless and therefore more susceptible to
304 304 race conditions
305 305
306 306 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
307 307 $ cat pull-race.pid >> $DAEMON_PIDS
308 308
309 309 $ cat <<EOF > $TESTTMP/out_makecommit.sh
310 310 > #!/bin/sh
311 311 > hg ci -Am5
312 312 > echo committed in pull-race
313 313 > EOF
314 314
315 315 $ hg clone -q http://localhost:$HGPORT/ pull-race2
316 316 $ cd pull-race
317 317 $ hg up -q Y
318 318 $ echo c4 > f2
319 319 $ hg ci -Am4
320 320 $ echo c5 > f3
321 321 $ cat <<EOF > .hg/hgrc
322 322 > [hooks]
323 323 > outgoing.makecommit = sh $TESTTMP/out_makecommit.sh
324 324 > EOF
325 325
326 326 (new config needs a server restart)
327 327
328 328 $ cd ..
329 329 $ killdaemons.py
330 330 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
331 331 $ cat pull-race.pid >> $DAEMON_PIDS
332 332 $ cd pull-race2
333 333 $ hg -R $TESTTMP/pull-race book
334 334 @ 1:0d2164f0ce0d
335 335 X 1:0d2164f0ce0d
336 336 * Y 4:b0a5eff05604
337 337 Z 1:0d2164f0ce0d
338 338 $ hg pull
339 339 pulling from http://localhost:$HGPORT/
340 340 searching for changes
341 341 adding changesets
342 342 adding manifests
343 343 adding file changes
344 344 added 1 changesets with 1 changes to 1 files
345 345 updating bookmark Y
346 346 (run 'hg update' to get a working copy)
347 347 $ hg book
348 348 * @ 1:0d2164f0ce0d
349 349 X 1:0d2164f0ce0d
350 350 Y 4:b0a5eff05604
351 351 Z 1:0d2164f0ce0d
352 352
353 353 Update a bookmark right after the initial lookup -B (issue4689)
354 354
355 355 $ echo c6 > ../pull-race/f3 # to be committed during the race
356 356 $ cat <<EOF > $TESTTMP/listkeys_makecommit.sh
357 357 > #!/bin/sh
358 358 > if hg st | grep -q M; then
359 359 > hg commit -m race
360 360 > echo committed in pull-race
361 361 > else
362 362 > exit 0
363 363 > fi
364 364 > EOF
365 365 $ cat <<EOF > ../pull-race/.hg/hgrc
366 366 > [hooks]
367 367 > # If anything to commit, commit it right after the first key listing used
368 368 > # during lookup. This makes the commit appear before the actual getbundle
369 369 > # call.
370 370 > listkeys.makecommit= sh $TESTTMP/listkeys_makecommit.sh
371 371 > EOF
372 372
373 373 (new config need server restart)
374 374
375 375 $ killdaemons.py
376 376 $ hg serve -R ../pull-race -p $HGPORT -d --pid-file=../pull-race.pid -E main-error.log
377 377 $ cat ../pull-race.pid >> $DAEMON_PIDS
378 378
379 379 $ hg -R $TESTTMP/pull-race book
380 380 @ 1:0d2164f0ce0d
381 381 X 1:0d2164f0ce0d
382 382 * Y 5:35d1ef0a8d1b
383 383 Z 1:0d2164f0ce0d
384 384 $ hg update -r Y
385 385 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
386 386 (activating bookmark Y)
387 387 $ hg pull -B .
388 388 pulling from http://localhost:$HGPORT/
389 389 searching for changes
390 390 adding changesets
391 391 adding manifests
392 392 adding file changes
393 393 added 1 changesets with 1 changes to 1 files
394 394 updating bookmark Y
395 395 (run 'hg update' to get a working copy)
396 396 $ hg book
397 397 @ 1:0d2164f0ce0d
398 398 X 1:0d2164f0ce0d
399 399 * Y 5:35d1ef0a8d1b
400 400 Z 1:0d2164f0ce0d
401 401
402 402 (done with this section of the test)
403 403
404 404 $ killdaemons.py
405 405 $ cd ../b
406 406
407 407 diverging a remote bookmark fails
408 408
409 409 $ hg up -q 4e3505fd9583
410 410 $ echo c4 > f2
411 411 $ hg ci -Am4
412 412 adding f2
413 413 created new head
414 414 $ echo c5 > f2
415 415 $ hg ci -Am5
416 416 $ hg log -G
417 417 @ 5:c922c0139ca0 5
418 418 |
419 419 o 4:4efff6d98829 4
420 420 |
421 421 | o 3:f6fc62dde3c0 3
422 422 |/
423 423 | o 2:0d2164f0ce0d 1
424 424 |/
425 425 | o 1:9b140be10808 2
426 426 |/
427 427 o 0:4e3505fd9583 test
428 428
429 429
430 430 $ hg book -f Y
431 431
432 432 $ cat <<EOF > ../a/.hg/hgrc
433 433 > [web]
434 434 > push_ssl = false
435 435 > allow_push = *
436 436 > EOF
437 437
438 438 $ hg serve -R ../a -p $HGPORT2 -d --pid-file=../hg2.pid
439 439 $ cat ../hg2.pid >> $DAEMON_PIDS
440 440
441 441 $ hg push http://localhost:$HGPORT2/
442 442 pushing to http://localhost:$HGPORT2/
443 443 searching for changes
444 444 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
445 445 (merge or see 'hg help push' for details about pushing new heads)
446 446 [255]
447 447 $ hg -R ../a book
448 448 @ 1:0d2164f0ce0d
449 449 * X 1:0d2164f0ce0d
450 450 Y 3:f6fc62dde3c0
451 451 Z 1:0d2164f0ce0d
452 452
453 453
454 454 Unrelated marker does not alter the decision
455 455
456 456 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
457 457 $ hg push http://localhost:$HGPORT2/
458 458 pushing to http://localhost:$HGPORT2/
459 459 searching for changes
460 460 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
461 461 (merge or see 'hg help push' for details about pushing new heads)
462 462 [255]
463 463 $ hg -R ../a book
464 464 @ 1:0d2164f0ce0d
465 465 * X 1:0d2164f0ce0d
466 466 Y 3:f6fc62dde3c0
467 467 Z 1:0d2164f0ce0d
468 468
469 469 Update to a successor works
470 470
471 471 $ hg id --debug -r 3
472 472 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
473 473 $ hg id --debug -r 4
474 474 4efff6d98829d9c824c621afd6e3f01865f5439f
475 475 $ hg id --debug -r 5
476 476 c922c0139ca03858f655e4a2af4dd02796a63969 tip Y
477 477 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f cccccccccccccccccccccccccccccccccccccccc
478 478 $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc 4efff6d98829d9c824c621afd6e3f01865f5439f
479 479 $ hg push http://localhost:$HGPORT2/
480 480 pushing to http://localhost:$HGPORT2/
481 481 searching for changes
482 482 remote: adding changesets
483 483 remote: adding manifests
484 484 remote: adding file changes
485 485 remote: added 2 changesets with 2 changes to 1 files (+1 heads)
486 486 remote: 2 new obsolescence markers
487 remote: obsoleted 1 changesets
487 488 updating bookmark Y
488 489 $ hg -R ../a book
489 490 @ 1:0d2164f0ce0d
490 491 * X 1:0d2164f0ce0d
491 492 Y 5:c922c0139ca0
492 493 Z 1:0d2164f0ce0d
493 494
494 495 hgweb
495 496
496 497 $ cat <<EOF > .hg/hgrc
497 498 > [web]
498 499 > push_ssl = false
499 500 > allow_push = *
500 501 > EOF
501 502
502 503 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
503 504 $ cat ../hg.pid >> $DAEMON_PIDS
504 505 $ cd ../a
505 506
506 507 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
507 508 bookmarks
508 509 namespaces
509 510 obsolete
510 511 phases
511 512 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
512 513 @ 9b140be1080824d768c5a4691a564088eede71f9
513 514 X 9b140be1080824d768c5a4691a564088eede71f9
514 515 Y c922c0139ca03858f655e4a2af4dd02796a63969
515 516 Z 9b140be1080824d768c5a4691a564088eede71f9
516 517 foo 0000000000000000000000000000000000000000
517 518 foobar 9b140be1080824d768c5a4691a564088eede71f9
518 519 $ hg out -B http://localhost:$HGPORT/
519 520 comparing with http://localhost:$HGPORT/
520 521 searching for changed bookmarks
521 522 @ 0d2164f0ce0d
522 523 X 0d2164f0ce0d
523 524 Z 0d2164f0ce0d
524 525 foo
525 526 foobar
526 527 $ hg push -B Z http://localhost:$HGPORT/
527 528 pushing to http://localhost:$HGPORT/
528 529 searching for changes
529 530 no changes found
530 531 updating bookmark Z
531 532 [1]
532 533 $ hg book -d Z
533 534 $ hg in -B http://localhost:$HGPORT/
534 535 comparing with http://localhost:$HGPORT/
535 536 searching for changed bookmarks
536 537 @ 9b140be10808
537 538 X 9b140be10808
538 539 Z 0d2164f0ce0d
539 540 foo 000000000000
540 541 foobar 9b140be10808
541 542 $ hg pull -B Z http://localhost:$HGPORT/
542 543 pulling from http://localhost:$HGPORT/
543 544 no changes found
544 545 divergent bookmark @ stored as @1
545 546 divergent bookmark X stored as X@1
546 547 adding remote bookmark Z
547 548 adding remote bookmark foo
548 549 adding remote bookmark foobar
549 550 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
550 551 requesting all changes
551 552 adding changesets
552 553 adding manifests
553 554 adding file changes
554 555 added 5 changesets with 5 changes to 3 files (+2 heads)
555 556 2 new obsolescence markers
556 557 updating to bookmark @
557 558 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
558 559 $ hg -R cloned-bookmarks bookmarks
559 560 * @ 1:9b140be10808
560 561 X 1:9b140be10808
561 562 Y 4:c922c0139ca0
562 563 Z 2:0d2164f0ce0d
563 564 foo -1:000000000000
564 565 foobar 1:9b140be10808
565 566
566 567 $ cd ..
567 568
568 569 Test to show result of bookmarks comparison
569 570
570 571 $ mkdir bmcomparison
571 572 $ cd bmcomparison
572 573
573 574 $ hg init source
574 575 $ hg -R source debugbuilddag '+2*2*3*4'
575 576 $ hg -R source log -G --template '{rev}:{node|short}'
576 577 o 4:e7bd5218ca15
577 578 |
578 579 | o 3:6100d3090acf
579 580 |/
580 581 | o 2:fa942426a6fd
581 582 |/
582 583 | o 1:66f7d451a68b
583 584 |/
584 585 o 0:1ea73414a91b
585 586
586 587 $ hg -R source bookmarks -r 0 SAME
587 588 $ hg -R source bookmarks -r 0 ADV_ON_REPO1
588 589 $ hg -R source bookmarks -r 0 ADV_ON_REPO2
589 590 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO1
590 591 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO2
591 592 $ hg -R source bookmarks -r 1 DIVERGED
592 593
593 594 $ hg clone -U source repo1
594 595
595 596 (test that incoming/outgoing exit with 1, if there is no bookmark to
596 597 be exchanged)
597 598
598 599 $ hg -R repo1 incoming -B
599 600 comparing with $TESTTMP/bmcomparison/source (glob)
600 601 searching for changed bookmarks
601 602 no changed bookmarks found
602 603 [1]
603 604 $ hg -R repo1 outgoing -B
604 605 comparing with $TESTTMP/bmcomparison/source (glob)
605 606 searching for changed bookmarks
606 607 no changed bookmarks found
607 608 [1]
608 609
609 610 $ hg -R repo1 bookmarks -f -r 1 ADD_ON_REPO1
610 611 $ hg -R repo1 bookmarks -f -r 2 ADV_ON_REPO1
611 612 $ hg -R repo1 bookmarks -f -r 3 DIFF_ADV_ON_REPO1
612 613 $ hg -R repo1 bookmarks -f -r 3 DIFF_DIVERGED
613 614 $ hg -R repo1 -q --config extensions.mq= strip 4
614 615 $ hg -R repo1 log -G --template '{node|short} ({bookmarks})'
615 616 o 6100d3090acf (DIFF_ADV_ON_REPO1 DIFF_DIVERGED)
616 617 |
617 618 | o fa942426a6fd (ADV_ON_REPO1)
618 619 |/
619 620 | o 66f7d451a68b (ADD_ON_REPO1 DIVERGED)
620 621 |/
621 622 o 1ea73414a91b (ADV_ON_REPO2 DIFF_ADV_ON_REPO2 SAME)
622 623
623 624
624 625 $ hg clone -U source repo2
625 626 $ hg -R repo2 bookmarks -f -r 1 ADD_ON_REPO2
626 627 $ hg -R repo2 bookmarks -f -r 1 ADV_ON_REPO2
627 628 $ hg -R repo2 bookmarks -f -r 2 DIVERGED
628 629 $ hg -R repo2 bookmarks -f -r 4 DIFF_ADV_ON_REPO2
629 630 $ hg -R repo2 bookmarks -f -r 4 DIFF_DIVERGED
630 631 $ hg -R repo2 -q --config extensions.mq= strip 3
631 632 $ hg -R repo2 log -G --template '{node|short} ({bookmarks})'
632 633 o e7bd5218ca15 (DIFF_ADV_ON_REPO2 DIFF_DIVERGED)
633 634 |
634 635 | o fa942426a6fd (DIVERGED)
635 636 |/
636 637 | o 66f7d451a68b (ADD_ON_REPO2 ADV_ON_REPO2)
637 638 |/
638 639 o 1ea73414a91b (ADV_ON_REPO1 DIFF_ADV_ON_REPO1 SAME)
639 640
640 641
641 642 (test that difference of bookmarks between repositories are fully shown)
642 643
643 644 $ hg -R repo1 incoming -B repo2 -v
644 645 comparing with repo2
645 646 searching for changed bookmarks
646 647 ADD_ON_REPO2 66f7d451a68b added
647 648 ADV_ON_REPO2 66f7d451a68b advanced
648 649 DIFF_ADV_ON_REPO2 e7bd5218ca15 changed
649 650 DIFF_DIVERGED e7bd5218ca15 changed
650 651 DIVERGED fa942426a6fd diverged
651 652 $ hg -R repo1 outgoing -B repo2 -v
652 653 comparing with repo2
653 654 searching for changed bookmarks
654 655 ADD_ON_REPO1 66f7d451a68b added
655 656 ADD_ON_REPO2 deleted
656 657 ADV_ON_REPO1 fa942426a6fd advanced
657 658 DIFF_ADV_ON_REPO1 6100d3090acf advanced
658 659 DIFF_ADV_ON_REPO2 1ea73414a91b changed
659 660 DIFF_DIVERGED 6100d3090acf changed
660 661 DIVERGED 66f7d451a68b diverged
661 662
662 663 $ hg -R repo2 incoming -B repo1 -v
663 664 comparing with repo1
664 665 searching for changed bookmarks
665 666 ADD_ON_REPO1 66f7d451a68b added
666 667 ADV_ON_REPO1 fa942426a6fd advanced
667 668 DIFF_ADV_ON_REPO1 6100d3090acf changed
668 669 DIFF_DIVERGED 6100d3090acf changed
669 670 DIVERGED 66f7d451a68b diverged
670 671 $ hg -R repo2 outgoing -B repo1 -v
671 672 comparing with repo1
672 673 searching for changed bookmarks
673 674 ADD_ON_REPO1 deleted
674 675 ADD_ON_REPO2 66f7d451a68b added
675 676 ADV_ON_REPO2 66f7d451a68b advanced
676 677 DIFF_ADV_ON_REPO1 1ea73414a91b changed
677 678 DIFF_ADV_ON_REPO2 e7bd5218ca15 advanced
678 679 DIFF_DIVERGED e7bd5218ca15 changed
679 680 DIVERGED fa942426a6fd diverged
680 681
681 682 $ cd ..
682 683
683 684 Pushing a bookmark should only push the changes required by that
684 685 bookmark, not all outgoing changes:
685 686 $ hg clone http://localhost:$HGPORT/ addmarks
686 687 requesting all changes
687 688 adding changesets
688 689 adding manifests
689 690 adding file changes
690 691 added 5 changesets with 5 changes to 3 files (+2 heads)
691 692 2 new obsolescence markers
692 693 updating to bookmark @
693 694 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
694 695 $ cd addmarks
695 696 $ echo foo > foo
696 697 $ hg add foo
697 698 $ hg commit -m 'add foo'
698 699 $ echo bar > bar
699 700 $ hg add bar
700 701 $ hg commit -m 'add bar'
701 702 $ hg co "tip^"
702 703 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
703 704 (leaving bookmark @)
704 705 $ hg book add-foo
705 706 $ hg book -r tip add-bar
706 707 Note: this push *must* push only a single changeset, as that's the point
707 708 of this test.
708 709 $ hg push -B add-foo --traceback
709 710 pushing to http://localhost:$HGPORT/
710 711 searching for changes
711 712 remote: adding changesets
712 713 remote: adding manifests
713 714 remote: adding file changes
714 715 remote: added 1 changesets with 1 changes to 1 files
715 716 exporting bookmark add-foo
716 717
717 718 pushing a new bookmark on a new head does not require -f if -B is specified
718 719
719 720 $ hg up -q X
720 721 $ hg book W
721 722 $ echo c5 > f2
722 723 $ hg ci -Am5
723 724 created new head
724 725 $ hg push -B .
725 726 pushing to http://localhost:$HGPORT/
726 727 searching for changes
727 728 remote: adding changesets
728 729 remote: adding manifests
729 730 remote: adding file changes
730 731 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
731 732 exporting bookmark W
732 733 $ hg -R ../b id -r W
733 734 cc978a373a53 tip W
734 735
735 736 pushing an existing but divergent bookmark with -B still requires -f
736 737
737 738 $ hg clone -q . ../r
738 739 $ hg up -q X
739 740 $ echo 1 > f2
740 741 $ hg ci -qAml
741 742
742 743 $ cd ../r
743 744 $ hg up -q X
744 745 $ echo 2 > f2
745 746 $ hg ci -qAmr
746 747 $ hg push -B X
747 748 pushing to $TESTTMP/addmarks (glob)
748 749 searching for changes
749 750 remote has heads on branch 'default' that are not known locally: a2a606d9ff1b
750 751 abort: push creates new remote head 54694f811df9 with bookmark 'X'!
751 752 (pull and merge or see 'hg help push' for details about pushing new heads)
752 753 [255]
753 754 $ cd ../addmarks
754 755
755 756 Check summary output for incoming/outgoing bookmarks
756 757
757 758 $ hg bookmarks -d X
758 759 $ hg bookmarks -d Y
759 760 $ hg summary --remote | grep '^remote:'
760 761 remote: *, 2 incoming bookmarks, 1 outgoing bookmarks (glob)
761 762
762 763 $ cd ..
763 764
764 765 pushing an unchanged bookmark should result in no changes
765 766
766 767 $ hg init unchanged-a
767 768 $ hg init unchanged-b
768 769 $ cd unchanged-a
769 770 $ echo initial > foo
770 771 $ hg commit -A -m initial
771 772 adding foo
772 773 $ hg bookmark @
773 774 $ hg push -B @ ../unchanged-b
774 775 pushing to ../unchanged-b
775 776 searching for changes
776 777 adding changesets
777 778 adding manifests
778 779 adding file changes
779 780 added 1 changesets with 1 changes to 1 files
780 781 exporting bookmark @
781 782
782 783 $ hg push -B @ ../unchanged-b
783 784 pushing to ../unchanged-b
784 785 searching for changes
785 786 no changes found
786 787 [1]
787 788
788 789
789 790 Check hook preventing push (issue4455)
790 791 ======================================
791 792
792 793 $ hg bookmarks
793 794 * @ 0:55482a6fb4b1
794 795 $ hg log -G
795 796 @ 0:55482a6fb4b1 initial
796 797
797 798 $ hg init ../issue4455-dest
798 799 $ hg push ../issue4455-dest # changesets only
799 800 pushing to ../issue4455-dest
800 801 searching for changes
801 802 adding changesets
802 803 adding manifests
803 804 adding file changes
804 805 added 1 changesets with 1 changes to 1 files
805 806 $ cat >> .hg/hgrc << EOF
806 807 > [paths]
807 808 > local=../issue4455-dest/
808 809 > ssh=ssh://user@dummy/issue4455-dest
809 810 > http=http://localhost:$HGPORT/
810 811 > [ui]
811 812 > ssh=python "$TESTDIR/dummyssh"
812 813 > EOF
813 814 $ cat >> ../issue4455-dest/.hg/hgrc << EOF
814 815 > [hooks]
815 816 > prepushkey=false
816 817 > [web]
817 818 > push_ssl = false
818 819 > allow_push = *
819 820 > EOF
820 821 $ killdaemons.py
821 822 $ hg serve -R ../issue4455-dest -p $HGPORT -d --pid-file=../issue4455.pid -E ../issue4455-error.log
822 823 $ cat ../issue4455.pid >> $DAEMON_PIDS
823 824
824 825 Local push
825 826 ----------
826 827
827 828 $ hg push -B @ local
828 829 pushing to $TESTTMP/issue4455-dest (glob)
829 830 searching for changes
830 831 no changes found
831 832 pushkey-abort: prepushkey hook exited with status 1
832 833 abort: exporting bookmark @ failed!
833 834 [255]
834 835 $ hg -R ../issue4455-dest/ bookmarks
835 836 no bookmarks set
836 837
837 838 Using ssh
838 839 ---------
839 840
840 841 $ hg push -B @ ssh # bundle2+
841 842 pushing to ssh://user@dummy/issue4455-dest
842 843 searching for changes
843 844 no changes found
844 845 remote: pushkey-abort: prepushkey hook exited with status 1
845 846 abort: exporting bookmark @ failed!
846 847 [255]
847 848 $ hg -R ../issue4455-dest/ bookmarks
848 849 no bookmarks set
849 850
850 851 $ hg push -B @ ssh --config devel.legacy.exchange=bundle1
851 852 pushing to ssh://user@dummy/issue4455-dest
852 853 searching for changes
853 854 no changes found
854 855 remote: pushkey-abort: prepushkey hook exited with status 1
855 856 exporting bookmark @ failed!
856 857 [1]
857 858 $ hg -R ../issue4455-dest/ bookmarks
858 859 no bookmarks set
859 860
860 861 Using http
861 862 ----------
862 863
863 864 $ hg push -B @ http # bundle2+
864 865 pushing to http://localhost:$HGPORT/
865 866 searching for changes
866 867 no changes found
867 868 remote: pushkey-abort: prepushkey hook exited with status 1
868 869 abort: exporting bookmark @ failed!
869 870 [255]
870 871 $ hg -R ../issue4455-dest/ bookmarks
871 872 no bookmarks set
872 873
873 874 $ hg push -B @ http --config devel.legacy.exchange=bundle1
874 875 pushing to http://localhost:$HGPORT/
875 876 searching for changes
876 877 no changes found
877 878 remote: pushkey-abort: prepushkey hook exited with status 1
878 879 exporting bookmark @ failed!
879 880 [1]
880 881 $ hg -R ../issue4455-dest/ bookmarks
881 882 no bookmarks set
@@ -1,238 +1,240 b''
1 1 ============================================
2 2 Testing obsolescence markers push: Cases A.3
3 3 ============================================
4 4
5 5 Mercurial pushes obsolescences markers relevant to the "pushed-set", the set of
6 6 all changesets that requested to be "in sync" after the push (even if they are
7 7 already on both side).
8 8
9 9 This test belongs to a series of tests checking such set is properly computed
10 10 and applied. This does not tests "obsmarkers" discovery capabilities.
11 11
12 12 Category A: simple cases
13 13 TestCase 3: old branch split in two, only one of the new one pushed
14 14 Variants:
15 15 # a: changesets are known on remote
16 16 # b: changesets are known on remote (push needs -f)
17 17
18 18 A.3 new branchs created, one pushed.
19 19 ====================================
20 20
21 21 .. {{{
22 22 .. B' ○⇢ø B
23 23 .. | |
24 24 .. \Aø⇠◔ A'
25 25 .. \|/
26 26 .. O
27 27 .. }}}
28 28 ..
29 29 .. Markers exist from:
30 30 ..
31 31 .. * `A ø⇠○ A'`
32 32 .. * `B ø⇠○ B'`
33 33 ..
34 34 .. Command runs:
35 35 ..
36 36 .. * hg push -r A
37 37 ..
38 38 .. Expected exchange:
39 39 ..
40 40 .. * chain from A
41 41 ..
42 42 .. Expected exclude:
43 43 ..
44 44 .. * chain from B
45 45 ..
46 46 .. Extra note:
47 47 ..
48 48 .. If A and B are remontly known, we should expect:
49 49 ..
50 50 .. * `hg push` will complain about the new head
51 51 .. * `hg push` should complain about unstable history creation
52 52
53 53 Setup
54 54 -----
55 55
56 56 $ . $TESTDIR/testlib/exchange-obsmarker-util.sh
57 57
58 58 initial
59 59
60 60 $ setuprepos A.3.a
61 61 creating test repo for test case A.3.a
62 62 - pulldest
63 63 - main
64 64 - pushdest
65 65 cd into `main` and proceed with env setup
66 66 $ cd main
67 67 $ mkcommit A0
68 68 $ mkcommit B0
69 69 $ hg update -q 0
70 70 $ mkcommit A1
71 71 created new head
72 72 $ hg update -q 0
73 73 $ mkcommit B1
74 74 created new head
75 75 $ hg debugobsolete `getid 'desc(A0)'` `getid 'desc(A1)'`
76 76 $ hg debugobsolete `getid 'desc(B0)'` `getid 'desc(B1)'`
77 77 $ hg log -G --hidden
78 78 @ f6298a8ac3a4 (draft): B1
79 79 |
80 80 | o e5ea8f9c7314 (draft): A1
81 81 |/
82 82 | x 6e72f0a95b5e (draft): B0
83 83 | |
84 84 | x 28b51eb45704 (draft): A0
85 85 |/
86 86 o a9bdc8b26820 (public): O
87 87
88 88 $ inspect_obsmarkers
89 89 obsstore content
90 90 ================
91 91 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
92 92 6e72f0a95b5e01a7504743aa941f69cb1fbef8b0 f6298a8ac3a4b78bbeae5f1d3dc5bc3c3812f0f3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
93 93 $ cd ..
94 94 $ cd ..
95 95
96 96 Actual Test for first version (changeset unknown in remote)
97 97 -----------------------------------------------------------
98 98
99 99 $ dotest A.3.a A1
100 100 ## Running testcase A.3.a
101 101 # testing echange of "A1" (e5ea8f9c7314)
102 102 ## initial state
103 103 # obstore: main
104 104 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
105 105 6e72f0a95b5e01a7504743aa941f69cb1fbef8b0 f6298a8ac3a4b78bbeae5f1d3dc5bc3c3812f0f3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
106 106 # obstore: pushdest
107 107 # obstore: pulldest
108 108 ## pushing "A1" from main to pushdest
109 109 pushing to pushdest
110 110 searching for changes
111 111 remote: adding changesets
112 112 remote: adding manifests
113 113 remote: adding file changes
114 114 remote: added 1 changesets with 1 changes to 1 files
115 115 remote: 1 new obsolescence markers
116 116 ## post push state
117 117 # obstore: main
118 118 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
119 119 6e72f0a95b5e01a7504743aa941f69cb1fbef8b0 f6298a8ac3a4b78bbeae5f1d3dc5bc3c3812f0f3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
120 120 # obstore: pushdest
121 121 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
122 122 # obstore: pulldest
123 123 ## pulling "e5ea8f9c7314" from main into pulldest
124 124 pulling from main
125 125 searching for changes
126 126 adding changesets
127 127 adding manifests
128 128 adding file changes
129 129 added 1 changesets with 1 changes to 1 files
130 130 1 new obsolescence markers
131 131 (run 'hg update' to get a working copy)
132 132 ## post pull state
133 133 # obstore: main
134 134 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
135 135 6e72f0a95b5e01a7504743aa941f69cb1fbef8b0 f6298a8ac3a4b78bbeae5f1d3dc5bc3c3812f0f3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
136 136 # obstore: pushdest
137 137 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
138 138 # obstore: pulldest
139 139 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
140 140
141 141 other variant: changeset known in remote
142 142 ----------------------------------------
143 143
144 144 $ setuprepos A.3.b
145 145 creating test repo for test case A.3.b
146 146 - pulldest
147 147 - main
148 148 - pushdest
149 149 cd into `main` and proceed with env setup
150 150 $ cd main
151 151 $ mkcommit A0
152 152 $ mkcommit B0
153 153 $ hg push -q ../pushdest
154 154 $ hg push -q ../pulldest
155 155 $ hg update -q 0
156 156 $ mkcommit A1
157 157 created new head
158 158 $ hg update -q 0
159 159 $ mkcommit B1
160 160 created new head
161 161 $ hg debugobsolete `getid 'desc(A0)'` `getid 'desc(A1)'`
162 162 $ hg debugobsolete `getid 'desc(B0)'` `getid 'desc(B1)'`
163 163 $ hg log -G --hidden
164 164 @ f6298a8ac3a4 (draft): B1
165 165 |
166 166 | o e5ea8f9c7314 (draft): A1
167 167 |/
168 168 | x 6e72f0a95b5e (draft): B0
169 169 | |
170 170 | x 28b51eb45704 (draft): A0
171 171 |/
172 172 o a9bdc8b26820 (public): O
173 173
174 174 $ inspect_obsmarkers
175 175 obsstore content
176 176 ================
177 177 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
178 178 6e72f0a95b5e01a7504743aa941f69cb1fbef8b0 f6298a8ac3a4b78bbeae5f1d3dc5bc3c3812f0f3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
179 179 $ cd ..
180 180 $ cd ..
181 181
182 182 Actual Test for first version (changeset known in remote)
183 183 -----------------------------------------------------------
184 184
185 185 check it complains about multiple heads
186 186
187 187 $ cd A.3.b
188 188 $ hg push -R main -r 'desc(A1)' pushdest
189 189 pushing to pushdest
190 190 searching for changes
191 191 abort: push creates new remote head e5ea8f9c7314!
192 192 (merge or see 'hg help push' for details about pushing new heads)
193 193 [255]
194 194 $ cd ..
195 195
196 196 test obsmarkers exchange.
197 197
198 198 $ dotest A.3.b A1 -f
199 199 ## Running testcase A.3.b
200 200 # testing echange of "A1" (e5ea8f9c7314)
201 201 ## initial state
202 202 # obstore: main
203 203 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
204 204 6e72f0a95b5e01a7504743aa941f69cb1fbef8b0 f6298a8ac3a4b78bbeae5f1d3dc5bc3c3812f0f3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
205 205 # obstore: pushdest
206 206 # obstore: pulldest
207 207 ## pushing "A1" from main to pushdest
208 208 pushing to pushdest
209 209 searching for changes
210 210 remote: adding changesets
211 211 remote: adding manifests
212 212 remote: adding file changes
213 213 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
214 214 remote: 1 new obsolescence markers
215 remote: obsoleted 1 changesets
215 216 ## post push state
216 217 # obstore: main
217 218 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
218 219 6e72f0a95b5e01a7504743aa941f69cb1fbef8b0 f6298a8ac3a4b78bbeae5f1d3dc5bc3c3812f0f3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
219 220 # obstore: pushdest
220 221 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
221 222 # obstore: pulldest
222 223 ## pulling "e5ea8f9c7314" from main into pulldest
223 224 pulling from main
224 225 searching for changes
225 226 adding changesets
226 227 adding manifests
227 228 adding file changes
228 229 added 1 changesets with 1 changes to 1 files (+1 heads)
229 230 1 new obsolescence markers
231 obsoleted 1 changesets
230 232 (run 'hg heads' to see heads, 'hg merge' to merge)
231 233 ## post pull state
232 234 # obstore: main
233 235 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
234 236 6e72f0a95b5e01a7504743aa941f69cb1fbef8b0 f6298a8ac3a4b78bbeae5f1d3dc5bc3c3812f0f3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
235 237 # obstore: pushdest
236 238 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
237 239 # obstore: pulldest
238 240 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
@@ -1,150 +1,154 b''
1 1 ============================================
2 2 Testing obsolescence markers push: Cases A.6
3 3 ============================================
4 4
5 5 Mercurial pushes obsolescences markers relevant to the "pushed-set", the set of
6 6 all changesets that requested to be "in sync" after the push (even if they are
7 7 already on both side).
8 8
9 9 This test belongs to a series of tests checking such set is properly computed
10 10 and applied. This does not tests "obsmarkers" discovery capabilities.
11 11
12 12 Category A: simple cases
13 13 TestCase 6: new markers between changesets already known on both side
14 14 Variants:
15 15 # a: explicit push
16 16 # b: bare push
17 17
18 18 A.6 new markers between changesets already known on both side
19 19 ==============================================================
20 20
21 21 .. {{{
22 22 .. A ◕⇠● B
23 23 .. |/
24 24 .. O
25 25 .. }}}
26 26 ..
27 27 .. Marker exist from:
28 28 ..
29 29 .. * `A◕⇠● B`
30 30 ..
31 31 .. Command runs:
32 32 ..
33 33 .. * hg push -r B
34 34 .. * hg push
35 35 ..
36 36 .. Expected exchange:
37 37 ..
38 38 .. * `A◕⇠● B`
39 39
40 40 Setup
41 41 -----
42 42
43 43 $ . $TESTDIR/testlib/exchange-obsmarker-util.sh
44 44
45 45 initial
46 46
47 47 $ setuprepos A.6
48 48 creating test repo for test case A.6
49 49 - pulldest
50 50 - main
51 51 - pushdest
52 52 cd into `main` and proceed with env setup
53 53 $ cd main
54 54 $ mkcommit A0
55 55 $ hg update -q 0
56 56 $ mkcommit A1
57 57 created new head
58 58
59 59 make both changeset known in remote
60 60
61 61 $ hg push -qf ../pushdest
62 62 $ hg push -qf ../pulldest
63 63
64 64 create a marker after this
65 65
66 66 $ hg debugobsolete `getid 'desc(A0)'` `getid 'desc(A1)'`
67 67 $ hg log -G --hidden
68 68 @ e5ea8f9c7314 (draft): A1
69 69 |
70 70 | x 28b51eb45704 (draft): A0
71 71 |/
72 72 o a9bdc8b26820 (public): O
73 73
74 74 $ inspect_obsmarkers
75 75 obsstore content
76 76 ================
77 77 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
78 78 $ cd ..
79 79 $ cd ..
80 80
81 81 $ cp -R A.6 A.6.a
82 82 $ cp -R A.6 A.6.b
83 83
84 84 Actual Test (explicit push version)
85 85 -----------------------------------
86 86
87 87 $ dotest A.6.a A1
88 88 ## Running testcase A.6.a
89 89 # testing echange of "A1" (e5ea8f9c7314)
90 90 ## initial state
91 91 # obstore: main
92 92 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
93 93 # obstore: pushdest
94 94 # obstore: pulldest
95 95 ## pushing "A1" from main to pushdest
96 96 pushing to pushdest
97 97 searching for changes
98 98 no changes found
99 99 remote: 1 new obsolescence markers
100 remote: obsoleted 1 changesets
100 101 ## post push state
101 102 # obstore: main
102 103 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
103 104 # obstore: pushdest
104 105 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
105 106 # obstore: pulldest
106 107 ## pulling "e5ea8f9c7314" from main into pulldest
107 108 pulling from main
108 109 no changes found
109 110 1 new obsolescence markers
111 obsoleted 1 changesets
110 112 ## post pull state
111 113 # obstore: main
112 114 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
113 115 # obstore: pushdest
114 116 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
115 117 # obstore: pulldest
116 118 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
117 119
118 120 Actual Test (bare push version)
119 121 -------------------------------
120 122
121 123 $ dotest A.6.b
122 124 ## Running testcase A.6.b
123 125 ## initial state
124 126 # obstore: main
125 127 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
126 128 # obstore: pushdest
127 129 # obstore: pulldest
128 130 ## pushing from main to pushdest
129 131 pushing to pushdest
130 132 searching for changes
131 133 no changes found
132 134 remote: 1 new obsolescence markers
135 remote: obsoleted 1 changesets
133 136 ## post push state
134 137 # obstore: main
135 138 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
136 139 # obstore: pushdest
137 140 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
138 141 # obstore: pulldest
139 142 ## pulling from main into pulldest
140 143 pulling from main
141 144 searching for changes
142 145 no changes found
143 146 1 new obsolescence markers
147 obsoleted 1 changesets
144 148 ## post pull state
145 149 # obstore: main
146 150 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
147 151 # obstore: pushdest
148 152 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
149 153 # obstore: pulldest
150 154 28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
@@ -1,888 +1,889 b''
1 1 This test file test the various templates related to obsmarkers.
2 2
3 3 Global setup
4 4 ============
5 5
6 6 $ . $TESTDIR/testlib/obsmarker-common.sh
7 7 $ cat >> $HGRCPATH <<EOF
8 8 > [ui]
9 9 > interactive = true
10 10 > [phases]
11 11 > publish=False
12 12 > [experimental]
13 13 > evolution=all
14 14 > [alias]
15 15 > tlog = log -G -T '{node|short}\
16 16 > {if(predecessors, "\n Predecessors: {predecessors}")}\
17 17 > {if(predecessors, "\n semi-colon: {join(predecessors, "; ")}")}\
18 18 > {if(predecessors, "\n json: {predecessors|json}")}\
19 19 > {if(predecessors, "\n map: {join(predecessors % "{rev}:{node}", " ")}")}\n'
20 20 > EOF
21 21
22 22 Test templates on amended commit
23 23 ================================
24 24
25 25 Test setup
26 26 ----------
27 27
28 28 $ hg init $TESTTMP/templates-local-amend
29 29 $ cd $TESTTMP/templates-local-amend
30 30 $ mkcommit ROOT
31 31 $ mkcommit A0
32 32 $ echo 42 >> A0
33 33 $ hg commit --amend -m "A1"
34 34 $ hg commit --amend -m "A2"
35 35
36 36 $ hg log --hidden -G
37 37 @ changeset: 4:d004c8f274b9
38 38 | tag: tip
39 39 | parent: 0:ea207398892e
40 40 | user: test
41 41 | date: Thu Jan 01 00:00:00 1970 +0000
42 42 | summary: A2
43 43 |
44 44 | x changeset: 3:a468dc9b3633
45 45 |/ parent: 0:ea207398892e
46 46 | user: test
47 47 | date: Thu Jan 01 00:00:00 1970 +0000
48 48 | summary: A1
49 49 |
50 50 | x changeset: 2:f137d23bb3e1
51 51 | | user: test
52 52 | | date: Thu Jan 01 00:00:00 1970 +0000
53 53 | | summary: temporary amend commit for 471f378eab4c
54 54 | |
55 55 | x changeset: 1:471f378eab4c
56 56 |/ user: test
57 57 | date: Thu Jan 01 00:00:00 1970 +0000
58 58 | summary: A0
59 59 |
60 60 o changeset: 0:ea207398892e
61 61 user: test
62 62 date: Thu Jan 01 00:00:00 1970 +0000
63 63 summary: ROOT
64 64
65 65 Check templates
66 66 ---------------
67 67 $ hg up 'desc(A0)' --hidden
68 68 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
69 69
70 70 Predecessors template should show current revision as it is the working copy
71 71 $ hg tlog
72 72 o d004c8f274b9
73 73 | Predecessors: 1:471f378eab4c
74 74 | semi-colon: 1:471f378eab4c
75 75 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
76 76 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
77 77 | @ 471f378eab4c
78 78 |/
79 79 o ea207398892e
80 80
81 81 $ hg up 'desc(A1)' --hidden
82 82 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
83 83
84 84 Predecessors template should show current revision as it is the working copy
85 85 $ hg tlog
86 86 o d004c8f274b9
87 87 | Predecessors: 3:a468dc9b3633
88 88 | semi-colon: 3:a468dc9b3633
89 89 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
90 90 | map: 3:a468dc9b36338b14fdb7825f55ce3df4e71517ad
91 91 | @ a468dc9b3633
92 92 |/
93 93 o ea207398892e
94 94
95 95 Predecessors template should show all the predecessors as we force their display
96 96 with --hidden
97 97 $ hg tlog --hidden
98 98 o d004c8f274b9
99 99 | Predecessors: 3:a468dc9b3633
100 100 | semi-colon: 3:a468dc9b3633
101 101 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
102 102 | map: 3:a468dc9b36338b14fdb7825f55ce3df4e71517ad
103 103 | @ a468dc9b3633
104 104 |/ Predecessors: 1:471f378eab4c
105 105 | semi-colon: 1:471f378eab4c
106 106 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
107 107 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
108 108 | x f137d23bb3e1
109 109 | |
110 110 | x 471f378eab4c
111 111 |/
112 112 o ea207398892e
113 113
114 114
115 115 Predecessors template shouldn't show anything as all obsolete commit are not
116 116 visible.
117 117 $ hg up 'desc(A2)'
118 118 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
119 119 $ hg tlog
120 120 @ d004c8f274b9
121 121 |
122 122 o ea207398892e
123 123
124 124 $ hg tlog --hidden
125 125 @ d004c8f274b9
126 126 | Predecessors: 3:a468dc9b3633
127 127 | semi-colon: 3:a468dc9b3633
128 128 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
129 129 | map: 3:a468dc9b36338b14fdb7825f55ce3df4e71517ad
130 130 | x a468dc9b3633
131 131 |/ Predecessors: 1:471f378eab4c
132 132 | semi-colon: 1:471f378eab4c
133 133 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
134 134 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
135 135 | x f137d23bb3e1
136 136 | |
137 137 | x 471f378eab4c
138 138 |/
139 139 o ea207398892e
140 140
141 141
142 142 Test templates with splitted commit
143 143 ===================================
144 144
145 145 $ hg init $TESTTMP/templates-local-split
146 146 $ cd $TESTTMP/templates-local-split
147 147 $ mkcommit ROOT
148 148 $ echo 42 >> a
149 149 $ echo 43 >> b
150 150 $ hg commit -A -m "A0"
151 151 adding a
152 152 adding b
153 153 $ hg log --hidden -G
154 154 @ changeset: 1:471597cad322
155 155 | tag: tip
156 156 | user: test
157 157 | date: Thu Jan 01 00:00:00 1970 +0000
158 158 | summary: A0
159 159 |
160 160 o changeset: 0:ea207398892e
161 161 user: test
162 162 date: Thu Jan 01 00:00:00 1970 +0000
163 163 summary: ROOT
164 164
165 165 # Simulate split
166 166 $ hg up -r "desc(ROOT)"
167 167 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
168 168 $ echo 42 >> a
169 169 $ hg commit -A -m "A0"
170 170 adding a
171 171 created new head
172 172 $ echo 43 >> b
173 173 $ hg commit -A -m "A0"
174 174 adding b
175 175 $ hg debugobsolete `getid "1"` `getid "2"` `getid "3"`
176 176
177 177 $ hg log --hidden -G
178 178 @ changeset: 3:f257fde29c7a
179 179 | tag: tip
180 180 | user: test
181 181 | date: Thu Jan 01 00:00:00 1970 +0000
182 182 | summary: A0
183 183 |
184 184 o changeset: 2:337fec4d2edc
185 185 | parent: 0:ea207398892e
186 186 | user: test
187 187 | date: Thu Jan 01 00:00:00 1970 +0000
188 188 | summary: A0
189 189 |
190 190 | x changeset: 1:471597cad322
191 191 |/ user: test
192 192 | date: Thu Jan 01 00:00:00 1970 +0000
193 193 | summary: A0
194 194 |
195 195 o changeset: 0:ea207398892e
196 196 user: test
197 197 date: Thu Jan 01 00:00:00 1970 +0000
198 198 summary: ROOT
199 199
200 200 Check templates
201 201 ---------------
202 202
203 203 $ hg up 'obsolete()' --hidden
204 204 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
205 205
206 206 Predecessors template should show current revision as it is the working copy
207 207 $ hg tlog
208 208 o f257fde29c7a
209 209 | Predecessors: 1:471597cad322
210 210 | semi-colon: 1:471597cad322
211 211 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
212 212 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
213 213 o 337fec4d2edc
214 214 | Predecessors: 1:471597cad322
215 215 | semi-colon: 1:471597cad322
216 216 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
217 217 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
218 218 | @ 471597cad322
219 219 |/
220 220 o ea207398892e
221 221
222 222 $ hg up f257fde29c7a
223 223 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
224 224
225 225 Predecessors template should not show a predecessor as it's not displayed in
226 226 the log
227 227 $ hg tlog
228 228 @ f257fde29c7a
229 229 |
230 230 o 337fec4d2edc
231 231 |
232 232 o ea207398892e
233 233
234 234 Predecessors template should show both predecessors as we force their display
235 235 with --hidden
236 236 $ hg tlog --hidden
237 237 @ f257fde29c7a
238 238 | Predecessors: 1:471597cad322
239 239 | semi-colon: 1:471597cad322
240 240 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
241 241 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
242 242 o 337fec4d2edc
243 243 | Predecessors: 1:471597cad322
244 244 | semi-colon: 1:471597cad322
245 245 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
246 246 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
247 247 | x 471597cad322
248 248 |/
249 249 o ea207398892e
250 250
251 251 Test templates with folded commit
252 252 =================================
253 253
254 254 Test setup
255 255 ----------
256 256
257 257 $ hg init $TESTTMP/templates-local-fold
258 258 $ cd $TESTTMP/templates-local-fold
259 259 $ mkcommit ROOT
260 260 $ mkcommit A0
261 261 $ mkcommit B0
262 262 $ hg log --hidden -G
263 263 @ changeset: 2:0dec01379d3b
264 264 | tag: tip
265 265 | user: test
266 266 | date: Thu Jan 01 00:00:00 1970 +0000
267 267 | summary: B0
268 268 |
269 269 o changeset: 1:471f378eab4c
270 270 | user: test
271 271 | date: Thu Jan 01 00:00:00 1970 +0000
272 272 | summary: A0
273 273 |
274 274 o changeset: 0:ea207398892e
275 275 user: test
276 276 date: Thu Jan 01 00:00:00 1970 +0000
277 277 summary: ROOT
278 278
279 279 Simulate a fold
280 280 $ hg up -r "desc(ROOT)"
281 281 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
282 282 $ echo "A0" > A0
283 283 $ echo "B0" > B0
284 284 $ hg commit -A -m "C0"
285 285 adding A0
286 286 adding B0
287 287 created new head
288 288 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(C0)"`
289 289 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(C0)"`
290 290
291 291 $ hg log --hidden -G
292 292 @ changeset: 3:eb5a0daa2192
293 293 | tag: tip
294 294 | parent: 0:ea207398892e
295 295 | user: test
296 296 | date: Thu Jan 01 00:00:00 1970 +0000
297 297 | summary: C0
298 298 |
299 299 | x changeset: 2:0dec01379d3b
300 300 | | user: test
301 301 | | date: Thu Jan 01 00:00:00 1970 +0000
302 302 | | summary: B0
303 303 | |
304 304 | x changeset: 1:471f378eab4c
305 305 |/ user: test
306 306 | date: Thu Jan 01 00:00:00 1970 +0000
307 307 | summary: A0
308 308 |
309 309 o changeset: 0:ea207398892e
310 310 user: test
311 311 date: Thu Jan 01 00:00:00 1970 +0000
312 312 summary: ROOT
313 313
314 314 Check templates
315 315 ---------------
316 316
317 317 $ hg up 'desc(A0)' --hidden
318 318 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
319 319
320 320 Predecessors template should show current revision as it is the working copy
321 321 $ hg tlog
322 322 o eb5a0daa2192
323 323 | Predecessors: 1:471f378eab4c
324 324 | semi-colon: 1:471f378eab4c
325 325 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
326 326 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
327 327 | @ 471f378eab4c
328 328 |/
329 329 o ea207398892e
330 330
331 331 $ hg up 'desc(B0)' --hidden
332 332 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
333 333
334 334 Predecessors template should show both predecessors as they should be both
335 335 displayed
336 336 $ hg tlog
337 337 o eb5a0daa2192
338 338 | Predecessors: 2:0dec01379d3b 1:471f378eab4c
339 339 | semi-colon: 2:0dec01379d3b; 1:471f378eab4c
340 340 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
341 341 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5 1:471f378eab4c5e25f6c77f785b27c936efb22874
342 342 | @ 0dec01379d3b
343 343 | |
344 344 | x 471f378eab4c
345 345 |/
346 346 o ea207398892e
347 347
348 348 $ hg up 'desc(C0)'
349 349 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
350 350
351 351 Predecessors template should not show predecessors as they are not displayed in
352 352 the log
353 353 $ hg tlog
354 354 @ eb5a0daa2192
355 355 |
356 356 o ea207398892e
357 357
358 358 Predecessors template should show both predecessors as we force their display
359 359 with --hidden
360 360 $ hg tlog --hidden
361 361 @ eb5a0daa2192
362 362 | Predecessors: 2:0dec01379d3b 1:471f378eab4c
363 363 | semi-colon: 2:0dec01379d3b; 1:471f378eab4c
364 364 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
365 365 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5 1:471f378eab4c5e25f6c77f785b27c936efb22874
366 366 | x 0dec01379d3b
367 367 | |
368 368 | x 471f378eab4c
369 369 |/
370 370 o ea207398892e
371 371
372 372
373 373 Test templates with divergence
374 374 ==============================
375 375
376 376 Test setup
377 377 ----------
378 378
379 379 $ hg init $TESTTMP/templates-local-divergence
380 380 $ cd $TESTTMP/templates-local-divergence
381 381 $ mkcommit ROOT
382 382 $ mkcommit A0
383 383 $ hg commit --amend -m "A1"
384 384 $ hg log --hidden -G
385 385 @ changeset: 2:fdf9bde5129a
386 386 | tag: tip
387 387 | parent: 0:ea207398892e
388 388 | user: test
389 389 | date: Thu Jan 01 00:00:00 1970 +0000
390 390 | summary: A1
391 391 |
392 392 | x changeset: 1:471f378eab4c
393 393 |/ user: test
394 394 | date: Thu Jan 01 00:00:00 1970 +0000
395 395 | summary: A0
396 396 |
397 397 o changeset: 0:ea207398892e
398 398 user: test
399 399 date: Thu Jan 01 00:00:00 1970 +0000
400 400 summary: ROOT
401 401
402 402 $ hg update --hidden 'desc(A0)'
403 403 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
404 404 $ hg commit --amend -m "A2"
405 405 $ hg log --hidden -G
406 406 @ changeset: 3:65b757b745b9
407 407 | tag: tip
408 408 | parent: 0:ea207398892e
409 409 | user: test
410 410 | date: Thu Jan 01 00:00:00 1970 +0000
411 411 | trouble: divergent
412 412 | summary: A2
413 413 |
414 414 | o changeset: 2:fdf9bde5129a
415 415 |/ parent: 0:ea207398892e
416 416 | user: test
417 417 | date: Thu Jan 01 00:00:00 1970 +0000
418 418 | trouble: divergent
419 419 | summary: A1
420 420 |
421 421 | x changeset: 1:471f378eab4c
422 422 |/ user: test
423 423 | date: Thu Jan 01 00:00:00 1970 +0000
424 424 | summary: A0
425 425 |
426 426 o changeset: 0:ea207398892e
427 427 user: test
428 428 date: Thu Jan 01 00:00:00 1970 +0000
429 429 summary: ROOT
430 430
431 431 $ hg commit --amend -m 'A3'
432 432 $ hg log --hidden -G
433 433 @ changeset: 4:019fadeab383
434 434 | tag: tip
435 435 | parent: 0:ea207398892e
436 436 | user: test
437 437 | date: Thu Jan 01 00:00:00 1970 +0000
438 438 | trouble: divergent
439 439 | summary: A3
440 440 |
441 441 | x changeset: 3:65b757b745b9
442 442 |/ parent: 0:ea207398892e
443 443 | user: test
444 444 | date: Thu Jan 01 00:00:00 1970 +0000
445 445 | summary: A2
446 446 |
447 447 | o changeset: 2:fdf9bde5129a
448 448 |/ parent: 0:ea207398892e
449 449 | user: test
450 450 | date: Thu Jan 01 00:00:00 1970 +0000
451 451 | trouble: divergent
452 452 | summary: A1
453 453 |
454 454 | x changeset: 1:471f378eab4c
455 455 |/ user: test
456 456 | date: Thu Jan 01 00:00:00 1970 +0000
457 457 | summary: A0
458 458 |
459 459 o changeset: 0:ea207398892e
460 460 user: test
461 461 date: Thu Jan 01 00:00:00 1970 +0000
462 462 summary: ROOT
463 463
464 464
465 465 Check templates
466 466 ---------------
467 467
468 468 $ hg up 'desc(A0)' --hidden
469 469 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
470 470
471 471 Predecessors template should show current revision as it is the working copy
472 472 $ hg tlog
473 473 o 019fadeab383
474 474 | Predecessors: 1:471f378eab4c
475 475 | semi-colon: 1:471f378eab4c
476 476 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
477 477 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
478 478 | o fdf9bde5129a
479 479 |/ Predecessors: 1:471f378eab4c
480 480 | semi-colon: 1:471f378eab4c
481 481 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
482 482 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
483 483 | @ 471f378eab4c
484 484 |/
485 485 o ea207398892e
486 486
487 487 $ hg up 'desc(A1)'
488 488 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
489 489
490 490 Predecessors template should not show predecessors as they are not displayed in
491 491 the log
492 492 $ hg tlog
493 493 o 019fadeab383
494 494 |
495 495 | @ fdf9bde5129a
496 496 |/
497 497 o ea207398892e
498 498
499 499 Predecessors template should the predecessors as we force their display with
500 500 --hidden
501 501 $ hg tlog --hidden
502 502 o 019fadeab383
503 503 | Predecessors: 3:65b757b745b9
504 504 | semi-colon: 3:65b757b745b9
505 505 | json: ["65b757b745b935093c87a2bccd877521cccffcbd"]
506 506 | map: 3:65b757b745b935093c87a2bccd877521cccffcbd
507 507 | x 65b757b745b9
508 508 |/ Predecessors: 1:471f378eab4c
509 509 | semi-colon: 1:471f378eab4c
510 510 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
511 511 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
512 512 | @ fdf9bde5129a
513 513 |/ Predecessors: 1:471f378eab4c
514 514 | semi-colon: 1:471f378eab4c
515 515 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
516 516 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
517 517 | x 471f378eab4c
518 518 |/
519 519 o ea207398892e
520 520
521 521
522 522 Test templates with amended + folded commit
523 523 ===========================================
524 524
525 525 Test setup
526 526 ----------
527 527
528 528 $ hg init $TESTTMP/templates-local-amend-fold
529 529 $ cd $TESTTMP/templates-local-amend-fold
530 530 $ mkcommit ROOT
531 531 $ mkcommit A0
532 532 $ mkcommit B0
533 533 $ hg commit --amend -m "B1"
534 534 $ hg log --hidden -G
535 535 @ changeset: 3:b7ea6d14e664
536 536 | tag: tip
537 537 | parent: 1:471f378eab4c
538 538 | user: test
539 539 | date: Thu Jan 01 00:00:00 1970 +0000
540 540 | summary: B1
541 541 |
542 542 | x changeset: 2:0dec01379d3b
543 543 |/ user: test
544 544 | date: Thu Jan 01 00:00:00 1970 +0000
545 545 | summary: B0
546 546 |
547 547 o changeset: 1:471f378eab4c
548 548 | user: test
549 549 | date: Thu Jan 01 00:00:00 1970 +0000
550 550 | summary: A0
551 551 |
552 552 o changeset: 0:ea207398892e
553 553 user: test
554 554 date: Thu Jan 01 00:00:00 1970 +0000
555 555 summary: ROOT
556 556
557 557 # Simulate a fold
558 558 $ hg up -r "desc(ROOT)"
559 559 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
560 560 $ echo "A0" > A0
561 561 $ echo "B0" > B0
562 562 $ hg commit -A -m "C0"
563 563 adding A0
564 564 adding B0
565 565 created new head
566 566 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(C0)"`
567 567 $ hg debugobsolete `getid "desc(B1)"` `getid "desc(C0)"`
568 568
569 569 $ hg log --hidden -G
570 570 @ changeset: 4:eb5a0daa2192
571 571 | tag: tip
572 572 | parent: 0:ea207398892e
573 573 | user: test
574 574 | date: Thu Jan 01 00:00:00 1970 +0000
575 575 | summary: C0
576 576 |
577 577 | x changeset: 3:b7ea6d14e664
578 578 | | parent: 1:471f378eab4c
579 579 | | user: test
580 580 | | date: Thu Jan 01 00:00:00 1970 +0000
581 581 | | summary: B1
582 582 | |
583 583 | | x changeset: 2:0dec01379d3b
584 584 | |/ user: test
585 585 | | date: Thu Jan 01 00:00:00 1970 +0000
586 586 | | summary: B0
587 587 | |
588 588 | x changeset: 1:471f378eab4c
589 589 |/ user: test
590 590 | date: Thu Jan 01 00:00:00 1970 +0000
591 591 | summary: A0
592 592 |
593 593 o changeset: 0:ea207398892e
594 594 user: test
595 595 date: Thu Jan 01 00:00:00 1970 +0000
596 596 summary: ROOT
597 597
598 598 Check templates
599 599 ---------------
600 600
601 601 $ hg up 'desc(A0)' --hidden
602 602 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
603 603
604 604 Predecessors template should show current revision as it is the working copy
605 605 $ hg tlog
606 606 o eb5a0daa2192
607 607 | Predecessors: 1:471f378eab4c
608 608 | semi-colon: 1:471f378eab4c
609 609 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
610 610 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
611 611 | @ 471f378eab4c
612 612 |/
613 613 o ea207398892e
614 614
615 615 $ hg up 'desc(B0)' --hidden
616 616 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
617 617
618 618 Predecessors template should both predecessors as they are visible
619 619 $ hg tlog
620 620 o eb5a0daa2192
621 621 | Predecessors: 2:0dec01379d3b 1:471f378eab4c
622 622 | semi-colon: 2:0dec01379d3b; 1:471f378eab4c
623 623 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
624 624 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5 1:471f378eab4c5e25f6c77f785b27c936efb22874
625 625 | @ 0dec01379d3b
626 626 | |
627 627 | x 471f378eab4c
628 628 |/
629 629 o ea207398892e
630 630
631 631 $ hg up 'desc(B1)' --hidden
632 632 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
633 633
634 634 Predecessors template should both predecessors as they are visible
635 635 $ hg tlog
636 636 o eb5a0daa2192
637 637 | Predecessors: 1:471f378eab4c 3:b7ea6d14e664
638 638 | semi-colon: 1:471f378eab4c; 3:b7ea6d14e664
639 639 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874", "b7ea6d14e664bdc8922221f7992631b50da3fb07"]
640 640 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874 3:b7ea6d14e664bdc8922221f7992631b50da3fb07
641 641 | @ b7ea6d14e664
642 642 | |
643 643 | x 471f378eab4c
644 644 |/
645 645 o ea207398892e
646 646
647 647 $ hg up 'desc(C0)'
648 648 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
649 649
650 650 Predecessors template should show no predecessors as they are both non visible
651 651 $ hg tlog
652 652 @ eb5a0daa2192
653 653 |
654 654 o ea207398892e
655 655
656 656 Predecessors template should show all predecessors as we force their display
657 657 with --hidden
658 658 $ hg tlog --hidden
659 659 @ eb5a0daa2192
660 660 | Predecessors: 1:471f378eab4c 3:b7ea6d14e664
661 661 | semi-colon: 1:471f378eab4c; 3:b7ea6d14e664
662 662 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874", "b7ea6d14e664bdc8922221f7992631b50da3fb07"]
663 663 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874 3:b7ea6d14e664bdc8922221f7992631b50da3fb07
664 664 | x b7ea6d14e664
665 665 | | Predecessors: 2:0dec01379d3b
666 666 | | semi-colon: 2:0dec01379d3b
667 667 | | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
668 668 | | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
669 669 | | x 0dec01379d3b
670 670 | |/
671 671 | x 471f378eab4c
672 672 |/
673 673 o ea207398892e
674 674
675 675
676 676 Test template with pushed and pulled obs markers
677 677 ================================================
678 678
679 679 Test setup
680 680 ----------
681 681
682 682 $ hg init $TESTTMP/templates-local-remote-markers-1
683 683 $ cd $TESTTMP/templates-local-remote-markers-1
684 684 $ mkcommit ROOT
685 685 $ mkcommit A0
686 686 $ hg clone $TESTTMP/templates-local-remote-markers-1 $TESTTMP/templates-local-remote-markers-2
687 687 updating to branch default
688 688 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
689 689 $ cd $TESTTMP/templates-local-remote-markers-2
690 690 $ hg log --hidden -G
691 691 @ changeset: 1:471f378eab4c
692 692 | tag: tip
693 693 | user: test
694 694 | date: Thu Jan 01 00:00:00 1970 +0000
695 695 | summary: A0
696 696 |
697 697 o changeset: 0:ea207398892e
698 698 user: test
699 699 date: Thu Jan 01 00:00:00 1970 +0000
700 700 summary: ROOT
701 701
702 702 $ cd $TESTTMP/templates-local-remote-markers-1
703 703 $ hg commit --amend -m "A1"
704 704 $ hg commit --amend -m "A2"
705 705 $ hg log --hidden -G
706 706 @ changeset: 3:7a230b46bf61
707 707 | tag: tip
708 708 | parent: 0:ea207398892e
709 709 | user: test
710 710 | date: Thu Jan 01 00:00:00 1970 +0000
711 711 | summary: A2
712 712 |
713 713 | x changeset: 2:fdf9bde5129a
714 714 |/ parent: 0:ea207398892e
715 715 | user: test
716 716 | date: Thu Jan 01 00:00:00 1970 +0000
717 717 | summary: A1
718 718 |
719 719 | x changeset: 1:471f378eab4c
720 720 |/ user: test
721 721 | date: Thu Jan 01 00:00:00 1970 +0000
722 722 | summary: A0
723 723 |
724 724 o changeset: 0:ea207398892e
725 725 user: test
726 726 date: Thu Jan 01 00:00:00 1970 +0000
727 727 summary: ROOT
728 728
729 729 $ cd $TESTTMP/templates-local-remote-markers-2
730 730 $ hg pull
731 731 pulling from $TESTTMP/templates-local-remote-markers-1 (glob)
732 732 searching for changes
733 733 adding changesets
734 734 adding manifests
735 735 adding file changes
736 736 added 1 changesets with 0 changes to 1 files (+1 heads)
737 737 2 new obsolescence markers
738 obsoleted 1 changesets
738 739 (run 'hg heads' to see heads, 'hg merge' to merge)
739 740 $ hg log --hidden -G
740 741 o changeset: 2:7a230b46bf61
741 742 | tag: tip
742 743 | parent: 0:ea207398892e
743 744 | user: test
744 745 | date: Thu Jan 01 00:00:00 1970 +0000
745 746 | summary: A2
746 747 |
747 748 | @ changeset: 1:471f378eab4c
748 749 |/ user: test
749 750 | date: Thu Jan 01 00:00:00 1970 +0000
750 751 | summary: A0
751 752 |
752 753 o changeset: 0:ea207398892e
753 754 user: test
754 755 date: Thu Jan 01 00:00:00 1970 +0000
755 756 summary: ROOT
756 757
757 758
758 759 $ hg debugobsolete
759 760 471f378eab4c5e25f6c77f785b27c936efb22874 fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
760 761 fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e 7a230b46bf61e50b30308c6cfd7bd1269ef54702 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
761 762
762 763 Check templates
763 764 ---------------
764 765
765 766 Predecessors template should show current revision as it is the working copy
766 767 $ hg tlog
767 768 o 7a230b46bf61
768 769 | Predecessors: 1:471f378eab4c
769 770 | semi-colon: 1:471f378eab4c
770 771 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
771 772 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
772 773 | @ 471f378eab4c
773 774 |/
774 775 o ea207398892e
775 776
776 777 $ hg up 'desc(A2)'
777 778 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
778 779
779 780 Predecessors template should show no predecessors as they are non visible
780 781 $ hg tlog
781 782 @ 7a230b46bf61
782 783 |
783 784 o ea207398892e
784 785
785 786 Predecessors template should show all predecessors as we force their display
786 787 with --hidden
787 788 $ hg tlog --hidden
788 789 @ 7a230b46bf61
789 790 | Predecessors: 1:471f378eab4c
790 791 | semi-colon: 1:471f378eab4c
791 792 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
792 793 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
793 794 | x 471f378eab4c
794 795 |/
795 796 o ea207398892e
796 797
797 798
798 799 Test template with obsmarkers cycle
799 800 ===================================
800 801
801 802 Test setup
802 803 ----------
803 804
804 805 $ hg init $TESTTMP/templates-local-cycle
805 806 $ cd $TESTTMP/templates-local-cycle
806 807 $ mkcommit ROOT
807 808 $ mkcommit A0
808 809 $ mkcommit B0
809 810 $ hg up -r 0
810 811 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
811 812 $ mkcommit C0
812 813 created new head
813 814
814 815 Create the cycle
815 816
816 817 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(B0)"`
817 818 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(C0)"`
818 819 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(A0)"`
819 820
820 821 Check templates
821 822 ---------------
822 823
823 824 $ hg tlog
824 825 @ f897c6137566
825 826 |
826 827 o ea207398892e
827 828
828 829
829 830 $ hg up -r "desc(B0)" --hidden
830 831 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
831 832 $ hg tlog
832 833 o f897c6137566
833 834 | Predecessors: 2:0dec01379d3b
834 835 | semi-colon: 2:0dec01379d3b
835 836 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
836 837 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
837 838 | @ 0dec01379d3b
838 839 | | Predecessors: 1:471f378eab4c
839 840 | | semi-colon: 1:471f378eab4c
840 841 | | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
841 842 | | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
842 843 | x 471f378eab4c
843 844 |/ Predecessors: 2:0dec01379d3b
844 845 | semi-colon: 2:0dec01379d3b
845 846 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
846 847 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
847 848 o ea207398892e
848 849
849 850
850 851 $ hg up -r "desc(A0)" --hidden
851 852 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
852 853 $ hg tlog
853 854 o f897c6137566
854 855 | Predecessors: 1:471f378eab4c
855 856 | semi-colon: 1:471f378eab4c
856 857 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
857 858 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
858 859 | @ 471f378eab4c
859 860 |/
860 861 o ea207398892e
861 862
862 863
863 864 $ hg up -r "desc(ROOT)" --hidden
864 865 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
865 866 $ hg tlog
866 867 o f897c6137566
867 868 |
868 869 @ ea207398892e
869 870
870 871
871 872 $ hg tlog --hidden
872 873 o f897c6137566
873 874 | Predecessors: 2:0dec01379d3b
874 875 | semi-colon: 2:0dec01379d3b
875 876 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
876 877 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
877 878 | x 0dec01379d3b
878 879 | | Predecessors: 1:471f378eab4c
879 880 | | semi-colon: 1:471f378eab4c
880 881 | | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
881 882 | | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
882 883 | x 471f378eab4c
883 884 |/ Predecessors: 2:0dec01379d3b
884 885 | semi-colon: 2:0dec01379d3b
885 886 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
886 887 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
887 888 @ ea207398892e
888 889
@@ -1,1366 +1,1372 b''
1 1 ==================================================
2 2 Test obsmarkers interaction with bundle and strip
3 3 ==================================================
4 4
5 5 Setup a repository with various case
6 6 ====================================
7 7
8 8 Config setup
9 9 ------------
10 10
11 11 $ cat >> $HGRCPATH <<EOF
12 12 > [ui]
13 13 > # simpler log output
14 14 > logtemplate = "{node|short}: {desc}\n"
15 15 >
16 16 > [experimental]
17 17 > # enable evolution
18 18 > evolution = all
19 19 >
20 20 > # include obsmarkers in bundle
21 21 > evolution.bundle-obsmarker = yes
22 22 >
23 23 > [extensions]
24 24 > # needed for some tests
25 25 > strip =
26 26 > [defaults]
27 27 > # we'll query many hidden changeset
28 28 > debugobsolete = --hidden
29 29 > EOF
30 30
31 31 $ mkcommit() {
32 32 > echo "$1" > "$1"
33 33 > hg add "$1"
34 34 > hg ci -m "$1"
35 35 > }
36 36
37 37 $ getid() {
38 38 > hg log --hidden --template '{node}\n' --rev "$1"
39 39 > }
40 40
41 41 $ mktestrepo () {
42 42 > [ -n "$1" ] || exit 1
43 43 > cd $TESTTMP
44 44 > hg init $1
45 45 > cd $1
46 46 > mkcommit ROOT
47 47 > }
48 48
49 49 Function to compare the expected bundled obsmarkers with the actually bundled
50 50 obsmarkers. It also check the obsmarkers backed up during strip.
51 51
52 52 $ testrevs () {
53 53 > revs="$1"
54 54 > testname=`basename \`pwd\``
55 55 > revsname=`hg --hidden log -T '-{desc}' --rev "${revs}"`
56 56 > prefix="${TESTTMP}/${testname}${revsname}"
57 57 > markersfile="${prefix}-relevant-markers.txt"
58 58 > exclufile="${prefix}-exclusive-markers.txt"
59 59 > bundlefile="${prefix}-bundle.hg"
60 60 > contentfile="${prefix}-bundle-markers.hg"
61 61 > stripcontentfile="${prefix}-bundle-markers.hg"
62 62 > hg debugobsolete --hidden --rev "${revs}" | sed 's/^/ /' > "${markersfile}"
63 63 > hg debugobsolete --hidden --rev "${revs}" --exclusive | sed 's/^/ /' > "${exclufile}"
64 64 > echo '### Matched revisions###'
65 65 > hg log --hidden --rev "${revs}" | sort
66 66 > echo '### Relevant markers ###'
67 67 > cat "${markersfile}"
68 68 > printf "# bundling: "
69 69 > hg bundle --hidden --base "parents(roots(${revs}))" --rev "${revs}" "${bundlefile}"
70 70 > hg debugbundle --part-type obsmarkers "${bundlefile}" | sed 1,3d > "${contentfile}"
71 71 > echo '### Bundled markers ###'
72 72 > cat "${contentfile}"
73 73 > echo '### diff <relevant> <bundled> ###'
74 74 > cmp "${markersfile}" "${contentfile}" || diff -u "${markersfile}" "${contentfile}"
75 75 > echo '#################################'
76 76 > echo '### Exclusive markers ###'
77 77 > cat "${exclufile}"
78 78 > # if the matched revs do not have children, we also check the result of strip
79 79 > children=`hg log --hidden --rev "((${revs})::) - (${revs})"`
80 80 > if [ -z "$children" ];
81 81 > then
82 82 > printf "# stripping: "
83 83 > prestripfile="${prefix}-pre-strip.txt"
84 84 > poststripfile="${prefix}-post-strip.txt"
85 85 > strippedfile="${prefix}-stripped-markers.txt"
86 86 > hg debugobsolete --hidden | sort | sed 's/^/ /' > "${prestripfile}"
87 87 > hg strip --hidden --rev "${revs}"
88 88 > hg debugobsolete --hidden | sort | sed 's/^/ /' > "${poststripfile}"
89 89 > hg debugbundle --part-type obsmarkers .hg/strip-backup/* | sed 1,3d > "${stripcontentfile}"
90 90 > echo '### Backup markers ###'
91 91 > cat "${stripcontentfile}"
92 92 > echo '### diff <relevant> <backed-up> ###'
93 93 > cmp "${markersfile}" "${stripcontentfile}" || diff -u "${markersfile}" "${stripcontentfile}"
94 94 > echo '#################################'
95 95 > cat "${prestripfile}" "${poststripfile}" | sort | uniq -u > "${strippedfile}"
96 96 > echo '### Stripped markers ###'
97 97 > cat "${strippedfile}"
98 98 > echo '### diff <exclusive> <stripped> ###'
99 99 > cmp "${exclufile}" "${strippedfile}" || diff -u "${exclufile}" "${strippedfile}"
100 100 > echo '#################################'
101 101 > # restore and clean up repo for the next test
102 102 > hg unbundle .hg/strip-backup/* | sed 's/^/# unbundling: /'
103 103 > # clean up directory for the next test
104 104 > rm .hg/strip-backup/*
105 105 > fi
106 106 > }
107 107
108 108 root setup
109 109 -------------
110 110
111 111 simple chain
112 112 ============
113 113
114 114 . A0
115 115 . ⇠ø⇠◔ A1
116 116 . |/
117 117 . ●
118 118
119 119 setup
120 120 -----
121 121
122 122 $ mktestrepo simple-chain
123 123 $ mkcommit 'C-A0'
124 124 $ hg up 'desc("ROOT")'
125 125 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
126 126 $ mkcommit 'C-A1'
127 127 created new head
128 128 $ hg debugobsolete a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 `getid 'desc("C-A0")'`
129 129 $ hg debugobsolete `getid 'desc("C-A0")'` a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1
130 130 $ hg debugobsolete a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 `getid 'desc("C-A1")'`
131 131
132 132 $ hg up 'desc("ROOT")'
133 133 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
134 134 $ hg log --hidden -G
135 135 o cf2c22470d67: C-A1
136 136 |
137 137 | x 84fcb0dfe17b: C-A0
138 138 |/
139 139 @ ea207398892e: ROOT
140 140
141 141 $ hg debugobsolete
142 142 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
143 143 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
144 144 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
145 145
146 146 Actual testing
147 147 --------------
148 148
149 149 $ testrevs 'desc("C-A0")'
150 150 ### Matched revisions###
151 151 84fcb0dfe17b: C-A0
152 152 ### Relevant markers ###
153 153 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
154 154 # bundling: 1 changesets found
155 155 ### Bundled markers ###
156 156 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
157 157 ### diff <relevant> <bundled> ###
158 158 #################################
159 159 ### Exclusive markers ###
160 160 # stripping: saved backup bundle to $TESTTMP/simple-chain/.hg/strip-backup/84fcb0dfe17b-6454bbdc-backup.hg (glob)
161 161 ### Backup markers ###
162 162 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
163 163 ### diff <relevant> <backed-up> ###
164 164 #################################
165 165 ### Stripped markers ###
166 166 ### diff <exclusive> <stripped> ###
167 167 #################################
168 168 # unbundling: adding changesets
169 169 # unbundling: adding manifests
170 170 # unbundling: adding file changes
171 171 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
172 172 # unbundling: (run 'hg heads' to see heads)
173 173
174 174 $ testrevs 'desc("C-A1")'
175 175 ### Matched revisions###
176 176 cf2c22470d67: C-A1
177 177 ### Relevant markers ###
178 178 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
179 179 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
180 180 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
181 181 # bundling: 1 changesets found
182 182 ### Bundled markers ###
183 183 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
184 184 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
185 185 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
186 186 ### diff <relevant> <bundled> ###
187 187 #################################
188 188 ### Exclusive markers ###
189 189 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
190 190 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
191 191 # stripping: saved backup bundle to $TESTTMP/simple-chain/.hg/strip-backup/cf2c22470d67-fa0f07b0-backup.hg (glob)
192 192 ### Backup markers ###
193 193 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
194 194 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
195 195 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
196 196 ### diff <relevant> <backed-up> ###
197 197 #################################
198 198 ### Stripped markers ###
199 199 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
200 200 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
201 201 ### diff <exclusive> <stripped> ###
202 202 #################################
203 203 # unbundling: adding changesets
204 204 # unbundling: adding manifests
205 205 # unbundling: adding file changes
206 206 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
207 207 # unbundling: 2 new obsolescence markers
208 # unbundling: obsoleted 1 changesets
208 209 # unbundling: (run 'hg heads' to see heads)
209 210
210 211 $ testrevs 'desc("C-A")'
211 212 ### Matched revisions###
212 213 84fcb0dfe17b: C-A0
213 214 cf2c22470d67: C-A1
214 215 ### Relevant markers ###
215 216 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
216 217 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
217 218 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
218 219 # bundling: 2 changesets found
219 220 ### Bundled markers ###
220 221 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
221 222 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
222 223 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
223 224 ### diff <relevant> <bundled> ###
224 225 #################################
225 226 ### Exclusive markers ###
226 227 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
227 228 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
228 229 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
229 230 # stripping: saved backup bundle to $TESTTMP/simple-chain/.hg/strip-backup/cf2c22470d67-fce4fc64-backup.hg (glob)
230 231 ### Backup markers ###
231 232 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
232 233 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
233 234 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
234 235 ### diff <relevant> <backed-up> ###
235 236 #################################
236 237 ### Stripped markers ###
237 238 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
238 239 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
239 240 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
240 241 ### diff <exclusive> <stripped> ###
241 242 #################################
242 243 # unbundling: adding changesets
243 244 # unbundling: adding manifests
244 245 # unbundling: adding file changes
245 246 # unbundling: added 2 changesets with 2 changes to 2 files (+1 heads)
246 247 # unbundling: 3 new obsolescence markers
247 248 # unbundling: (run 'hg heads' to see heads)
248 249
249 250 chain with prune children
250 251 =========================
251 252
252 253 . ⇠⊗ B0
253 254 . |
254 255 . ⇠ø⇠◔ A1
255 256 . |
256 257 . ●
257 258
258 259 setup
259 260 -----
260 261
261 262 $ mktestrepo prune
262 263 $ mkcommit 'C-A0'
263 264 $ mkcommit 'C-B0'
264 265 $ hg up 'desc("ROOT")'
265 266 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
266 267 $ mkcommit 'C-A1'
267 268 created new head
268 269 $ hg debugobsolete a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 `getid 'desc("C-A0")'`
269 270 $ hg debugobsolete `getid 'desc("C-A0")'` `getid 'desc("C-A1")'`
270 271 $ hg debugobsolete --record-parents `getid 'desc("C-B0")'`
271 272 $ hg up 'desc("ROOT")'
272 273 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
273 274 $ hg log --hidden -G
274 275 o cf2c22470d67: C-A1
275 276 |
276 277 | x 29f93b1df87b: C-B0
277 278 | |
278 279 | x 84fcb0dfe17b: C-A0
279 280 |/
280 281 @ ea207398892e: ROOT
281 282
282 283 $ hg debugobsolete
283 284 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
284 285 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
285 286 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
286 287
287 288 Actual testing
288 289 --------------
289 290
290 291 $ testrevs 'desc("C-A0")'
291 292 ### Matched revisions###
292 293 84fcb0dfe17b: C-A0
293 294 ### Relevant markers ###
294 295 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
295 296 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
296 297 # bundling: 1 changesets found
297 298 ### Bundled markers ###
298 299 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
299 300 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
300 301 ### diff <relevant> <bundled> ###
301 302 #################################
302 303 ### Exclusive markers ###
303 304
304 305 (The strip markers is considered exclusive to the pruned changeset even if it
305 306 is also considered "relevant" to its parent. This allows to strip prune
306 307 markers. This avoid leaving prune markers from dead-end that could be
307 308 problematic)
308 309
309 310 $ testrevs 'desc("C-B0")'
310 311 ### Matched revisions###
311 312 29f93b1df87b: C-B0
312 313 ### Relevant markers ###
313 314 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
314 315 # bundling: 1 changesets found
315 316 ### Bundled markers ###
316 317 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
317 318 ### diff <relevant> <bundled> ###
318 319 #################################
319 320 ### Exclusive markers ###
320 321 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
321 322 # stripping: saved backup bundle to $TESTTMP/prune/.hg/strip-backup/29f93b1df87b-7fb32101-backup.hg (glob)
322 323 ### Backup markers ###
323 324 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
324 325 ### diff <relevant> <backed-up> ###
325 326 #################################
326 327 ### Stripped markers ###
327 328 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
328 329 ### diff <exclusive> <stripped> ###
329 330 #################################
330 331 # unbundling: adding changesets
331 332 # unbundling: adding manifests
332 333 # unbundling: adding file changes
333 334 # unbundling: added 1 changesets with 1 changes to 1 files
334 335 # unbundling: 1 new obsolescence markers
335 336 # unbundling: (run 'hg update' to get a working copy)
336 337
337 338 $ testrevs 'desc("C-A1")'
338 339 ### Matched revisions###
339 340 cf2c22470d67: C-A1
340 341 ### Relevant markers ###
341 342 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
342 343 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
343 344 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
344 345 # bundling: 1 changesets found
345 346 ### Bundled markers ###
346 347 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
347 348 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
348 349 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
349 350 ### diff <relevant> <bundled> ###
350 351 #################################
351 352 ### Exclusive markers ###
352 353 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
353 354 # stripping: saved backup bundle to $TESTTMP/prune/.hg/strip-backup/cf2c22470d67-fa0f07b0-backup.hg (glob)
354 355 ### Backup markers ###
355 356 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
356 357 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
357 358 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
358 359 ### diff <relevant> <backed-up> ###
359 360 #################################
360 361 ### Stripped markers ###
361 362 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
362 363 ### diff <exclusive> <stripped> ###
363 364 #################################
364 365 # unbundling: adding changesets
365 366 # unbundling: adding manifests
366 367 # unbundling: adding file changes
367 368 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
368 369 # unbundling: 1 new obsolescence markers
370 # unbundling: obsoleted 1 changesets
369 371 # unbundling: (run 'hg heads' to see heads)
370 372
371 373 bundling multiple revisions
372 374
373 375 $ testrevs 'desc("C-A")'
374 376 ### Matched revisions###
375 377 84fcb0dfe17b: C-A0
376 378 cf2c22470d67: C-A1
377 379 ### Relevant markers ###
378 380 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
379 381 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
380 382 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
381 383 # bundling: 2 changesets found
382 384 ### Bundled markers ###
383 385 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
384 386 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
385 387 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
386 388 ### diff <relevant> <bundled> ###
387 389 #################################
388 390 ### Exclusive markers ###
389 391 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
390 392 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
391 393
392 394 $ testrevs 'desc("C-")'
393 395 ### Matched revisions###
394 396 29f93b1df87b: C-B0
395 397 84fcb0dfe17b: C-A0
396 398 cf2c22470d67: C-A1
397 399 ### Relevant markers ###
398 400 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
399 401 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
400 402 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
401 403 # bundling: 3 changesets found
402 404 ### Bundled markers ###
403 405 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
404 406 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
405 407 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
406 408 ### diff <relevant> <bundled> ###
407 409 #################################
408 410 ### Exclusive markers ###
409 411 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
410 412 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
411 413 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
412 414 # stripping: saved backup bundle to $TESTTMP/prune/.hg/strip-backup/cf2c22470d67-884c33b0-backup.hg (glob)
413 415 ### Backup markers ###
414 416 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
415 417 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
416 418 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
417 419 ### diff <relevant> <backed-up> ###
418 420 #################################
419 421 ### Stripped markers ###
420 422 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
421 423 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
422 424 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
423 425 ### diff <exclusive> <stripped> ###
424 426 #################################
425 427 # unbundling: adding changesets
426 428 # unbundling: adding manifests
427 429 # unbundling: adding file changes
428 430 # unbundling: added 3 changesets with 3 changes to 3 files (+1 heads)
429 431 # unbundling: 3 new obsolescence markers
430 432 # unbundling: (run 'hg heads' to see heads)
431 433
432 434 chain with precursors also pruned
433 435 =================================
434 436
435 437 . A0 (also pruned)
436 438 . ⇠ø⇠◔ A1
437 439 . |
438 440 . ●
439 441
440 442 setup
441 443 -----
442 444
443 445 $ mktestrepo prune-inline
444 446 $ mkcommit 'C-A0'
445 447 $ hg up 'desc("ROOT")'
446 448 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
447 449 $ mkcommit 'C-A1'
448 450 created new head
449 451 $ hg debugobsolete a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 `getid 'desc("C-A0")'`
450 452 $ hg debugobsolete --record-parents `getid 'desc("C-A0")'`
451 453 $ hg debugobsolete `getid 'desc("C-A0")'` `getid 'desc("C-A1")'`
452 454 $ hg up 'desc("ROOT")'
453 455 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
454 456 $ hg log --hidden -G
455 457 o cf2c22470d67: C-A1
456 458 |
457 459 | x 84fcb0dfe17b: C-A0
458 460 |/
459 461 @ ea207398892e: ROOT
460 462
461 463 $ hg debugobsolete
462 464 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
463 465 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
464 466 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
465 467
466 468 Actual testing
467 469 --------------
468 470
469 471 $ testrevs 'desc("C-A0")'
470 472 ### Matched revisions###
471 473 84fcb0dfe17b: C-A0
472 474 ### Relevant markers ###
473 475 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
474 476 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
475 477 # bundling: 1 changesets found
476 478 ### Bundled markers ###
477 479 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
478 480 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
479 481 ### diff <relevant> <bundled> ###
480 482 #################################
481 483 ### Exclusive markers ###
482 484 # stripping: saved backup bundle to $TESTTMP/prune-inline/.hg/strip-backup/84fcb0dfe17b-6454bbdc-backup.hg (glob)
483 485 ### Backup markers ###
484 486 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
485 487 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
486 488 ### diff <relevant> <backed-up> ###
487 489 #################################
488 490 ### Stripped markers ###
489 491 ### diff <exclusive> <stripped> ###
490 492 #################################
491 493 # unbundling: adding changesets
492 494 # unbundling: adding manifests
493 495 # unbundling: adding file changes
494 496 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
495 497 # unbundling: (run 'hg heads' to see heads)
496 498
497 499 $ testrevs 'desc("C-A1")'
498 500 ### Matched revisions###
499 501 cf2c22470d67: C-A1
500 502 ### Relevant markers ###
501 503 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
502 504 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
503 505 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
504 506 # bundling: 1 changesets found
505 507 ### Bundled markers ###
506 508 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
507 509 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
508 510 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
509 511 ### diff <relevant> <bundled> ###
510 512 #################################
511 513 ### Exclusive markers ###
512 514 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
513 515 # stripping: saved backup bundle to $TESTTMP/prune-inline/.hg/strip-backup/cf2c22470d67-fa0f07b0-backup.hg (glob)
514 516 ### Backup markers ###
515 517 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
516 518 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
517 519 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
518 520 ### diff <relevant> <backed-up> ###
519 521 #################################
520 522 ### Stripped markers ###
521 523 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
522 524 ### diff <exclusive> <stripped> ###
523 525 #################################
524 526 # unbundling: adding changesets
525 527 # unbundling: adding manifests
526 528 # unbundling: adding file changes
527 529 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
528 530 # unbundling: 1 new obsolescence markers
529 531 # unbundling: (run 'hg heads' to see heads)
530 532
531 533 $ testrevs 'desc("C-A")'
532 534 ### Matched revisions###
533 535 84fcb0dfe17b: C-A0
534 536 cf2c22470d67: C-A1
535 537 ### Relevant markers ###
536 538 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
537 539 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
538 540 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
539 541 # bundling: 2 changesets found
540 542 ### Bundled markers ###
541 543 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
542 544 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
543 545 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
544 546 ### diff <relevant> <bundled> ###
545 547 #################################
546 548 ### Exclusive markers ###
547 549 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
548 550 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
549 551 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
550 552 # stripping: saved backup bundle to $TESTTMP/prune-inline/.hg/strip-backup/cf2c22470d67-fce4fc64-backup.hg (glob)
551 553 ### Backup markers ###
552 554 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
553 555 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
554 556 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
555 557 ### diff <relevant> <backed-up> ###
556 558 #################################
557 559 ### Stripped markers ###
558 560 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
559 561 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
560 562 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
561 563 ### diff <exclusive> <stripped> ###
562 564 #################################
563 565 # unbundling: adding changesets
564 566 # unbundling: adding manifests
565 567 # unbundling: adding file changes
566 568 # unbundling: added 2 changesets with 2 changes to 2 files (+1 heads)
567 569 # unbundling: 3 new obsolescence markers
568 570 # unbundling: (run 'hg heads' to see heads)
569 571
570 572 chain with missing prune
571 573 ========================
572 574
573 575 . ⊗ B
574 576 . |
575 577 . ⇠◌⇠◔ A1
576 578 . |
577 579 . ●
578 580
579 581 setup
580 582 -----
581 583
582 584 $ mktestrepo missing-prune
583 585 $ mkcommit 'C-A0'
584 586 $ mkcommit 'C-B0'
585 587 $ hg up 'desc("ROOT")'
586 588 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
587 589 $ mkcommit 'C-A1'
588 590 created new head
589 591 $ hg debugobsolete a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 `getid 'desc("C-A0")'`
590 592 $ hg debugobsolete `getid 'desc("C-A0")'` `getid 'desc("C-A1")'`
591 593 $ hg debugobsolete --record-parents `getid 'desc("C-B0")'`
592 594
593 595 (it is annoying to create prune with parent data without the changeset, so we strip it after the fact)
594 596
595 597 $ hg strip --hidden --rev 'desc("C-A0")::' --no-backup --config devel.strip-obsmarkers=no
596 598
597 599 $ hg up 'desc("ROOT")'
598 600 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
599 601 $ hg log --hidden -G
600 602 o cf2c22470d67: C-A1
601 603 |
602 604 @ ea207398892e: ROOT
603 605
604 606 $ hg debugobsolete
605 607 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
606 608 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
607 609 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
608 610
609 611 Actual testing
610 612 --------------
611 613
612 614 $ testrevs 'desc("C-A1")'
613 615 ### Matched revisions###
614 616 cf2c22470d67: C-A1
615 617 ### Relevant markers ###
616 618 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
617 619 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
618 620 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
619 621 # bundling: 1 changesets found
620 622 ### Bundled markers ###
621 623 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
622 624 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
623 625 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
624 626 ### diff <relevant> <bundled> ###
625 627 #################################
626 628 ### Exclusive markers ###
627 629 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
628 630 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
629 631 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
630 632 # stripping: saved backup bundle to $TESTTMP/missing-prune/.hg/strip-backup/cf2c22470d67-fa0f07b0-backup.hg (glob)
631 633 ### Backup markers ###
632 634 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
633 635 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
634 636 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
635 637 ### diff <relevant> <backed-up> ###
636 638 #################################
637 639 ### Stripped markers ###
638 640 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
639 641 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
640 642 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
641 643 ### diff <exclusive> <stripped> ###
642 644 #################################
643 645 # unbundling: adding changesets
644 646 # unbundling: adding manifests
645 647 # unbundling: adding file changes
646 648 # unbundling: added 1 changesets with 1 changes to 1 files
647 649 # unbundling: 3 new obsolescence markers
648 650 # unbundling: (run 'hg update' to get a working copy)
649 651
650 652 chain with precursors also pruned
651 653 =================================
652 654
653 655 . A0 (also pruned)
654 656 . ⇠◌⇠◔ A1
655 657 . |
656 658 . ●
657 659
658 660 setup
659 661 -----
660 662
661 663 $ mktestrepo prune-inline-missing
662 664 $ mkcommit 'C-A0'
663 665 $ hg up 'desc("ROOT")'
664 666 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
665 667 $ mkcommit 'C-A1'
666 668 created new head
667 669 $ hg debugobsolete a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 `getid 'desc("C-A0")'`
668 670 $ hg debugobsolete --record-parents `getid 'desc("C-A0")'`
669 671 $ hg debugobsolete `getid 'desc("C-A0")'` `getid 'desc("C-A1")'`
670 672
671 673 (it is annoying to create prune with parent data without the changeset, so we strip it after the fact)
672 674
673 675 $ hg strip --hidden --rev 'desc("C-A0")::' --no-backup --config devel.strip-obsmarkers=no
674 676
675 677 $ hg up 'desc("ROOT")'
676 678 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
677 679 $ hg log --hidden -G
678 680 o cf2c22470d67: C-A1
679 681 |
680 682 @ ea207398892e: ROOT
681 683
682 684 $ hg debugobsolete
683 685 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
684 686 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
685 687 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
686 688
687 689 Actual testing
688 690 --------------
689 691
690 692 $ testrevs 'desc("C-A1")'
691 693 ### Matched revisions###
692 694 cf2c22470d67: C-A1
693 695 ### Relevant markers ###
694 696 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
695 697 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
696 698 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
697 699 # bundling: 1 changesets found
698 700 ### Bundled markers ###
699 701 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
700 702 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
701 703 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
702 704 ### diff <relevant> <bundled> ###
703 705 #################################
704 706 ### Exclusive markers ###
705 707 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
706 708 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
707 709 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
708 710 # stripping: saved backup bundle to $TESTTMP/prune-inline-missing/.hg/strip-backup/cf2c22470d67-fa0f07b0-backup.hg (glob)
709 711 ### Backup markers ###
710 712 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
711 713 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
712 714 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
713 715 ### diff <relevant> <backed-up> ###
714 716 #################################
715 717 ### Stripped markers ###
716 718 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
717 719 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
718 720 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
719 721 ### diff <exclusive> <stripped> ###
720 722 #################################
721 723 # unbundling: adding changesets
722 724 # unbundling: adding manifests
723 725 # unbundling: adding file changes
724 726 # unbundling: added 1 changesets with 1 changes to 1 files
725 727 # unbundling: 3 new obsolescence markers
726 728 # unbundling: (run 'hg update' to get a working copy)
727 729
728 730 Chain with fold and split
729 731 =========================
730 732
731 733 setup
732 734 -----
733 735
734 736 $ mktestrepo split-fold
735 737 $ mkcommit 'C-A'
736 738 $ hg up 'desc("ROOT")'
737 739 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
738 740 $ mkcommit 'C-B'
739 741 created new head
740 742 $ hg up 'desc("ROOT")'
741 743 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
742 744 $ mkcommit 'C-C'
743 745 created new head
744 746 $ hg up 'desc("ROOT")'
745 747 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
746 748 $ mkcommit 'C-D'
747 749 created new head
748 750 $ hg up 'desc("ROOT")'
749 751 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
750 752 $ mkcommit 'C-E'
751 753 created new head
752 754 $ hg debugobsolete a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 `getid 'desc("C-A")'`
753 755 $ hg debugobsolete `getid 'desc("C-A")'` `getid 'desc("C-B")'` `getid 'desc("C-C")'` # record split
754 756 $ hg debugobsolete `getid 'desc("C-A")'` `getid 'desc("C-D")'` # other divergent
755 757 $ hg debugobsolete `getid 'desc("C-A")'` b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0
756 758 $ hg debugobsolete b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 `getid 'desc("C-E")'`
757 759 $ hg debugobsolete `getid 'desc("C-B")'` `getid 'desc("C-E")'`
758 760 $ hg debugobsolete `getid 'desc("C-C")'` `getid 'desc("C-E")'`
759 761 $ hg debugobsolete `getid 'desc("C-D")'` `getid 'desc("C-E")'`
760 762 $ hg debugobsolete c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 `getid 'desc("C-E")'`
761 763
762 764 $ hg up 'desc("ROOT")'
763 765 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
764 766 $ hg log --hidden -G
765 767 o 2f20ff6509f0: C-E
766 768 |
767 769 | x 06dc9da25ef0: C-D
768 770 |/
769 771 | x 27ec657ca21d: C-C
770 772 |/
771 773 | x a9b9da38ed96: C-B
772 774 |/
773 775 | x 9ac430e15fca: C-A
774 776 |/
775 777 @ ea207398892e: ROOT
776 778
777 779 $ hg debugobsolete
778 780 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
779 781 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
780 782 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
781 783 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
782 784 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
783 785 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
784 786 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
785 787 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
786 788 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
787 789
788 790 Actual testing
789 791 --------------
790 792
791 793 $ testrevs 'desc("C-A")'
792 794 ### Matched revisions###
793 795 9ac430e15fca: C-A
794 796 ### Relevant markers ###
795 797 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
796 798 # bundling: 1 changesets found
797 799 ### Bundled markers ###
798 800 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
799 801 ### diff <relevant> <bundled> ###
800 802 #################################
801 803 ### Exclusive markers ###
802 804 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/9ac430e15fca-81204eba-backup.hg (glob)
803 805 ### Backup markers ###
804 806 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
805 807 ### diff <relevant> <backed-up> ###
806 808 #################################
807 809 ### Stripped markers ###
808 810 ### diff <exclusive> <stripped> ###
809 811 #################################
810 812 # unbundling: adding changesets
811 813 # unbundling: adding manifests
812 814 # unbundling: adding file changes
813 815 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
814 816 # unbundling: (run 'hg heads' to see heads)
815 817
816 818 $ testrevs 'desc("C-B")'
817 819 ### Matched revisions###
818 820 a9b9da38ed96: C-B
819 821 ### Relevant markers ###
820 822 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
821 823 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
822 824 # bundling: 1 changesets found
823 825 ### Bundled markers ###
824 826 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
825 827 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
826 828 ### diff <relevant> <bundled> ###
827 829 #################################
828 830 ### Exclusive markers ###
829 831 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/a9b9da38ed96-7465d6e9-backup.hg (glob)
830 832 ### Backup markers ###
831 833 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
832 834 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
833 835 ### diff <relevant> <backed-up> ###
834 836 #################################
835 837 ### Stripped markers ###
836 838 ### diff <exclusive> <stripped> ###
837 839 #################################
838 840 # unbundling: adding changesets
839 841 # unbundling: adding manifests
840 842 # unbundling: adding file changes
841 843 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
842 844 # unbundling: (run 'hg heads' to see heads)
843 845
844 846 $ testrevs 'desc("C-C")'
845 847 ### Matched revisions###
846 848 27ec657ca21d: C-C
847 849 ### Relevant markers ###
848 850 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
849 851 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
850 852 # bundling: 1 changesets found
851 853 ### Bundled markers ###
852 854 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
853 855 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
854 856 ### diff <relevant> <bundled> ###
855 857 #################################
856 858 ### Exclusive markers ###
857 859 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/27ec657ca21d-d5dd1c7c-backup.hg (glob)
858 860 ### Backup markers ###
859 861 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
860 862 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
861 863 ### diff <relevant> <backed-up> ###
862 864 #################################
863 865 ### Stripped markers ###
864 866 ### diff <exclusive> <stripped> ###
865 867 #################################
866 868 # unbundling: adding changesets
867 869 # unbundling: adding manifests
868 870 # unbundling: adding file changes
869 871 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
870 872 # unbundling: (run 'hg heads' to see heads)
871 873
872 874 $ testrevs 'desc("C-D")'
873 875 ### Matched revisions###
874 876 06dc9da25ef0: C-D
875 877 ### Relevant markers ###
876 878 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
877 879 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
878 880 # bundling: 1 changesets found
879 881 ### Bundled markers ###
880 882 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
881 883 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
882 884 ### diff <relevant> <bundled> ###
883 885 #################################
884 886 ### Exclusive markers ###
885 887 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/06dc9da25ef0-9b1c0a91-backup.hg (glob)
886 888 ### Backup markers ###
887 889 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
888 890 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
889 891 ### diff <relevant> <backed-up> ###
890 892 #################################
891 893 ### Stripped markers ###
892 894 ### diff <exclusive> <stripped> ###
893 895 #################################
894 896 # unbundling: adding changesets
895 897 # unbundling: adding manifests
896 898 # unbundling: adding file changes
897 899 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
898 900 # unbundling: (run 'hg heads' to see heads)
899 901
900 902 $ testrevs 'desc("C-E")'
901 903 ### Matched revisions###
902 904 2f20ff6509f0: C-E
903 905 ### Relevant markers ###
904 906 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
905 907 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
906 908 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
907 909 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
908 910 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
909 911 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
910 912 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
911 913 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
912 914 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
913 915 # bundling: 1 changesets found
914 916 ### Bundled markers ###
915 917 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
916 918 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
917 919 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
918 920 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
919 921 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
920 922 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
921 923 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
922 924 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
923 925 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
924 926 ### diff <relevant> <bundled> ###
925 927 #################################
926 928 ### Exclusive markers ###
927 929 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
928 930 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
929 931 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
930 932 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
931 933 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
932 934 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
933 935 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/2f20ff6509f0-8adeb22d-backup.hg (glob)
934 936 ### Backup markers ###
935 937 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
936 938 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
937 939 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
938 940 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
939 941 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
940 942 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
941 943 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
942 944 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
943 945 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
944 946 ### diff <relevant> <backed-up> ###
945 947 #################################
946 948 ### Stripped markers ###
947 949 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
948 950 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
949 951 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
950 952 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
951 953 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
952 954 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
953 955 ### diff <exclusive> <stripped> ###
954 956 #################################
955 957 # unbundling: adding changesets
956 958 # unbundling: adding manifests
957 959 # unbundling: adding file changes
958 960 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
959 961 # unbundling: 6 new obsolescence markers
962 # unbundling: obsoleted 3 changesets
960 963 # unbundling: (run 'hg heads' to see heads)
961 964
962 965 Bundle multiple revisions
963 966
964 967 * each part of the split
965 968
966 969 $ testrevs 'desc("C-B") + desc("C-C")'
967 970 ### Matched revisions###
968 971 27ec657ca21d: C-C
969 972 a9b9da38ed96: C-B
970 973 ### Relevant markers ###
971 974 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
972 975 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
973 976 # bundling: 2 changesets found
974 977 ### Bundled markers ###
975 978 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
976 979 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
977 980 ### diff <relevant> <bundled> ###
978 981 #################################
979 982 ### Exclusive markers ###
980 983 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/a9b9da38ed96-0daf625a-backup.hg (glob)
981 984 ### Backup markers ###
982 985 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
983 986 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
984 987 ### diff <relevant> <backed-up> ###
985 988 #################################
986 989 ### Stripped markers ###
987 990 ### diff <exclusive> <stripped> ###
988 991 #################################
989 992 # unbundling: adding changesets
990 993 # unbundling: adding manifests
991 994 # unbundling: adding file changes
992 995 # unbundling: added 2 changesets with 2 changes to 2 files (+2 heads)
993 996 # unbundling: (run 'hg heads' to see heads)
994 997
995 998 * top one and other divergent
996 999
997 1000 $ testrevs 'desc("C-E") + desc("C-D")'
998 1001 ### Matched revisions###
999 1002 06dc9da25ef0: C-D
1000 1003 2f20ff6509f0: C-E
1001 1004 ### Relevant markers ###
1002 1005 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1003 1006 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1004 1007 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1005 1008 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1006 1009 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1007 1010 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1008 1011 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1009 1012 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1010 1013 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1011 1014 # bundling: 2 changesets found
1012 1015 ### Bundled markers ###
1013 1016 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1014 1017 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1015 1018 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1016 1019 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1017 1020 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1018 1021 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1019 1022 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1020 1023 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1021 1024 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1022 1025 ### diff <relevant> <bundled> ###
1023 1026 #################################
1024 1027 ### Exclusive markers ###
1025 1028 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1026 1029 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1027 1030 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1028 1031 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1029 1032 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1030 1033 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1031 1034 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1032 1035 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/2f20ff6509f0-bf1b80f4-backup.hg (glob)
1033 1036 ### Backup markers ###
1034 1037 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1035 1038 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1036 1039 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1037 1040 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1038 1041 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1039 1042 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1040 1043 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1041 1044 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1042 1045 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1043 1046 ### diff <relevant> <backed-up> ###
1044 1047 #################################
1045 1048 ### Stripped markers ###
1046 1049 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1047 1050 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1048 1051 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1049 1052 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1050 1053 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1051 1054 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1052 1055 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1053 1056 ### diff <exclusive> <stripped> ###
1054 1057 #################################
1055 1058 # unbundling: adding changesets
1056 1059 # unbundling: adding manifests
1057 1060 # unbundling: adding file changes
1058 1061 # unbundling: added 2 changesets with 2 changes to 2 files (+2 heads)
1059 1062 # unbundling: 7 new obsolescence markers
1063 # unbundling: obsoleted 2 changesets
1060 1064 # unbundling: (run 'hg heads' to see heads)
1061 1065
1062 1066 * top one and initial precursors
1063 1067
1064 1068 $ testrevs 'desc("C-E") + desc("C-A")'
1065 1069 ### Matched revisions###
1066 1070 2f20ff6509f0: C-E
1067 1071 9ac430e15fca: C-A
1068 1072 ### Relevant markers ###
1069 1073 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1070 1074 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1071 1075 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1072 1076 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1073 1077 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1074 1078 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1075 1079 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1076 1080 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1077 1081 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1078 1082 # bundling: 2 changesets found
1079 1083 ### Bundled markers ###
1080 1084 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1081 1085 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1082 1086 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1083 1087 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1084 1088 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1085 1089 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1086 1090 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1087 1091 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1088 1092 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1089 1093 ### diff <relevant> <bundled> ###
1090 1094 #################################
1091 1095 ### Exclusive markers ###
1092 1096 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1093 1097 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1094 1098 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1095 1099 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1096 1100 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1097 1101 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1098 1102 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/9ac430e15fca-36b6476a-backup.hg (glob)
1099 1103 ### Backup markers ###
1100 1104 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1101 1105 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1102 1106 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1103 1107 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1104 1108 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1105 1109 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1106 1110 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1107 1111 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1108 1112 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1109 1113 ### diff <relevant> <backed-up> ###
1110 1114 #################################
1111 1115 ### Stripped markers ###
1112 1116 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1113 1117 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1114 1118 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1115 1119 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1116 1120 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1117 1121 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1118 1122 ### diff <exclusive> <stripped> ###
1119 1123 #################################
1120 1124 # unbundling: adding changesets
1121 1125 # unbundling: adding manifests
1122 1126 # unbundling: adding file changes
1123 1127 # unbundling: added 2 changesets with 2 changes to 2 files (+2 heads)
1124 1128 # unbundling: 6 new obsolescence markers
1129 # unbundling: obsoleted 3 changesets
1125 1130 # unbundling: (run 'hg heads' to see heads)
1126 1131
1127 1132 * top one and one of the split
1128 1133
1129 1134 $ testrevs 'desc("C-E") + desc("C-C")'
1130 1135 ### Matched revisions###
1131 1136 27ec657ca21d: C-C
1132 1137 2f20ff6509f0: C-E
1133 1138 ### Relevant markers ###
1134 1139 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1135 1140 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1136 1141 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1137 1142 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1138 1143 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1139 1144 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1140 1145 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1141 1146 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1142 1147 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1143 1148 # bundling: 2 changesets found
1144 1149 ### Bundled markers ###
1145 1150 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1146 1151 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1147 1152 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1148 1153 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1149 1154 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1150 1155 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1151 1156 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1152 1157 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1153 1158 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1154 1159 ### diff <relevant> <bundled> ###
1155 1160 #################################
1156 1161 ### Exclusive markers ###
1157 1162 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1158 1163 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1159 1164 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1160 1165 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1161 1166 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1162 1167 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1163 1168 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1164 1169 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/2f20ff6509f0-5fdfcd7d-backup.hg (glob)
1165 1170 ### Backup markers ###
1166 1171 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1167 1172 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1168 1173 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1169 1174 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1170 1175 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1171 1176 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1172 1177 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1173 1178 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1174 1179 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1175 1180 ### diff <relevant> <backed-up> ###
1176 1181 #################################
1177 1182 ### Stripped markers ###
1178 1183 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1179 1184 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1180 1185 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1181 1186 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1182 1187 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1183 1188 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1184 1189 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1185 1190 ### diff <exclusive> <stripped> ###
1186 1191 #################################
1187 1192 # unbundling: adding changesets
1188 1193 # unbundling: adding manifests
1189 1194 # unbundling: adding file changes
1190 1195 # unbundling: added 2 changesets with 2 changes to 2 files (+2 heads)
1191 1196 # unbundling: 7 new obsolescence markers
1197 # unbundling: obsoleted 2 changesets
1192 1198 # unbundling: (run 'hg heads' to see heads)
1193 1199
1194 1200 * all
1195 1201
1196 1202 $ testrevs 'desc("C-")'
1197 1203 ### Matched revisions###
1198 1204 06dc9da25ef0: C-D
1199 1205 27ec657ca21d: C-C
1200 1206 2f20ff6509f0: C-E
1201 1207 9ac430e15fca: C-A
1202 1208 a9b9da38ed96: C-B
1203 1209 ### Relevant markers ###
1204 1210 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1205 1211 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1206 1212 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1207 1213 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1208 1214 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1209 1215 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1210 1216 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1211 1217 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1212 1218 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1213 1219 # bundling: 5 changesets found
1214 1220 ### Bundled markers ###
1215 1221 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1216 1222 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1217 1223 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1218 1224 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1219 1225 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1220 1226 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1221 1227 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1222 1228 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1223 1229 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1224 1230 ### diff <relevant> <bundled> ###
1225 1231 #################################
1226 1232 ### Exclusive markers ###
1227 1233 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1228 1234 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1229 1235 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1230 1236 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1231 1237 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1232 1238 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1233 1239 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1234 1240 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1235 1241 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1236 1242 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/a9b9da38ed96-eeb4258f-backup.hg (glob)
1237 1243 ### Backup markers ###
1238 1244 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1239 1245 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1240 1246 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1241 1247 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1242 1248 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1243 1249 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1244 1250 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1245 1251 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1246 1252 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1247 1253 ### diff <relevant> <backed-up> ###
1248 1254 #################################
1249 1255 ### Stripped markers ###
1250 1256 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1251 1257 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1252 1258 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1253 1259 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1254 1260 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1255 1261 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1256 1262 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1257 1263 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1258 1264 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1259 1265 ### diff <exclusive> <stripped> ###
1260 1266 #################################
1261 1267 # unbundling: adding changesets
1262 1268 # unbundling: adding manifests
1263 1269 # unbundling: adding file changes
1264 1270 # unbundling: added 5 changesets with 5 changes to 5 files (+4 heads)
1265 1271 # unbundling: 9 new obsolescence markers
1266 1272 # unbundling: (run 'hg heads' to see heads)
1267 1273
1268 1274 changeset pruned on its own
1269 1275 ===========================
1270 1276
1271 1277 . ⊗ B
1272 1278 . |
1273 1279 . ◕ A
1274 1280 . |
1275 1281 . ●
1276 1282
1277 1283 setup
1278 1284 -----
1279 1285
1280 1286 $ mktestrepo lonely-prune
1281 1287 $ hg up 'desc("ROOT")'
1282 1288 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1283 1289 $ mkcommit 'C-A'
1284 1290 $ mkcommit 'C-B'
1285 1291 $ hg debugobsolete --record-parent `getid 'desc("C-B")'`
1286 1292
1287 1293 $ hg up 'desc("ROOT")'
1288 1294 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1289 1295 $ hg log --hidden -G
1290 1296 x cefb651fc2fd: C-B
1291 1297 |
1292 1298 o 9ac430e15fca: C-A
1293 1299 |
1294 1300 @ ea207398892e: ROOT
1295 1301
1296 1302 $ hg debugobsolete
1297 1303 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1298 1304
1299 1305 Actual testing
1300 1306 --------------
1301 1307 $ testrevs 'desc("C-A")'
1302 1308 ### Matched revisions###
1303 1309 9ac430e15fca: C-A
1304 1310 ### Relevant markers ###
1305 1311 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1306 1312 # bundling: 1 changesets found
1307 1313 ### Bundled markers ###
1308 1314 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1309 1315 ### diff <relevant> <bundled> ###
1310 1316 #################################
1311 1317 ### Exclusive markers ###
1312 1318 $ testrevs 'desc("C-B")'
1313 1319 ### Matched revisions###
1314 1320 cefb651fc2fd: C-B
1315 1321 ### Relevant markers ###
1316 1322 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1317 1323 # bundling: 1 changesets found
1318 1324 ### Bundled markers ###
1319 1325 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1320 1326 ### diff <relevant> <bundled> ###
1321 1327 #################################
1322 1328 ### Exclusive markers ###
1323 1329 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1324 1330 # stripping: saved backup bundle to $TESTTMP/lonely-prune/.hg/strip-backup/cefb651fc2fd-345c8dfa-backup.hg (glob)
1325 1331 ### Backup markers ###
1326 1332 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1327 1333 ### diff <relevant> <backed-up> ###
1328 1334 #################################
1329 1335 ### Stripped markers ###
1330 1336 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1331 1337 ### diff <exclusive> <stripped> ###
1332 1338 #################################
1333 1339 # unbundling: adding changesets
1334 1340 # unbundling: adding manifests
1335 1341 # unbundling: adding file changes
1336 1342 # unbundling: added 1 changesets with 1 changes to 1 files
1337 1343 # unbundling: 1 new obsolescence markers
1338 1344 # unbundling: (run 'hg update' to get a working copy)
1339 1345 $ testrevs 'desc("C-")'
1340 1346 ### Matched revisions###
1341 1347 9ac430e15fca: C-A
1342 1348 cefb651fc2fd: C-B
1343 1349 ### Relevant markers ###
1344 1350 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1345 1351 # bundling: 2 changesets found
1346 1352 ### Bundled markers ###
1347 1353 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1348 1354 ### diff <relevant> <bundled> ###
1349 1355 #################################
1350 1356 ### Exclusive markers ###
1351 1357 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1352 1358 # stripping: saved backup bundle to $TESTTMP/lonely-prune/.hg/strip-backup/9ac430e15fca-b9855b02-backup.hg (glob)
1353 1359 ### Backup markers ###
1354 1360 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1355 1361 ### diff <relevant> <backed-up> ###
1356 1362 #################################
1357 1363 ### Stripped markers ###
1358 1364 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1359 1365 ### diff <exclusive> <stripped> ###
1360 1366 #################################
1361 1367 # unbundling: adding changesets
1362 1368 # unbundling: adding manifests
1363 1369 # unbundling: adding file changes
1364 1370 # unbundling: added 2 changesets with 2 changes to 2 files
1365 1371 # unbundling: 1 new obsolescence markers
1366 1372 # unbundling: (run 'hg update' to get a working copy)
@@ -1,1401 +1,1402 b''
1 1 $ cat >> $HGRCPATH << EOF
2 2 > [phases]
3 3 > # public changeset are not obsolete
4 4 > publish=false
5 5 > [ui]
6 6 > logtemplate="{rev}:{node|short} ({phase}{if(obsolete, ' *{obsolete}*')}{if(troubles, ' {troubles}')}) [{tags} {bookmarks}] {desc|firstline}\n"
7 7 > EOF
8 8 $ mkcommit() {
9 9 > echo "$1" > "$1"
10 10 > hg add "$1"
11 11 > hg ci -m "add $1"
12 12 > }
13 13 $ getid() {
14 14 > hg log -T "{node}\n" --hidden -r "desc('$1')"
15 15 > }
16 16
17 17 $ cat > debugkeys.py <<EOF
18 18 > def reposetup(ui, repo):
19 19 > class debugkeysrepo(repo.__class__):
20 20 > def listkeys(self, namespace):
21 21 > ui.write('listkeys %s\n' % (namespace,))
22 22 > return super(debugkeysrepo, self).listkeys(namespace)
23 23 >
24 24 > if repo.local():
25 25 > repo.__class__ = debugkeysrepo
26 26 > EOF
27 27
28 28 $ hg init tmpa
29 29 $ cd tmpa
30 30 $ mkcommit kill_me
31 31
32 32 Checking that the feature is properly disabled
33 33
34 34 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
35 35 abort: creating obsolete markers is not enabled on this repo
36 36 [255]
37 37
38 38 Enabling it
39 39
40 40 $ cat >> $HGRCPATH << EOF
41 41 > [experimental]
42 42 > evolution=createmarkers,exchange
43 43 > EOF
44 44
45 45 Killing a single changeset without replacement
46 46
47 47 $ hg debugobsolete 0
48 48 abort: changeset references must be full hexadecimal node identifiers
49 49 [255]
50 50 $ hg debugobsolete '00'
51 51 abort: changeset references must be full hexadecimal node identifiers
52 52 [255]
53 53 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
54 54 $ hg debugobsolete
55 55 97b7c2d76b1845ed3eb988cd612611e72406cef0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'babar'}
56 56
57 57 (test that mercurial is not confused)
58 58
59 59 $ hg up null --quiet # having 0 as parent prevents it to be hidden
60 60 $ hg tip
61 61 -1:000000000000 (public) [tip ]
62 62 $ hg up --hidden tip --quiet
63 63
64 64 Killing a single changeset with itself should fail
65 65 (simple local safeguard)
66 66
67 67 $ hg debugobsolete `getid kill_me` `getid kill_me`
68 68 abort: bad obsmarker input: in-marker cycle with 97b7c2d76b1845ed3eb988cd612611e72406cef0
69 69 [255]
70 70
71 71 $ cd ..
72 72
73 73 Killing a single changeset with replacement
74 74 (and testing the format option)
75 75
76 76 $ hg init tmpb
77 77 $ cd tmpb
78 78 $ mkcommit a
79 79 $ mkcommit b
80 80 $ mkcommit original_c
81 81 $ hg up "desc('b')"
82 82 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
83 83 $ mkcommit new_c
84 84 created new head
85 85 $ hg log -r 'hidden()' --template '{rev}:{node|short} {desc}\n' --hidden
86 86 $ hg debugobsolete --config format.obsstore-version=0 --flag 12 `getid original_c` `getid new_c` -d '121 120'
87 87 $ hg log -r 'hidden()' --template '{rev}:{node|short} {desc}\n' --hidden
88 88 2:245bde4270cd add original_c
89 89 $ hg debugrevlog -cd
90 90 # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads chainlen
91 91 0 -1 -1 0 59 0 0 0 0 58 58 0 1 0
92 92 1 0 -1 59 118 59 59 0 0 58 116 0 1 0
93 93 2 1 -1 118 193 118 118 59 0 76 192 0 1 0
94 94 3 1 -1 193 260 193 193 59 0 66 258 0 2 0
95 95 $ hg debugobsolete
96 96 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
97 97
98 98 (check for version number of the obsstore)
99 99
100 100 $ dd bs=1 count=1 if=.hg/store/obsstore 2>/dev/null
101 101 \x00 (no-eol) (esc)
102 102
103 103 do it again (it read the obsstore before adding new changeset)
104 104
105 105 $ hg up '.^'
106 106 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
107 107 $ mkcommit new_2_c
108 108 created new head
109 109 $ hg debugobsolete -d '1337 0' `getid new_c` `getid new_2_c`
110 110 $ hg debugobsolete
111 111 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
112 112 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
113 113
114 114 Register two markers with a missing node
115 115
116 116 $ hg up '.^'
117 117 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
118 118 $ mkcommit new_3_c
119 119 created new head
120 120 $ hg debugobsolete -d '1338 0' `getid new_2_c` 1337133713371337133713371337133713371337
121 121 $ hg debugobsolete -d '1339 0' 1337133713371337133713371337133713371337 `getid new_3_c`
122 122 $ hg debugobsolete
123 123 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
124 124 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
125 125 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
126 126 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
127 127
128 128 Test the --index option of debugobsolete command
129 129 $ hg debugobsolete --index
130 130 0 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
131 131 1 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
132 132 2 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
133 133 3 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
134 134
135 135 Refuse pathological nullid successors
136 136 $ hg debugobsolete -d '9001 0' 1337133713371337133713371337133713371337 0000000000000000000000000000000000000000
137 137 transaction abort!
138 138 rollback completed
139 139 abort: bad obsolescence marker detected: invalid successors nullid
140 140 [255]
141 141
142 142 Check that graphlog detect that a changeset is obsolete:
143 143
144 144 $ hg log -G
145 145 @ 5:5601fb93a350 (draft) [tip ] add new_3_c
146 146 |
147 147 o 1:7c3bad9141dc (draft) [ ] add b
148 148 |
149 149 o 0:1f0dee641bb7 (draft) [ ] add a
150 150
151 151
152 152 check that heads does not report them
153 153
154 154 $ hg heads
155 155 5:5601fb93a350 (draft) [tip ] add new_3_c
156 156 $ hg heads --hidden
157 157 5:5601fb93a350 (draft) [tip ] add new_3_c
158 158 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c
159 159 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c
160 160 2:245bde4270cd (draft *obsolete*) [ ] add original_c
161 161
162 162
163 163 check that summary does not report them
164 164
165 165 $ hg init ../sink
166 166 $ echo '[paths]' >> .hg/hgrc
167 167 $ echo 'default=../sink' >> .hg/hgrc
168 168 $ hg summary --remote
169 169 parent: 5:5601fb93a350 tip
170 170 add new_3_c
171 171 branch: default
172 172 commit: (clean)
173 173 update: (current)
174 174 phases: 3 draft
175 175 remote: 3 outgoing
176 176
177 177 $ hg summary --remote --hidden
178 178 parent: 5:5601fb93a350 tip
179 179 add new_3_c
180 180 branch: default
181 181 commit: (clean)
182 182 update: 3 new changesets, 4 branch heads (merge)
183 183 phases: 6 draft
184 184 remote: 3 outgoing
185 185
186 186 check that various commands work well with filtering
187 187
188 188 $ hg tip
189 189 5:5601fb93a350 (draft) [tip ] add new_3_c
190 190 $ hg log -r 6
191 191 abort: unknown revision '6'!
192 192 [255]
193 193 $ hg log -r 4
194 194 abort: hidden revision '4'!
195 195 (use --hidden to access hidden revisions)
196 196 [255]
197 197 $ hg debugrevspec 'rev(6)'
198 198 $ hg debugrevspec 'rev(4)'
199 199 $ hg debugrevspec 'null'
200 200 -1
201 201
202 202 Check that public changeset are not accounted as obsolete:
203 203
204 204 $ hg --hidden phase --public 2
205 205 $ hg log -G
206 206 @ 5:5601fb93a350 (draft bumped) [tip ] add new_3_c
207 207 |
208 208 | o 2:245bde4270cd (public) [ ] add original_c
209 209 |/
210 210 o 1:7c3bad9141dc (public) [ ] add b
211 211 |
212 212 o 0:1f0dee641bb7 (public) [ ] add a
213 213
214 214
215 215 And that bumped changeset are detected
216 216 --------------------------------------
217 217
218 218 If we didn't filtered obsolete changesets out, 3 and 4 would show up too. Also
219 219 note that the bumped changeset (5:5601fb93a350) is not a direct successor of
220 220 the public changeset
221 221
222 222 $ hg log --hidden -r 'bumped()'
223 223 5:5601fb93a350 (draft bumped) [tip ] add new_3_c
224 224
225 225 And that we can't push bumped changeset
226 226
227 227 $ hg push ../tmpa -r 0 --force #(make repo related)
228 228 pushing to ../tmpa
229 229 searching for changes
230 230 warning: repository is unrelated
231 231 adding changesets
232 232 adding manifests
233 233 adding file changes
234 234 added 1 changesets with 1 changes to 1 files (+1 heads)
235 235 $ hg push ../tmpa
236 236 pushing to ../tmpa
237 237 searching for changes
238 238 abort: push includes bumped changeset: 5601fb93a350!
239 239 [255]
240 240
241 241 Fixing "bumped" situation
242 242 We need to create a clone of 5 and add a special marker with a flag
243 243
244 244 $ hg summary
245 245 parent: 5:5601fb93a350 tip (bumped)
246 246 add new_3_c
247 247 branch: default
248 248 commit: (clean)
249 249 update: 1 new changesets, 2 branch heads (merge)
250 250 phases: 1 draft
251 251 bumped: 1 changesets
252 252 $ hg up '5^'
253 253 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
254 254 $ hg revert -ar 5
255 255 adding new_3_c
256 256 $ hg ci -m 'add n3w_3_c'
257 257 created new head
258 258 $ hg debugobsolete -d '1338 0' --flags 1 `getid new_3_c` `getid n3w_3_c`
259 259 $ hg log -r 'bumped()'
260 260 $ hg log -G
261 261 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
262 262 |
263 263 | o 2:245bde4270cd (public) [ ] add original_c
264 264 |/
265 265 o 1:7c3bad9141dc (public) [ ] add b
266 266 |
267 267 o 0:1f0dee641bb7 (public) [ ] add a
268 268
269 269
270 270 Basic exclusive testing
271 271
272 272 $ hg log -G --hidden
273 273 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
274 274 |
275 275 | x 5:5601fb93a350 (draft *obsolete*) [ ] add new_3_c
276 276 |/
277 277 | x 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c
278 278 |/
279 279 | x 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c
280 280 |/
281 281 | o 2:245bde4270cd (public) [ ] add original_c
282 282 |/
283 283 o 1:7c3bad9141dc (public) [ ] add b
284 284 |
285 285 o 0:1f0dee641bb7 (public) [ ] add a
286 286
287 287 $ hg debugobsolete --rev 6f9641995072
288 288 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
289 289 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
290 290 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
291 291 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
292 292 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
293 293 $ hg debugobsolete --rev 6f9641995072 --exclusive
294 294 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
295 295 $ hg debugobsolete --rev 5601fb93a350 --hidden
296 296 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
297 297 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
298 298 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
299 299 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
300 300 $ hg debugobsolete --rev 5601fb93a350 --hidden --exclusive
301 301 $ hg debugobsolete --rev 5601fb93a350+6f9641995072 --hidden --exclusive
302 302 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
303 303 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
304 304 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
305 305
306 306 $ cd ..
307 307
308 308 Revision 0 is hidden
309 309 --------------------
310 310
311 311 $ hg init rev0hidden
312 312 $ cd rev0hidden
313 313
314 314 $ mkcommit kill0
315 315 $ hg up -q null
316 316 $ hg debugobsolete `getid kill0`
317 317 $ mkcommit a
318 318 $ mkcommit b
319 319
320 320 Should pick the first visible revision as "repo" node
321 321
322 322 $ hg archive ../archive-null
323 323 $ cat ../archive-null/.hg_archival.txt
324 324 repo: 1f0dee641bb7258c56bd60e93edfa2405381c41e
325 325 node: 7c3bad9141dcb46ff89abf5f61856facd56e476c
326 326 branch: default
327 327 latesttag: null
328 328 latesttagdistance: 2
329 329 changessincelatesttag: 2
330 330
331 331
332 332 $ cd ..
333 333
334 334 Exchange Test
335 335 ============================
336 336
337 337 Destination repo does not have any data
338 338 ---------------------------------------
339 339
340 340 Simple incoming test
341 341
342 342 $ hg init tmpc
343 343 $ cd tmpc
344 344 $ hg incoming ../tmpb
345 345 comparing with ../tmpb
346 346 0:1f0dee641bb7 (public) [ ] add a
347 347 1:7c3bad9141dc (public) [ ] add b
348 348 2:245bde4270cd (public) [ ] add original_c
349 349 6:6f9641995072 (draft) [tip ] add n3w_3_c
350 350
351 351 Try to pull markers
352 352 (extinct changeset are excluded but marker are pushed)
353 353
354 354 $ hg pull ../tmpb
355 355 pulling from ../tmpb
356 356 requesting all changes
357 357 adding changesets
358 358 adding manifests
359 359 adding file changes
360 360 added 4 changesets with 4 changes to 4 files (+1 heads)
361 361 5 new obsolescence markers
362 362 (run 'hg heads' to see heads, 'hg merge' to merge)
363 363 $ hg debugobsolete
364 364 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
365 365 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
366 366 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
367 367 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
368 368 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
369 369
370 370 Rollback//Transaction support
371 371
372 372 $ hg debugobsolete -d '1340 0' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
373 373 $ hg debugobsolete
374 374 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
375 375 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
376 376 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
377 377 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
378 378 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
379 379 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 (Thu Jan 01 00:22:20 1970 +0000) {'user': 'test'}
380 380 $ hg rollback -n
381 381 repository tip rolled back to revision 3 (undo debugobsolete)
382 382 $ hg rollback
383 383 repository tip rolled back to revision 3 (undo debugobsolete)
384 384 $ hg debugobsolete
385 385 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
386 386 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
387 387 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
388 388 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
389 389 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
390 390
391 391 $ cd ..
392 392
393 393 Try to push markers
394 394
395 395 $ hg init tmpd
396 396 $ hg -R tmpb push tmpd
397 397 pushing to tmpd
398 398 searching for changes
399 399 adding changesets
400 400 adding manifests
401 401 adding file changes
402 402 added 4 changesets with 4 changes to 4 files (+1 heads)
403 403 5 new obsolescence markers
404 404 $ hg -R tmpd debugobsolete | sort
405 405 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
406 406 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
407 407 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
408 408 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
409 409 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
410 410
411 411 Check obsolete keys are exchanged only if source has an obsolete store
412 412
413 413 $ hg init empty
414 414 $ hg --config extensions.debugkeys=debugkeys.py -R empty push tmpd
415 415 pushing to tmpd
416 416 listkeys phases
417 417 listkeys bookmarks
418 418 no changes found
419 419 listkeys phases
420 420 [1]
421 421
422 422 clone support
423 423 (markers are copied and extinct changesets are included to allow hardlinks)
424 424
425 425 $ hg clone tmpb clone-dest
426 426 updating to branch default
427 427 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
428 428 $ hg -R clone-dest log -G --hidden
429 429 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
430 430 |
431 431 | x 5:5601fb93a350 (draft *obsolete*) [ ] add new_3_c
432 432 |/
433 433 | x 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c
434 434 |/
435 435 | x 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c
436 436 |/
437 437 | o 2:245bde4270cd (public) [ ] add original_c
438 438 |/
439 439 o 1:7c3bad9141dc (public) [ ] add b
440 440 |
441 441 o 0:1f0dee641bb7 (public) [ ] add a
442 442
443 443 $ hg -R clone-dest debugobsolete
444 444 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
445 445 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
446 446 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
447 447 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
448 448 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
449 449
450 450
451 451 Destination repo have existing data
452 452 ---------------------------------------
453 453
454 454 On pull
455 455
456 456 $ hg init tmpe
457 457 $ cd tmpe
458 458 $ hg debugobsolete -d '1339 0' 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00
459 459 $ hg pull ../tmpb
460 460 pulling from ../tmpb
461 461 requesting all changes
462 462 adding changesets
463 463 adding manifests
464 464 adding file changes
465 465 added 4 changesets with 4 changes to 4 files (+1 heads)
466 466 5 new obsolescence markers
467 467 (run 'hg heads' to see heads, 'hg merge' to merge)
468 468 $ hg debugobsolete
469 469 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
470 470 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
471 471 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
472 472 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
473 473 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
474 474 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
475 475
476 476
477 477 On push
478 478
479 479 $ hg push ../tmpc
480 480 pushing to ../tmpc
481 481 searching for changes
482 482 no changes found
483 483 1 new obsolescence markers
484 484 [1]
485 485 $ hg -R ../tmpc debugobsolete
486 486 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
487 487 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
488 488 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
489 489 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
490 490 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
491 491 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
492 492
493 493 detect outgoing obsolete and unstable
494 494 ---------------------------------------
495 495
496 496
497 497 $ hg log -G
498 498 o 3:6f9641995072 (draft) [tip ] add n3w_3_c
499 499 |
500 500 | o 2:245bde4270cd (public) [ ] add original_c
501 501 |/
502 502 o 1:7c3bad9141dc (public) [ ] add b
503 503 |
504 504 o 0:1f0dee641bb7 (public) [ ] add a
505 505
506 506 $ hg up 'desc("n3w_3_c")'
507 507 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
508 508 $ mkcommit original_d
509 509 $ mkcommit original_e
510 510 $ hg debugobsolete --record-parents `getid original_d` -d '0 0'
511 511 $ hg debugobsolete | grep `getid original_d`
512 512 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
513 513 $ hg log -r 'obsolete()'
514 514 4:94b33453f93b (draft *obsolete*) [ ] add original_d
515 515 $ hg summary
516 516 parent: 5:cda648ca50f5 tip (unstable)
517 517 add original_e
518 518 branch: default
519 519 commit: (clean)
520 520 update: 1 new changesets, 2 branch heads (merge)
521 521 phases: 3 draft
522 522 unstable: 1 changesets
523 523 $ hg log -G -r '::unstable()'
524 524 @ 5:cda648ca50f5 (draft unstable) [tip ] add original_e
525 525 |
526 526 x 4:94b33453f93b (draft *obsolete*) [ ] add original_d
527 527 |
528 528 o 3:6f9641995072 (draft) [ ] add n3w_3_c
529 529 |
530 530 o 1:7c3bad9141dc (public) [ ] add b
531 531 |
532 532 o 0:1f0dee641bb7 (public) [ ] add a
533 533
534 534
535 535 refuse to push obsolete changeset
536 536
537 537 $ hg push ../tmpc/ -r 'desc("original_d")'
538 538 pushing to ../tmpc/
539 539 searching for changes
540 540 abort: push includes obsolete changeset: 94b33453f93b!
541 541 [255]
542 542
543 543 refuse to push unstable changeset
544 544
545 545 $ hg push ../tmpc/
546 546 pushing to ../tmpc/
547 547 searching for changes
548 548 abort: push includes unstable changeset: cda648ca50f5!
549 549 [255]
550 550
551 551 Test that extinct changeset are properly detected
552 552
553 553 $ hg log -r 'extinct()'
554 554
555 555 Don't try to push extinct changeset
556 556
557 557 $ hg init ../tmpf
558 558 $ hg out ../tmpf
559 559 comparing with ../tmpf
560 560 searching for changes
561 561 0:1f0dee641bb7 (public) [ ] add a
562 562 1:7c3bad9141dc (public) [ ] add b
563 563 2:245bde4270cd (public) [ ] add original_c
564 564 3:6f9641995072 (draft) [ ] add n3w_3_c
565 565 4:94b33453f93b (draft *obsolete*) [ ] add original_d
566 566 5:cda648ca50f5 (draft unstable) [tip ] add original_e
567 567 $ hg push ../tmpf -f # -f because be push unstable too
568 568 pushing to ../tmpf
569 569 searching for changes
570 570 adding changesets
571 571 adding manifests
572 572 adding file changes
573 573 added 6 changesets with 6 changes to 6 files (+1 heads)
574 574 7 new obsolescence markers
575 575
576 576 no warning displayed
577 577
578 578 $ hg push ../tmpf
579 579 pushing to ../tmpf
580 580 searching for changes
581 581 no changes found
582 582 [1]
583 583
584 584 Do not warn about new head when the new head is a successors of a remote one
585 585
586 586 $ hg log -G
587 587 @ 5:cda648ca50f5 (draft unstable) [tip ] add original_e
588 588 |
589 589 x 4:94b33453f93b (draft *obsolete*) [ ] add original_d
590 590 |
591 591 o 3:6f9641995072 (draft) [ ] add n3w_3_c
592 592 |
593 593 | o 2:245bde4270cd (public) [ ] add original_c
594 594 |/
595 595 o 1:7c3bad9141dc (public) [ ] add b
596 596 |
597 597 o 0:1f0dee641bb7 (public) [ ] add a
598 598
599 599 $ hg up -q 'desc(n3w_3_c)'
600 600 $ mkcommit obsolete_e
601 601 created new head
602 602 $ hg debugobsolete `getid 'original_e'` `getid 'obsolete_e'` \
603 603 > -u 'test <test@example.net>'
604 604 $ hg outgoing ../tmpf # parasite hg outgoing testin
605 605 comparing with ../tmpf
606 606 searching for changes
607 607 6:3de5eca88c00 (draft) [tip ] add obsolete_e
608 608 $ hg push ../tmpf
609 609 pushing to ../tmpf
610 610 searching for changes
611 611 adding changesets
612 612 adding manifests
613 613 adding file changes
614 614 added 1 changesets with 1 changes to 1 files (+1 heads)
615 615 1 new obsolescence markers
616 obsoleted 1 changesets
616 617
617 618 test relevance computation
618 619 ---------------------------------------
619 620
620 621 Checking simple case of "marker relevance".
621 622
622 623
623 624 Reminder of the repo situation
624 625
625 626 $ hg log --hidden --graph
626 627 @ 6:3de5eca88c00 (draft) [tip ] add obsolete_e
627 628 |
628 629 | x 5:cda648ca50f5 (draft *obsolete*) [ ] add original_e
629 630 | |
630 631 | x 4:94b33453f93b (draft *obsolete*) [ ] add original_d
631 632 |/
632 633 o 3:6f9641995072 (draft) [ ] add n3w_3_c
633 634 |
634 635 | o 2:245bde4270cd (public) [ ] add original_c
635 636 |/
636 637 o 1:7c3bad9141dc (public) [ ] add b
637 638 |
638 639 o 0:1f0dee641bb7 (public) [ ] add a
639 640
640 641
641 642 List of all markers
642 643
643 644 $ hg debugobsolete
644 645 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
645 646 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
646 647 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
647 648 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
648 649 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
649 650 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
650 651 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
651 652 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test <test@example.net>'} (glob)
652 653
653 654 List of changesets with no chain
654 655
655 656 $ hg debugobsolete --hidden --rev ::2
656 657
657 658 List of changesets that are included on marker chain
658 659
659 660 $ hg debugobsolete --hidden --rev 6
660 661 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test <test@example.net>'} (glob)
661 662
662 663 List of changesets with a longer chain, (including a pruned children)
663 664
664 665 $ hg debugobsolete --hidden --rev 3
665 666 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
666 667 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
667 668 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
668 669 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
669 670 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
670 671 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
671 672 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
672 673
673 674 List of both
674 675
675 676 $ hg debugobsolete --hidden --rev 3::6
676 677 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
677 678 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
678 679 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
679 680 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
680 681 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
681 682 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
682 683 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test <test@example.net>'} (glob)
683 684 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
684 685
685 686 List of all markers in JSON
686 687
687 688 $ hg debugobsolete -Tjson
688 689 [
689 690 {
690 691 "date": [1339.0, 0],
691 692 "flag": 0,
692 693 "metadata": {"user": "test"},
693 694 "precnode": "1339133913391339133913391339133913391339",
694 695 "succnodes": ["ca819180edb99ed25ceafb3e9584ac287e240b00"]
695 696 },
696 697 {
697 698 "date": [1339.0, 0],
698 699 "flag": 0,
699 700 "metadata": {"user": "test"},
700 701 "precnode": "1337133713371337133713371337133713371337",
701 702 "succnodes": ["5601fb93a350734d935195fee37f4054c529ff39"]
702 703 },
703 704 {
704 705 "date": [121.0, 120],
705 706 "flag": 12,
706 707 "metadata": {"user": "test"},
707 708 "precnode": "245bde4270cd1072a27757984f9cda8ba26f08ca",
708 709 "succnodes": ["cdbce2fbb16313928851e97e0d85413f3f7eb77f"]
709 710 },
710 711 {
711 712 "date": [1338.0, 0],
712 713 "flag": 1,
713 714 "metadata": {"user": "test"},
714 715 "precnode": "5601fb93a350734d935195fee37f4054c529ff39",
715 716 "succnodes": ["6f96419950729f3671185b847352890f074f7557"]
716 717 },
717 718 {
718 719 "date": [1338.0, 0],
719 720 "flag": 0,
720 721 "metadata": {"user": "test"},
721 722 "precnode": "ca819180edb99ed25ceafb3e9584ac287e240b00",
722 723 "succnodes": ["1337133713371337133713371337133713371337"]
723 724 },
724 725 {
725 726 "date": [1337.0, 0],
726 727 "flag": 0,
727 728 "metadata": {"user": "test"},
728 729 "precnode": "cdbce2fbb16313928851e97e0d85413f3f7eb77f",
729 730 "succnodes": ["ca819180edb99ed25ceafb3e9584ac287e240b00"]
730 731 },
731 732 {
732 733 "date": [0.0, 0],
733 734 "flag": 0,
734 735 "metadata": {"user": "test"},
735 736 "parentnodes": ["6f96419950729f3671185b847352890f074f7557"],
736 737 "precnode": "94b33453f93bdb8d457ef9b770851a618bf413e1",
737 738 "succnodes": []
738 739 },
739 740 {
740 741 "date": *, (glob)
741 742 "flag": 0,
742 743 "metadata": {"user": "test <test@example.net>"},
743 744 "precnode": "cda648ca50f50482b7055c0b0c4c117bba6733d9",
744 745 "succnodes": ["3de5eca88c00aa039da7399a220f4a5221faa585"]
745 746 }
746 747 ]
747 748
748 749 Template keywords
749 750
750 751 $ hg debugobsolete -r6 -T '{succnodes % "{node|short}"} {date|shortdate}\n'
751 752 3de5eca88c00 ????-??-?? (glob)
752 753 $ hg debugobsolete -r6 -T '{join(metadata % "{key}={value}", " ")}\n'
753 754 user=test <test@example.net>
754 755 $ hg debugobsolete -r6 -T '{metadata}\n'
755 756 'user': 'test <test@example.net>'
756 757 $ hg debugobsolete -r6 -T '{flag} {get(metadata, "user")}\n'
757 758 0 test <test@example.net>
758 759
759 760 Test the debug output for exchange
760 761 ----------------------------------
761 762
762 763 $ hg pull ../tmpb --config 'experimental.obsmarkers-exchange-debug=True' # bundle2
763 764 pulling from ../tmpb
764 765 searching for changes
765 766 no changes found
766 767 obsmarker-exchange: 346 bytes received
767 768
768 769 check hgweb does not explode
769 770 ====================================
770 771
771 772 $ hg unbundle $TESTDIR/bundles/hgweb+obs.hg
772 773 adding changesets
773 774 adding manifests
774 775 adding file changes
775 776 added 62 changesets with 63 changes to 9 files (+60 heads)
776 777 (run 'hg heads .' to see heads, 'hg merge' to merge)
777 778 $ for node in `hg log -r 'desc(babar_)' --template '{node}\n'`;
778 779 > do
779 780 > hg debugobsolete $node
780 781 > done
781 782 $ hg up tip
782 783 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
783 784
784 785 #if serve
785 786
786 787 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
787 788 $ cat hg.pid >> $DAEMON_PIDS
788 789
789 790 check changelog view
790 791
791 792 $ get-with-headers.py --headeronly localhost:$HGPORT 'shortlog/'
792 793 200 Script output follows
793 794
794 795 check graph view
795 796
796 797 $ get-with-headers.py --headeronly localhost:$HGPORT 'graph'
797 798 200 Script output follows
798 799
799 800 check filelog view
800 801
801 802 $ get-with-headers.py --headeronly localhost:$HGPORT 'log/'`hg log -r . -T "{node}"`/'babar'
802 803 200 Script output follows
803 804
804 805 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/68'
805 806 200 Script output follows
806 807 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/67'
807 808 404 Not Found
808 809 [1]
809 810
810 811 check that web.view config option:
811 812
812 813 $ killdaemons.py hg.pid
813 814 $ cat >> .hg/hgrc << EOF
814 815 > [web]
815 816 > view=all
816 817 > EOF
817 818 $ wait
818 819 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
819 820 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/67'
820 821 200 Script output follows
821 822 $ killdaemons.py hg.pid
822 823
823 824 Checking _enable=False warning if obsolete marker exists
824 825
825 826 $ echo '[experimental]' >> $HGRCPATH
826 827 $ echo "evolution=" >> $HGRCPATH
827 828 $ hg log -r tip
828 829 obsolete feature not enabled but 68 markers found!
829 830 68:c15e9edfca13 (draft) [tip ] add celestine
830 831
831 832 reenable for later test
832 833
833 834 $ echo '[experimental]' >> $HGRCPATH
834 835 $ echo "evolution=createmarkers,exchange" >> $HGRCPATH
835 836
836 837 $ rm hg.pid access.log errors.log
837 838 #endif
838 839
839 840 Several troubles on the same changeset (create an unstable and bumped changeset)
840 841
841 842 $ hg debugobsolete `getid obsolete_e`
842 843 $ hg debugobsolete `getid original_c` `getid babar`
843 844 $ hg log --config ui.logtemplate= -r 'bumped() and unstable()'
844 845 changeset: 7:50c51b361e60
845 846 user: test
846 847 date: Thu Jan 01 00:00:00 1970 +0000
847 848 trouble: unstable, bumped
848 849 summary: add babar
849 850
850 851
851 852 test the "obsolete" templatekw
852 853
853 854 $ hg log -r 'obsolete()'
854 855 6:3de5eca88c00 (draft *obsolete*) [ ] add obsolete_e
855 856
856 857 test the "troubles" templatekw
857 858
858 859 $ hg log -r 'bumped() and unstable()'
859 860 7:50c51b361e60 (draft unstable bumped) [ ] add babar
860 861
861 862 test the default cmdline template
862 863
863 864 $ hg log -T default -r 'bumped()'
864 865 changeset: 7:50c51b361e60
865 866 user: test
866 867 date: Thu Jan 01 00:00:00 1970 +0000
867 868 trouble: unstable, bumped
868 869 summary: add babar
869 870
870 871 $ hg log -T default -r 'obsolete()'
871 872 changeset: 6:3de5eca88c00
872 873 parent: 3:6f9641995072
873 874 user: test
874 875 date: Thu Jan 01 00:00:00 1970 +0000
875 876 summary: add obsolete_e
876 877
877 878
878 879 test summary output
879 880
880 881 $ hg up -r 'bumped() and unstable()'
881 882 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
882 883 $ hg summary
883 884 parent: 7:50c51b361e60 (unstable, bumped)
884 885 add babar
885 886 branch: default
886 887 commit: (clean)
887 888 update: 2 new changesets (update)
888 889 phases: 4 draft
889 890 unstable: 2 changesets
890 891 bumped: 1 changesets
891 892 $ hg up -r 'obsolete()'
892 893 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
893 894 $ hg summary
894 895 parent: 6:3de5eca88c00 (obsolete)
895 896 add obsolete_e
896 897 branch: default
897 898 commit: (clean)
898 899 update: 3 new changesets (update)
899 900 phases: 4 draft
900 901 unstable: 2 changesets
901 902 bumped: 1 changesets
902 903
903 904 Test incoming/outcoming with changesets obsoleted remotely, known locally
904 905 ===============================================================================
905 906
906 907 This test issue 3805
907 908
908 909 $ hg init repo-issue3805
909 910 $ cd repo-issue3805
910 911 $ echo "base" > base
911 912 $ hg ci -Am "base"
912 913 adding base
913 914 $ echo "foo" > foo
914 915 $ hg ci -Am "A"
915 916 adding foo
916 917 $ hg clone . ../other-issue3805
917 918 updating to branch default
918 919 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
919 920 $ echo "bar" >> foo
920 921 $ hg ci --amend
921 922 $ cd ../other-issue3805
922 923 $ hg log -G
923 924 @ 1:29f0c6921ddd (draft) [tip ] A
924 925 |
925 926 o 0:d20a80d4def3 (draft) [ ] base
926 927
927 928 $ hg log -G -R ../repo-issue3805
928 929 @ 3:323a9c3ddd91 (draft) [tip ] A
929 930 |
930 931 o 0:d20a80d4def3 (draft) [ ] base
931 932
932 933 $ hg incoming
933 934 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
934 935 searching for changes
935 936 3:323a9c3ddd91 (draft) [tip ] A
936 937 $ hg incoming --bundle ../issue3805.hg
937 938 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
938 939 searching for changes
939 940 3:323a9c3ddd91 (draft) [tip ] A
940 941 $ hg outgoing
941 942 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
942 943 searching for changes
943 944 1:29f0c6921ddd (draft) [tip ] A
944 945
945 946 #if serve
946 947
947 948 $ hg serve -R ../repo-issue3805 -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
948 949 $ cat hg.pid >> $DAEMON_PIDS
949 950
950 951 $ hg incoming http://localhost:$HGPORT
951 952 comparing with http://localhost:$HGPORT/
952 953 searching for changes
953 954 2:323a9c3ddd91 (draft) [tip ] A
954 955 $ hg outgoing http://localhost:$HGPORT
955 956 comparing with http://localhost:$HGPORT/
956 957 searching for changes
957 958 1:29f0c6921ddd (draft) [tip ] A
958 959
959 960 $ killdaemons.py
960 961
961 962 #endif
962 963
963 964 This test issue 3814
964 965
965 966 (nothing to push but locally hidden changeset)
966 967
967 968 $ cd ..
968 969 $ hg init repo-issue3814
969 970 $ cd repo-issue3805
970 971 $ hg push -r 323a9c3ddd91 ../repo-issue3814
971 972 pushing to ../repo-issue3814
972 973 searching for changes
973 974 adding changesets
974 975 adding manifests
975 976 adding file changes
976 977 added 2 changesets with 2 changes to 2 files
977 978 2 new obsolescence markers
978 979 $ hg out ../repo-issue3814
979 980 comparing with ../repo-issue3814
980 981 searching for changes
981 982 no changes found
982 983 [1]
983 984
984 985 Test that a local tag blocks a changeset from being hidden
985 986
986 987 $ hg tag -l visible -r 1 --hidden
987 988 $ hg log -G
988 989 @ 3:323a9c3ddd91 (draft) [tip ] A
989 990 |
990 991 | x 1:29f0c6921ddd (draft *obsolete*) [visible ] A
991 992 |/
992 993 o 0:d20a80d4def3 (draft) [ ] base
993 994
994 995 Test that removing a local tag does not cause some commands to fail
995 996
996 997 $ hg tag -l -r tip tiptag
997 998 $ hg tags
998 999 tiptag 3:323a9c3ddd91
999 1000 tip 3:323a9c3ddd91
1000 1001 visible 1:29f0c6921ddd
1001 1002 $ hg --config extensions.strip= strip -r tip --no-backup
1002 1003 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1003 1004 $ hg tags
1004 1005 visible 1:29f0c6921ddd
1005 1006 tip 1:29f0c6921ddd
1006 1007
1007 1008 Test bundle overlay onto hidden revision
1008 1009
1009 1010 $ cd ..
1010 1011 $ hg init repo-bundleoverlay
1011 1012 $ cd repo-bundleoverlay
1012 1013 $ echo "A" > foo
1013 1014 $ hg ci -Am "A"
1014 1015 adding foo
1015 1016 $ echo "B" >> foo
1016 1017 $ hg ci -m "B"
1017 1018 $ hg up 0
1018 1019 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1019 1020 $ echo "C" >> foo
1020 1021 $ hg ci -m "C"
1021 1022 created new head
1022 1023 $ hg log -G
1023 1024 @ 2:c186d7714947 (draft) [tip ] C
1024 1025 |
1025 1026 | o 1:44526ebb0f98 (draft) [ ] B
1026 1027 |/
1027 1028 o 0:4b34ecfb0d56 (draft) [ ] A
1028 1029
1029 1030
1030 1031 $ hg clone -r1 . ../other-bundleoverlay
1031 1032 adding changesets
1032 1033 adding manifests
1033 1034 adding file changes
1034 1035 added 2 changesets with 2 changes to 1 files
1035 1036 updating to branch default
1036 1037 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1037 1038 $ cd ../other-bundleoverlay
1038 1039 $ echo "B+" >> foo
1039 1040 $ hg ci --amend -m "B+"
1040 1041 $ hg log -G --hidden
1041 1042 @ 3:b7d587542d40 (draft) [tip ] B+
1042 1043 |
1043 1044 | x 2:eb95e9297e18 (draft *obsolete*) [ ] temporary amend commit for 44526ebb0f98
1044 1045 | |
1045 1046 | x 1:44526ebb0f98 (draft *obsolete*) [ ] B
1046 1047 |/
1047 1048 o 0:4b34ecfb0d56 (draft) [ ] A
1048 1049
1049 1050
1050 1051 $ hg incoming ../repo-bundleoverlay --bundle ../bundleoverlay.hg
1051 1052 comparing with ../repo-bundleoverlay
1052 1053 searching for changes
1053 1054 1:44526ebb0f98 (draft) [ ] B
1054 1055 2:c186d7714947 (draft) [tip ] C
1055 1056 $ hg log -G -R ../bundleoverlay.hg
1056 1057 o 4:c186d7714947 (draft) [tip ] C
1057 1058 |
1058 1059 | @ 3:b7d587542d40 (draft) [ ] B+
1059 1060 |/
1060 1061 o 0:4b34ecfb0d56 (draft) [ ] A
1061 1062
1062 1063
1063 1064 #if serve
1064 1065
1065 1066 Test issue 4506
1066 1067
1067 1068 $ cd ..
1068 1069 $ hg init repo-issue4506
1069 1070 $ cd repo-issue4506
1070 1071 $ echo "0" > foo
1071 1072 $ hg add foo
1072 1073 $ hg ci -m "content-0"
1073 1074
1074 1075 $ hg up null
1075 1076 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1076 1077 $ echo "1" > bar
1077 1078 $ hg add bar
1078 1079 $ hg ci -m "content-1"
1079 1080 created new head
1080 1081 $ hg up 0
1081 1082 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1082 1083 $ hg graft 1
1083 1084 grafting 1:1c9eddb02162 "content-1" (tip)
1084 1085
1085 1086 $ hg debugobsolete `hg log -r1 -T'{node}'` `hg log -r2 -T'{node}'`
1086 1087
1087 1088 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1088 1089 $ cat hg.pid >> $DAEMON_PIDS
1089 1090
1090 1091 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/1'
1091 1092 404 Not Found
1092 1093 [1]
1093 1094 $ get-with-headers.py --headeronly localhost:$HGPORT 'file/tip/bar'
1094 1095 200 Script output follows
1095 1096 $ get-with-headers.py --headeronly localhost:$HGPORT 'annotate/tip/bar'
1096 1097 200 Script output follows
1097 1098
1098 1099 $ killdaemons.py
1099 1100
1100 1101 #endif
1101 1102
1102 1103 Test heads computation on pending index changes with obsolescence markers
1103 1104 $ cd ..
1104 1105 $ cat >$TESTTMP/test_extension.py << EOF
1105 1106 > from mercurial import cmdutil, registrar
1106 1107 > from mercurial.i18n import _
1107 1108 >
1108 1109 > cmdtable = {}
1109 1110 > command = registrar.command(cmdtable)
1110 1111 > @command(b"amendtransient",[], _('hg amendtransient [rev]'))
1111 1112 > def amend(ui, repo, *pats, **opts):
1112 1113 > def commitfunc(ui, repo, message, match, opts):
1113 1114 > return repo.commit(message, repo['.'].user(), repo['.'].date(), match)
1114 1115 > opts['message'] = 'Test'
1115 1116 > opts['logfile'] = None
1116 1117 > cmdutil.amend(ui, repo, commitfunc, repo['.'], {}, pats, opts)
1117 1118 > ui.write('%s\n' % repo.changelog.headrevs())
1118 1119 > EOF
1119 1120 $ cat >> $HGRCPATH << EOF
1120 1121 > [extensions]
1121 1122 > testextension=$TESTTMP/test_extension.py
1122 1123 > EOF
1123 1124 $ hg init repo-issue-nativerevs-pending-changes
1124 1125 $ cd repo-issue-nativerevs-pending-changes
1125 1126 $ mkcommit a
1126 1127 $ mkcommit b
1127 1128 $ hg up ".^"
1128 1129 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1129 1130 $ echo aa > a
1130 1131 $ hg amendtransient
1131 1132 [1, 3]
1132 1133
1133 1134 Test cache consistency for the visible filter
1134 1135 1) We want to make sure that the cached filtered revs are invalidated when
1135 1136 bookmarks change
1136 1137 $ cd ..
1137 1138 $ cat >$TESTTMP/test_extension.py << EOF
1138 1139 > import weakref
1139 1140 > from mercurial import cmdutil, extensions, bookmarks, repoview
1140 1141 > def _bookmarkchanged(orig, bkmstoreinst, *args, **kwargs):
1141 1142 > reporef = weakref.ref(bkmstoreinst._repo)
1142 1143 > def trhook(tr):
1143 1144 > repo = reporef()
1144 1145 > hidden1 = repoview.computehidden(repo)
1145 1146 > hidden = repoview.filterrevs(repo, 'visible')
1146 1147 > if sorted(hidden1) != sorted(hidden):
1147 1148 > print "cache inconsistency"
1148 1149 > bkmstoreinst._repo.currenttransaction().addpostclose('test_extension', trhook)
1149 1150 > orig(bkmstoreinst, *args, **kwargs)
1150 1151 > def extsetup(ui):
1151 1152 > extensions.wrapfunction(bookmarks.bmstore, 'recordchange',
1152 1153 > _bookmarkchanged)
1153 1154 > EOF
1154 1155
1155 1156 $ hg init repo-cache-inconsistency
1156 1157 $ cd repo-issue-nativerevs-pending-changes
1157 1158 $ mkcommit a
1158 1159 a already tracked!
1159 1160 $ mkcommit b
1160 1161 $ hg id
1161 1162 13bedc178fce tip
1162 1163 $ echo "hello" > b
1163 1164 $ hg commit --amend -m "message"
1164 1165 $ hg book bookb -r 13bedc178fce --hidden
1165 1166 $ hg log -r 13bedc178fce
1166 1167 5:13bedc178fce (draft *obsolete*) [ bookb] add b
1167 1168 $ hg book -d bookb
1168 1169 $ hg log -r 13bedc178fce
1169 1170 abort: hidden revision '13bedc178fce'!
1170 1171 (use --hidden to access hidden revisions)
1171 1172 [255]
1172 1173
1173 1174 Empty out the test extension, as it isn't compatible with later parts
1174 1175 of the test.
1175 1176 $ echo > $TESTTMP/test_extension.py
1176 1177
1177 1178 Test ability to pull changeset with locally applying obsolescence markers
1178 1179 (issue4945)
1179 1180
1180 1181 $ cd ..
1181 1182 $ hg init issue4845
1182 1183 $ cd issue4845
1183 1184
1184 1185 $ echo foo > f0
1185 1186 $ hg add f0
1186 1187 $ hg ci -m '0'
1187 1188 $ echo foo > f1
1188 1189 $ hg add f1
1189 1190 $ hg ci -m '1'
1190 1191 $ echo foo > f2
1191 1192 $ hg add f2
1192 1193 $ hg ci -m '2'
1193 1194
1194 1195 $ echo bar > f2
1195 1196 $ hg commit --amend --config experimetnal.evolution=createmarkers
1196 1197 $ hg log -G
1197 1198 @ 4:b0551702f918 (draft) [tip ] 2
1198 1199 |
1199 1200 o 1:e016b03fd86f (draft) [ ] 1
1200 1201 |
1201 1202 o 0:a78f55e5508c (draft) [ ] 0
1202 1203
1203 1204 $ hg log -G --hidden
1204 1205 @ 4:b0551702f918 (draft) [tip ] 2
1205 1206 |
1206 1207 | x 3:f27abbcc1f77 (draft *obsolete*) [ ] temporary amend commit for e008cf283490
1207 1208 | |
1208 1209 | x 2:e008cf283490 (draft *obsolete*) [ ] 2
1209 1210 |/
1210 1211 o 1:e016b03fd86f (draft) [ ] 1
1211 1212 |
1212 1213 o 0:a78f55e5508c (draft) [ ] 0
1213 1214
1214 1215
1215 1216 $ hg strip --hidden -r 2 --config extensions.strip= --config devel.strip-obsmarkers=no
1216 1217 saved backup bundle to $TESTTMP/tmpe/issue4845/.hg/strip-backup/e008cf283490-39c978dc-backup.hg (glob)
1217 1218 $ hg debugobsolete
1218 1219 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (*) {'user': 'test'} (glob)
1219 1220 f27abbcc1f77fb409cf9160482fe619541e2d605 0 {e008cf2834908e5d6b0f792a9d4b0e2272260fb8} (*) {'user': 'test'} (glob)
1220 1221 $ hg log -G
1221 1222 @ 2:b0551702f918 (draft) [tip ] 2
1222 1223 |
1223 1224 o 1:e016b03fd86f (draft) [ ] 1
1224 1225 |
1225 1226 o 0:a78f55e5508c (draft) [ ] 0
1226 1227
1227 1228 $ hg log -G --hidden
1228 1229 @ 2:b0551702f918 (draft) [tip ] 2
1229 1230 |
1230 1231 o 1:e016b03fd86f (draft) [ ] 1
1231 1232 |
1232 1233 o 0:a78f55e5508c (draft) [ ] 0
1233 1234
1234 1235 $ hg debugbundle .hg/strip-backup/e008cf283490-*-backup.hg
1235 1236 Stream params: sortdict([('Compression', 'BZ')])
1236 1237 changegroup -- "sortdict([('version', '02'), ('nbchanges', '2')])"
1237 1238 e008cf2834908e5d6b0f792a9d4b0e2272260fb8
1238 1239 f27abbcc1f77fb409cf9160482fe619541e2d605
1239 1240 obsmarkers -- 'sortdict()'
1240 1241 version: 1 (70 bytes)
1241 1242 f27abbcc1f77fb409cf9160482fe619541e2d605 0 {e008cf2834908e5d6b0f792a9d4b0e2272260fb8} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1242 1243 phase-heads -- 'sortdict()'
1243 1244 f27abbcc1f77fb409cf9160482fe619541e2d605 draft
1244 1245
1245 1246 $ hg pull .hg/strip-backup/e008cf283490-*-backup.hg
1246 1247 pulling from .hg/strip-backup/e008cf283490-39c978dc-backup.hg
1247 1248 searching for changes
1248 1249 no changes found
1249 1250 $ hg debugobsolete
1250 1251 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (*) {'user': 'test'} (glob)
1251 1252 f27abbcc1f77fb409cf9160482fe619541e2d605 0 {e008cf2834908e5d6b0f792a9d4b0e2272260fb8} (*) {'user': 'test'} (glob)
1252 1253 $ hg log -G
1253 1254 @ 2:b0551702f918 (draft) [tip ] 2
1254 1255 |
1255 1256 o 1:e016b03fd86f (draft) [ ] 1
1256 1257 |
1257 1258 o 0:a78f55e5508c (draft) [ ] 0
1258 1259
1259 1260 $ hg log -G --hidden
1260 1261 @ 2:b0551702f918 (draft) [tip ] 2
1261 1262 |
1262 1263 o 1:e016b03fd86f (draft) [ ] 1
1263 1264 |
1264 1265 o 0:a78f55e5508c (draft) [ ] 0
1265 1266
1266 1267
1267 1268 Testing that strip remove markers:
1268 1269
1269 1270 $ hg strip -r 1 --config extensions.strip=
1270 1271 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1271 1272 saved backup bundle to $TESTTMP/tmpe/issue4845/.hg/strip-backup/e016b03fd86f-65ede734-backup.hg (glob)
1272 1273 $ hg debugobsolete
1273 1274 $ hg log -G
1274 1275 @ 0:a78f55e5508c (draft) [tip ] 0
1275 1276
1276 1277 $ hg log -G --hidden
1277 1278 @ 0:a78f55e5508c (draft) [tip ] 0
1278 1279
1279 1280 $ hg debugbundle .hg/strip-backup/e016b03fd86f-*-backup.hg
1280 1281 Stream params: sortdict([('Compression', 'BZ')])
1281 1282 changegroup -- "sortdict([('version', '02'), ('nbchanges', '2')])"
1282 1283 e016b03fd86fcccc54817d120b90b751aaf367d6
1283 1284 b0551702f918510f01ae838ab03a463054c67b46
1284 1285 obsmarkers -- 'sortdict()'
1285 1286 version: 1 (139 bytes)
1286 1287 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1287 1288 f27abbcc1f77fb409cf9160482fe619541e2d605 0 {e008cf2834908e5d6b0f792a9d4b0e2272260fb8} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1288 1289 phase-heads -- 'sortdict()'
1289 1290 b0551702f918510f01ae838ab03a463054c67b46 draft
1290 1291
1291 1292 $ hg unbundle .hg/strip-backup/e016b03fd86f-*-backup.hg
1292 1293 adding changesets
1293 1294 adding manifests
1294 1295 adding file changes
1295 1296 added 2 changesets with 2 changes to 2 files
1296 1297 2 new obsolescence markers
1297 1298 (run 'hg update' to get a working copy)
1298 1299 $ hg debugobsolete | sort
1299 1300 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (*) {'user': 'test'} (glob)
1300 1301 f27abbcc1f77fb409cf9160482fe619541e2d605 0 {e008cf2834908e5d6b0f792a9d4b0e2272260fb8} (*) {'user': 'test'} (glob)
1301 1302 $ hg log -G
1302 1303 o 2:b0551702f918 (draft) [tip ] 2
1303 1304 |
1304 1305 o 1:e016b03fd86f (draft) [ ] 1
1305 1306 |
1306 1307 @ 0:a78f55e5508c (draft) [ ] 0
1307 1308
1308 1309 $ hg log -G --hidden
1309 1310 o 2:b0551702f918 (draft) [tip ] 2
1310 1311 |
1311 1312 o 1:e016b03fd86f (draft) [ ] 1
1312 1313 |
1313 1314 @ 0:a78f55e5508c (draft) [ ] 0
1314 1315
1315 1316 Test that 'hg debugobsolete --index --rev' can show indices of obsmarkers when
1316 1317 only a subset of those are displayed (because of --rev option)
1317 1318 $ hg init doindexrev
1318 1319 $ cd doindexrev
1319 1320 $ echo a > a
1320 1321 $ hg ci -Am a
1321 1322 adding a
1322 1323 $ hg ci --amend -m aa
1323 1324 $ echo b > b
1324 1325 $ hg ci -Am b
1325 1326 adding b
1326 1327 $ hg ci --amend -m bb
1327 1328 $ echo c > c
1328 1329 $ hg ci -Am c
1329 1330 adding c
1330 1331 $ hg ci --amend -m cc
1331 1332 $ echo d > d
1332 1333 $ hg ci -Am d
1333 1334 adding d
1334 1335 $ hg ci --amend -m dd --config experimental.evolution.track-operation=1
1335 1336 $ hg debugobsolete --index --rev "3+7"
1336 1337 1 6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1 d27fb9b066076fd921277a4b9e8b9cb48c95bc6a 0 \(.*\) {'user': 'test'} (re)
1337 1338 3 4715cf767440ed891755448016c2b8cf70760c30 7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d 0 \(.*\) {'operation': 'amend', 'user': 'test'} (re)
1338 1339 $ hg debugobsolete --index --rev "3+7" -Tjson
1339 1340 [
1340 1341 {
1341 1342 "date": [0.0, 0],
1342 1343 "flag": 0,
1343 1344 "index": 1,
1344 1345 "metadata": {"user": "test"},
1345 1346 "precnode": "6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1",
1346 1347 "succnodes": ["d27fb9b066076fd921277a4b9e8b9cb48c95bc6a"]
1347 1348 },
1348 1349 {
1349 1350 "date": [0.0, 0],
1350 1351 "flag": 0,
1351 1352 "index": 3,
1352 1353 "metadata": {"operation": "amend", "user": "test"},
1353 1354 "precnode": "4715cf767440ed891755448016c2b8cf70760c30",
1354 1355 "succnodes": ["7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d"]
1355 1356 }
1356 1357 ]
1357 1358
1358 1359 Test the --delete option of debugobsolete command
1359 1360 $ hg debugobsolete --index
1360 1361 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b f9bd49731b0b175e42992a3c8fa6c678b2bc11f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1361 1362 1 6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1 d27fb9b066076fd921277a4b9e8b9cb48c95bc6a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1362 1363 2 1ab51af8f9b41ef8c7f6f3312d4706d870b1fb74 29346082e4a9e27042b62d2da0e2de211c027621 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1363 1364 3 4715cf767440ed891755448016c2b8cf70760c30 7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1364 1365 $ hg debugobsolete --delete 1 --delete 3
1365 1366 deleted 2 obsolescence markers
1366 1367 $ hg debugobsolete
1367 1368 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b f9bd49731b0b175e42992a3c8fa6c678b2bc11f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1368 1369 1ab51af8f9b41ef8c7f6f3312d4706d870b1fb74 29346082e4a9e27042b62d2da0e2de211c027621 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1369 1370
1370 1371 Test adding changeset after obsmarkers affecting it
1371 1372 (eg: during pull, or unbundle)
1372 1373
1373 1374 $ mkcommit e
1374 1375 $ hg bundle -r . --base .~1 ../bundle-2.hg
1375 1376 1 changesets found
1376 1377 $ getid .
1377 1378 $ hg --config extensions.strip= strip -r .
1378 1379 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1379 1380 saved backup bundle to $TESTTMP/tmpe/issue4845/doindexrev/.hg/strip-backup/9bc153528424-ee80edd4-backup.hg (glob)
1380 1381 $ hg debugobsolete 9bc153528424ea266d13e57f9ff0d799dfe61e4b
1381 1382 $ hg unbundle ../bundle-2.hg
1382 1383 adding changesets
1383 1384 adding manifests
1384 1385 adding file changes
1385 1386 added 1 changesets with 1 changes to 1 files
1386 1387 (run 'hg update' to get a working copy)
1387 1388 $ hg log -G
1388 1389 @ 7:7ae79c5d60f0 (draft) [tip ] dd
1389 1390 |
1390 1391 | o 6:4715cf767440 (draft) [ ] d
1391 1392 |/
1392 1393 o 5:29346082e4a9 (draft) [ ] cc
1393 1394 |
1394 1395 o 3:d27fb9b06607 (draft) [ ] bb
1395 1396 |
1396 1397 | o 2:6fdef60fcbab (draft) [ ] b
1397 1398 |/
1398 1399 o 1:f9bd49731b0b (draft) [ ] aa
1399 1400
1400 1401
1401 1402 $ cd ..
@@ -1,72 +1,73 b''
1 1 ====================================
2 2 Testing head checking code: Case B-1
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category B: simple case involving pruned changesets
12 12 TestCase 1: single pruned changeset
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 1 changeset branch
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * old branch is pruned
21 21 .. * 1 new unrelated branch
22 22 ..
23 23 .. expected-result:
24 24 ..
25 25 .. * push allowed
26 26 ..
27 27 .. graph-summary:
28 28 ..
29 29 .. B
30 30 .. |
31 31 .. A |
32 32 .. |/
33 33 ..
34 34
35 35 $ . $TESTDIR/testlib/push-checkheads-util.sh
36 36
37 37 Test setup
38 38 ----------
39 39
40 40 $ mkdir B1
41 41 $ cd B1
42 42 $ setuprepos
43 43 creating basic server and client repo
44 44 updating to branch default
45 45 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
46 46 $ cd client
47 47 $ hg up 0
48 48 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
49 49 $ mkcommit B0
50 50 created new head
51 51 $ hg debugobsolete --record-parents `getid "desc(A0)"`
52 52 $ hg log -G --hidden
53 53 @ 74ff5441d343 (draft): B0
54 54 |
55 55 | x 8aaa48160adc (draft): A0
56 56 |/
57 57 o 1e4be0697311 (public): root
58 58
59 59
60 60 Actual testing
61 61 --------------
62 62
63 63 $ hg push
64 64 pushing to $TESTTMP/B1/server (glob)
65 65 searching for changes
66 66 adding changesets
67 67 adding manifests
68 68 adding file changes
69 69 added 1 changesets with 1 changes to 1 files (+1 heads)
70 70 1 new obsolescence markers
71 obsoleted 1 changesets
71 72
72 73 $ cd ../..
@@ -1,85 +1,86 b''
1 1 ====================================
2 2 Testing head checking code: Case B-2
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category B: simple case involving pruned changesets
12 12 TestCase 2: multi-changeset branch, head is pruned, rest is superceeded
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 2 changeset branch
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * old head is pruned
21 21 .. * 1 new branch succeeding to the other changeset in the old branch
22 22 ..
23 23 .. expected-result:
24 24 ..
25 25 .. * push allowed
26 26 ..
27 27 .. graph-summary:
28 28 ..
29 29 .. B
30 30 .. |
31 31 .. A ø⇠◔ A'
32 32 .. |/
33 33 .. ●
34 34
35 35 $ . $TESTDIR/testlib/push-checkheads-util.sh
36 36
37 37 Test setup
38 38 ----------
39 39
40 40 $ mkdir B2
41 41 $ cd B2
42 42 $ setuprepos
43 43 creating basic server and client repo
44 44 updating to branch default
45 45 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
46 46 $ cd server
47 47 $ mkcommit B0
48 48 $ cd ../client
49 49 $ hg pull
50 50 pulling from $TESTTMP/B2/server (glob)
51 51 searching for changes
52 52 adding changesets
53 53 adding manifests
54 54 adding file changes
55 55 added 1 changesets with 1 changes to 1 files
56 56 (run 'hg update' to get a working copy)
57 57 $ hg up 0
58 58 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
59 59 $ mkcommit A1
60 60 created new head
61 61 $ hg debugobsolete `getid "desc(A0)" ` `getid "desc(A1)"`
62 62 $ hg debugobsolete --record-parents `getid "desc(B0)"`
63 63 $ hg log -G --hidden
64 64 @ f6082bc4ffef (draft): A1
65 65 |
66 66 | x d73caddc5533 (draft): B0
67 67 | |
68 68 | x 8aaa48160adc (draft): A0
69 69 |/
70 70 o 1e4be0697311 (public): root
71 71
72 72
73 73 Actual testing
74 74 --------------
75 75
76 76 $ hg push
77 77 pushing to $TESTTMP/B2/server (glob)
78 78 searching for changes
79 79 adding changesets
80 80 adding manifests
81 81 adding file changes
82 82 added 1 changesets with 1 changes to 1 files (+1 heads)
83 83 2 new obsolescence markers
84 obsoleted 2 changesets
84 85
85 86 $ cd ../..
@@ -1,86 +1,87 b''
1 1 ====================================
2 2 Testing head checking code: Case B-3
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category B: simple case involving pruned changesets
12 12 TestCase 3: multi-changeset branch, other is pruned, rest is superceeded
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 2 changeset branch
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * old head is superceeded
21 21 .. * old other is pruned
22 22 ..
23 23 .. expected-result:
24 24 ..
25 25 .. * push allowed
26 26 ..
27 27 .. graph-summary:
28 28 ..
29 29 .. B ø⇠◔ B'
30 30 .. | |
31 31 .. A ⊗ |
32 32 .. |/
33 33 .. ●
34 34
35 35 $ . $TESTDIR/testlib/push-checkheads-util.sh
36 36
37 37 Test setup
38 38 ----------
39 39
40 40 $ mkdir B3
41 41 $ cd B3
42 42 $ setuprepos
43 43 creating basic server and client repo
44 44 updating to branch default
45 45 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
46 46 $ cd server
47 47 $ mkcommit B0
48 48 $ cd ../client
49 49 $ hg pull
50 50 pulling from $TESTTMP/B3/server (glob)
51 51 searching for changes
52 52 adding changesets
53 53 adding manifests
54 54 adding file changes
55 55 added 1 changesets with 1 changes to 1 files
56 56 (run 'hg update' to get a working copy)
57 57 $ hg up 0
58 58 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
59 59 $ mkcommit B1
60 60 created new head
61 61 $ hg debugobsolete --record-parents `getid "desc(A0)"`
62 62 $ hg debugobsolete `getid "desc(B0)" ` `getid "desc(B1)"`
63 63 $ hg log -G --hidden
64 64 @ 25c56d33e4c4 (draft): B1
65 65 |
66 66 | x d73caddc5533 (draft): B0
67 67 | |
68 68 | x 8aaa48160adc (draft): A0
69 69 |/
70 70 o 1e4be0697311 (public): root
71 71
72 72
73 73 Actual testing
74 74 --------------
75 75
76 76 $ hg push
77 77 pushing to $TESTTMP/B3/server (glob)
78 78 searching for changes
79 79 adding changesets
80 80 adding manifests
81 81 adding file changes
82 82 added 1 changesets with 1 changes to 1 files (+1 heads)
83 83 2 new obsolescence markers
84 obsoleted 2 changesets
84 85
85 86 $ cd ../..
86 87
@@ -1,86 +1,87 b''
1 1 ====================================
2 2 Testing head checking code: Case B-4
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category B: simple case involving pruned changesets
12 12 TestCase 4: multi-changeset branch, all are pruned
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 2 changeset branch
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * old branch is pruned
21 21 ..
22 22 .. expected-result:
23 23 ..
24 24 .. * push allowed
25 25 ..
26 26 .. graph-summary:
27 27 ..
28 28 .. B
29 29 .. |
30 30 .. A
31 31 .. |
32 32 .. | C
33 33 .. |/
34 34 ..
35 35
36 36 $ . $TESTDIR/testlib/push-checkheads-util.sh
37 37
38 38 Test setup
39 39 ----------
40 40
41 41 $ mkdir B4
42 42 $ cd B4
43 43 $ setuprepos
44 44 creating basic server and client repo
45 45 updating to branch default
46 46 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
47 47 $ cd server
48 48 $ mkcommit B0
49 49 $ cd ../client
50 50 $ hg pull
51 51 pulling from $TESTTMP/B4/server (glob)
52 52 searching for changes
53 53 adding changesets
54 54 adding manifests
55 55 adding file changes
56 56 added 1 changesets with 1 changes to 1 files
57 57 (run 'hg update' to get a working copy)
58 58 $ hg up 0
59 59 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
60 60 $ mkcommit C0
61 61 created new head
62 62 $ hg debugobsolete --record-parents `getid "desc(A0)"`
63 63 $ hg debugobsolete --record-parents `getid "desc(B0)"`
64 64 $ hg log -G --hidden
65 65 @ 0f88766e02d6 (draft): C0
66 66 |
67 67 | x d73caddc5533 (draft): B0
68 68 | |
69 69 | x 8aaa48160adc (draft): A0
70 70 |/
71 71 o 1e4be0697311 (public): root
72 72
73 73
74 74 Actual testing
75 75 --------------
76 76
77 77 $ hg push
78 78 pushing to $TESTTMP/B4/server (glob)
79 79 searching for changes
80 80 adding changesets
81 81 adding manifests
82 82 adding file changes
83 83 added 1 changesets with 1 changes to 1 files (+1 heads)
84 84 2 new obsolescence markers
85 obsoleted 2 changesets
85 86
86 87 $ cd ../..
@@ -1,92 +1,93 b''
1 1 ====================================
2 2 Testing head checking code: Case B-5
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category B: simple case involving pruned changesets
12 12 TestCase 5: multi-changeset branch, mix of pruned and superceeded
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 3 changeset branch
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * old head is pruned
21 21 .. * old mid is superceeded
22 22 .. * old root is pruned
23 23 ..
24 24 .. expected-result:
25 25 ..
26 26 .. * push allowed
27 27 ..
28 28 .. graph-summary:
29 29 ..
30 30 .. B
31 31 .. |
32 32 .. A ø⇠◔ A'
33 33 .. | |
34 34 .. B ⊗ |
35 35 .. |/
36 36 .. ●
37 37
38 38 $ . $TESTDIR/testlib/push-checkheads-util.sh
39 39
40 40 Test setup
41 41 ----------
42 42
43 43 $ mkdir B5
44 44 $ cd B5
45 45 $ setuprepos
46 46 creating basic server and client repo
47 47 updating to branch default
48 48 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 49 $ cd server
50 50 $ mkcommit B0
51 51 $ mkcommit C0
52 52 $ cd ../client
53 53 $ hg pull
54 54 pulling from $TESTTMP/B5/server (glob)
55 55 searching for changes
56 56 adding changesets
57 57 adding manifests
58 58 adding file changes
59 59 added 2 changesets with 2 changes to 2 files
60 60 (run 'hg update' to get a working copy)
61 61 $ hg up 0
62 62 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
63 63 $ mkcommit B1
64 64 created new head
65 65 $ hg debugobsolete --record-parents `getid "desc(A0)"`
66 66 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(B1)"`
67 67 $ hg debugobsolete --record-parents `getid "desc(C0)"`
68 68 $ hg log -G --hidden
69 69 @ 25c56d33e4c4 (draft): B1
70 70 |
71 71 | x 821fb21d0dd2 (draft): C0
72 72 | |
73 73 | x d73caddc5533 (draft): B0
74 74 | |
75 75 | x 8aaa48160adc (draft): A0
76 76 |/
77 77 o 1e4be0697311 (public): root
78 78
79 79
80 80 Actual testing
81 81 --------------
82 82
83 83 $ hg push
84 84 pushing to $TESTTMP/B5/server (glob)
85 85 searching for changes
86 86 adding changesets
87 87 adding manifests
88 88 adding file changes
89 89 added 1 changesets with 1 changes to 1 files (+1 heads)
90 90 3 new obsolescence markers
91 obsoleted 3 changesets
91 92
92 93 $ cd ../..
@@ -1,78 +1,79 b''
1 1 ====================================
2 2 Testing head checking code: Case B-6
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category B: simple case involving pruned changesets
12 12 TestCase 6: single changesets, pruned then superseeded (on a new changeset)
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 1 changeset branch
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * old branch is rewritten onto another one,
21 21 .. * the new version is then pruned.
22 22 ..
23 23 .. expected-result:
24 24 ..
25 25 .. * push allowed
26 26 ..
27 27 .. graph-summary:
28 28 ..
29 29 .. A ø⇠⊗ A'
30 30 .. | |
31 31 .. | ◔ B
32 32 .. |/
33 33 .. ●
34 34
35 35 $ . $TESTDIR/testlib/push-checkheads-util.sh
36 36
37 37 Test setup
38 38 ----------
39 39
40 40 $ mkdir B6
41 41 $ cd B6
42 42 $ setuprepos
43 43 creating basic server and client repo
44 44 updating to branch default
45 45 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
46 46 $ cd client
47 47 $ hg up 0
48 48 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
49 49 $ mkcommit B0
50 50 created new head
51 51 $ mkcommit A1
52 52 $ hg up 'desc(B0)'
53 53 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
54 54 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(A1)"`
55 55 $ hg debugobsolete --record-parents `getid "desc(A1)"`
56 56 $ hg log -G --hidden
57 57 x ba93660aff8d (draft): A1
58 58 |
59 59 @ 74ff5441d343 (draft): B0
60 60 |
61 61 | x 8aaa48160adc (draft): A0
62 62 |/
63 63 o 1e4be0697311 (public): root
64 64
65 65
66 66 Actual testing
67 67 --------------
68 68
69 69 $ hg push
70 70 pushing to $TESTTMP/B6/server (glob)
71 71 searching for changes
72 72 adding changesets
73 73 adding manifests
74 74 adding file changes
75 75 added 1 changesets with 1 changes to 1 files (+1 heads)
76 76 2 new obsolescence markers
77 obsoleted 1 changesets
77 78
78 79 $ cd ../..
@@ -1,77 +1,78 b''
1 1 ====================================
2 2 Testing head checking code: Case B-7
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category B: simple case involving pruned changesets
12 12 TestCase 7: single changesets, pruned then superseeded (on an existing changeset)
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 1 changeset branch
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * old branch is rewritten onto the common set,
21 21 .. * the new version is then pruned.
22 22 ..
23 23 .. expected-result:
24 24 ..
25 25 .. * push allowed
26 26 ..
27 27 .. graph-summary:
28 28 ..
29 29 .. A ø⇠⊗ A'
30 30 .. B ◔ | |
31 31 .. \|/
32 32 .. ●
33 33
34 34 $ . $TESTDIR/testlib/push-checkheads-util.sh
35 35
36 36 Test setup
37 37 ----------
38 38
39 39 $ mkdir B7
40 40 $ cd B7
41 41 $ setuprepos
42 42 creating basic server and client repo
43 43 updating to branch default
44 44 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
45 45 $ cd client
46 46 $ hg up 0
47 47 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
48 48 $ mkcommit B0
49 49 created new head
50 50 $ mkcommit A1
51 51 $ hg up 'desc(B0)'
52 52 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
53 53 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(A1)"`
54 54 $ hg debugobsolete --record-parents `getid "desc(A1)"`
55 55 $ hg log -G --hidden
56 56 x ba93660aff8d (draft): A1
57 57 |
58 58 @ 74ff5441d343 (draft): B0
59 59 |
60 60 | x 8aaa48160adc (draft): A0
61 61 |/
62 62 o 1e4be0697311 (public): root
63 63
64 64
65 65 Actual testing
66 66 --------------
67 67
68 68 $ hg push
69 69 pushing to $TESTTMP/B7/server (glob)
70 70 searching for changes
71 71 adding changesets
72 72 adding manifests
73 73 adding file changes
74 74 added 1 changesets with 1 changes to 1 files (+1 heads)
75 75 2 new obsolescence markers
76 obsoleted 1 changesets
76 77
77 78 $ cd ../..
@@ -1,98 +1,99 b''
1 1 ====================================
2 2 Testing head checking code: Case B-2
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category B: simple case involving pruned changesets
12 12 TestCase 2: multi-changeset branch, head is pruned, rest is superceeded, through other
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 2 changeset branch
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * old head is rewritten then pruned
21 21 .. * 1 new branch succeeding to the other changeset in the old branch (through another obsolete branch)
22 22 ..
23 23 .. expected-result:
24 24 ..
25 25 .. * push allowed
26 26 ..
27 27 .. graph-summary:
28 28 ..
29 29 .. B ø⇠⊗ B'
30 30 .. | | A'
31 31 .. A ø⇠ø⇠◔ A''
32 32 .. |/ /
33 33 .. | /
34 34 .. |/
35 35 ..
36 36
37 37 $ . $TESTDIR/testlib/push-checkheads-util.sh
38 38
39 39 Test setup
40 40 ----------
41 41
42 42 $ mkdir B8
43 43 $ cd B8
44 44 $ setuprepos
45 45 creating basic server and client repo
46 46 updating to branch default
47 47 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 48 $ cd server
49 49 $ mkcommit B0
50 50 $ cd ../client
51 51 $ hg pull
52 52 pulling from $TESTTMP/B8/server (glob)
53 53 searching for changes
54 54 adding changesets
55 55 adding manifests
56 56 adding file changes
57 57 added 1 changesets with 1 changes to 1 files
58 58 (run 'hg update' to get a working copy)
59 59 $ hg up 0
60 60 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
61 61 $ mkcommit A1
62 62 created new head
63 63 $ mkcommit B1
64 64 $ hg up 0
65 65 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
66 66 $ mkcommit A2
67 67 created new head
68 68 $ hg debugobsolete `getid "desc(A0)" ` `getid "desc(A1)"`
69 69 $ hg debugobsolete `getid "desc(B0)" ` `getid "desc(B1)"`
70 70 $ hg debugobsolete --record-parents `getid "desc(B1)"`
71 71 $ hg debugobsolete `getid "desc(A1)" ` `getid "desc(A2)"`
72 72 $ hg log -G --hidden
73 73 @ c1f8d089020f (draft): A2
74 74 |
75 75 | x 262c8c798096 (draft): B1
76 76 | |
77 77 | x f6082bc4ffef (draft): A1
78 78 |/
79 79 | x d73caddc5533 (draft): B0
80 80 | |
81 81 | x 8aaa48160adc (draft): A0
82 82 |/
83 83 o 1e4be0697311 (public): root
84 84
85 85
86 86 Actual testing
87 87 --------------
88 88
89 89 $ hg push
90 90 pushing to $TESTTMP/B8/server (glob)
91 91 searching for changes
92 92 adding changesets
93 93 adding manifests
94 94 adding file changes
95 95 added 1 changesets with 1 changes to 1 files (+1 heads)
96 96 4 new obsolescence markers
97 obsoleted 2 changesets
97 98
98 99 $ cd ../..
@@ -1,69 +1,70 b''
1 1 ====================================
2 2 Testing head checking code: Case A-1
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category A: simple case involving a branch being superceeded by another.
12 12 TestCase 1: single-changeset branch
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 1 changeset branch
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * 1 changeset branch succeeding to A
21 21 ..
22 22 .. expected-result:
23 23 ..
24 24 .. * push allowed
25 25 ..
26 26 .. graph-summary:
27 27 ..
28 28 .. A ø⇠◔ A'
29 29 .. |/
30 30 .. ●
31 31
32 32 $ . $TESTDIR/testlib/push-checkheads-util.sh
33 33
34 34 Test setup
35 35 ----------
36 36
37 37 $ mkdir A1
38 38 $ cd A1
39 39 $ setuprepos
40 40 creating basic server and client repo
41 41 updating to branch default
42 42 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
43 43 $ cd client
44 44 $ hg up 0
45 45 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
46 46 $ mkcommit A1
47 47 created new head
48 48 $ hg debugobsolete `getid "desc(A0)" ` `getid "desc(A1)"`
49 49 $ hg log -G --hidden
50 50 @ f6082bc4ffef (draft): A1
51 51 |
52 52 | x 8aaa48160adc (draft): A0
53 53 |/
54 54 o 1e4be0697311 (public): root
55 55
56 56
57 57 Actual testing
58 58 --------------
59 59
60 60 $ hg push
61 61 pushing to $TESTTMP/A1/server (glob)
62 62 searching for changes
63 63 adding changesets
64 64 adding manifests
65 65 adding file changes
66 66 added 1 changesets with 1 changes to 1 files (+1 heads)
67 67 1 new obsolescence markers
68 obsoleted 1 changesets
68 69
69 70 $ cd ../..
@@ -1,87 +1,88 b''
1 1 ====================================
2 2 Testing head checking code: Case A-2
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category A: simple case involving a branch being superceeded by another.
12 12 TestCase 2: multi-changeset branch
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 1 branch with 2 changesets
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * another 2-changeset branch succeeding the old one
21 21 ..
22 22 .. expected-result:
23 23 ..
24 24 .. * push allowed
25 25 ..
26 26 .. graph-summary:
27 27 ..
28 28 .. B ø⇠◔ B'
29 29 .. | |
30 30 .. A ø⇠◔ A'
31 31 .. |/
32 32 ..
33 33
34 34 $ . $TESTDIR/testlib/push-checkheads-util.sh
35 35
36 36 Test setup
37 37 ----------
38 38
39 39 $ mkdir A2
40 40 $ cd A2
41 41 $ setuprepos
42 42 creating basic server and client repo
43 43 updating to branch default
44 44 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
45 45 $ cd server
46 46 $ mkcommit B0
47 47 $ cd ../client
48 48 $ hg pull
49 49 pulling from $TESTTMP/A2/server (glob)
50 50 searching for changes
51 51 adding changesets
52 52 adding manifests
53 53 adding file changes
54 54 added 1 changesets with 1 changes to 1 files
55 55 (run 'hg update' to get a working copy)
56 56 $ hg up 0
57 57 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
58 58 $ mkcommit A1
59 59 created new head
60 60 $ mkcommit B1
61 61 $ hg debugobsolete `getid "desc(A0)" ` `getid "desc(A1)"`
62 62 $ hg debugobsolete `getid "desc(B0)" ` `getid "desc(B1)"`
63 63 $ hg log -G --hidden
64 64 @ 262c8c798096 (draft): B1
65 65 |
66 66 o f6082bc4ffef (draft): A1
67 67 |
68 68 | x d73caddc5533 (draft): B0
69 69 | |
70 70 | x 8aaa48160adc (draft): A0
71 71 |/
72 72 o 1e4be0697311 (public): root
73 73
74 74
75 75 Actual testing
76 76 --------------
77 77
78 78 $ hg push
79 79 pushing to $TESTTMP/A2/server (glob)
80 80 searching for changes
81 81 adding changesets
82 82 adding manifests
83 83 adding file changes
84 84 added 2 changesets with 2 changes to 2 files (+1 heads)
85 85 2 new obsolescence markers
86 obsoleted 2 changesets
86 87
87 88 $ cd ../..
@@ -1,90 +1,91 b''
1 1 ====================================
2 2 Testing head checking code: Case A-3
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category A: simple case involving a branch being superceeded by another.
12 12 TestCase 3: multi-changeset branch with reordering
13 13
14 14 Push should be allowed
15 15 .. old-state:
16 16 ..
17 17 .. * 2 changeset branch
18 18 ..
19 19 .. new-state:
20 20 ..
21 21 .. * 2 changeset branch succeeding the old one with reordering
22 22 ..
23 23 .. expected-result:
24 24 ..
25 25 .. * push allowed
26 26 ..
27 27 .. graph-summary:
28 28 ..
29 29 .. B ø⇠⇠
30 30 .. |
31 31 .. A ø⇠⇠⇠○ A'
32 32 .. | ⇡/
33 33 .. | ○ B'
34 34 .. |/
35 35 ..
36 36
37 37 $ . $TESTDIR/testlib/push-checkheads-util.sh
38 38
39 39 Test setup
40 40 ----------
41 41
42 42 $ mkdir A3
43 43 $ cd A3
44 44 $ setuprepos
45 45 creating basic server and client repo
46 46 updating to branch default
47 47 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 48 $ cd server
49 49 $ mkcommit B0
50 50 $ cd ../client
51 51 $ hg pull
52 52 pulling from $TESTTMP/A3/server (glob)
53 53 searching for changes
54 54 adding changesets
55 55 adding manifests
56 56 adding file changes
57 57 added 1 changesets with 1 changes to 1 files
58 58 (run 'hg update' to get a working copy)
59 59 $ hg up 0
60 60 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
61 61 $ mkcommit B1
62 62 created new head
63 63 $ mkcommit A1
64 64 $ hg debugobsolete `getid "desc(A0)" ` `getid "desc(A1)"`
65 65 $ hg debugobsolete `getid "desc(B0)" ` `getid "desc(B1)"`
66 66 $ hg log -G --hidden
67 67 @ c1c7524e9488 (draft): A1
68 68 |
69 69 o 25c56d33e4c4 (draft): B1
70 70 |
71 71 | x d73caddc5533 (draft): B0
72 72 | |
73 73 | x 8aaa48160adc (draft): A0
74 74 |/
75 75 o 1e4be0697311 (public): root
76 76
77 77
78 78 Actual testing
79 79 --------------
80 80
81 81 $ hg push
82 82 pushing to $TESTTMP/A3/server (glob)
83 83 searching for changes
84 84 adding changesets
85 85 adding manifests
86 86 adding file changes
87 87 added 2 changesets with 2 changes to 2 files (+1 heads)
88 88 2 new obsolescence markers
89 obsoleted 2 changesets
89 90
90 91 $ cd ../..
@@ -1,74 +1,75 b''
1 1 ====================================
2 2 Testing head checking code: Case A-4
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category A: simple case involving a branch being superceeded by another.
12 12 TestCase 4: New changeset as children of the successor
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 1-changeset branch
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * 2-changeset branch, first is a successor, but head is new
21 21 ..
22 22 .. expected-result:
23 23 ..
24 24 .. * push allowed
25 25 ..
26 26 .. graph-summary:
27 27 ..
28 28 .. B
29 29 .. |
30 30 .. A ø⇠◔ A'
31 31 .. |/
32 32 .. ●
33 33
34 34 $ . $TESTDIR/testlib/push-checkheads-util.sh
35 35
36 36 Test setup
37 37 ----------
38 38
39 39 $ mkdir A4
40 40 $ cd A4
41 41 $ setuprepos
42 42 creating basic server and client repo
43 43 updating to branch default
44 44 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
45 45 $ cd client
46 46 $ hg up 0
47 47 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
48 48 $ mkcommit A1
49 49 created new head
50 50 $ hg debugobsolete `getid "desc(A0)" ` `getid "desc(A1)"`
51 51 $ mkcommit B0
52 52 $ hg log -G --hidden
53 53 @ f40ded968333 (draft): B0
54 54 |
55 55 o f6082bc4ffef (draft): A1
56 56 |
57 57 | x 8aaa48160adc (draft): A0
58 58 |/
59 59 o 1e4be0697311 (public): root
60 60
61 61
62 62 Actual testing
63 63 --------------
64 64
65 65 $ hg push
66 66 pushing to $TESTTMP/A4/server (glob)
67 67 searching for changes
68 68 adding changesets
69 69 adding manifests
70 70 adding file changes
71 71 added 2 changesets with 2 changes to 2 files (+1 heads)
72 72 1 new obsolescence markers
73 obsoleted 1 changesets
73 74
74 75 $ cd ../../
@@ -1,75 +1,76 b''
1 1 ====================================
2 2 Testing head checking code: Case A-5
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category A: simple case involving a branch being superceeded by another.
12 12 TestCase 5: New changeset as parent of the successor
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 1-changeset branch
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * 2rchangeset branch, head is a successor, but other is new
21 21 ..
22 22 .. expected-result:
23 23 ..
24 24 .. * push allowed
25 25 ..
26 26 .. graph-summary:
27 27 ..
28 28 .. A ø⇠◔ A'
29 29 .. | |
30 30 .. | ◔ B
31 31 .. |/
32 32 .. ●
33 33
34 34 $ . $TESTDIR/testlib/push-checkheads-util.sh
35 35
36 36 Test setup
37 37 ----------
38 38
39 39 $ mkdir A5
40 40 $ cd A5
41 41 $ setuprepos
42 42 creating basic server and client repo
43 43 updating to branch default
44 44 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
45 45 $ cd client
46 46 $ hg up 0
47 47 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
48 48 $ mkcommit B0
49 49 created new head
50 50 $ mkcommit A1
51 51 $ hg debugobsolete `getid "desc(A0)" ` `getid "desc(A1)"`
52 52 $ hg log -G --hidden
53 53 @ ba93660aff8d (draft): A1
54 54 |
55 55 o 74ff5441d343 (draft): B0
56 56 |
57 57 | x 8aaa48160adc (draft): A0
58 58 |/
59 59 o 1e4be0697311 (public): root
60 60
61 61
62 62 Actual testing
63 63 --------------
64 64
65 65 $ hg push
66 66 pushing to $TESTTMP/A5/server (glob)
67 67 searching for changes
68 68 adding changesets
69 69 adding manifests
70 70 adding file changes
71 71 added 2 changesets with 2 changes to 2 files (+1 heads)
72 72 1 new obsolescence markers
73 obsoleted 1 changesets
73 74
74 75 $ cd ../..
75 76
@@ -1,98 +1,99 b''
1 1 ====================================
2 2 Testing head checking code: Case A-6
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category A: simple case involving a branch being superceeded by another.
12 12 TestCase 6: multi-changeset branch, split on multiple other, (base on its own branch), same number of head
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 2 branch (1-changeset, and 2-changesets)
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * 1 new branch superceeding the base of the old-2-changesets-branch,
21 21 .. * 1 new changesets on the old-1-changeset-branch superceeding the head of the other
22 22 ..
23 23 .. expected-result:
24 24 ..
25 25 .. * push allowed
26 26 ..
27 27 .. graph-summary:
28 28 ..
29 29 .. B'◔⇢ø B
30 30 .. | |
31 31 .. A | ø⇠◔ A'
32 32 .. | |/
33 33 .. C |
34 34 .. \|
35 35 ..
36 36
37 37 $ . $TESTDIR/testlib/push-checkheads-util.sh
38 38
39 39 Test setup
40 40 ----------
41 41
42 42 $ mkdir A6
43 43 $ cd A6
44 44 $ setuprepos
45 45 creating basic server and client repo
46 46 updating to branch default
47 47 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 48 $ cd server
49 49 $ mkcommit B0
50 50 $ hg up 0
51 51 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
52 52 $ mkcommit C0
53 53 created new head
54 54 $ cd ../client
55 55 $ hg pull
56 56 pulling from $TESTTMP/A6/server (glob)
57 57 searching for changes
58 58 adding changesets
59 59 adding manifests
60 60 adding file changes
61 61 added 2 changesets with 2 changes to 2 files (+1 heads)
62 62 (run 'hg heads' to see heads, 'hg merge' to merge)
63 63 $ hg up 0
64 64 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
65 65 $ mkcommit A1
66 66 created new head
67 67 $ hg up 'desc(C0)'
68 68 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
69 69 $ mkcommit B1
70 70 $ hg debugobsolete `getid "desc(A0)" ` `getid "desc(A1)"`
71 71 $ hg debugobsolete `getid "desc(B0)" ` `getid "desc(B1)"`
72 72 $ hg log -G --hidden
73 73 @ d70a1f75a020 (draft): B1
74 74 |
75 75 | o f6082bc4ffef (draft): A1
76 76 | |
77 77 o | 0f88766e02d6 (draft): C0
78 78 |/
79 79 | x d73caddc5533 (draft): B0
80 80 | |
81 81 | x 8aaa48160adc (draft): A0
82 82 |/
83 83 o 1e4be0697311 (public): root
84 84
85 85
86 86 Actual testing
87 87 --------------
88 88
89 89 $ hg push
90 90 pushing to $TESTTMP/A6/server (glob)
91 91 searching for changes
92 92 adding changesets
93 93 adding manifests
94 94 adding file changes
95 95 added 2 changesets with 2 changes to 2 files (+1 heads)
96 96 2 new obsolescence markers
97 obsoleted 2 changesets
97 98
98 99 $ cd ../..
@@ -1,98 +1,99 b''
1 1 ====================================
2 2 Testing head checking code: Case A-7
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category A: simple case involving a branch being superceeded by another.
12 12 TestCase 7: multi-changeset branch, split on multiple other, (head on its own branch), same number of head
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 2 branch (1-changeset, and 2-changesets)
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * 1 new branch superceeding the head of the old-2-changesets-branch,
21 21 .. * 1 new changesets on the old-1-changeset-branch superceeding the base of the other
22 22 ..
23 23 .. expected-result:
24 24 ..
25 25 .. * push allowed
26 26 ..
27 27 .. graph-summary:
28 28 ..
29 29 .. B ø⇠◔ B'
30 30 .. | |
31 31 .. A'◔⇢ø |
32 32 .. | |/
33 33 .. C |
34 34 .. \|
35 35 ..
36 36
37 37 $ . $TESTDIR/testlib/push-checkheads-util.sh
38 38
39 39 Test setup
40 40 ----------
41 41
42 42 $ mkdir A7
43 43 $ cd A7
44 44 $ setuprepos
45 45 creating basic server and client repo
46 46 updating to branch default
47 47 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 48 $ cd server
49 49 $ mkcommit B0
50 50 $ hg up 0
51 51 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
52 52 $ mkcommit C0
53 53 created new head
54 54 $ cd ../client
55 55 $ hg pull
56 56 pulling from $TESTTMP/A7/server (glob)
57 57 searching for changes
58 58 adding changesets
59 59 adding manifests
60 60 adding file changes
61 61 added 2 changesets with 2 changes to 2 files (+1 heads)
62 62 (run 'hg heads' to see heads, 'hg merge' to merge)
63 63 $ hg up 'desc(C0)'
64 64 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
65 65 $ mkcommit A1
66 66 $ hg up 0
67 67 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
68 68 $ mkcommit B1
69 69 created new head
70 70 $ hg debugobsolete `getid "desc(A0)" ` `getid "desc(A1)"`
71 71 $ hg debugobsolete `getid "desc(B0)" ` `getid "desc(B1)"`
72 72 $ hg log -G --hidden
73 73 @ 25c56d33e4c4 (draft): B1
74 74 |
75 75 | o a0802eb7fc1b (draft): A1
76 76 | |
77 77 | o 0f88766e02d6 (draft): C0
78 78 |/
79 79 | x d73caddc5533 (draft): B0
80 80 | |
81 81 | x 8aaa48160adc (draft): A0
82 82 |/
83 83 o 1e4be0697311 (public): root
84 84
85 85
86 86 Actual testing
87 87 --------------
88 88
89 89 $ hg push
90 90 pushing to $TESTTMP/A7/server (glob)
91 91 searching for changes
92 92 adding changesets
93 93 adding manifests
94 94 adding file changes
95 95 added 2 changesets with 2 changes to 2 files (+1 heads)
96 96 2 new obsolescence markers
97 obsoleted 2 changesets
97 98
98 99 $ cd ../..
@@ -1,79 +1,80 b''
1 1 ====================================
2 2 Testing head checking code: Case A-8
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category A: simple case involving a branch being superceeded by another.
12 12 TestCase 8: single-changeset branch indirect rewrite
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 1-changeset branch
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * 1-changeset branch succeeding to A, through another unpushed changesets
21 21 ..
22 22 .. expected-result:
23 23 ..
24 24 .. * push allowed
25 25 ..
26 26 .. graph-summary:
27 27 ..
28 28 .. A'
29 29 .. A ø⇠ø⇠◔ A''
30 30 .. |/ /
31 31 .. | /
32 32 .. |/
33 33 .. ●
34 34
35 35 $ . $TESTDIR/testlib/push-checkheads-util.sh
36 36
37 37 Test setup
38 38 ----------
39 39
40 40 $ mkdir A8
41 41 $ cd A8
42 42 $ setuprepos
43 43 creating basic server and client repo
44 44 updating to branch default
45 45 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
46 46 $ cd client
47 47 $ hg up 0
48 48 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
49 49 $ mkcommit A1
50 50 created new head
51 51 $ hg up 0
52 52 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
53 53 $ mkcommit A2
54 54 created new head
55 55 $ hg debugobsolete `getid "desc(A0)" ` `getid "desc(A1)"`
56 56 $ hg debugobsolete `getid "desc(A1)" ` `getid "desc(A2)"`
57 57 $ hg log -G --hidden
58 58 @ c1f8d089020f (draft): A2
59 59 |
60 60 | x f6082bc4ffef (draft): A1
61 61 |/
62 62 | x 8aaa48160adc (draft): A0
63 63 |/
64 64 o 1e4be0697311 (public): root
65 65
66 66
67 67 Actual testing
68 68 --------------
69 69
70 70 $ hg push
71 71 pushing to $TESTTMP/A8/server (glob)
72 72 searching for changes
73 73 adding changesets
74 74 adding manifests
75 75 adding file changes
76 76 added 1 changesets with 1 changes to 1 files (+1 heads)
77 77 2 new obsolescence markers
78 obsoleted 1 changesets
78 79
79 80 $ cd ../..
@@ -1,122 +1,123 b''
1 1 ====================================
2 2 Testing head checking code: Case D-4
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category D: remote head is "obs-affected" locally, but result is not part of the push
12 12 TestCase 4: multi-changeset branch, split on multiple other, (base on its own new branch)
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 2 branch (1 changeset, and 2 changesets)
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * 1 new branch superceeding the base of the old-2-changesets-branch,
21 21 .. * 1 new changesets on the old-1-changeset-branch superceeding the head of the other
22 22 ..
23 23 .. expected-result:
24 24 ..
25 25 .. * push the new branch only -> push denied (variant a)
26 26 .. * push the existing branch only -> push allowed (variant b)
27 27 .. (pushing all is tested as case A-7)
28 28 ..
29 29 .. graph-summary:
30 30 ..
31 31 .. (variant a)
32 32 ..
33 33 .. B'○⇢ø B
34 34 .. | |
35 35 .. A | ø⇠◔ A'
36 36 .. | |/
37 37 .. C |
38 38 .. \|
39 39 ..
40 40 ..
41 41 .. or (variant b)
42 42 ..
43 43 .. B'◔⇢ø B
44 44 .. | |
45 45 .. A | ø⇠○ A'
46 46 .. | |/
47 47 .. C |
48 48 .. \|
49 49 ..
50 50
51 51 $ . $TESTDIR/testlib/push-checkheads-util.sh
52 52
53 53 Test setup
54 54 ----------
55 55
56 56 $ mkdir D4
57 57 $ cd D4
58 58 $ setuprepos
59 59 creating basic server and client repo
60 60 updating to branch default
61 61 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
62 62 $ cd server
63 63 $ mkcommit B0
64 64 $ hg up 0
65 65 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
66 66 $ mkcommit C0
67 67 created new head
68 68 $ cd ../client
69 69 $ hg pull
70 70 pulling from $TESTTMP/D4/server (glob)
71 71 searching for changes
72 72 adding changesets
73 73 adding manifests
74 74 adding file changes
75 75 added 2 changesets with 2 changes to 2 files (+1 heads)
76 76 (run 'hg heads' to see heads, 'hg merge' to merge)
77 77 $ hg up 0
78 78 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
79 79 $ mkcommit A1
80 80 created new head
81 81 $ hg up 'desc(C0)'
82 82 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
83 83 $ mkcommit B1
84 84 $ hg debugobsolete `getid "desc(A0)" ` `getid "desc(A1)"`
85 85 $ hg debugobsolete `getid "desc(B0)" ` `getid "desc(B1)"`
86 86 $ hg log -G --hidden
87 87 @ d70a1f75a020 (draft): B1
88 88 |
89 89 | o f6082bc4ffef (draft): A1
90 90 | |
91 91 o | 0f88766e02d6 (draft): C0
92 92 |/
93 93 | x d73caddc5533 (draft): B0
94 94 | |
95 95 | x 8aaa48160adc (draft): A0
96 96 |/
97 97 o 1e4be0697311 (public): root
98 98
99 99
100 100 Actual testing (new branch only)
101 101 --------------------------------
102 102
103 103 $ hg push --rev 'desc(A1)'
104 104 pushing to $TESTTMP/D4/server (glob)
105 105 searching for changes
106 106 abort: push creates new remote head f6082bc4ffef!
107 107 (merge or see 'hg help push' for details about pushing new heads)
108 108 [255]
109 109
110 110 Actual testing (existing branch only)
111 111 ------------------------------------
112 112
113 113 $ hg push --rev 'desc(B1)'
114 114 pushing to $TESTTMP/D4/server (glob)
115 115 searching for changes
116 116 adding changesets
117 117 adding manifests
118 118 adding file changes
119 119 added 1 changesets with 1 changes to 1 files
120 120 1 new obsolescence markers
121 obsoleted 1 changesets
121 122
122 123 $ cd ../..
@@ -1,107 +1,108 b''
1 1 ====================================
2 2 Testing head checking code: Case D-5
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category D: remote head is "obs-affected" locally, but result is not part of the push
12 12 TestCase 5: multi-changeset branch, split on multiple other, (head on its own new branch)
13 13
14 14 .. old-state:
15 15 ..
16 16 .. * 2 branch (1 changeset, and 2 changesets)
17 17 ..
18 18 .. new-state:
19 19 ..
20 20 .. * 1 new branch superceeding the head of the old-2-changesets-branch,
21 21 .. * 1 new changesets on the old-1-changeset-branch superceeding the base of the other
22 22 ..
23 23 .. expected-result:
24 24 ..
25 25 .. * push the new branch only -> push denied
26 26 .. * push the existing branch only -> push allowed
27 27 .. /!\ This push create unstability/orphaning on the other hand and we should
28 28 .. probably detect/warn agains that.
29 29 ..
30 30 .. graph-summary:
31 31 ..
32 32 .. B ø⇠◔ B'
33 33 .. | |
34 34 .. A'◔⇢ø |
35 35 .. | |/
36 36 .. C |
37 37 .. \|
38 38 ..
39 39
40 40 $ . $TESTDIR/testlib/push-checkheads-util.sh
41 41
42 42 Test setup
43 43 ----------
44 44
45 45 $ mkdir D5
46 46 $ cd D5
47 47 $ setuprepos
48 48 creating basic server and client repo
49 49 updating to branch default
50 50 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
51 51 $ cd server
52 52 $ mkcommit B0
53 53 $ hg up 0
54 54 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
55 55 $ mkcommit C0
56 56 created new head
57 57 $ cd ../client
58 58 $ hg pull
59 59 pulling from $TESTTMP/D5/server (glob)
60 60 searching for changes
61 61 adding changesets
62 62 adding manifests
63 63 adding file changes
64 64 added 2 changesets with 2 changes to 2 files (+1 heads)
65 65 (run 'hg heads' to see heads, 'hg merge' to merge)
66 66 $ hg up 'desc(C0)'
67 67 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
68 68 $ mkcommit A1
69 69 $ hg up 0
70 70 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
71 71 $ mkcommit B1
72 72 created new head
73 73 $ hg debugobsolete `getid "desc(A0)" ` `getid "desc(A1)"`
74 74 $ hg debugobsolete `getid "desc(B0)" ` `getid "desc(B1)"`
75 75 $ hg log -G --hidden
76 76 @ 25c56d33e4c4 (draft): B1
77 77 |
78 78 | o a0802eb7fc1b (draft): A1
79 79 | |
80 80 | o 0f88766e02d6 (draft): C0
81 81 |/
82 82 | x d73caddc5533 (draft): B0
83 83 | |
84 84 | x 8aaa48160adc (draft): A0
85 85 |/
86 86 o 1e4be0697311 (public): root
87 87
88 88
89 89 Actual testing
90 90 --------------
91 91
92 92 $ hg push --rev 'desc(B1)'
93 93 pushing to $TESTTMP/D5/server (glob)
94 94 searching for changes
95 95 abort: push creates new remote head 25c56d33e4c4!
96 96 (merge or see 'hg help push' for details about pushing new heads)
97 97 [255]
98 98 $ hg push --rev 'desc(A1)'
99 99 pushing to $TESTTMP/D5/server (glob)
100 100 searching for changes
101 101 adding changesets
102 102 adding manifests
103 103 adding file changes
104 104 added 1 changesets with 1 changes to 1 files
105 105 1 new obsolescence markers
106 obsoleted 1 changesets
106 107
107 108 $ cd ../..
@@ -1,96 +1,97 b''
1 1 ====================================
2 2 Testing head checking code: Case D-7
3 3 ====================================
4 4
5 5 Mercurial checks for the introduction of new heads on push. Evolution comes
6 6 into play to detect if existing branches on the server are being replaced by
7 7 some of the new one we push.
8 8
9 9 This case is part of a series of tests checking this behavior.
10 10
11 11 Category D: remote head is "obs-affected" locally, but result is not part of the push
12 12 TestCase 7: single changesets, superseeded multiple time then pruned (on a new changeset unpushed) changeset
13 13
14 14 This is a partial push variation of B6
15 15
16 16 .. old-state:
17 17 ..
18 18 .. * 1 changeset branch
19 19 ..
20 20 .. new-state:
21 21 ..
22 22 .. * old branch is rewritten onto another one,
23 23 .. * The rewriting it again rewritten on the root
24 24 .. * the new version is then pruned.
25 25 ..
26 26 .. expected-result:
27 27 ..
28 28 .. * push allowed
29 29 ..
30 30 .. graph-summary:
31 31 ..
32 32 .. A'
33 33 .. A ø⇠ø⇠⊗ A''
34 34 .. | | |
35 35 .. C ◔ | ◔ | B
36 36 .. \|/ /
37 37 .. | /
38 38 .. |/
39 39 .. |
40 40 .. ●
41 41
42 42 $ . $TESTDIR/testlib/push-checkheads-util.sh
43 43
44 44 Test setup
45 45 ----------
46 46
47 47 $ mkdir D7
48 48 $ cd D7
49 49 $ setuprepos
50 50 creating basic server and client repo
51 51 updating to branch default
52 52 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
53 53 $ cd client
54 54 $ hg up 0
55 55 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
56 56 $ mkcommit B0
57 57 created new head
58 58 $ mkcommit A1
59 59 $ hg up '0'
60 60 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
61 61 $ mkcommit A2
62 62 created new head
63 63 $ hg up '0'
64 64 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
65 65 $ mkcommit C0
66 66 created new head
67 67 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(A1)"`
68 68 $ hg debugobsolete `getid "desc(A1)"` `getid "desc(A2)"`
69 69 $ hg debugobsolete --record-parents `getid "desc(A2)"`
70 70 $ hg log -G --hidden
71 71 @ 0f88766e02d6 (draft): C0
72 72 |
73 73 | x c1f8d089020f (draft): A2
74 74 |/
75 75 | x ba93660aff8d (draft): A1
76 76 | |
77 77 | o 74ff5441d343 (draft): B0
78 78 |/
79 79 | x 8aaa48160adc (draft): A0
80 80 |/
81 81 o 1e4be0697311 (public): root
82 82
83 83
84 84 Actual testing
85 85 --------------
86 86
87 87 $ hg push --rev 'desc(C0)'
88 88 pushing to $TESTTMP/D7/server (glob)
89 89 searching for changes
90 90 adding changesets
91 91 adding manifests
92 92 adding file changes
93 93 added 1 changesets with 1 changes to 1 files (+1 heads)
94 94 3 new obsolescence markers
95 obsoleted 1 changesets
95 96
96 97 $ cd ../..
@@ -1,1839 +1,1842 b''
1 1 ============================================================================================
2 2 Test cases where there are race condition between two clients pushing to the same repository
3 3 ============================================================================================
4 4
5 5 This file tests cases where two clients push to a server at the same time. The
6 6 "raced" client is done preparing it push bundle when the "racing" client
7 7 perform its push. The "raced" client starts its actual push after the "racing"
8 8 client push is fully complete.
9 9
10 10 A set of extension and shell functions ensures this scheduling.
11 11
12 12 $ cat >> delaypush.py << EOF
13 13 > """small extension orchestrate push race
14 14 >
15 15 > Client with the extensions will create a file when ready and get stuck until
16 16 > a file is created."""
17 17 >
18 18 > import atexit
19 19 > import errno
20 20 > import os
21 21 > import time
22 22 >
23 23 > from mercurial import (
24 24 > exchange,
25 25 > extensions,
26 26 > )
27 27 >
28 28 > def delaypush(orig, pushop):
29 29 > # notify we are done preparing
30 30 > readypath = pushop.repo.ui.config('delaypush', 'ready-path', None)
31 31 > if readypath is not None:
32 32 > with open(readypath, 'w') as r:
33 33 > r.write('foo')
34 34 > pushop.repo.ui.status('wrote ready: %s\n' % readypath)
35 35 > # now wait for the other process to be done
36 36 > watchpath = pushop.repo.ui.config('delaypush', 'release-path', None)
37 37 > if watchpath is not None:
38 38 > pushop.repo.ui.status('waiting on: %s\n' % watchpath)
39 39 > limit = 100
40 40 > while 0 < limit and not os.path.exists(watchpath):
41 41 > limit -= 1
42 42 > time.sleep(0.1)
43 43 > if limit <= 0:
44 44 > repo.ui.warn('exiting without watchfile: %s' % watchpath)
45 45 > else:
46 46 > # delete the file at the end of the push
47 47 > def delete():
48 48 > try:
49 49 > os.unlink(watchpath)
50 50 > except OSError as exc:
51 51 > if exc.errno != errno.ENOENT:
52 52 > raise
53 53 > atexit.register(delete)
54 54 > return orig(pushop)
55 55 >
56 56 > def uisetup(ui):
57 57 > extensions.wrapfunction(exchange, '_pushbundle2', delaypush)
58 58 > EOF
59 59
60 60 $ waiton () {
61 61 > # wait for a file to be created (then delete it)
62 62 > count=100
63 63 > while [ ! -f $1 ] ;
64 64 > do
65 65 > sleep 0.1;
66 66 > count=`expr $count - 1`;
67 67 > if [ $count -lt 0 ];
68 68 > then
69 69 > break
70 70 > fi;
71 71 > done
72 72 > [ -f $1 ] || echo "ready file still missing: $1"
73 73 > rm -f $1
74 74 > }
75 75
76 76 $ release () {
77 77 > # create a file and wait for it be deleted
78 78 > count=100
79 79 > touch $1
80 80 > while [ -f $1 ] ;
81 81 > do
82 82 > sleep 0.1;
83 83 > count=`expr $count - 1`;
84 84 > if [ $count -lt 0 ];
85 85 > then
86 86 > break
87 87 > fi;
88 88 > done
89 89 > [ ! -f $1 ] || echo "delay file still exist: $1"
90 90 > }
91 91
92 92 $ cat >> $HGRCPATH << EOF
93 93 > [ui]
94 94 > ssh = python "$TESTDIR/dummyssh"
95 95 > # simplify output
96 96 > logtemplate = {node|short} {desc} ({branch})
97 97 > [phases]
98 98 > publish = no
99 99 > [experimental]
100 100 > evolution = all
101 101 > [alias]
102 102 > graph = log -G --rev 'sort(all(), "topo")'
103 103 > EOF
104 104
105 105 We tests multiple cases:
106 106 * strict: no race detected,
107 107 * unrelated: race on unrelated heads are allowed.
108 108
109 109 #testcases strict unrelated
110 110
111 111 #if unrelated
112 112
113 113 $ cat >> $HGRCPATH << EOF
114 114 > [server]
115 115 > concurrent-push-mode = check-related
116 116 > EOF
117 117
118 118 #endif
119 119
120 120 Setup
121 121 -----
122 122
123 123 create a repo with one root
124 124
125 125 $ hg init server
126 126 $ cd server
127 127 $ echo root > root
128 128 $ hg ci -Am "C-ROOT"
129 129 adding root
130 130 $ cd ..
131 131
132 132 clone it in two clients
133 133
134 134 $ hg clone ssh://user@dummy/server client-racy
135 135 requesting all changes
136 136 adding changesets
137 137 adding manifests
138 138 adding file changes
139 139 added 1 changesets with 1 changes to 1 files
140 140 updating to branch default
141 141 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 142 $ hg clone ssh://user@dummy/server client-other
143 143 requesting all changes
144 144 adding changesets
145 145 adding manifests
146 146 adding file changes
147 147 added 1 changesets with 1 changes to 1 files
148 148 updating to branch default
149 149 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
150 150
151 151 setup one to allow race on push
152 152
153 153 $ cat >> client-racy/.hg/hgrc << EOF
154 154 > [extensions]
155 155 > delaypush = $TESTTMP/delaypush.py
156 156 > [delaypush]
157 157 > ready-path = $TESTTMP/readyfile
158 158 > release-path = $TESTTMP/watchfile
159 159 > EOF
160 160
161 161 Simple race, both try to push to the server at the same time
162 162 ------------------------------------------------------------
163 163
164 164 Both try to replace the same head
165 165
166 166 # a
167 167 # | b
168 168 # |/
169 169 # *
170 170
171 171 Creating changesets
172 172
173 173 $ echo b > client-other/a
174 174 $ hg -R client-other/ add client-other/a
175 175 $ hg -R client-other/ commit -m "C-A"
176 176 $ echo b > client-racy/b
177 177 $ hg -R client-racy/ add client-racy/b
178 178 $ hg -R client-racy/ commit -m "C-B"
179 179
180 180 Pushing
181 181
182 182 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
183 183
184 184 $ waiton $TESTTMP/readyfile
185 185
186 186 $ hg -R client-other push -r 'tip'
187 187 pushing to ssh://user@dummy/server
188 188 searching for changes
189 189 remote: adding changesets
190 190 remote: adding manifests
191 191 remote: adding file changes
192 192 remote: added 1 changesets with 1 changes to 1 files
193 193
194 194 $ release $TESTTMP/watchfile
195 195
196 196 Check the result of the push
197 197
198 198 $ cat ./push-log
199 199 pushing to ssh://user@dummy/server
200 200 searching for changes
201 201 wrote ready: $TESTTMP/readyfile
202 202 waiting on: $TESTTMP/watchfile
203 203 abort: push failed:
204 204 'repository changed while pushing - please try again'
205 205
206 206 $ hg -R server graph
207 207 o 98217d5a1659 C-A (default)
208 208 |
209 209 @ 842e2fac6304 C-ROOT (default)
210 210
211 211
212 212 Pushing on two different heads
213 213 ------------------------------
214 214
215 215 Both try to replace a different head
216 216
217 217 # a b
218 218 # | |
219 219 # * *
220 220 # |/
221 221 # *
222 222
223 223 (resync-all)
224 224
225 225 $ hg -R ./server pull ./client-racy
226 226 pulling from ./client-racy
227 227 searching for changes
228 228 adding changesets
229 229 adding manifests
230 230 adding file changes
231 231 added 1 changesets with 1 changes to 1 files (+1 heads)
232 232 (run 'hg heads' to see heads, 'hg merge' to merge)
233 233 $ hg -R ./client-other pull
234 234 pulling from ssh://user@dummy/server
235 235 searching for changes
236 236 adding changesets
237 237 adding manifests
238 238 adding file changes
239 239 added 1 changesets with 1 changes to 1 files (+1 heads)
240 240 (run 'hg heads' to see heads, 'hg merge' to merge)
241 241 $ hg -R ./client-racy pull
242 242 pulling from ssh://user@dummy/server
243 243 searching for changes
244 244 adding changesets
245 245 adding manifests
246 246 adding file changes
247 247 added 1 changesets with 1 changes to 1 files (+1 heads)
248 248 (run 'hg heads' to see heads, 'hg merge' to merge)
249 249
250 250 $ hg -R server graph
251 251 o a9149a1428e2 C-B (default)
252 252 |
253 253 | o 98217d5a1659 C-A (default)
254 254 |/
255 255 @ 842e2fac6304 C-ROOT (default)
256 256
257 257
258 258 Creating changesets
259 259
260 260 $ echo aa >> client-other/a
261 261 $ hg -R client-other/ commit -m "C-C"
262 262 $ echo bb >> client-racy/b
263 263 $ hg -R client-racy/ commit -m "C-D"
264 264
265 265 Pushing
266 266
267 267 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
268 268
269 269 $ waiton $TESTTMP/readyfile
270 270
271 271 $ hg -R client-other push -r 'tip'
272 272 pushing to ssh://user@dummy/server
273 273 searching for changes
274 274 remote: adding changesets
275 275 remote: adding manifests
276 276 remote: adding file changes
277 277 remote: added 1 changesets with 1 changes to 1 files
278 278
279 279 $ release $TESTTMP/watchfile
280 280
281 281 Check the result of the push
282 282
283 283 #if strict
284 284 $ cat ./push-log
285 285 pushing to ssh://user@dummy/server
286 286 searching for changes
287 287 wrote ready: $TESTTMP/readyfile
288 288 waiting on: $TESTTMP/watchfile
289 289 abort: push failed:
290 290 'repository changed while pushing - please try again'
291 291
292 292 $ hg -R server graph
293 293 o 51c544a58128 C-C (default)
294 294 |
295 295 o 98217d5a1659 C-A (default)
296 296 |
297 297 | o a9149a1428e2 C-B (default)
298 298 |/
299 299 @ 842e2fac6304 C-ROOT (default)
300 300
301 301 #endif
302 302 #if unrelated
303 303
304 304 (The two heads are unrelated, push should be allowed)
305 305
306 306 $ cat ./push-log
307 307 pushing to ssh://user@dummy/server
308 308 searching for changes
309 309 wrote ready: $TESTTMP/readyfile
310 310 waiting on: $TESTTMP/watchfile
311 311 remote: adding changesets
312 312 remote: adding manifests
313 313 remote: adding file changes
314 314 remote: added 1 changesets with 1 changes to 1 files
315 315
316 316 $ hg -R server graph
317 317 o 59e76faf78bd C-D (default)
318 318 |
319 319 o a9149a1428e2 C-B (default)
320 320 |
321 321 | o 51c544a58128 C-C (default)
322 322 | |
323 323 | o 98217d5a1659 C-A (default)
324 324 |/
325 325 @ 842e2fac6304 C-ROOT (default)
326 326
327 327 #endif
328 328
329 329 Pushing while someone creates a new head
330 330 -----------------------------------------
331 331
332 332 Pushing a new changeset while someone creates a new branch.
333 333
334 334 # a (raced)
335 335 # |
336 336 # * b
337 337 # |/
338 338 # *
339 339
340 340 (resync-all)
341 341
342 342 #if strict
343 343
344 344 $ hg -R ./server pull ./client-racy
345 345 pulling from ./client-racy
346 346 searching for changes
347 347 adding changesets
348 348 adding manifests
349 349 adding file changes
350 350 added 1 changesets with 1 changes to 1 files
351 351 (run 'hg update' to get a working copy)
352 352
353 353 #endif
354 354 #if unrelated
355 355
356 356 $ hg -R ./server pull ./client-racy
357 357 pulling from ./client-racy
358 358 searching for changes
359 359 no changes found
360 360
361 361 #endif
362 362
363 363 $ hg -R ./client-other pull
364 364 pulling from ssh://user@dummy/server
365 365 searching for changes
366 366 adding changesets
367 367 adding manifests
368 368 adding file changes
369 369 added 1 changesets with 1 changes to 1 files
370 370 (run 'hg update' to get a working copy)
371 371 $ hg -R ./client-racy pull
372 372 pulling from ssh://user@dummy/server
373 373 searching for changes
374 374 adding changesets
375 375 adding manifests
376 376 adding file changes
377 377 added 1 changesets with 1 changes to 1 files
378 378 (run 'hg update' to get a working copy)
379 379
380 380 $ hg -R server graph
381 381 o 59e76faf78bd C-D (default)
382 382 |
383 383 o a9149a1428e2 C-B (default)
384 384 |
385 385 | o 51c544a58128 C-C (default)
386 386 | |
387 387 | o 98217d5a1659 C-A (default)
388 388 |/
389 389 @ 842e2fac6304 C-ROOT (default)
390 390
391 391
392 392 Creating changesets
393 393
394 394 (new head)
395 395
396 396 $ hg -R client-other/ up 'desc("C-A")'
397 397 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
398 398 $ echo aaa >> client-other/a
399 399 $ hg -R client-other/ commit -m "C-E"
400 400 created new head
401 401
402 402 (children of existing head)
403 403
404 404 $ hg -R client-racy/ up 'desc("C-C")'
405 405 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
406 406 $ echo bbb >> client-racy/a
407 407 $ hg -R client-racy/ commit -m "C-F"
408 408
409 409 Pushing
410 410
411 411 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
412 412
413 413 $ waiton $TESTTMP/readyfile
414 414
415 415 $ hg -R client-other push -fr 'tip'
416 416 pushing to ssh://user@dummy/server
417 417 searching for changes
418 418 remote: adding changesets
419 419 remote: adding manifests
420 420 remote: adding file changes
421 421 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
422 422
423 423 $ release $TESTTMP/watchfile
424 424
425 425 Check the result of the push
426 426
427 427 #if strict
428 428
429 429 $ cat ./push-log
430 430 pushing to ssh://user@dummy/server
431 431 searching for changes
432 432 wrote ready: $TESTTMP/readyfile
433 433 waiting on: $TESTTMP/watchfile
434 434 abort: push failed:
435 435 'repository changed while pushing - please try again'
436 436
437 437 $ hg -R server graph
438 438 o d603e2c0cdd7 C-E (default)
439 439 |
440 440 | o 51c544a58128 C-C (default)
441 441 |/
442 442 o 98217d5a1659 C-A (default)
443 443 |
444 444 | o 59e76faf78bd C-D (default)
445 445 | |
446 446 | o a9149a1428e2 C-B (default)
447 447 |/
448 448 @ 842e2fac6304 C-ROOT (default)
449 449
450 450
451 451 #endif
452 452
453 453 #if unrelated
454 454
455 455 (The racing new head do not affect existing heads, push should go through)
456 456
457 457 $ cat ./push-log
458 458 pushing to ssh://user@dummy/server
459 459 searching for changes
460 460 wrote ready: $TESTTMP/readyfile
461 461 waiting on: $TESTTMP/watchfile
462 462 remote: adding changesets
463 463 remote: adding manifests
464 464 remote: adding file changes
465 465 remote: added 1 changesets with 1 changes to 1 files
466 466
467 467 $ hg -R server graph
468 468 o d9e379a8c432 C-F (default)
469 469 |
470 470 o 51c544a58128 C-C (default)
471 471 |
472 472 | o d603e2c0cdd7 C-E (default)
473 473 |/
474 474 o 98217d5a1659 C-A (default)
475 475 |
476 476 | o 59e76faf78bd C-D (default)
477 477 | |
478 478 | o a9149a1428e2 C-B (default)
479 479 |/
480 480 @ 842e2fac6304 C-ROOT (default)
481 481
482 482 #endif
483 483
484 484 Pushing touching different named branch (same topo): new branch raced
485 485 ---------------------------------------------------------------------
486 486
487 487 Pushing two children on the same head, one is a different named branch
488 488
489 489 # a (raced, branch-a)
490 490 # |
491 491 # | b (default branch)
492 492 # |/
493 493 # *
494 494
495 495 (resync-all)
496 496
497 497 #if strict
498 498
499 499 $ hg -R ./server pull ./client-racy
500 500 pulling from ./client-racy
501 501 searching for changes
502 502 adding changesets
503 503 adding manifests
504 504 adding file changes
505 505 added 1 changesets with 1 changes to 1 files
506 506 (run 'hg update' to get a working copy)
507 507
508 508 #endif
509 509 #if unrelated
510 510
511 511 $ hg -R ./server pull ./client-racy
512 512 pulling from ./client-racy
513 513 searching for changes
514 514 no changes found
515 515
516 516 #endif
517 517
518 518 $ hg -R ./client-other pull
519 519 pulling from ssh://user@dummy/server
520 520 searching for changes
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 (run 'hg update' to get a working copy)
526 526 $ hg -R ./client-racy pull
527 527 pulling from ssh://user@dummy/server
528 528 searching for changes
529 529 adding changesets
530 530 adding manifests
531 531 adding file changes
532 532 added 1 changesets with 1 changes to 1 files (+1 heads)
533 533 (run 'hg heads .' to see heads, 'hg merge' to merge)
534 534
535 535 $ hg -R server graph
536 536 o d9e379a8c432 C-F (default)
537 537 |
538 538 o 51c544a58128 C-C (default)
539 539 |
540 540 | o d603e2c0cdd7 C-E (default)
541 541 |/
542 542 o 98217d5a1659 C-A (default)
543 543 |
544 544 | o 59e76faf78bd C-D (default)
545 545 | |
546 546 | o a9149a1428e2 C-B (default)
547 547 |/
548 548 @ 842e2fac6304 C-ROOT (default)
549 549
550 550
551 551 Creating changesets
552 552
553 553 (update existing head)
554 554
555 555 $ hg -R client-other/ up 'desc("C-F")'
556 556 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
557 557 $ echo aaa >> client-other/a
558 558 $ hg -R client-other/ commit -m "C-G"
559 559
560 560 (new named branch from that existing head)
561 561
562 562 $ hg -R client-racy/ up 'desc("C-F")'
563 563 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
564 564 $ echo bbb >> client-racy/a
565 565 $ hg -R client-racy/ branch my-first-test-branch
566 566 marked working directory as branch my-first-test-branch
567 567 (branches are permanent and global, did you want a bookmark?)
568 568 $ hg -R client-racy/ commit -m "C-H"
569 569
570 570 Pushing
571 571
572 572 $ hg -R client-racy push -r 'tip' --new-branch > ./push-log 2>&1 &
573 573
574 574 $ waiton $TESTTMP/readyfile
575 575
576 576 $ hg -R client-other push -fr 'tip'
577 577 pushing to ssh://user@dummy/server
578 578 searching for changes
579 579 remote: adding changesets
580 580 remote: adding manifests
581 581 remote: adding file changes
582 582 remote: added 1 changesets with 1 changes to 1 files
583 583
584 584 $ release $TESTTMP/watchfile
585 585
586 586 Check the result of the push
587 587
588 588 #if strict
589 589 $ cat ./push-log
590 590 pushing to ssh://user@dummy/server
591 591 searching for changes
592 592 wrote ready: $TESTTMP/readyfile
593 593 waiting on: $TESTTMP/watchfile
594 594 abort: push failed:
595 595 'repository changed while pushing - please try again'
596 596
597 597 $ hg -R server graph
598 598 o 75d69cba5402 C-G (default)
599 599 |
600 600 o d9e379a8c432 C-F (default)
601 601 |
602 602 o 51c544a58128 C-C (default)
603 603 |
604 604 | o d603e2c0cdd7 C-E (default)
605 605 |/
606 606 o 98217d5a1659 C-A (default)
607 607 |
608 608 | o 59e76faf78bd C-D (default)
609 609 | |
610 610 | o a9149a1428e2 C-B (default)
611 611 |/
612 612 @ 842e2fac6304 C-ROOT (default)
613 613
614 614 #endif
615 615 #if unrelated
616 616
617 617 (unrelated named branches are unrelated)
618 618
619 619 $ cat ./push-log
620 620 pushing to ssh://user@dummy/server
621 621 searching for changes
622 622 wrote ready: $TESTTMP/readyfile
623 623 waiting on: $TESTTMP/watchfile
624 624 remote: adding changesets
625 625 remote: adding manifests
626 626 remote: adding file changes
627 627 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
628 628
629 629 $ hg -R server graph
630 630 o 833be552cfe6 C-H (my-first-test-branch)
631 631 |
632 632 | o 75d69cba5402 C-G (default)
633 633 |/
634 634 o d9e379a8c432 C-F (default)
635 635 |
636 636 o 51c544a58128 C-C (default)
637 637 |
638 638 | o d603e2c0cdd7 C-E (default)
639 639 |/
640 640 o 98217d5a1659 C-A (default)
641 641 |
642 642 | o 59e76faf78bd C-D (default)
643 643 | |
644 644 | o a9149a1428e2 C-B (default)
645 645 |/
646 646 @ 842e2fac6304 C-ROOT (default)
647 647
648 648 #endif
649 649
650 650 The racing new head do not affect existing heads, push should go through
651 651
652 652 pushing touching different named branch (same topo): old branch raced
653 653 ---------------------------------------------------------------------
654 654
655 655 Pushing two children on the same head, one is a different named branch
656 656
657 657 # a (raced, default-branch)
658 658 # |
659 659 # | b (new branch)
660 660 # |/
661 661 # * (default-branch)
662 662
663 663 (resync-all)
664 664
665 665 #if strict
666 666
667 667 $ hg -R ./server pull ./client-racy
668 668 pulling from ./client-racy
669 669 searching for changes
670 670 adding changesets
671 671 adding manifests
672 672 adding file changes
673 673 added 1 changesets with 1 changes to 1 files (+1 heads)
674 674 (run 'hg heads .' to see heads, 'hg merge' to merge)
675 675
676 676 #endif
677 677 #if unrelated
678 678
679 679 $ hg -R ./server pull ./client-racy
680 680 pulling from ./client-racy
681 681 searching for changes
682 682 no changes found
683 683
684 684 #endif
685 685
686 686 $ hg -R ./client-other pull
687 687 pulling from ssh://user@dummy/server
688 688 searching for changes
689 689 adding changesets
690 690 adding manifests
691 691 adding file changes
692 692 added 1 changesets with 1 changes to 1 files (+1 heads)
693 693 (run 'hg heads .' to see heads, 'hg merge' to merge)
694 694 $ hg -R ./client-racy pull
695 695 pulling from ssh://user@dummy/server
696 696 searching for changes
697 697 adding changesets
698 698 adding manifests
699 699 adding file changes
700 700 added 1 changesets with 1 changes to 1 files (+1 heads)
701 701 (run 'hg heads' to see heads)
702 702
703 703 $ hg -R server graph
704 704 o 833be552cfe6 C-H (my-first-test-branch)
705 705 |
706 706 | o 75d69cba5402 C-G (default)
707 707 |/
708 708 o d9e379a8c432 C-F (default)
709 709 |
710 710 o 51c544a58128 C-C (default)
711 711 |
712 712 | o d603e2c0cdd7 C-E (default)
713 713 |/
714 714 o 98217d5a1659 C-A (default)
715 715 |
716 716 | o 59e76faf78bd C-D (default)
717 717 | |
718 718 | o a9149a1428e2 C-B (default)
719 719 |/
720 720 @ 842e2fac6304 C-ROOT (default)
721 721
722 722
723 723 Creating changesets
724 724
725 725 (new named branch from one head)
726 726
727 727 $ hg -R client-other/ up 'desc("C-G")'
728 728 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
729 729 $ echo aaa >> client-other/a
730 730 $ hg -R client-other/ branch my-second-test-branch
731 731 marked working directory as branch my-second-test-branch
732 732 $ hg -R client-other/ commit -m "C-I"
733 733
734 734 (children "updating" that same head)
735 735
736 736 $ hg -R client-racy/ up 'desc("C-G")'
737 737 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
738 738 $ echo bbb >> client-racy/a
739 739 $ hg -R client-racy/ commit -m "C-J"
740 740
741 741 Pushing
742 742
743 743 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
744 744
745 745 $ waiton $TESTTMP/readyfile
746 746
747 747 $ hg -R client-other push -fr 'tip' --new-branch
748 748 pushing to ssh://user@dummy/server
749 749 searching for changes
750 750 remote: adding changesets
751 751 remote: adding manifests
752 752 remote: adding file changes
753 753 remote: added 1 changesets with 1 changes to 1 files
754 754
755 755 $ release $TESTTMP/watchfile
756 756
757 757 Check the result of the push
758 758
759 759 #if strict
760 760
761 761 $ cat ./push-log
762 762 pushing to ssh://user@dummy/server
763 763 searching for changes
764 764 wrote ready: $TESTTMP/readyfile
765 765 waiting on: $TESTTMP/watchfile
766 766 abort: push failed:
767 767 'repository changed while pushing - please try again'
768 768
769 769 $ hg -R server graph
770 770 o b35ed749f288 C-I (my-second-test-branch)
771 771 |
772 772 o 75d69cba5402 C-G (default)
773 773 |
774 774 | o 833be552cfe6 C-H (my-first-test-branch)
775 775 |/
776 776 o d9e379a8c432 C-F (default)
777 777 |
778 778 o 51c544a58128 C-C (default)
779 779 |
780 780 | o d603e2c0cdd7 C-E (default)
781 781 |/
782 782 o 98217d5a1659 C-A (default)
783 783 |
784 784 | o 59e76faf78bd C-D (default)
785 785 | |
786 786 | o a9149a1428e2 C-B (default)
787 787 |/
788 788 @ 842e2fac6304 C-ROOT (default)
789 789
790 790
791 791 #endif
792 792
793 793 #if unrelated
794 794
795 795 (unrelated named branches are unrelated)
796 796
797 797 $ cat ./push-log
798 798 pushing to ssh://user@dummy/server
799 799 searching for changes
800 800 wrote ready: $TESTTMP/readyfile
801 801 waiting on: $TESTTMP/watchfile
802 802 remote: adding changesets
803 803 remote: adding manifests
804 804 remote: adding file changes
805 805 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
806 806
807 807 $ hg -R server graph
808 808 o 89420bf00fae C-J (default)
809 809 |
810 810 | o b35ed749f288 C-I (my-second-test-branch)
811 811 |/
812 812 o 75d69cba5402 C-G (default)
813 813 |
814 814 | o 833be552cfe6 C-H (my-first-test-branch)
815 815 |/
816 816 o d9e379a8c432 C-F (default)
817 817 |
818 818 o 51c544a58128 C-C (default)
819 819 |
820 820 | o d603e2c0cdd7 C-E (default)
821 821 |/
822 822 o 98217d5a1659 C-A (default)
823 823 |
824 824 | o 59e76faf78bd C-D (default)
825 825 | |
826 826 | o a9149a1428e2 C-B (default)
827 827 |/
828 828 @ 842e2fac6304 C-ROOT (default)
829 829
830 830
831 831 #endif
832 832
833 833 pushing racing push touch multiple heads
834 834 ----------------------------------------
835 835
836 836 There are multiple heads, but the racing push touch all of them
837 837
838 838 # a (raced)
839 839 # | b
840 840 # |/|
841 841 # * *
842 842 # |/
843 843 # *
844 844
845 845 (resync-all)
846 846
847 847 #if strict
848 848
849 849 $ hg -R ./server pull ./client-racy
850 850 pulling from ./client-racy
851 851 searching for changes
852 852 adding changesets
853 853 adding manifests
854 854 adding file changes
855 855 added 1 changesets with 1 changes to 1 files (+1 heads)
856 856 (run 'hg heads .' to see heads, 'hg merge' to merge)
857 857
858 858 #endif
859 859
860 860 #if unrelated
861 861
862 862 $ hg -R ./server pull ./client-racy
863 863 pulling from ./client-racy
864 864 searching for changes
865 865 no changes found
866 866
867 867 #endif
868 868
869 869 $ hg -R ./client-other pull
870 870 pulling from ssh://user@dummy/server
871 871 searching for changes
872 872 adding changesets
873 873 adding manifests
874 874 adding file changes
875 875 added 1 changesets with 1 changes to 1 files (+1 heads)
876 876 (run 'hg heads' to see heads)
877 877 $ hg -R ./client-racy pull
878 878 pulling from ssh://user@dummy/server
879 879 searching for changes
880 880 adding changesets
881 881 adding manifests
882 882 adding file changes
883 883 added 1 changesets with 1 changes to 1 files (+1 heads)
884 884 (run 'hg heads .' to see heads, 'hg merge' to merge)
885 885
886 886 $ hg -R server graph
887 887 o 89420bf00fae C-J (default)
888 888 |
889 889 | o b35ed749f288 C-I (my-second-test-branch)
890 890 |/
891 891 o 75d69cba5402 C-G (default)
892 892 |
893 893 | o 833be552cfe6 C-H (my-first-test-branch)
894 894 |/
895 895 o d9e379a8c432 C-F (default)
896 896 |
897 897 o 51c544a58128 C-C (default)
898 898 |
899 899 | o d603e2c0cdd7 C-E (default)
900 900 |/
901 901 o 98217d5a1659 C-A (default)
902 902 |
903 903 | o 59e76faf78bd C-D (default)
904 904 | |
905 905 | o a9149a1428e2 C-B (default)
906 906 |/
907 907 @ 842e2fac6304 C-ROOT (default)
908 908
909 909
910 910 Creating changesets
911 911
912 912 (merges heads)
913 913
914 914 $ hg -R client-other/ up 'desc("C-E")'
915 915 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
916 916 $ hg -R client-other/ merge 'desc("C-D")'
917 917 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
918 918 (branch merge, don't forget to commit)
919 919 $ hg -R client-other/ commit -m "C-K"
920 920
921 921 (update one head)
922 922
923 923 $ hg -R client-racy/ up 'desc("C-D")'
924 924 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
925 925 $ echo bbb >> client-racy/b
926 926 $ hg -R client-racy/ commit -m "C-L"
927 927
928 928 Pushing
929 929
930 930 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
931 931
932 932 $ waiton $TESTTMP/readyfile
933 933
934 934 $ hg -R client-other push -fr 'tip' --new-branch
935 935 pushing to ssh://user@dummy/server
936 936 searching for changes
937 937 remote: adding changesets
938 938 remote: adding manifests
939 939 remote: adding file changes
940 940 remote: added 1 changesets with 0 changes to 0 files (-1 heads)
941 941
942 942 $ release $TESTTMP/watchfile
943 943
944 944 Check the result of the push
945 945
946 946 $ cat ./push-log
947 947 pushing to ssh://user@dummy/server
948 948 searching for changes
949 949 wrote ready: $TESTTMP/readyfile
950 950 waiting on: $TESTTMP/watchfile
951 951 abort: push failed:
952 952 'repository changed while pushing - please try again'
953 953
954 954 $ hg -R server graph
955 955 o be705100c623 C-K (default)
956 956 |\
957 957 | o d603e2c0cdd7 C-E (default)
958 958 | |
959 959 o | 59e76faf78bd C-D (default)
960 960 | |
961 961 | | o 89420bf00fae C-J (default)
962 962 | | |
963 963 | | | o b35ed749f288 C-I (my-second-test-branch)
964 964 | | |/
965 965 | | o 75d69cba5402 C-G (default)
966 966 | | |
967 967 | | | o 833be552cfe6 C-H (my-first-test-branch)
968 968 | | |/
969 969 | | o d9e379a8c432 C-F (default)
970 970 | | |
971 971 | | o 51c544a58128 C-C (default)
972 972 | |/
973 973 o | a9149a1428e2 C-B (default)
974 974 | |
975 975 | o 98217d5a1659 C-A (default)
976 976 |/
977 977 @ 842e2fac6304 C-ROOT (default)
978 978
979 979
980 980 pushing raced push touch multiple heads
981 981 ---------------------------------------
982 982
983 983 There are multiple heads, the raced push touch all of them
984 984
985 985 # b
986 986 # | a (raced)
987 987 # |/|
988 988 # * *
989 989 # |/
990 990 # *
991 991
992 992 (resync-all)
993 993
994 994 $ hg -R ./server pull ./client-racy
995 995 pulling from ./client-racy
996 996 searching for changes
997 997 adding changesets
998 998 adding manifests
999 999 adding file changes
1000 1000 added 1 changesets with 1 changes to 1 files (+1 heads)
1001 1001 (run 'hg heads .' to see heads, 'hg merge' to merge)
1002 1002 $ hg -R ./client-other pull
1003 1003 pulling from ssh://user@dummy/server
1004 1004 searching for changes
1005 1005 adding changesets
1006 1006 adding manifests
1007 1007 adding file changes
1008 1008 added 1 changesets with 1 changes to 1 files (+1 heads)
1009 1009 (run 'hg heads .' to see heads, 'hg merge' to merge)
1010 1010 $ hg -R ./client-racy pull
1011 1011 pulling from ssh://user@dummy/server
1012 1012 searching for changes
1013 1013 adding changesets
1014 1014 adding manifests
1015 1015 adding file changes
1016 1016 added 1 changesets with 0 changes to 0 files
1017 1017 (run 'hg update' to get a working copy)
1018 1018
1019 1019 $ hg -R server graph
1020 1020 o cac2cead0ff0 C-L (default)
1021 1021 |
1022 1022 | o be705100c623 C-K (default)
1023 1023 |/|
1024 1024 | o d603e2c0cdd7 C-E (default)
1025 1025 | |
1026 1026 o | 59e76faf78bd C-D (default)
1027 1027 | |
1028 1028 | | o 89420bf00fae C-J (default)
1029 1029 | | |
1030 1030 | | | o b35ed749f288 C-I (my-second-test-branch)
1031 1031 | | |/
1032 1032 | | o 75d69cba5402 C-G (default)
1033 1033 | | |
1034 1034 | | | o 833be552cfe6 C-H (my-first-test-branch)
1035 1035 | | |/
1036 1036 | | o d9e379a8c432 C-F (default)
1037 1037 | | |
1038 1038 | | o 51c544a58128 C-C (default)
1039 1039 | |/
1040 1040 o | a9149a1428e2 C-B (default)
1041 1041 | |
1042 1042 | o 98217d5a1659 C-A (default)
1043 1043 |/
1044 1044 @ 842e2fac6304 C-ROOT (default)
1045 1045
1046 1046
1047 1047 Creating changesets
1048 1048
1049 1049 (update existing head)
1050 1050
1051 1051 $ echo aaa >> client-other/a
1052 1052 $ hg -R client-other/ commit -m "C-M"
1053 1053
1054 1054 (merge heads)
1055 1055
1056 1056 $ hg -R client-racy/ merge 'desc("C-K")'
1057 1057 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1058 1058 (branch merge, don't forget to commit)
1059 1059 $ hg -R client-racy/ commit -m "C-N"
1060 1060
1061 1061 Pushing
1062 1062
1063 1063 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1064 1064
1065 1065 $ waiton $TESTTMP/readyfile
1066 1066
1067 1067 $ hg -R client-other push -fr 'tip' --new-branch
1068 1068 pushing to ssh://user@dummy/server
1069 1069 searching for changes
1070 1070 remote: adding changesets
1071 1071 remote: adding manifests
1072 1072 remote: adding file changes
1073 1073 remote: added 1 changesets with 1 changes to 1 files
1074 1074
1075 1075 $ release $TESTTMP/watchfile
1076 1076
1077 1077 Check the result of the push
1078 1078
1079 1079 $ cat ./push-log
1080 1080 pushing to ssh://user@dummy/server
1081 1081 searching for changes
1082 1082 wrote ready: $TESTTMP/readyfile
1083 1083 waiting on: $TESTTMP/watchfile
1084 1084 abort: push failed:
1085 1085 'repository changed while pushing - please try again'
1086 1086
1087 1087 $ hg -R server graph
1088 1088 o 6fd3090135df C-M (default)
1089 1089 |
1090 1090 o be705100c623 C-K (default)
1091 1091 |\
1092 1092 | o d603e2c0cdd7 C-E (default)
1093 1093 | |
1094 1094 +---o cac2cead0ff0 C-L (default)
1095 1095 | |
1096 1096 o | 59e76faf78bd C-D (default)
1097 1097 | |
1098 1098 | | o 89420bf00fae C-J (default)
1099 1099 | | |
1100 1100 | | | o b35ed749f288 C-I (my-second-test-branch)
1101 1101 | | |/
1102 1102 | | o 75d69cba5402 C-G (default)
1103 1103 | | |
1104 1104 | | | o 833be552cfe6 C-H (my-first-test-branch)
1105 1105 | | |/
1106 1106 | | o d9e379a8c432 C-F (default)
1107 1107 | | |
1108 1108 | | o 51c544a58128 C-C (default)
1109 1109 | |/
1110 1110 o | a9149a1428e2 C-B (default)
1111 1111 | |
1112 1112 | o 98217d5a1659 C-A (default)
1113 1113 |/
1114 1114 @ 842e2fac6304 C-ROOT (default)
1115 1115
1116 1116
1117 1117 racing commit push a new head behind another named branch
1118 1118 ---------------------------------------------------------
1119 1119
1120 1120 non-continuous branch are valid case, we tests for them.
1121 1121
1122 1122 # b (branch default)
1123 1123 # |
1124 1124 # o (branch foo)
1125 1125 # |
1126 1126 # | a (raced, branch default)
1127 1127 # |/
1128 1128 # * (branch foo)
1129 1129 # |
1130 1130 # * (branch default)
1131 1131
1132 1132 (resync-all + other branch)
1133 1133
1134 1134 $ hg -R ./server pull ./client-racy
1135 1135 pulling from ./client-racy
1136 1136 searching for changes
1137 1137 adding changesets
1138 1138 adding manifests
1139 1139 adding file changes
1140 1140 added 1 changesets with 0 changes to 0 files
1141 1141 (run 'hg update' to get a working copy)
1142 1142
1143 1143 (creates named branch on head)
1144 1144
1145 1145 $ hg -R ./server/ up 'desc("C-N")'
1146 1146 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1147 1147 $ hg -R ./server/ branch other
1148 1148 marked working directory as branch other
1149 1149 $ hg -R ./server/ ci -m "C-Z"
1150 1150 $ hg -R ./server/ up null
1151 1151 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
1152 1152
1153 1153 (sync client)
1154 1154
1155 1155 $ hg -R ./client-other pull
1156 1156 pulling from ssh://user@dummy/server
1157 1157 searching for changes
1158 1158 adding changesets
1159 1159 adding manifests
1160 1160 adding file changes
1161 1161 added 2 changesets with 0 changes to 0 files
1162 1162 (run 'hg update' to get a working copy)
1163 1163 $ hg -R ./client-racy pull
1164 1164 pulling from ssh://user@dummy/server
1165 1165 searching for changes
1166 1166 adding changesets
1167 1167 adding manifests
1168 1168 adding file changes
1169 1169 added 2 changesets with 1 changes to 1 files (+1 heads)
1170 1170 (run 'hg heads .' to see heads, 'hg merge' to merge)
1171 1171
1172 1172 $ hg -R server graph
1173 1173 o 55a6f1c01b48 C-Z (other)
1174 1174 |
1175 1175 o 866a66e18630 C-N (default)
1176 1176 |\
1177 1177 +---o 6fd3090135df C-M (default)
1178 1178 | |
1179 1179 | o cac2cead0ff0 C-L (default)
1180 1180 | |
1181 1181 o | be705100c623 C-K (default)
1182 1182 |\|
1183 1183 o | d603e2c0cdd7 C-E (default)
1184 1184 | |
1185 1185 | o 59e76faf78bd C-D (default)
1186 1186 | |
1187 1187 | | o 89420bf00fae C-J (default)
1188 1188 | | |
1189 1189 | | | o b35ed749f288 C-I (my-second-test-branch)
1190 1190 | | |/
1191 1191 | | o 75d69cba5402 C-G (default)
1192 1192 | | |
1193 1193 | | | o 833be552cfe6 C-H (my-first-test-branch)
1194 1194 | | |/
1195 1195 | | o d9e379a8c432 C-F (default)
1196 1196 | | |
1197 1197 +---o 51c544a58128 C-C (default)
1198 1198 | |
1199 1199 | o a9149a1428e2 C-B (default)
1200 1200 | |
1201 1201 o | 98217d5a1659 C-A (default)
1202 1202 |/
1203 1203 o 842e2fac6304 C-ROOT (default)
1204 1204
1205 1205
1206 1206 Creating changesets
1207 1207
1208 1208 (update default head through another named branch one)
1209 1209
1210 1210 $ hg -R client-other/ up 'desc("C-Z")'
1211 1211 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1212 1212 $ echo aaa >> client-other/a
1213 1213 $ hg -R client-other/ commit -m "C-O"
1214 1214 $ echo aaa >> client-other/a
1215 1215 $ hg -R client-other/ branch --force default
1216 1216 marked working directory as branch default
1217 1217 $ hg -R client-other/ commit -m "C-P"
1218 1218 created new head
1219 1219
1220 1220 (update default head)
1221 1221
1222 1222 $ hg -R client-racy/ up 'desc("C-Z")'
1223 1223 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1224 1224 $ echo bbb >> client-other/a
1225 1225 $ hg -R client-racy/ branch --force default
1226 1226 marked working directory as branch default
1227 1227 $ hg -R client-racy/ commit -m "C-Q"
1228 1228 created new head
1229 1229
1230 1230 Pushing
1231 1231
1232 1232 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1233 1233
1234 1234 $ waiton $TESTTMP/readyfile
1235 1235
1236 1236 $ hg -R client-other push -fr 'tip' --new-branch
1237 1237 pushing to ssh://user@dummy/server
1238 1238 searching for changes
1239 1239 remote: adding changesets
1240 1240 remote: adding manifests
1241 1241 remote: adding file changes
1242 1242 remote: added 2 changesets with 1 changes to 1 files
1243 1243
1244 1244 $ release $TESTTMP/watchfile
1245 1245
1246 1246 Check the result of the push
1247 1247
1248 1248 $ cat ./push-log
1249 1249 pushing to ssh://user@dummy/server
1250 1250 searching for changes
1251 1251 wrote ready: $TESTTMP/readyfile
1252 1252 waiting on: $TESTTMP/watchfile
1253 1253 abort: push failed:
1254 1254 'repository changed while pushing - please try again'
1255 1255
1256 1256 $ hg -R server graph
1257 1257 o 1b58ee3f79e5 C-P (default)
1258 1258 |
1259 1259 o d0a85b2252a9 C-O (other)
1260 1260 |
1261 1261 o 55a6f1c01b48 C-Z (other)
1262 1262 |
1263 1263 o 866a66e18630 C-N (default)
1264 1264 |\
1265 1265 +---o 6fd3090135df C-M (default)
1266 1266 | |
1267 1267 | o cac2cead0ff0 C-L (default)
1268 1268 | |
1269 1269 o | be705100c623 C-K (default)
1270 1270 |\|
1271 1271 o | d603e2c0cdd7 C-E (default)
1272 1272 | |
1273 1273 | o 59e76faf78bd C-D (default)
1274 1274 | |
1275 1275 | | o 89420bf00fae C-J (default)
1276 1276 | | |
1277 1277 | | | o b35ed749f288 C-I (my-second-test-branch)
1278 1278 | | |/
1279 1279 | | o 75d69cba5402 C-G (default)
1280 1280 | | |
1281 1281 | | | o 833be552cfe6 C-H (my-first-test-branch)
1282 1282 | | |/
1283 1283 | | o d9e379a8c432 C-F (default)
1284 1284 | | |
1285 1285 +---o 51c544a58128 C-C (default)
1286 1286 | |
1287 1287 | o a9149a1428e2 C-B (default)
1288 1288 | |
1289 1289 o | 98217d5a1659 C-A (default)
1290 1290 |/
1291 1291 o 842e2fac6304 C-ROOT (default)
1292 1292
1293 1293
1294 1294 raced commit push a new head behind another named branch
1295 1295 ---------------------------------------------------------
1296 1296
1297 1297 non-continuous branch are valid case, we tests for them.
1298 1298
1299 1299 # b (raced branch default)
1300 1300 # |
1301 1301 # o (branch foo)
1302 1302 # |
1303 1303 # | a (branch default)
1304 1304 # |/
1305 1305 # * (branch foo)
1306 1306 # |
1307 1307 # * (branch default)
1308 1308
1309 1309 (resync-all)
1310 1310
1311 1311 $ hg -R ./server pull ./client-racy
1312 1312 pulling from ./client-racy
1313 1313 searching for changes
1314 1314 adding changesets
1315 1315 adding manifests
1316 1316 adding file changes
1317 1317 added 1 changesets with 0 changes to 0 files (+1 heads)
1318 1318 (run 'hg heads .' to see heads, 'hg merge' to merge)
1319 1319 $ hg -R ./client-other pull
1320 1320 pulling from ssh://user@dummy/server
1321 1321 searching for changes
1322 1322 adding changesets
1323 1323 adding manifests
1324 1324 adding file changes
1325 1325 added 1 changesets with 0 changes to 0 files (+1 heads)
1326 1326 (run 'hg heads .' to see heads, 'hg merge' to merge)
1327 1327 $ hg -R ./client-racy pull
1328 1328 pulling from ssh://user@dummy/server
1329 1329 searching for changes
1330 1330 adding changesets
1331 1331 adding manifests
1332 1332 adding file changes
1333 1333 added 2 changesets with 1 changes to 1 files (+1 heads)
1334 1334 (run 'hg heads .' to see heads, 'hg merge' to merge)
1335 1335
1336 1336 $ hg -R server graph
1337 1337 o b0ee3d6f51bc C-Q (default)
1338 1338 |
1339 1339 | o 1b58ee3f79e5 C-P (default)
1340 1340 | |
1341 1341 | o d0a85b2252a9 C-O (other)
1342 1342 |/
1343 1343 o 55a6f1c01b48 C-Z (other)
1344 1344 |
1345 1345 o 866a66e18630 C-N (default)
1346 1346 |\
1347 1347 +---o 6fd3090135df C-M (default)
1348 1348 | |
1349 1349 | o cac2cead0ff0 C-L (default)
1350 1350 | |
1351 1351 o | be705100c623 C-K (default)
1352 1352 |\|
1353 1353 o | d603e2c0cdd7 C-E (default)
1354 1354 | |
1355 1355 | o 59e76faf78bd C-D (default)
1356 1356 | |
1357 1357 | | o 89420bf00fae C-J (default)
1358 1358 | | |
1359 1359 | | | o b35ed749f288 C-I (my-second-test-branch)
1360 1360 | | |/
1361 1361 | | o 75d69cba5402 C-G (default)
1362 1362 | | |
1363 1363 | | | o 833be552cfe6 C-H (my-first-test-branch)
1364 1364 | | |/
1365 1365 | | o d9e379a8c432 C-F (default)
1366 1366 | | |
1367 1367 +---o 51c544a58128 C-C (default)
1368 1368 | |
1369 1369 | o a9149a1428e2 C-B (default)
1370 1370 | |
1371 1371 o | 98217d5a1659 C-A (default)
1372 1372 |/
1373 1373 o 842e2fac6304 C-ROOT (default)
1374 1374
1375 1375
1376 1376 Creating changesets
1377 1377
1378 1378 (update 'other' named branch head)
1379 1379
1380 1380 $ hg -R client-other/ up 'desc("C-P")'
1381 1381 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1382 1382 $ echo aaa >> client-other/a
1383 1383 $ hg -R client-other/ branch --force other
1384 1384 marked working directory as branch other
1385 1385 $ hg -R client-other/ commit -m "C-R"
1386 1386 created new head
1387 1387
1388 1388 (update 'other named brnach through a 'default' changeset')
1389 1389
1390 1390 $ hg -R client-racy/ up 'desc("C-P")'
1391 1391 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1392 1392 $ echo bbb >> client-racy/a
1393 1393 $ hg -R client-racy/ commit -m "C-S"
1394 1394 $ echo bbb >> client-racy/a
1395 1395 $ hg -R client-racy/ branch --force other
1396 1396 marked working directory as branch other
1397 1397 $ hg -R client-racy/ commit -m "C-T"
1398 1398 created new head
1399 1399
1400 1400 Pushing
1401 1401
1402 1402 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1403 1403
1404 1404 $ waiton $TESTTMP/readyfile
1405 1405
1406 1406 $ hg -R client-other push -fr 'tip' --new-branch
1407 1407 pushing to ssh://user@dummy/server
1408 1408 searching for changes
1409 1409 remote: adding changesets
1410 1410 remote: adding manifests
1411 1411 remote: adding file changes
1412 1412 remote: added 1 changesets with 1 changes to 1 files
1413 1413
1414 1414 $ release $TESTTMP/watchfile
1415 1415
1416 1416 Check the result of the push
1417 1417
1418 1418 $ cat ./push-log
1419 1419 pushing to ssh://user@dummy/server
1420 1420 searching for changes
1421 1421 wrote ready: $TESTTMP/readyfile
1422 1422 waiting on: $TESTTMP/watchfile
1423 1423 abort: push failed:
1424 1424 'repository changed while pushing - please try again'
1425 1425
1426 1426 $ hg -R server graph
1427 1427 o de7b9e2ba3f6 C-R (other)
1428 1428 |
1429 1429 o 1b58ee3f79e5 C-P (default)
1430 1430 |
1431 1431 o d0a85b2252a9 C-O (other)
1432 1432 |
1433 1433 | o b0ee3d6f51bc C-Q (default)
1434 1434 |/
1435 1435 o 55a6f1c01b48 C-Z (other)
1436 1436 |
1437 1437 o 866a66e18630 C-N (default)
1438 1438 |\
1439 1439 +---o 6fd3090135df C-M (default)
1440 1440 | |
1441 1441 | o cac2cead0ff0 C-L (default)
1442 1442 | |
1443 1443 o | be705100c623 C-K (default)
1444 1444 |\|
1445 1445 o | d603e2c0cdd7 C-E (default)
1446 1446 | |
1447 1447 | o 59e76faf78bd C-D (default)
1448 1448 | |
1449 1449 | | o 89420bf00fae C-J (default)
1450 1450 | | |
1451 1451 | | | o b35ed749f288 C-I (my-second-test-branch)
1452 1452 | | |/
1453 1453 | | o 75d69cba5402 C-G (default)
1454 1454 | | |
1455 1455 | | | o 833be552cfe6 C-H (my-first-test-branch)
1456 1456 | | |/
1457 1457 | | o d9e379a8c432 C-F (default)
1458 1458 | | |
1459 1459 +---o 51c544a58128 C-C (default)
1460 1460 | |
1461 1461 | o a9149a1428e2 C-B (default)
1462 1462 | |
1463 1463 o | 98217d5a1659 C-A (default)
1464 1464 |/
1465 1465 o 842e2fac6304 C-ROOT (default)
1466 1466
1467 1467
1468 1468 raced commit push a new head obsoleting the one touched by the racing push
1469 1469 --------------------------------------------------------------------------
1470 1470
1471 1471 # b (racing)
1472 1472 # |
1473 1473 # ø⇠◔ a (raced)
1474 1474 # |/
1475 1475 # *
1476 1476
1477 1477 (resync-all)
1478 1478
1479 1479 $ hg -R ./server pull ./client-racy
1480 1480 pulling from ./client-racy
1481 1481 searching for changes
1482 1482 adding changesets
1483 1483 adding manifests
1484 1484 adding file changes
1485 1485 added 2 changesets with 2 changes to 1 files (+1 heads)
1486 1486 (run 'hg heads .' to see heads, 'hg merge' to merge)
1487 1487 $ hg -R ./client-other pull
1488 1488 pulling from ssh://user@dummy/server
1489 1489 searching for changes
1490 1490 adding changesets
1491 1491 adding manifests
1492 1492 adding file changes
1493 1493 added 2 changesets with 2 changes to 1 files (+1 heads)
1494 1494 (run 'hg heads' to see heads, 'hg merge' to merge)
1495 1495 $ hg -R ./client-racy pull
1496 1496 pulling from ssh://user@dummy/server
1497 1497 searching for changes
1498 1498 adding changesets
1499 1499 adding manifests
1500 1500 adding file changes
1501 1501 added 1 changesets with 1 changes to 1 files (+1 heads)
1502 1502 (run 'hg heads' to see heads, 'hg merge' to merge)
1503 1503
1504 1504 $ hg -R server graph
1505 1505 o 3d57ed3c1091 C-T (other)
1506 1506 |
1507 1507 o 2efd43f7b5ba C-S (default)
1508 1508 |
1509 1509 | o de7b9e2ba3f6 C-R (other)
1510 1510 |/
1511 1511 o 1b58ee3f79e5 C-P (default)
1512 1512 |
1513 1513 o d0a85b2252a9 C-O (other)
1514 1514 |
1515 1515 | o b0ee3d6f51bc C-Q (default)
1516 1516 |/
1517 1517 o 55a6f1c01b48 C-Z (other)
1518 1518 |
1519 1519 o 866a66e18630 C-N (default)
1520 1520 |\
1521 1521 +---o 6fd3090135df C-M (default)
1522 1522 | |
1523 1523 | o cac2cead0ff0 C-L (default)
1524 1524 | |
1525 1525 o | be705100c623 C-K (default)
1526 1526 |\|
1527 1527 o | d603e2c0cdd7 C-E (default)
1528 1528 | |
1529 1529 | o 59e76faf78bd C-D (default)
1530 1530 | |
1531 1531 | | o 89420bf00fae C-J (default)
1532 1532 | | |
1533 1533 | | | o b35ed749f288 C-I (my-second-test-branch)
1534 1534 | | |/
1535 1535 | | o 75d69cba5402 C-G (default)
1536 1536 | | |
1537 1537 | | | o 833be552cfe6 C-H (my-first-test-branch)
1538 1538 | | |/
1539 1539 | | o d9e379a8c432 C-F (default)
1540 1540 | | |
1541 1541 +---o 51c544a58128 C-C (default)
1542 1542 | |
1543 1543 | o a9149a1428e2 C-B (default)
1544 1544 | |
1545 1545 o | 98217d5a1659 C-A (default)
1546 1546 |/
1547 1547 o 842e2fac6304 C-ROOT (default)
1548 1548
1549 1549
1550 1550 Creating changesets and markers
1551 1551
1552 1552 (continue existing head)
1553 1553
1554 1554 $ hg -R client-other/ up 'desc("C-Q")'
1555 1555 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1556 1556 $ echo aaa >> client-other/a
1557 1557 $ hg -R client-other/ commit -m "C-U"
1558 1558
1559 1559 (new topo branch obsoleting that same head)
1560 1560
1561 1561 $ hg -R client-racy/ up 'desc("C-Z")'
1562 1562 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1563 1563 $ echo bbb >> client-racy/a
1564 1564 $ hg -R client-racy/ branch --force default
1565 1565 marked working directory as branch default
1566 1566 $ hg -R client-racy/ commit -m "C-V"
1567 1567 created new head
1568 1568 $ ID_Q=`hg -R client-racy log -T '{node}\n' -r 'desc("C-Q")'`
1569 1569 $ ID_V=`hg -R client-racy log -T '{node}\n' -r 'desc("C-V")'`
1570 1570 $ hg -R client-racy debugobsolete $ID_Q $ID_V
1571 1571
1572 1572 Pushing
1573 1573
1574 1574 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1575 1575
1576 1576 $ waiton $TESTTMP/readyfile
1577 1577
1578 1578 $ hg -R client-other push -fr 'tip' --new-branch
1579 1579 pushing to ssh://user@dummy/server
1580 1580 searching for changes
1581 1581 remote: adding changesets
1582 1582 remote: adding manifests
1583 1583 remote: adding file changes
1584 1584 remote: added 1 changesets with 0 changes to 0 files
1585 1585
1586 1586 $ release $TESTTMP/watchfile
1587 1587
1588 1588 Check the result of the push
1589 1589
1590 1590 $ cat ./push-log
1591 1591 pushing to ssh://user@dummy/server
1592 1592 searching for changes
1593 1593 wrote ready: $TESTTMP/readyfile
1594 1594 waiting on: $TESTTMP/watchfile
1595 1595 abort: push failed:
1596 1596 'repository changed while pushing - please try again'
1597 1597
1598 1598 $ hg -R server debugobsolete
1599 1599 $ hg -R server graph
1600 1600 o a98a47d8b85b C-U (default)
1601 1601 |
1602 1602 o b0ee3d6f51bc C-Q (default)
1603 1603 |
1604 1604 | o 3d57ed3c1091 C-T (other)
1605 1605 | |
1606 1606 | o 2efd43f7b5ba C-S (default)
1607 1607 | |
1608 1608 | | o de7b9e2ba3f6 C-R (other)
1609 1609 | |/
1610 1610 | o 1b58ee3f79e5 C-P (default)
1611 1611 | |
1612 1612 | o d0a85b2252a9 C-O (other)
1613 1613 |/
1614 1614 o 55a6f1c01b48 C-Z (other)
1615 1615 |
1616 1616 o 866a66e18630 C-N (default)
1617 1617 |\
1618 1618 +---o 6fd3090135df C-M (default)
1619 1619 | |
1620 1620 | o cac2cead0ff0 C-L (default)
1621 1621 | |
1622 1622 o | be705100c623 C-K (default)
1623 1623 |\|
1624 1624 o | d603e2c0cdd7 C-E (default)
1625 1625 | |
1626 1626 | o 59e76faf78bd C-D (default)
1627 1627 | |
1628 1628 | | o 89420bf00fae C-J (default)
1629 1629 | | |
1630 1630 | | | o b35ed749f288 C-I (my-second-test-branch)
1631 1631 | | |/
1632 1632 | | o 75d69cba5402 C-G (default)
1633 1633 | | |
1634 1634 | | | o 833be552cfe6 C-H (my-first-test-branch)
1635 1635 | | |/
1636 1636 | | o d9e379a8c432 C-F (default)
1637 1637 | | |
1638 1638 +---o 51c544a58128 C-C (default)
1639 1639 | |
1640 1640 | o a9149a1428e2 C-B (default)
1641 1641 | |
1642 1642 o | 98217d5a1659 C-A (default)
1643 1643 |/
1644 1644 o 842e2fac6304 C-ROOT (default)
1645 1645
1646 1646
1647 1647 racing commit push a new head obsoleting the one touched by the raced push
1648 1648 --------------------------------------------------------------------------
1649 1649
1650 1650 (mirror test case of the previous one
1651 1651
1652 1652 # a (raced branch default)
1653 1653 # |
1654 1654 # ø⇠◔ b (racing)
1655 1655 # |/
1656 1656 # *
1657 1657
1658 1658 (resync-all)
1659 1659
1660 1660 $ hg -R ./server pull ./client-racy
1661 1661 pulling from ./client-racy
1662 1662 searching for changes
1663 1663 adding changesets
1664 1664 adding manifests
1665 1665 adding file changes
1666 1666 added 1 changesets with 1 changes to 1 files (+1 heads)
1667 1667 1 new obsolescence markers
1668 obsoleted 1 changesets
1668 1669 (run 'hg heads .' to see heads, 'hg merge' to merge)
1669 1670 $ hg -R ./client-other pull
1670 1671 pulling from ssh://user@dummy/server
1671 1672 searching for changes
1672 1673 adding changesets
1673 1674 adding manifests
1674 1675 adding file changes
1675 1676 added 1 changesets with 1 changes to 1 files (+1 heads)
1676 1677 1 new obsolescence markers
1678 obsoleted 1 changesets
1677 1679 (run 'hg heads .' to see heads, 'hg merge' to merge)
1678 1680 $ hg -R ./client-racy pull
1679 1681 pulling from ssh://user@dummy/server
1680 1682 searching for changes
1681 1683 adding changesets
1682 1684 adding manifests
1683 1685 adding file changes
1684 1686 added 1 changesets with 0 changes to 0 files
1685 1687 (run 'hg update' to get a working copy)
1686 1688
1687 1689 $ hg -R server debugobsolete
1688 1690 b0ee3d6f51bc4c0ca6d4f2907708027a6c376233 720c5163ecf64dcc6216bee2d62bf3edb1882499 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1689 1691 $ hg -R server graph
1690 1692 o 720c5163ecf6 C-V (default)
1691 1693 |
1692 1694 | o a98a47d8b85b C-U (default)
1693 1695 | |
1694 1696 | x b0ee3d6f51bc C-Q (default)
1695 1697 |/
1696 1698 | o 3d57ed3c1091 C-T (other)
1697 1699 | |
1698 1700 | o 2efd43f7b5ba C-S (default)
1699 1701 | |
1700 1702 | | o de7b9e2ba3f6 C-R (other)
1701 1703 | |/
1702 1704 | o 1b58ee3f79e5 C-P (default)
1703 1705 | |
1704 1706 | o d0a85b2252a9 C-O (other)
1705 1707 |/
1706 1708 o 55a6f1c01b48 C-Z (other)
1707 1709 |
1708 1710 o 866a66e18630 C-N (default)
1709 1711 |\
1710 1712 +---o 6fd3090135df C-M (default)
1711 1713 | |
1712 1714 | o cac2cead0ff0 C-L (default)
1713 1715 | |
1714 1716 o | be705100c623 C-K (default)
1715 1717 |\|
1716 1718 o | d603e2c0cdd7 C-E (default)
1717 1719 | |
1718 1720 | o 59e76faf78bd C-D (default)
1719 1721 | |
1720 1722 | | o 89420bf00fae C-J (default)
1721 1723 | | |
1722 1724 | | | o b35ed749f288 C-I (my-second-test-branch)
1723 1725 | | |/
1724 1726 | | o 75d69cba5402 C-G (default)
1725 1727 | | |
1726 1728 | | | o 833be552cfe6 C-H (my-first-test-branch)
1727 1729 | | |/
1728 1730 | | o d9e379a8c432 C-F (default)
1729 1731 | | |
1730 1732 +---o 51c544a58128 C-C (default)
1731 1733 | |
1732 1734 | o a9149a1428e2 C-B (default)
1733 1735 | |
1734 1736 o | 98217d5a1659 C-A (default)
1735 1737 |/
1736 1738 o 842e2fac6304 C-ROOT (default)
1737 1739
1738 1740
1739 1741 Creating changesets and markers
1740 1742
1741 1743 (new topo branch obsoleting that same head)
1742 1744
1743 1745 $ hg -R client-other/ up 'desc("C-Q")'
1744 1746 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1745 1747 $ echo bbb >> client-other/a
1746 1748 $ hg -R client-other/ branch --force default
1747 1749 marked working directory as branch default
1748 1750 $ hg -R client-other/ commit -m "C-W"
1749 1751 created new head
1750 1752 $ ID_V=`hg -R client-other log -T '{node}\n' -r 'desc("C-V")'`
1751 1753 $ ID_W=`hg -R client-other log -T '{node}\n' -r 'desc("C-W")'`
1752 1754 $ hg -R client-other debugobsolete $ID_V $ID_W
1753 1755
1754 1756 (continue the same head)
1755 1757
1756 1758 $ echo aaa >> client-racy/a
1757 1759 $ hg -R client-racy/ commit -m "C-X"
1758 1760
1759 1761 Pushing
1760 1762
1761 1763 $ hg -R client-racy push -r 'tip' > ./push-log 2>&1 &
1762 1764
1763 1765 $ waiton $TESTTMP/readyfile
1764 1766
1765 1767 $ hg -R client-other push -fr 'tip' --new-branch
1766 1768 pushing to ssh://user@dummy/server
1767 1769 searching for changes
1768 1770 remote: adding changesets
1769 1771 remote: adding manifests
1770 1772 remote: adding file changes
1771 1773 remote: added 1 changesets with 0 changes to 1 files (+1 heads)
1772 1774 remote: 1 new obsolescence markers
1775 remote: obsoleted 1 changesets
1773 1776
1774 1777 $ release $TESTTMP/watchfile
1775 1778
1776 1779 Check the result of the push
1777 1780
1778 1781 $ cat ./push-log
1779 1782 pushing to ssh://user@dummy/server
1780 1783 searching for changes
1781 1784 wrote ready: $TESTTMP/readyfile
1782 1785 waiting on: $TESTTMP/watchfile
1783 1786 abort: push failed:
1784 1787 'repository changed while pushing - please try again'
1785 1788
1786 1789 $ hg -R server debugobsolete
1787 1790 b0ee3d6f51bc4c0ca6d4f2907708027a6c376233 720c5163ecf64dcc6216bee2d62bf3edb1882499 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1788 1791 720c5163ecf64dcc6216bee2d62bf3edb1882499 39bc0598afe90ab18da460bafecc0fa953b77596 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1789 1792 $ hg -R server graph --hidden
1790 1793 o 39bc0598afe9 C-W (default)
1791 1794 |
1792 1795 | o a98a47d8b85b C-U (default)
1793 1796 |/
1794 1797 x b0ee3d6f51bc C-Q (default)
1795 1798 |
1796 1799 | o 3d57ed3c1091 C-T (other)
1797 1800 | |
1798 1801 | o 2efd43f7b5ba C-S (default)
1799 1802 | |
1800 1803 | | o de7b9e2ba3f6 C-R (other)
1801 1804 | |/
1802 1805 | o 1b58ee3f79e5 C-P (default)
1803 1806 | |
1804 1807 | o d0a85b2252a9 C-O (other)
1805 1808 |/
1806 1809 | x 720c5163ecf6 C-V (default)
1807 1810 |/
1808 1811 o 55a6f1c01b48 C-Z (other)
1809 1812 |
1810 1813 o 866a66e18630 C-N (default)
1811 1814 |\
1812 1815 +---o 6fd3090135df C-M (default)
1813 1816 | |
1814 1817 | o cac2cead0ff0 C-L (default)
1815 1818 | |
1816 1819 o | be705100c623 C-K (default)
1817 1820 |\|
1818 1821 o | d603e2c0cdd7 C-E (default)
1819 1822 | |
1820 1823 | o 59e76faf78bd C-D (default)
1821 1824 | |
1822 1825 | | o 89420bf00fae C-J (default)
1823 1826 | | |
1824 1827 | | | o b35ed749f288 C-I (my-second-test-branch)
1825 1828 | | |/
1826 1829 | | o 75d69cba5402 C-G (default)
1827 1830 | | |
1828 1831 | | | o 833be552cfe6 C-H (my-first-test-branch)
1829 1832 | | |/
1830 1833 | | o d9e379a8c432 C-F (default)
1831 1834 | | |
1832 1835 +---o 51c544a58128 C-C (default)
1833 1836 | |
1834 1837 | o a9149a1428e2 C-B (default)
1835 1838 | |
1836 1839 o | 98217d5a1659 C-A (default)
1837 1840 |/
1838 1841 o 842e2fac6304 C-ROOT (default)
1839 1842
General Comments 0
You need to be logged in to leave comments. Login now