##// END OF EJS Templates
bundlespec: handle the presence of obsmarker part...
marmoute -
r50230:04cdb442 default
parent child Browse files
Show More
@@ -1,2853 +1,2857 b''
1 1 # exchange.py - utility to exchange data between repos.
2 2 #
3 3 # Copyright 2005-2007 Olivia Mackall <olivia@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
9 9 import collections
10 10 import weakref
11 11
12 12 from .i18n import _
13 13 from .node import (
14 14 hex,
15 15 nullrev,
16 16 )
17 17 from . import (
18 18 bookmarks as bookmod,
19 19 bundle2,
20 20 bundlecaches,
21 21 changegroup,
22 22 discovery,
23 23 error,
24 24 lock as lockmod,
25 25 logexchange,
26 26 narrowspec,
27 27 obsolete,
28 28 obsutil,
29 29 phases,
30 30 pushkey,
31 31 pycompat,
32 32 requirements,
33 33 scmutil,
34 34 streamclone,
35 35 url as urlmod,
36 36 util,
37 37 wireprototypes,
38 38 )
39 39 from .utils import (
40 40 hashutil,
41 41 stringutil,
42 42 urlutil,
43 43 )
44 44 from .interfaces import repository
45 45
46 46 urlerr = util.urlerr
47 47 urlreq = util.urlreq
48 48
49 49 _NARROWACL_SECTION = b'narrowacl'
50 50
51 51
52 52 def readbundle(ui, fh, fname, vfs=None):
53 53 header = changegroup.readexactly(fh, 4)
54 54
55 55 alg = None
56 56 if not fname:
57 57 fname = b"stream"
58 58 if not header.startswith(b'HG') and header.startswith(b'\0'):
59 59 fh = changegroup.headerlessfixup(fh, header)
60 60 header = b"HG10"
61 61 alg = b'UN'
62 62 elif vfs:
63 63 fname = vfs.join(fname)
64 64
65 65 magic, version = header[0:2], header[2:4]
66 66
67 67 if magic != b'HG':
68 68 raise error.Abort(_(b'%s: not a Mercurial bundle') % fname)
69 69 if version == b'10':
70 70 if alg is None:
71 71 alg = changegroup.readexactly(fh, 2)
72 72 return changegroup.cg1unpacker(fh, alg)
73 73 elif version.startswith(b'2'):
74 74 return bundle2.getunbundler(ui, fh, magicstring=magic + version)
75 75 elif version == b'S1':
76 76 return streamclone.streamcloneapplier(fh)
77 77 else:
78 78 raise error.Abort(
79 79 _(b'%s: unknown bundle version %s') % (fname, version)
80 80 )
81 81
82 82
83 83 def _format_params(params):
84 84 parts = []
85 85 for key, value in sorted(params.items()):
86 86 value = urlreq.quote(value)
87 87 parts.append(b"%s=%s" % (key, value))
88 88 return b';'.join(parts)
89 89
90 90
91 91 def getbundlespec(ui, fh):
92 92 """Infer the bundlespec from a bundle file handle.
93 93
94 94 The input file handle is seeked and the original seek position is not
95 95 restored.
96 96 """
97 97
98 98 def speccompression(alg):
99 99 try:
100 100 return util.compengines.forbundletype(alg).bundletype()[0]
101 101 except KeyError:
102 102 return None
103 103
104 104 params = {}
105 105
106 106 b = readbundle(ui, fh, None)
107 107 if isinstance(b, changegroup.cg1unpacker):
108 108 alg = b._type
109 109 if alg == b'_truncatedBZ':
110 110 alg = b'BZ'
111 111 comp = speccompression(alg)
112 112 if not comp:
113 113 raise error.Abort(_(b'unknown compression algorithm: %s') % alg)
114 114 return b'%s-v1' % comp
115 115 elif isinstance(b, bundle2.unbundle20):
116 116 if b'Compression' in b.params:
117 117 comp = speccompression(b.params[b'Compression'])
118 118 if not comp:
119 119 raise error.Abort(
120 120 _(b'unknown compression algorithm: %s') % comp
121 121 )
122 122 else:
123 123 comp = b'none'
124 124
125 125 version = None
126 126 for part in b.iterparts():
127 127 if part.type == b'changegroup':
128 128 cgversion = part.params[b'version']
129 129 if cgversion in (b'01', b'02'):
130 130 version = b'v2'
131 131 elif cgversion in (b'03',):
132 132 version = b'v2'
133 133 params[b'cg.version'] = cgversion
134 134 else:
135 135 raise error.Abort(
136 136 _(
137 137 b'changegroup version %s does not have '
138 138 b'a known bundlespec'
139 139 )
140 140 % version,
141 141 hint=_(b'try upgrading your Mercurial client'),
142 142 )
143 143 elif part.type == b'stream2' and version is None:
144 144 # A stream2 part requires to be part of a v2 bundle
145 145 requirements = urlreq.unquote(part.params[b'requirements'])
146 146 splitted = requirements.split()
147 147 params = bundle2._formatrequirementsparams(splitted)
148 148 return b'none-v2;stream=v2;%s' % params
149 elif part.type == b'obsmarkers':
150 params[b'obsolescence'] = b'yes'
151 if not part.mandatory:
152 params[b'obsolescence-mandatory'] = b'no'
149 153
150 154 if not version:
151 155 raise error.Abort(
152 156 _(b'could not identify changegroup version in bundle')
153 157 )
154 158 spec = b'%s-%s' % (comp, version)
155 159 if params:
156 160 spec += b';'
157 161 spec += _format_params(params)
158 162 return spec
159 163
160 164 elif isinstance(b, streamclone.streamcloneapplier):
161 165 requirements = streamclone.readbundle1header(fh)[2]
162 166 formatted = bundle2._formatrequirementsparams(requirements)
163 167 return b'none-packed1;%s' % formatted
164 168 else:
165 169 raise error.Abort(_(b'unknown bundle type: %s') % b)
166 170
167 171
168 172 def _computeoutgoing(repo, heads, common):
169 173 """Computes which revs are outgoing given a set of common
170 174 and a set of heads.
171 175
172 176 This is a separate function so extensions can have access to
173 177 the logic.
174 178
175 179 Returns a discovery.outgoing object.
176 180 """
177 181 cl = repo.changelog
178 182 if common:
179 183 hasnode = cl.hasnode
180 184 common = [n for n in common if hasnode(n)]
181 185 else:
182 186 common = [repo.nullid]
183 187 if not heads:
184 188 heads = cl.heads()
185 189 return discovery.outgoing(repo, common, heads)
186 190
187 191
188 192 def _checkpublish(pushop):
189 193 repo = pushop.repo
190 194 ui = repo.ui
191 195 behavior = ui.config(b'experimental', b'auto-publish')
192 196 if pushop.publish or behavior not in (b'warn', b'confirm', b'abort'):
193 197 return
194 198 remotephases = listkeys(pushop.remote, b'phases')
195 199 if not remotephases.get(b'publishing', False):
196 200 return
197 201
198 202 if pushop.revs is None:
199 203 published = repo.filtered(b'served').revs(b'not public()')
200 204 else:
201 205 published = repo.revs(b'::%ln - public()', pushop.revs)
202 206 # we want to use pushop.revs in the revset even if they themselves are
203 207 # secret, but we don't want to have anything that the server won't see
204 208 # in the result of this expression
205 209 published &= repo.filtered(b'served')
206 210 if published:
207 211 if behavior == b'warn':
208 212 ui.warn(
209 213 _(b'%i changesets about to be published\n') % len(published)
210 214 )
211 215 elif behavior == b'confirm':
212 216 if ui.promptchoice(
213 217 _(b'push and publish %i changesets (yn)?$$ &Yes $$ &No')
214 218 % len(published)
215 219 ):
216 220 raise error.CanceledError(_(b'user quit'))
217 221 elif behavior == b'abort':
218 222 msg = _(b'push would publish %i changesets') % len(published)
219 223 hint = _(
220 224 b"use --publish or adjust 'experimental.auto-publish'"
221 225 b" config"
222 226 )
223 227 raise error.Abort(msg, hint=hint)
224 228
225 229
226 230 def _forcebundle1(op):
227 231 """return true if a pull/push must use bundle1
228 232
229 233 This function is used to allow testing of the older bundle version"""
230 234 ui = op.repo.ui
231 235 # The goal is this config is to allow developer to choose the bundle
232 236 # version used during exchanged. This is especially handy during test.
233 237 # Value is a list of bundle version to be picked from, highest version
234 238 # should be used.
235 239 #
236 240 # developer config: devel.legacy.exchange
237 241 exchange = ui.configlist(b'devel', b'legacy.exchange')
238 242 forcebundle1 = b'bundle2' not in exchange and b'bundle1' in exchange
239 243 return forcebundle1 or not op.remote.capable(b'bundle2')
240 244
241 245
242 246 class pushoperation:
243 247 """A object that represent a single push operation
244 248
245 249 Its purpose is to carry push related state and very common operations.
246 250
247 251 A new pushoperation should be created at the beginning of each push and
248 252 discarded afterward.
249 253 """
250 254
251 255 def __init__(
252 256 self,
253 257 repo,
254 258 remote,
255 259 force=False,
256 260 revs=None,
257 261 newbranch=False,
258 262 bookmarks=(),
259 263 publish=False,
260 264 pushvars=None,
261 265 ):
262 266 # repo we push from
263 267 self.repo = repo
264 268 self.ui = repo.ui
265 269 # repo we push to
266 270 self.remote = remote
267 271 # force option provided
268 272 self.force = force
269 273 # revs to be pushed (None is "all")
270 274 self.revs = revs
271 275 # bookmark explicitly pushed
272 276 self.bookmarks = bookmarks
273 277 # allow push of new branch
274 278 self.newbranch = newbranch
275 279 # step already performed
276 280 # (used to check what steps have been already performed through bundle2)
277 281 self.stepsdone = set()
278 282 # Integer version of the changegroup push result
279 283 # - None means nothing to push
280 284 # - 0 means HTTP error
281 285 # - 1 means we pushed and remote head count is unchanged *or*
282 286 # we have outgoing changesets but refused to push
283 287 # - other values as described by addchangegroup()
284 288 self.cgresult = None
285 289 # Boolean value for the bookmark push
286 290 self.bkresult = None
287 291 # discover.outgoing object (contains common and outgoing data)
288 292 self.outgoing = None
289 293 # all remote topological heads before the push
290 294 self.remoteheads = None
291 295 # Details of the remote branch pre and post push
292 296 #
293 297 # mapping: {'branch': ([remoteheads],
294 298 # [newheads],
295 299 # [unsyncedheads],
296 300 # [discardedheads])}
297 301 # - branch: the branch name
298 302 # - remoteheads: the list of remote heads known locally
299 303 # None if the branch is new
300 304 # - newheads: the new remote heads (known locally) with outgoing pushed
301 305 # - unsyncedheads: the list of remote heads unknown locally.
302 306 # - discardedheads: the list of remote heads made obsolete by the push
303 307 self.pushbranchmap = None
304 308 # testable as a boolean indicating if any nodes are missing locally.
305 309 self.incoming = None
306 310 # summary of the remote phase situation
307 311 self.remotephases = None
308 312 # phases changes that must be pushed along side the changesets
309 313 self.outdatedphases = None
310 314 # phases changes that must be pushed if changeset push fails
311 315 self.fallbackoutdatedphases = None
312 316 # outgoing obsmarkers
313 317 self.outobsmarkers = set()
314 318 # outgoing bookmarks, list of (bm, oldnode | '', newnode | '')
315 319 self.outbookmarks = []
316 320 # transaction manager
317 321 self.trmanager = None
318 322 # map { pushkey partid -> callback handling failure}
319 323 # used to handle exception from mandatory pushkey part failure
320 324 self.pkfailcb = {}
321 325 # an iterable of pushvars or None
322 326 self.pushvars = pushvars
323 327 # publish pushed changesets
324 328 self.publish = publish
325 329
326 330 @util.propertycache
327 331 def futureheads(self):
328 332 """future remote heads if the changeset push succeeds"""
329 333 return self.outgoing.ancestorsof
330 334
331 335 @util.propertycache
332 336 def fallbackheads(self):
333 337 """future remote heads if the changeset push fails"""
334 338 if self.revs is None:
335 339 # not target to push, all common are relevant
336 340 return self.outgoing.commonheads
337 341 unfi = self.repo.unfiltered()
338 342 # I want cheads = heads(::ancestorsof and ::commonheads)
339 343 # (ancestorsof is revs with secret changeset filtered out)
340 344 #
341 345 # This can be expressed as:
342 346 # cheads = ( (ancestorsof and ::commonheads)
343 347 # + (commonheads and ::ancestorsof))"
344 348 # )
345 349 #
346 350 # while trying to push we already computed the following:
347 351 # common = (::commonheads)
348 352 # missing = ((commonheads::ancestorsof) - commonheads)
349 353 #
350 354 # We can pick:
351 355 # * ancestorsof part of common (::commonheads)
352 356 common = self.outgoing.common
353 357 rev = self.repo.changelog.index.rev
354 358 cheads = [node for node in self.revs if rev(node) in common]
355 359 # and
356 360 # * commonheads parents on missing
357 361 revset = unfi.set(
358 362 b'%ln and parents(roots(%ln))',
359 363 self.outgoing.commonheads,
360 364 self.outgoing.missing,
361 365 )
362 366 cheads.extend(c.node() for c in revset)
363 367 return cheads
364 368
365 369 @property
366 370 def commonheads(self):
367 371 """set of all common heads after changeset bundle push"""
368 372 if self.cgresult:
369 373 return self.futureheads
370 374 else:
371 375 return self.fallbackheads
372 376
373 377
374 378 # mapping of message used when pushing bookmark
375 379 bookmsgmap = {
376 380 b'update': (
377 381 _(b"updating bookmark %s\n"),
378 382 _(b'updating bookmark %s failed\n'),
379 383 ),
380 384 b'export': (
381 385 _(b"exporting bookmark %s\n"),
382 386 _(b'exporting bookmark %s failed\n'),
383 387 ),
384 388 b'delete': (
385 389 _(b"deleting remote bookmark %s\n"),
386 390 _(b'deleting remote bookmark %s failed\n'),
387 391 ),
388 392 }
389 393
390 394
391 395 def push(
392 396 repo,
393 397 remote,
394 398 force=False,
395 399 revs=None,
396 400 newbranch=False,
397 401 bookmarks=(),
398 402 publish=False,
399 403 opargs=None,
400 404 ):
401 405 """Push outgoing changesets (limited by revs) from a local
402 406 repository to remote. Return an integer:
403 407 - None means nothing to push
404 408 - 0 means HTTP error
405 409 - 1 means we pushed and remote head count is unchanged *or*
406 410 we have outgoing changesets but refused to push
407 411 - other values as described by addchangegroup()
408 412 """
409 413 if opargs is None:
410 414 opargs = {}
411 415 pushop = pushoperation(
412 416 repo,
413 417 remote,
414 418 force,
415 419 revs,
416 420 newbranch,
417 421 bookmarks,
418 422 publish,
419 423 **pycompat.strkwargs(opargs)
420 424 )
421 425 if pushop.remote.local():
422 426 missing = (
423 427 set(pushop.repo.requirements) - pushop.remote.local().supported
424 428 )
425 429 if missing:
426 430 msg = _(
427 431 b"required features are not"
428 432 b" supported in the destination:"
429 433 b" %s"
430 434 ) % (b', '.join(sorted(missing)))
431 435 raise error.Abort(msg)
432 436
433 437 if not pushop.remote.canpush():
434 438 raise error.Abort(_(b"destination does not support push"))
435 439
436 440 if not pushop.remote.capable(b'unbundle'):
437 441 raise error.Abort(
438 442 _(
439 443 b'cannot push: destination does not support the '
440 444 b'unbundle wire protocol command'
441 445 )
442 446 )
443 447 for category in sorted(bundle2.read_remote_wanted_sidedata(pushop.remote)):
444 448 # Check that a computer is registered for that category for at least
445 449 # one revlog kind.
446 450 for kind, computers in repo._sidedata_computers.items():
447 451 if computers.get(category):
448 452 break
449 453 else:
450 454 raise error.Abort(
451 455 _(
452 456 b'cannot push: required sidedata category not supported'
453 457 b" by this client: '%s'"
454 458 )
455 459 % pycompat.bytestr(category)
456 460 )
457 461 # get lock as we might write phase data
458 462 wlock = lock = None
459 463 try:
460 464 # bundle2 push may receive a reply bundle touching bookmarks
461 465 # requiring the wlock. Take it now to ensure proper ordering.
462 466 maypushback = pushop.ui.configbool(b'experimental', b'bundle2.pushback')
463 467 if (
464 468 (not _forcebundle1(pushop))
465 469 and maypushback
466 470 and not bookmod.bookmarksinstore(repo)
467 471 ):
468 472 wlock = pushop.repo.wlock()
469 473 lock = pushop.repo.lock()
470 474 pushop.trmanager = transactionmanager(
471 475 pushop.repo, b'push-response', pushop.remote.url()
472 476 )
473 477 except error.LockUnavailable as err:
474 478 # source repo cannot be locked.
475 479 # We do not abort the push, but just disable the local phase
476 480 # synchronisation.
477 481 msg = b'cannot lock source repository: %s\n' % stringutil.forcebytestr(
478 482 err
479 483 )
480 484 pushop.ui.debug(msg)
481 485
482 486 with wlock or util.nullcontextmanager():
483 487 with lock or util.nullcontextmanager():
484 488 with pushop.trmanager or util.nullcontextmanager():
485 489 pushop.repo.checkpush(pushop)
486 490 _checkpublish(pushop)
487 491 _pushdiscovery(pushop)
488 492 if not pushop.force:
489 493 _checksubrepostate(pushop)
490 494 if not _forcebundle1(pushop):
491 495 _pushbundle2(pushop)
492 496 _pushchangeset(pushop)
493 497 _pushsyncphase(pushop)
494 498 _pushobsolete(pushop)
495 499 _pushbookmark(pushop)
496 500
497 501 if repo.ui.configbool(b'experimental', b'remotenames'):
498 502 logexchange.pullremotenames(repo, remote)
499 503
500 504 return pushop
501 505
502 506
503 507 # list of steps to perform discovery before push
504 508 pushdiscoveryorder = []
505 509
506 510 # Mapping between step name and function
507 511 #
508 512 # This exists to help extensions wrap steps if necessary
509 513 pushdiscoverymapping = {}
510 514
511 515
512 516 def pushdiscovery(stepname):
513 517 """decorator for function performing discovery before push
514 518
515 519 The function is added to the step -> function mapping and appended to the
516 520 list of steps. Beware that decorated function will be added in order (this
517 521 may matter).
518 522
519 523 You can only use this decorator for a new step, if you want to wrap a step
520 524 from an extension, change the pushdiscovery dictionary directly."""
521 525
522 526 def dec(func):
523 527 assert stepname not in pushdiscoverymapping
524 528 pushdiscoverymapping[stepname] = func
525 529 pushdiscoveryorder.append(stepname)
526 530 return func
527 531
528 532 return dec
529 533
530 534
531 535 def _pushdiscovery(pushop):
532 536 """Run all discovery steps"""
533 537 for stepname in pushdiscoveryorder:
534 538 step = pushdiscoverymapping[stepname]
535 539 step(pushop)
536 540
537 541
538 542 def _checksubrepostate(pushop):
539 543 """Ensure all outgoing referenced subrepo revisions are present locally"""
540 544
541 545 repo = pushop.repo
542 546
543 547 # If the repository does not use subrepos, skip the expensive
544 548 # manifest checks.
545 549 if not len(repo.file(b'.hgsub')) or not len(repo.file(b'.hgsubstate')):
546 550 return
547 551
548 552 for n in pushop.outgoing.missing:
549 553 ctx = repo[n]
550 554
551 555 if b'.hgsub' in ctx.manifest() and b'.hgsubstate' in ctx.files():
552 556 for subpath in sorted(ctx.substate):
553 557 sub = ctx.sub(subpath)
554 558 sub.verify(onpush=True)
555 559
556 560
557 561 @pushdiscovery(b'changeset')
558 562 def _pushdiscoverychangeset(pushop):
559 563 """discover the changeset that need to be pushed"""
560 564 fci = discovery.findcommonincoming
561 565 if pushop.revs:
562 566 commoninc = fci(
563 567 pushop.repo,
564 568 pushop.remote,
565 569 force=pushop.force,
566 570 ancestorsof=pushop.revs,
567 571 )
568 572 else:
569 573 commoninc = fci(pushop.repo, pushop.remote, force=pushop.force)
570 574 common, inc, remoteheads = commoninc
571 575 fco = discovery.findcommonoutgoing
572 576 outgoing = fco(
573 577 pushop.repo,
574 578 pushop.remote,
575 579 onlyheads=pushop.revs,
576 580 commoninc=commoninc,
577 581 force=pushop.force,
578 582 )
579 583 pushop.outgoing = outgoing
580 584 pushop.remoteheads = remoteheads
581 585 pushop.incoming = inc
582 586
583 587
584 588 @pushdiscovery(b'phase')
585 589 def _pushdiscoveryphase(pushop):
586 590 """discover the phase that needs to be pushed
587 591
588 592 (computed for both success and failure case for changesets push)"""
589 593 outgoing = pushop.outgoing
590 594 unfi = pushop.repo.unfiltered()
591 595 remotephases = listkeys(pushop.remote, b'phases')
592 596
593 597 if (
594 598 pushop.ui.configbool(b'ui', b'_usedassubrepo')
595 599 and remotephases # server supports phases
596 600 and not pushop.outgoing.missing # no changesets to be pushed
597 601 and remotephases.get(b'publishing', False)
598 602 ):
599 603 # When:
600 604 # - this is a subrepo push
601 605 # - and remote support phase
602 606 # - and no changeset are to be pushed
603 607 # - and remote is publishing
604 608 # We may be in issue 3781 case!
605 609 # We drop the possible phase synchronisation done by
606 610 # courtesy to publish changesets possibly locally draft
607 611 # on the remote.
608 612 pushop.outdatedphases = []
609 613 pushop.fallbackoutdatedphases = []
610 614 return
611 615
612 616 pushop.remotephases = phases.remotephasessummary(
613 617 pushop.repo, pushop.fallbackheads, remotephases
614 618 )
615 619 droots = pushop.remotephases.draftroots
616 620
617 621 extracond = b''
618 622 if not pushop.remotephases.publishing:
619 623 extracond = b' and public()'
620 624 revset = b'heads((%%ln::%%ln) %s)' % extracond
621 625 # Get the list of all revs draft on remote by public here.
622 626 # XXX Beware that revset break if droots is not strictly
623 627 # XXX root we may want to ensure it is but it is costly
624 628 fallback = list(unfi.set(revset, droots, pushop.fallbackheads))
625 629 if not pushop.remotephases.publishing and pushop.publish:
626 630 future = list(
627 631 unfi.set(
628 632 b'%ln and (not public() or %ln::)', pushop.futureheads, droots
629 633 )
630 634 )
631 635 elif not outgoing.missing:
632 636 future = fallback
633 637 else:
634 638 # adds changeset we are going to push as draft
635 639 #
636 640 # should not be necessary for publishing server, but because of an
637 641 # issue fixed in xxxxx we have to do it anyway.
638 642 fdroots = list(
639 643 unfi.set(b'roots(%ln + %ln::)', outgoing.missing, droots)
640 644 )
641 645 fdroots = [f.node() for f in fdroots]
642 646 future = list(unfi.set(revset, fdroots, pushop.futureheads))
643 647 pushop.outdatedphases = future
644 648 pushop.fallbackoutdatedphases = fallback
645 649
646 650
647 651 @pushdiscovery(b'obsmarker')
648 652 def _pushdiscoveryobsmarkers(pushop):
649 653 if not obsolete.isenabled(pushop.repo, obsolete.exchangeopt):
650 654 return
651 655
652 656 if not pushop.repo.obsstore:
653 657 return
654 658
655 659 if b'obsolete' not in listkeys(pushop.remote, b'namespaces'):
656 660 return
657 661
658 662 repo = pushop.repo
659 663 # very naive computation, that can be quite expensive on big repo.
660 664 # However: evolution is currently slow on them anyway.
661 665 nodes = (c.node() for c in repo.set(b'::%ln', pushop.futureheads))
662 666 pushop.outobsmarkers = pushop.repo.obsstore.relevantmarkers(nodes)
663 667
664 668
665 669 @pushdiscovery(b'bookmarks')
666 670 def _pushdiscoverybookmarks(pushop):
667 671 ui = pushop.ui
668 672 repo = pushop.repo.unfiltered()
669 673 remote = pushop.remote
670 674 ui.debug(b"checking for updated bookmarks\n")
671 675 ancestors = ()
672 676 if pushop.revs:
673 677 revnums = pycompat.maplist(repo.changelog.rev, pushop.revs)
674 678 ancestors = repo.changelog.ancestors(revnums, inclusive=True)
675 679
676 680 remotebookmark = bookmod.unhexlifybookmarks(listkeys(remote, b'bookmarks'))
677 681
678 682 explicit = {
679 683 repo._bookmarks.expandname(bookmark) for bookmark in pushop.bookmarks
680 684 }
681 685
682 686 comp = bookmod.comparebookmarks(repo, repo._bookmarks, remotebookmark)
683 687 return _processcompared(pushop, ancestors, explicit, remotebookmark, comp)
684 688
685 689
686 690 def _processcompared(pushop, pushed, explicit, remotebms, comp):
687 691 """take decision on bookmarks to push to the remote repo
688 692
689 693 Exists to help extensions alter this behavior.
690 694 """
691 695 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = comp
692 696
693 697 repo = pushop.repo
694 698
695 699 for b, scid, dcid in advsrc:
696 700 if b in explicit:
697 701 explicit.remove(b)
698 702 if not pushed or repo[scid].rev() in pushed:
699 703 pushop.outbookmarks.append((b, dcid, scid))
700 704 # search added bookmark
701 705 for b, scid, dcid in addsrc:
702 706 if b in explicit:
703 707 explicit.remove(b)
704 708 if bookmod.isdivergent(b):
705 709 pushop.ui.warn(_(b'cannot push divergent bookmark %s!\n') % b)
706 710 pushop.bkresult = 2
707 711 else:
708 712 pushop.outbookmarks.append((b, b'', scid))
709 713 # search for overwritten bookmark
710 714 for b, scid, dcid in list(advdst) + list(diverge) + list(differ):
711 715 if b in explicit:
712 716 explicit.remove(b)
713 717 pushop.outbookmarks.append((b, dcid, scid))
714 718 # search for bookmark to delete
715 719 for b, scid, dcid in adddst:
716 720 if b in explicit:
717 721 explicit.remove(b)
718 722 # treat as "deleted locally"
719 723 pushop.outbookmarks.append((b, dcid, b''))
720 724 # identical bookmarks shouldn't get reported
721 725 for b, scid, dcid in same:
722 726 if b in explicit:
723 727 explicit.remove(b)
724 728
725 729 if explicit:
726 730 explicit = sorted(explicit)
727 731 # we should probably list all of them
728 732 pushop.ui.warn(
729 733 _(
730 734 b'bookmark %s does not exist on the local '
731 735 b'or remote repository!\n'
732 736 )
733 737 % explicit[0]
734 738 )
735 739 pushop.bkresult = 2
736 740
737 741 pushop.outbookmarks.sort()
738 742
739 743
740 744 def _pushcheckoutgoing(pushop):
741 745 outgoing = pushop.outgoing
742 746 unfi = pushop.repo.unfiltered()
743 747 if not outgoing.missing:
744 748 # nothing to push
745 749 scmutil.nochangesfound(unfi.ui, unfi, outgoing.excluded)
746 750 return False
747 751 # something to push
748 752 if not pushop.force:
749 753 # if repo.obsstore == False --> no obsolete
750 754 # then, save the iteration
751 755 if unfi.obsstore:
752 756 # this message are here for 80 char limit reason
753 757 mso = _(b"push includes obsolete changeset: %s!")
754 758 mspd = _(b"push includes phase-divergent changeset: %s!")
755 759 mscd = _(b"push includes content-divergent changeset: %s!")
756 760 mst = {
757 761 b"orphan": _(b"push includes orphan changeset: %s!"),
758 762 b"phase-divergent": mspd,
759 763 b"content-divergent": mscd,
760 764 }
761 765 # If we are to push if there is at least one
762 766 # obsolete or unstable changeset in missing, at
763 767 # least one of the missinghead will be obsolete or
764 768 # unstable. So checking heads only is ok
765 769 for node in outgoing.ancestorsof:
766 770 ctx = unfi[node]
767 771 if ctx.obsolete():
768 772 raise error.Abort(mso % ctx)
769 773 elif ctx.isunstable():
770 774 # TODO print more than one instability in the abort
771 775 # message
772 776 raise error.Abort(mst[ctx.instabilities()[0]] % ctx)
773 777
774 778 discovery.checkheads(pushop)
775 779 return True
776 780
777 781
778 782 # List of names of steps to perform for an outgoing bundle2, order matters.
779 783 b2partsgenorder = []
780 784
781 785 # Mapping between step name and function
782 786 #
783 787 # This exists to help extensions wrap steps if necessary
784 788 b2partsgenmapping = {}
785 789
786 790
787 791 def b2partsgenerator(stepname, idx=None):
788 792 """decorator for function generating bundle2 part
789 793
790 794 The function is added to the step -> function mapping and appended to the
791 795 list of steps. Beware that decorated functions will be added in order
792 796 (this may matter).
793 797
794 798 You can only use this decorator for new steps, if you want to wrap a step
795 799 from an extension, attack the b2partsgenmapping dictionary directly."""
796 800
797 801 def dec(func):
798 802 assert stepname not in b2partsgenmapping
799 803 b2partsgenmapping[stepname] = func
800 804 if idx is None:
801 805 b2partsgenorder.append(stepname)
802 806 else:
803 807 b2partsgenorder.insert(idx, stepname)
804 808 return func
805 809
806 810 return dec
807 811
808 812
809 813 def _pushb2ctxcheckheads(pushop, bundler):
810 814 """Generate race condition checking parts
811 815
812 816 Exists as an independent function to aid extensions
813 817 """
814 818 # * 'force' do not check for push race,
815 819 # * if we don't push anything, there are nothing to check.
816 820 if not pushop.force and pushop.outgoing.ancestorsof:
817 821 allowunrelated = b'related' in bundler.capabilities.get(
818 822 b'checkheads', ()
819 823 )
820 824 emptyremote = pushop.pushbranchmap is None
821 825 if not allowunrelated or emptyremote:
822 826 bundler.newpart(b'check:heads', data=iter(pushop.remoteheads))
823 827 else:
824 828 affected = set()
825 829 for branch, heads in pushop.pushbranchmap.items():
826 830 remoteheads, newheads, unsyncedheads, discardedheads = heads
827 831 if remoteheads is not None:
828 832 remote = set(remoteheads)
829 833 affected |= set(discardedheads) & remote
830 834 affected |= remote - set(newheads)
831 835 if affected:
832 836 data = iter(sorted(affected))
833 837 bundler.newpart(b'check:updated-heads', data=data)
834 838
835 839
836 840 def _pushing(pushop):
837 841 """return True if we are pushing anything"""
838 842 return bool(
839 843 pushop.outgoing.missing
840 844 or pushop.outdatedphases
841 845 or pushop.outobsmarkers
842 846 or pushop.outbookmarks
843 847 )
844 848
845 849
846 850 @b2partsgenerator(b'check-bookmarks')
847 851 def _pushb2checkbookmarks(pushop, bundler):
848 852 """insert bookmark move checking"""
849 853 if not _pushing(pushop) or pushop.force:
850 854 return
851 855 b2caps = bundle2.bundle2caps(pushop.remote)
852 856 hasbookmarkcheck = b'bookmarks' in b2caps
853 857 if not (pushop.outbookmarks and hasbookmarkcheck):
854 858 return
855 859 data = []
856 860 for book, old, new in pushop.outbookmarks:
857 861 data.append((book, old))
858 862 checkdata = bookmod.binaryencode(pushop.repo, data)
859 863 bundler.newpart(b'check:bookmarks', data=checkdata)
860 864
861 865
862 866 @b2partsgenerator(b'check-phases')
863 867 def _pushb2checkphases(pushop, bundler):
864 868 """insert phase move checking"""
865 869 if not _pushing(pushop) or pushop.force:
866 870 return
867 871 b2caps = bundle2.bundle2caps(pushop.remote)
868 872 hasphaseheads = b'heads' in b2caps.get(b'phases', ())
869 873 if pushop.remotephases is not None and hasphaseheads:
870 874 # check that the remote phase has not changed
871 875 checks = {p: [] for p in phases.allphases}
872 876 checks[phases.public].extend(pushop.remotephases.publicheads)
873 877 checks[phases.draft].extend(pushop.remotephases.draftroots)
874 878 if any(checks.values()):
875 879 for phase in checks:
876 880 checks[phase].sort()
877 881 checkdata = phases.binaryencode(checks)
878 882 bundler.newpart(b'check:phases', data=checkdata)
879 883
880 884
881 885 @b2partsgenerator(b'changeset')
882 886 def _pushb2ctx(pushop, bundler):
883 887 """handle changegroup push through bundle2
884 888
885 889 addchangegroup result is stored in the ``pushop.cgresult`` attribute.
886 890 """
887 891 if b'changesets' in pushop.stepsdone:
888 892 return
889 893 pushop.stepsdone.add(b'changesets')
890 894 # Send known heads to the server for race detection.
891 895 if not _pushcheckoutgoing(pushop):
892 896 return
893 897 pushop.repo.prepushoutgoinghooks(pushop)
894 898
895 899 _pushb2ctxcheckheads(pushop, bundler)
896 900
897 901 b2caps = bundle2.bundle2caps(pushop.remote)
898 902 version = b'01'
899 903 cgversions = b2caps.get(b'changegroup')
900 904 if cgversions: # 3.1 and 3.2 ship with an empty value
901 905 cgversions = [
902 906 v
903 907 for v in cgversions
904 908 if v in changegroup.supportedoutgoingversions(pushop.repo)
905 909 ]
906 910 if not cgversions:
907 911 raise error.Abort(_(b'no common changegroup version'))
908 912 version = max(cgversions)
909 913
910 914 remote_sidedata = bundle2.read_remote_wanted_sidedata(pushop.remote)
911 915 cgstream = changegroup.makestream(
912 916 pushop.repo,
913 917 pushop.outgoing,
914 918 version,
915 919 b'push',
916 920 bundlecaps=b2caps,
917 921 remote_sidedata=remote_sidedata,
918 922 )
919 923 cgpart = bundler.newpart(b'changegroup', data=cgstream)
920 924 if cgversions:
921 925 cgpart.addparam(b'version', version)
922 926 if scmutil.istreemanifest(pushop.repo):
923 927 cgpart.addparam(b'treemanifest', b'1')
924 928 if repository.REPO_FEATURE_SIDE_DATA in pushop.repo.features:
925 929 cgpart.addparam(b'exp-sidedata', b'1')
926 930
927 931 def handlereply(op):
928 932 """extract addchangegroup returns from server reply"""
929 933 cgreplies = op.records.getreplies(cgpart.id)
930 934 assert len(cgreplies[b'changegroup']) == 1
931 935 pushop.cgresult = cgreplies[b'changegroup'][0][b'return']
932 936
933 937 return handlereply
934 938
935 939
936 940 @b2partsgenerator(b'phase')
937 941 def _pushb2phases(pushop, bundler):
938 942 """handle phase push through bundle2"""
939 943 if b'phases' in pushop.stepsdone:
940 944 return
941 945 b2caps = bundle2.bundle2caps(pushop.remote)
942 946 ui = pushop.repo.ui
943 947
944 948 legacyphase = b'phases' in ui.configlist(b'devel', b'legacy.exchange')
945 949 haspushkey = b'pushkey' in b2caps
946 950 hasphaseheads = b'heads' in b2caps.get(b'phases', ())
947 951
948 952 if hasphaseheads and not legacyphase:
949 953 return _pushb2phaseheads(pushop, bundler)
950 954 elif haspushkey:
951 955 return _pushb2phasespushkey(pushop, bundler)
952 956
953 957
954 958 def _pushb2phaseheads(pushop, bundler):
955 959 """push phase information through a bundle2 - binary part"""
956 960 pushop.stepsdone.add(b'phases')
957 961 if pushop.outdatedphases:
958 962 updates = {p: [] for p in phases.allphases}
959 963 updates[0].extend(h.node() for h in pushop.outdatedphases)
960 964 phasedata = phases.binaryencode(updates)
961 965 bundler.newpart(b'phase-heads', data=phasedata)
962 966
963 967
964 968 def _pushb2phasespushkey(pushop, bundler):
965 969 """push phase information through a bundle2 - pushkey part"""
966 970 pushop.stepsdone.add(b'phases')
967 971 part2node = []
968 972
969 973 def handlefailure(pushop, exc):
970 974 targetid = int(exc.partid)
971 975 for partid, node in part2node:
972 976 if partid == targetid:
973 977 raise error.Abort(_(b'updating %s to public failed') % node)
974 978
975 979 enc = pushkey.encode
976 980 for newremotehead in pushop.outdatedphases:
977 981 part = bundler.newpart(b'pushkey')
978 982 part.addparam(b'namespace', enc(b'phases'))
979 983 part.addparam(b'key', enc(newremotehead.hex()))
980 984 part.addparam(b'old', enc(b'%d' % phases.draft))
981 985 part.addparam(b'new', enc(b'%d' % phases.public))
982 986 part2node.append((part.id, newremotehead))
983 987 pushop.pkfailcb[part.id] = handlefailure
984 988
985 989 def handlereply(op):
986 990 for partid, node in part2node:
987 991 partrep = op.records.getreplies(partid)
988 992 results = partrep[b'pushkey']
989 993 assert len(results) <= 1
990 994 msg = None
991 995 if not results:
992 996 msg = _(b'server ignored update of %s to public!\n') % node
993 997 elif not int(results[0][b'return']):
994 998 msg = _(b'updating %s to public failed!\n') % node
995 999 if msg is not None:
996 1000 pushop.ui.warn(msg)
997 1001
998 1002 return handlereply
999 1003
1000 1004
1001 1005 @b2partsgenerator(b'obsmarkers')
1002 1006 def _pushb2obsmarkers(pushop, bundler):
1003 1007 if b'obsmarkers' in pushop.stepsdone:
1004 1008 return
1005 1009 remoteversions = bundle2.obsmarkersversion(bundler.capabilities)
1006 1010 if obsolete.commonversion(remoteversions) is None:
1007 1011 return
1008 1012 pushop.stepsdone.add(b'obsmarkers')
1009 1013 if pushop.outobsmarkers:
1010 1014 markers = obsutil.sortedmarkers(pushop.outobsmarkers)
1011 1015 bundle2.buildobsmarkerspart(bundler, markers)
1012 1016
1013 1017
1014 1018 @b2partsgenerator(b'bookmarks')
1015 1019 def _pushb2bookmarks(pushop, bundler):
1016 1020 """handle bookmark push through bundle2"""
1017 1021 if b'bookmarks' in pushop.stepsdone:
1018 1022 return
1019 1023 b2caps = bundle2.bundle2caps(pushop.remote)
1020 1024
1021 1025 legacy = pushop.repo.ui.configlist(b'devel', b'legacy.exchange')
1022 1026 legacybooks = b'bookmarks' in legacy
1023 1027
1024 1028 if not legacybooks and b'bookmarks' in b2caps:
1025 1029 return _pushb2bookmarkspart(pushop, bundler)
1026 1030 elif b'pushkey' in b2caps:
1027 1031 return _pushb2bookmarkspushkey(pushop, bundler)
1028 1032
1029 1033
1030 1034 def _bmaction(old, new):
1031 1035 """small utility for bookmark pushing"""
1032 1036 if not old:
1033 1037 return b'export'
1034 1038 elif not new:
1035 1039 return b'delete'
1036 1040 return b'update'
1037 1041
1038 1042
1039 1043 def _abortonsecretctx(pushop, node, b):
1040 1044 """abort if a given bookmark points to a secret changeset"""
1041 1045 if node and pushop.repo[node].phase() == phases.secret:
1042 1046 raise error.Abort(
1043 1047 _(b'cannot push bookmark %s as it points to a secret changeset') % b
1044 1048 )
1045 1049
1046 1050
1047 1051 def _pushb2bookmarkspart(pushop, bundler):
1048 1052 pushop.stepsdone.add(b'bookmarks')
1049 1053 if not pushop.outbookmarks:
1050 1054 return
1051 1055
1052 1056 allactions = []
1053 1057 data = []
1054 1058 for book, old, new in pushop.outbookmarks:
1055 1059 _abortonsecretctx(pushop, new, book)
1056 1060 data.append((book, new))
1057 1061 allactions.append((book, _bmaction(old, new)))
1058 1062 checkdata = bookmod.binaryencode(pushop.repo, data)
1059 1063 bundler.newpart(b'bookmarks', data=checkdata)
1060 1064
1061 1065 def handlereply(op):
1062 1066 ui = pushop.ui
1063 1067 # if success
1064 1068 for book, action in allactions:
1065 1069 ui.status(bookmsgmap[action][0] % book)
1066 1070
1067 1071 return handlereply
1068 1072
1069 1073
1070 1074 def _pushb2bookmarkspushkey(pushop, bundler):
1071 1075 pushop.stepsdone.add(b'bookmarks')
1072 1076 part2book = []
1073 1077 enc = pushkey.encode
1074 1078
1075 1079 def handlefailure(pushop, exc):
1076 1080 targetid = int(exc.partid)
1077 1081 for partid, book, action in part2book:
1078 1082 if partid == targetid:
1079 1083 raise error.Abort(bookmsgmap[action][1].rstrip() % book)
1080 1084 # we should not be called for part we did not generated
1081 1085 assert False
1082 1086
1083 1087 for book, old, new in pushop.outbookmarks:
1084 1088 _abortonsecretctx(pushop, new, book)
1085 1089 part = bundler.newpart(b'pushkey')
1086 1090 part.addparam(b'namespace', enc(b'bookmarks'))
1087 1091 part.addparam(b'key', enc(book))
1088 1092 part.addparam(b'old', enc(hex(old)))
1089 1093 part.addparam(b'new', enc(hex(new)))
1090 1094 action = b'update'
1091 1095 if not old:
1092 1096 action = b'export'
1093 1097 elif not new:
1094 1098 action = b'delete'
1095 1099 part2book.append((part.id, book, action))
1096 1100 pushop.pkfailcb[part.id] = handlefailure
1097 1101
1098 1102 def handlereply(op):
1099 1103 ui = pushop.ui
1100 1104 for partid, book, action in part2book:
1101 1105 partrep = op.records.getreplies(partid)
1102 1106 results = partrep[b'pushkey']
1103 1107 assert len(results) <= 1
1104 1108 if not results:
1105 1109 pushop.ui.warn(_(b'server ignored bookmark %s update\n') % book)
1106 1110 else:
1107 1111 ret = int(results[0][b'return'])
1108 1112 if ret:
1109 1113 ui.status(bookmsgmap[action][0] % book)
1110 1114 else:
1111 1115 ui.warn(bookmsgmap[action][1] % book)
1112 1116 if pushop.bkresult is not None:
1113 1117 pushop.bkresult = 1
1114 1118
1115 1119 return handlereply
1116 1120
1117 1121
1118 1122 @b2partsgenerator(b'pushvars', idx=0)
1119 1123 def _getbundlesendvars(pushop, bundler):
1120 1124 '''send shellvars via bundle2'''
1121 1125 pushvars = pushop.pushvars
1122 1126 if pushvars:
1123 1127 shellvars = {}
1124 1128 for raw in pushvars:
1125 1129 if b'=' not in raw:
1126 1130 msg = (
1127 1131 b"unable to parse variable '%s', should follow "
1128 1132 b"'KEY=VALUE' or 'KEY=' format"
1129 1133 )
1130 1134 raise error.Abort(msg % raw)
1131 1135 k, v = raw.split(b'=', 1)
1132 1136 shellvars[k] = v
1133 1137
1134 1138 part = bundler.newpart(b'pushvars')
1135 1139
1136 1140 for key, value in shellvars.items():
1137 1141 part.addparam(key, value, mandatory=False)
1138 1142
1139 1143
1140 1144 def _pushbundle2(pushop):
1141 1145 """push data to the remote using bundle2
1142 1146
1143 1147 The only currently supported type of data is changegroup but this will
1144 1148 evolve in the future."""
1145 1149 bundler = bundle2.bundle20(pushop.ui, bundle2.bundle2caps(pushop.remote))
1146 1150 pushback = pushop.trmanager and pushop.ui.configbool(
1147 1151 b'experimental', b'bundle2.pushback'
1148 1152 )
1149 1153
1150 1154 # create reply capability
1151 1155 capsblob = bundle2.encodecaps(
1152 1156 bundle2.getrepocaps(pushop.repo, allowpushback=pushback, role=b'client')
1153 1157 )
1154 1158 bundler.newpart(b'replycaps', data=capsblob)
1155 1159 replyhandlers = []
1156 1160 for partgenname in b2partsgenorder:
1157 1161 partgen = b2partsgenmapping[partgenname]
1158 1162 ret = partgen(pushop, bundler)
1159 1163 if callable(ret):
1160 1164 replyhandlers.append(ret)
1161 1165 # do not push if nothing to push
1162 1166 if bundler.nbparts <= 1:
1163 1167 return
1164 1168 stream = util.chunkbuffer(bundler.getchunks())
1165 1169 try:
1166 1170 try:
1167 1171 with pushop.remote.commandexecutor() as e:
1168 1172 reply = e.callcommand(
1169 1173 b'unbundle',
1170 1174 {
1171 1175 b'bundle': stream,
1172 1176 b'heads': [b'force'],
1173 1177 b'url': pushop.remote.url(),
1174 1178 },
1175 1179 ).result()
1176 1180 except error.BundleValueError as exc:
1177 1181 raise error.RemoteError(_(b'missing support for %s') % exc)
1178 1182 try:
1179 1183 trgetter = None
1180 1184 if pushback:
1181 1185 trgetter = pushop.trmanager.transaction
1182 1186 op = bundle2.processbundle(pushop.repo, reply, trgetter)
1183 1187 except error.BundleValueError as exc:
1184 1188 raise error.RemoteError(_(b'missing support for %s') % exc)
1185 1189 except bundle2.AbortFromPart as exc:
1186 1190 pushop.ui.error(_(b'remote: %s\n') % exc)
1187 1191 if exc.hint is not None:
1188 1192 pushop.ui.error(_(b'remote: %s\n') % (b'(%s)' % exc.hint))
1189 1193 raise error.RemoteError(_(b'push failed on remote'))
1190 1194 except error.PushkeyFailed as exc:
1191 1195 partid = int(exc.partid)
1192 1196 if partid not in pushop.pkfailcb:
1193 1197 raise
1194 1198 pushop.pkfailcb[partid](pushop, exc)
1195 1199 for rephand in replyhandlers:
1196 1200 rephand(op)
1197 1201
1198 1202
1199 1203 def _pushchangeset(pushop):
1200 1204 """Make the actual push of changeset bundle to remote repo"""
1201 1205 if b'changesets' in pushop.stepsdone:
1202 1206 return
1203 1207 pushop.stepsdone.add(b'changesets')
1204 1208 if not _pushcheckoutgoing(pushop):
1205 1209 return
1206 1210
1207 1211 # Should have verified this in push().
1208 1212 assert pushop.remote.capable(b'unbundle')
1209 1213
1210 1214 pushop.repo.prepushoutgoinghooks(pushop)
1211 1215 outgoing = pushop.outgoing
1212 1216 # TODO: get bundlecaps from remote
1213 1217 bundlecaps = None
1214 1218 # create a changegroup from local
1215 1219 if pushop.revs is None and not (
1216 1220 outgoing.excluded or pushop.repo.changelog.filteredrevs
1217 1221 ):
1218 1222 # push everything,
1219 1223 # use the fast path, no race possible on push
1220 1224 cg = changegroup.makechangegroup(
1221 1225 pushop.repo,
1222 1226 outgoing,
1223 1227 b'01',
1224 1228 b'push',
1225 1229 fastpath=True,
1226 1230 bundlecaps=bundlecaps,
1227 1231 )
1228 1232 else:
1229 1233 cg = changegroup.makechangegroup(
1230 1234 pushop.repo, outgoing, b'01', b'push', bundlecaps=bundlecaps
1231 1235 )
1232 1236
1233 1237 # apply changegroup to remote
1234 1238 # local repo finds heads on server, finds out what
1235 1239 # revs it must push. once revs transferred, if server
1236 1240 # finds it has different heads (someone else won
1237 1241 # commit/push race), server aborts.
1238 1242 if pushop.force:
1239 1243 remoteheads = [b'force']
1240 1244 else:
1241 1245 remoteheads = pushop.remoteheads
1242 1246 # ssh: return remote's addchangegroup()
1243 1247 # http: return remote's addchangegroup() or 0 for error
1244 1248 pushop.cgresult = pushop.remote.unbundle(cg, remoteheads, pushop.repo.url())
1245 1249
1246 1250
1247 1251 def _pushsyncphase(pushop):
1248 1252 """synchronise phase information locally and remotely"""
1249 1253 cheads = pushop.commonheads
1250 1254 # even when we don't push, exchanging phase data is useful
1251 1255 remotephases = listkeys(pushop.remote, b'phases')
1252 1256 if (
1253 1257 pushop.ui.configbool(b'ui', b'_usedassubrepo')
1254 1258 and remotephases # server supports phases
1255 1259 and pushop.cgresult is None # nothing was pushed
1256 1260 and remotephases.get(b'publishing', False)
1257 1261 ):
1258 1262 # When:
1259 1263 # - this is a subrepo push
1260 1264 # - and remote support phase
1261 1265 # - and no changeset was pushed
1262 1266 # - and remote is publishing
1263 1267 # We may be in issue 3871 case!
1264 1268 # We drop the possible phase synchronisation done by
1265 1269 # courtesy to publish changesets possibly locally draft
1266 1270 # on the remote.
1267 1271 remotephases = {b'publishing': b'True'}
1268 1272 if not remotephases: # old server or public only reply from non-publishing
1269 1273 _localphasemove(pushop, cheads)
1270 1274 # don't push any phase data as there is nothing to push
1271 1275 else:
1272 1276 ana = phases.analyzeremotephases(pushop.repo, cheads, remotephases)
1273 1277 pheads, droots = ana
1274 1278 ### Apply remote phase on local
1275 1279 if remotephases.get(b'publishing', False):
1276 1280 _localphasemove(pushop, cheads)
1277 1281 else: # publish = False
1278 1282 _localphasemove(pushop, pheads)
1279 1283 _localphasemove(pushop, cheads, phases.draft)
1280 1284 ### Apply local phase on remote
1281 1285
1282 1286 if pushop.cgresult:
1283 1287 if b'phases' in pushop.stepsdone:
1284 1288 # phases already pushed though bundle2
1285 1289 return
1286 1290 outdated = pushop.outdatedphases
1287 1291 else:
1288 1292 outdated = pushop.fallbackoutdatedphases
1289 1293
1290 1294 pushop.stepsdone.add(b'phases')
1291 1295
1292 1296 # filter heads already turned public by the push
1293 1297 outdated = [c for c in outdated if c.node() not in pheads]
1294 1298 # fallback to independent pushkey command
1295 1299 for newremotehead in outdated:
1296 1300 with pushop.remote.commandexecutor() as e:
1297 1301 r = e.callcommand(
1298 1302 b'pushkey',
1299 1303 {
1300 1304 b'namespace': b'phases',
1301 1305 b'key': newremotehead.hex(),
1302 1306 b'old': b'%d' % phases.draft,
1303 1307 b'new': b'%d' % phases.public,
1304 1308 },
1305 1309 ).result()
1306 1310
1307 1311 if not r:
1308 1312 pushop.ui.warn(
1309 1313 _(b'updating %s to public failed!\n') % newremotehead
1310 1314 )
1311 1315
1312 1316
1313 1317 def _localphasemove(pushop, nodes, phase=phases.public):
1314 1318 """move <nodes> to <phase> in the local source repo"""
1315 1319 if pushop.trmanager:
1316 1320 phases.advanceboundary(
1317 1321 pushop.repo, pushop.trmanager.transaction(), phase, nodes
1318 1322 )
1319 1323 else:
1320 1324 # repo is not locked, do not change any phases!
1321 1325 # Informs the user that phases should have been moved when
1322 1326 # applicable.
1323 1327 actualmoves = [n for n in nodes if phase < pushop.repo[n].phase()]
1324 1328 phasestr = phases.phasenames[phase]
1325 1329 if actualmoves:
1326 1330 pushop.ui.status(
1327 1331 _(
1328 1332 b'cannot lock source repo, skipping '
1329 1333 b'local %s phase update\n'
1330 1334 )
1331 1335 % phasestr
1332 1336 )
1333 1337
1334 1338
1335 1339 def _pushobsolete(pushop):
1336 1340 """utility function to push obsolete markers to a remote"""
1337 1341 if b'obsmarkers' in pushop.stepsdone:
1338 1342 return
1339 1343 repo = pushop.repo
1340 1344 remote = pushop.remote
1341 1345 pushop.stepsdone.add(b'obsmarkers')
1342 1346 if pushop.outobsmarkers:
1343 1347 pushop.ui.debug(b'try to push obsolete markers to remote\n')
1344 1348 rslts = []
1345 1349 markers = obsutil.sortedmarkers(pushop.outobsmarkers)
1346 1350 remotedata = obsolete._pushkeyescape(markers)
1347 1351 for key in sorted(remotedata, reverse=True):
1348 1352 # reverse sort to ensure we end with dump0
1349 1353 data = remotedata[key]
1350 1354 rslts.append(remote.pushkey(b'obsolete', key, b'', data))
1351 1355 if [r for r in rslts if not r]:
1352 1356 msg = _(b'failed to push some obsolete markers!\n')
1353 1357 repo.ui.warn(msg)
1354 1358
1355 1359
1356 1360 def _pushbookmark(pushop):
1357 1361 """Update bookmark position on remote"""
1358 1362 if pushop.cgresult == 0 or b'bookmarks' in pushop.stepsdone:
1359 1363 return
1360 1364 pushop.stepsdone.add(b'bookmarks')
1361 1365 ui = pushop.ui
1362 1366 remote = pushop.remote
1363 1367
1364 1368 for b, old, new in pushop.outbookmarks:
1365 1369 action = b'update'
1366 1370 if not old:
1367 1371 action = b'export'
1368 1372 elif not new:
1369 1373 action = b'delete'
1370 1374
1371 1375 with remote.commandexecutor() as e:
1372 1376 r = e.callcommand(
1373 1377 b'pushkey',
1374 1378 {
1375 1379 b'namespace': b'bookmarks',
1376 1380 b'key': b,
1377 1381 b'old': hex(old),
1378 1382 b'new': hex(new),
1379 1383 },
1380 1384 ).result()
1381 1385
1382 1386 if r:
1383 1387 ui.status(bookmsgmap[action][0] % b)
1384 1388 else:
1385 1389 ui.warn(bookmsgmap[action][1] % b)
1386 1390 # discovery can have set the value form invalid entry
1387 1391 if pushop.bkresult is not None:
1388 1392 pushop.bkresult = 1
1389 1393
1390 1394
1391 1395 class pulloperation:
1392 1396 """A object that represent a single pull operation
1393 1397
1394 1398 It purpose is to carry pull related state and very common operation.
1395 1399
1396 1400 A new should be created at the beginning of each pull and discarded
1397 1401 afterward.
1398 1402 """
1399 1403
1400 1404 def __init__(
1401 1405 self,
1402 1406 repo,
1403 1407 remote,
1404 1408 heads=None,
1405 1409 force=False,
1406 1410 bookmarks=(),
1407 1411 remotebookmarks=None,
1408 1412 streamclonerequested=None,
1409 1413 includepats=None,
1410 1414 excludepats=None,
1411 1415 depth=None,
1412 1416 path=None,
1413 1417 ):
1414 1418 # repo we pull into
1415 1419 self.repo = repo
1416 1420 # repo we pull from
1417 1421 self.remote = remote
1418 1422 # path object used to build this remote
1419 1423 #
1420 1424 # Ideally, the remote peer would carry that directly.
1421 1425 self.remote_path = path
1422 1426 # revision we try to pull (None is "all")
1423 1427 self.heads = heads
1424 1428 # bookmark pulled explicitly
1425 1429 self.explicitbookmarks = [
1426 1430 repo._bookmarks.expandname(bookmark) for bookmark in bookmarks
1427 1431 ]
1428 1432 # do we force pull?
1429 1433 self.force = force
1430 1434 # whether a streaming clone was requested
1431 1435 self.streamclonerequested = streamclonerequested
1432 1436 # transaction manager
1433 1437 self.trmanager = None
1434 1438 # set of common changeset between local and remote before pull
1435 1439 self.common = None
1436 1440 # set of pulled head
1437 1441 self.rheads = None
1438 1442 # list of missing changeset to fetch remotely
1439 1443 self.fetch = None
1440 1444 # remote bookmarks data
1441 1445 self.remotebookmarks = remotebookmarks
1442 1446 # result of changegroup pulling (used as return code by pull)
1443 1447 self.cgresult = None
1444 1448 # list of step already done
1445 1449 self.stepsdone = set()
1446 1450 # Whether we attempted a clone from pre-generated bundles.
1447 1451 self.clonebundleattempted = False
1448 1452 # Set of file patterns to include.
1449 1453 self.includepats = includepats
1450 1454 # Set of file patterns to exclude.
1451 1455 self.excludepats = excludepats
1452 1456 # Number of ancestor changesets to pull from each pulled head.
1453 1457 self.depth = depth
1454 1458
1455 1459 @util.propertycache
1456 1460 def pulledsubset(self):
1457 1461 """heads of the set of changeset target by the pull"""
1458 1462 # compute target subset
1459 1463 if self.heads is None:
1460 1464 # We pulled every thing possible
1461 1465 # sync on everything common
1462 1466 c = set(self.common)
1463 1467 ret = list(self.common)
1464 1468 for n in self.rheads:
1465 1469 if n not in c:
1466 1470 ret.append(n)
1467 1471 return ret
1468 1472 else:
1469 1473 # We pulled a specific subset
1470 1474 # sync on this subset
1471 1475 return self.heads
1472 1476
1473 1477 @util.propertycache
1474 1478 def canusebundle2(self):
1475 1479 return not _forcebundle1(self)
1476 1480
1477 1481 @util.propertycache
1478 1482 def remotebundle2caps(self):
1479 1483 return bundle2.bundle2caps(self.remote)
1480 1484
1481 1485 def gettransaction(self):
1482 1486 # deprecated; talk to trmanager directly
1483 1487 return self.trmanager.transaction()
1484 1488
1485 1489
1486 1490 class transactionmanager(util.transactional):
1487 1491 """An object to manage the life cycle of a transaction
1488 1492
1489 1493 It creates the transaction on demand and calls the appropriate hooks when
1490 1494 closing the transaction."""
1491 1495
1492 1496 def __init__(self, repo, source, url):
1493 1497 self.repo = repo
1494 1498 self.source = source
1495 1499 self.url = url
1496 1500 self._tr = None
1497 1501
1498 1502 def transaction(self):
1499 1503 """Return an open transaction object, constructing if necessary"""
1500 1504 if not self._tr:
1501 1505 trname = b'%s\n%s' % (self.source, urlutil.hidepassword(self.url))
1502 1506 self._tr = self.repo.transaction(trname)
1503 1507 self._tr.hookargs[b'source'] = self.source
1504 1508 self._tr.hookargs[b'url'] = self.url
1505 1509 return self._tr
1506 1510
1507 1511 def close(self):
1508 1512 """close transaction if created"""
1509 1513 if self._tr is not None:
1510 1514 self._tr.close()
1511 1515
1512 1516 def release(self):
1513 1517 """release transaction if created"""
1514 1518 if self._tr is not None:
1515 1519 self._tr.release()
1516 1520
1517 1521
1518 1522 def listkeys(remote, namespace):
1519 1523 with remote.commandexecutor() as e:
1520 1524 return e.callcommand(b'listkeys', {b'namespace': namespace}).result()
1521 1525
1522 1526
1523 1527 def _fullpullbundle2(repo, pullop):
1524 1528 # The server may send a partial reply, i.e. when inlining
1525 1529 # pre-computed bundles. In that case, update the common
1526 1530 # set based on the results and pull another bundle.
1527 1531 #
1528 1532 # There are two indicators that the process is finished:
1529 1533 # - no changeset has been added, or
1530 1534 # - all remote heads are known locally.
1531 1535 # The head check must use the unfiltered view as obsoletion
1532 1536 # markers can hide heads.
1533 1537 unfi = repo.unfiltered()
1534 1538 unficl = unfi.changelog
1535 1539
1536 1540 def headsofdiff(h1, h2):
1537 1541 """Returns heads(h1 % h2)"""
1538 1542 res = unfi.set(b'heads(%ln %% %ln)', h1, h2)
1539 1543 return {ctx.node() for ctx in res}
1540 1544
1541 1545 def headsofunion(h1, h2):
1542 1546 """Returns heads((h1 + h2) - null)"""
1543 1547 res = unfi.set(b'heads((%ln + %ln - null))', h1, h2)
1544 1548 return {ctx.node() for ctx in res}
1545 1549
1546 1550 while True:
1547 1551 old_heads = unficl.heads()
1548 1552 clstart = len(unficl)
1549 1553 _pullbundle2(pullop)
1550 1554 if requirements.NARROW_REQUIREMENT in repo.requirements:
1551 1555 # XXX narrow clones filter the heads on the server side during
1552 1556 # XXX getbundle and result in partial replies as well.
1553 1557 # XXX Disable pull bundles in this case as band aid to avoid
1554 1558 # XXX extra round trips.
1555 1559 break
1556 1560 if clstart == len(unficl):
1557 1561 break
1558 1562 if all(unficl.hasnode(n) for n in pullop.rheads):
1559 1563 break
1560 1564 new_heads = headsofdiff(unficl.heads(), old_heads)
1561 1565 pullop.common = headsofunion(new_heads, pullop.common)
1562 1566 pullop.rheads = set(pullop.rheads) - pullop.common
1563 1567
1564 1568
1565 1569 def add_confirm_callback(repo, pullop):
1566 1570 """adds a finalize callback to transaction which can be used to show stats
1567 1571 to user and confirm the pull before committing transaction"""
1568 1572
1569 1573 tr = pullop.trmanager.transaction()
1570 1574 scmutil.registersummarycallback(
1571 1575 repo, tr, txnname=b'pull', as_validator=True
1572 1576 )
1573 1577 reporef = weakref.ref(repo.unfiltered())
1574 1578
1575 1579 def prompt(tr):
1576 1580 repo = reporef()
1577 1581 cm = _(b'accept incoming changes (yn)?$$ &Yes $$ &No')
1578 1582 if repo.ui.promptchoice(cm):
1579 1583 raise error.Abort(b"user aborted")
1580 1584
1581 1585 tr.addvalidator(b'900-pull-prompt', prompt)
1582 1586
1583 1587
1584 1588 def pull(
1585 1589 repo,
1586 1590 remote,
1587 1591 path=None,
1588 1592 heads=None,
1589 1593 force=False,
1590 1594 bookmarks=(),
1591 1595 opargs=None,
1592 1596 streamclonerequested=None,
1593 1597 includepats=None,
1594 1598 excludepats=None,
1595 1599 depth=None,
1596 1600 confirm=None,
1597 1601 ):
1598 1602 """Fetch repository data from a remote.
1599 1603
1600 1604 This is the main function used to retrieve data from a remote repository.
1601 1605
1602 1606 ``repo`` is the local repository to clone into.
1603 1607 ``remote`` is a peer instance.
1604 1608 ``heads`` is an iterable of revisions we want to pull. ``None`` (the
1605 1609 default) means to pull everything from the remote.
1606 1610 ``bookmarks`` is an iterable of bookmarks requesting to be pulled. By
1607 1611 default, all remote bookmarks are pulled.
1608 1612 ``opargs`` are additional keyword arguments to pass to ``pulloperation``
1609 1613 initialization.
1610 1614 ``streamclonerequested`` is a boolean indicating whether a "streaming
1611 1615 clone" is requested. A "streaming clone" is essentially a raw file copy
1612 1616 of revlogs from the server. This only works when the local repository is
1613 1617 empty. The default value of ``None`` means to respect the server
1614 1618 configuration for preferring stream clones.
1615 1619 ``includepats`` and ``excludepats`` define explicit file patterns to
1616 1620 include and exclude in storage, respectively. If not defined, narrow
1617 1621 patterns from the repo instance are used, if available.
1618 1622 ``depth`` is an integer indicating the DAG depth of history we're
1619 1623 interested in. If defined, for each revision specified in ``heads``, we
1620 1624 will fetch up to this many of its ancestors and data associated with them.
1621 1625 ``confirm`` is a boolean indicating whether the pull should be confirmed
1622 1626 before committing the transaction. This overrides HGPLAIN.
1623 1627
1624 1628 Returns the ``pulloperation`` created for this pull.
1625 1629 """
1626 1630 if opargs is None:
1627 1631 opargs = {}
1628 1632
1629 1633 # We allow the narrow patterns to be passed in explicitly to provide more
1630 1634 # flexibility for API consumers.
1631 1635 if includepats or excludepats:
1632 1636 includepats = includepats or set()
1633 1637 excludepats = excludepats or set()
1634 1638 else:
1635 1639 includepats, excludepats = repo.narrowpats
1636 1640
1637 1641 narrowspec.validatepatterns(includepats)
1638 1642 narrowspec.validatepatterns(excludepats)
1639 1643
1640 1644 pullop = pulloperation(
1641 1645 repo,
1642 1646 remote,
1643 1647 path=path,
1644 1648 heads=heads,
1645 1649 force=force,
1646 1650 bookmarks=bookmarks,
1647 1651 streamclonerequested=streamclonerequested,
1648 1652 includepats=includepats,
1649 1653 excludepats=excludepats,
1650 1654 depth=depth,
1651 1655 **pycompat.strkwargs(opargs)
1652 1656 )
1653 1657
1654 1658 peerlocal = pullop.remote.local()
1655 1659 if peerlocal:
1656 1660 missing = set(peerlocal.requirements) - pullop.repo.supported
1657 1661 if missing:
1658 1662 msg = _(
1659 1663 b"required features are not"
1660 1664 b" supported in the destination:"
1661 1665 b" %s"
1662 1666 ) % (b', '.join(sorted(missing)))
1663 1667 raise error.Abort(msg)
1664 1668
1665 1669 for category in repo._wanted_sidedata:
1666 1670 # Check that a computer is registered for that category for at least
1667 1671 # one revlog kind.
1668 1672 for kind, computers in repo._sidedata_computers.items():
1669 1673 if computers.get(category):
1670 1674 break
1671 1675 else:
1672 1676 # This should never happen since repos are supposed to be able to
1673 1677 # generate the sidedata they require.
1674 1678 raise error.ProgrammingError(
1675 1679 _(
1676 1680 b'sidedata category requested by local side without local'
1677 1681 b"support: '%s'"
1678 1682 )
1679 1683 % pycompat.bytestr(category)
1680 1684 )
1681 1685
1682 1686 pullop.trmanager = transactionmanager(repo, b'pull', remote.url())
1683 1687 wlock = util.nullcontextmanager()
1684 1688 if not bookmod.bookmarksinstore(repo):
1685 1689 wlock = repo.wlock()
1686 1690 with wlock, repo.lock(), pullop.trmanager:
1687 1691 if confirm or (
1688 1692 repo.ui.configbool(b"pull", b"confirm") and not repo.ui.plain()
1689 1693 ):
1690 1694 add_confirm_callback(repo, pullop)
1691 1695
1692 1696 # This should ideally be in _pullbundle2(). However, it needs to run
1693 1697 # before discovery to avoid extra work.
1694 1698 _maybeapplyclonebundle(pullop)
1695 1699 streamclone.maybeperformlegacystreamclone(pullop)
1696 1700 _pulldiscovery(pullop)
1697 1701 if pullop.canusebundle2:
1698 1702 _fullpullbundle2(repo, pullop)
1699 1703 _pullchangeset(pullop)
1700 1704 _pullphase(pullop)
1701 1705 _pullbookmarks(pullop)
1702 1706 _pullobsolete(pullop)
1703 1707
1704 1708 # storing remotenames
1705 1709 if repo.ui.configbool(b'experimental', b'remotenames'):
1706 1710 logexchange.pullremotenames(repo, remote)
1707 1711
1708 1712 return pullop
1709 1713
1710 1714
1711 1715 # list of steps to perform discovery before pull
1712 1716 pulldiscoveryorder = []
1713 1717
1714 1718 # Mapping between step name and function
1715 1719 #
1716 1720 # This exists to help extensions wrap steps if necessary
1717 1721 pulldiscoverymapping = {}
1718 1722
1719 1723
1720 1724 def pulldiscovery(stepname):
1721 1725 """decorator for function performing discovery before pull
1722 1726
1723 1727 The function is added to the step -> function mapping and appended to the
1724 1728 list of steps. Beware that decorated function will be added in order (this
1725 1729 may matter).
1726 1730
1727 1731 You can only use this decorator for a new step, if you want to wrap a step
1728 1732 from an extension, change the pulldiscovery dictionary directly."""
1729 1733
1730 1734 def dec(func):
1731 1735 assert stepname not in pulldiscoverymapping
1732 1736 pulldiscoverymapping[stepname] = func
1733 1737 pulldiscoveryorder.append(stepname)
1734 1738 return func
1735 1739
1736 1740 return dec
1737 1741
1738 1742
1739 1743 def _pulldiscovery(pullop):
1740 1744 """Run all discovery steps"""
1741 1745 for stepname in pulldiscoveryorder:
1742 1746 step = pulldiscoverymapping[stepname]
1743 1747 step(pullop)
1744 1748
1745 1749
1746 1750 @pulldiscovery(b'b1:bookmarks')
1747 1751 def _pullbookmarkbundle1(pullop):
1748 1752 """fetch bookmark data in bundle1 case
1749 1753
1750 1754 If not using bundle2, we have to fetch bookmarks before changeset
1751 1755 discovery to reduce the chance and impact of race conditions."""
1752 1756 if pullop.remotebookmarks is not None:
1753 1757 return
1754 1758 if pullop.canusebundle2 and b'listkeys' in pullop.remotebundle2caps:
1755 1759 # all known bundle2 servers now support listkeys, but lets be nice with
1756 1760 # new implementation.
1757 1761 return
1758 1762 books = listkeys(pullop.remote, b'bookmarks')
1759 1763 pullop.remotebookmarks = bookmod.unhexlifybookmarks(books)
1760 1764
1761 1765
1762 1766 @pulldiscovery(b'changegroup')
1763 1767 def _pulldiscoverychangegroup(pullop):
1764 1768 """discovery phase for the pull
1765 1769
1766 1770 Current handle changeset discovery only, will change handle all discovery
1767 1771 at some point."""
1768 1772 tmp = discovery.findcommonincoming(
1769 1773 pullop.repo, pullop.remote, heads=pullop.heads, force=pullop.force
1770 1774 )
1771 1775 common, fetch, rheads = tmp
1772 1776 has_node = pullop.repo.unfiltered().changelog.index.has_node
1773 1777 if fetch and rheads:
1774 1778 # If a remote heads is filtered locally, put in back in common.
1775 1779 #
1776 1780 # This is a hackish solution to catch most of "common but locally
1777 1781 # hidden situation". We do not performs discovery on unfiltered
1778 1782 # repository because it end up doing a pathological amount of round
1779 1783 # trip for w huge amount of changeset we do not care about.
1780 1784 #
1781 1785 # If a set of such "common but filtered" changeset exist on the server
1782 1786 # but are not including a remote heads, we'll not be able to detect it,
1783 1787 scommon = set(common)
1784 1788 for n in rheads:
1785 1789 if has_node(n):
1786 1790 if n not in scommon:
1787 1791 common.append(n)
1788 1792 if set(rheads).issubset(set(common)):
1789 1793 fetch = []
1790 1794 pullop.common = common
1791 1795 pullop.fetch = fetch
1792 1796 pullop.rheads = rheads
1793 1797
1794 1798
1795 1799 def _pullbundle2(pullop):
1796 1800 """pull data using bundle2
1797 1801
1798 1802 For now, the only supported data are changegroup."""
1799 1803 kwargs = {b'bundlecaps': caps20to10(pullop.repo, role=b'client')}
1800 1804
1801 1805 # make ui easier to access
1802 1806 ui = pullop.repo.ui
1803 1807
1804 1808 # At the moment we don't do stream clones over bundle2. If that is
1805 1809 # implemented then here's where the check for that will go.
1806 1810 streaming = streamclone.canperformstreamclone(pullop, bundle2=True)[0]
1807 1811
1808 1812 # declare pull perimeters
1809 1813 kwargs[b'common'] = pullop.common
1810 1814 kwargs[b'heads'] = pullop.heads or pullop.rheads
1811 1815
1812 1816 # check server supports narrow and then adding includepats and excludepats
1813 1817 servernarrow = pullop.remote.capable(wireprototypes.NARROWCAP)
1814 1818 if servernarrow and pullop.includepats:
1815 1819 kwargs[b'includepats'] = pullop.includepats
1816 1820 if servernarrow and pullop.excludepats:
1817 1821 kwargs[b'excludepats'] = pullop.excludepats
1818 1822
1819 1823 if streaming:
1820 1824 kwargs[b'cg'] = False
1821 1825 kwargs[b'stream'] = True
1822 1826 pullop.stepsdone.add(b'changegroup')
1823 1827 pullop.stepsdone.add(b'phases')
1824 1828
1825 1829 else:
1826 1830 # pulling changegroup
1827 1831 pullop.stepsdone.add(b'changegroup')
1828 1832
1829 1833 kwargs[b'cg'] = pullop.fetch
1830 1834
1831 1835 legacyphase = b'phases' in ui.configlist(b'devel', b'legacy.exchange')
1832 1836 hasbinaryphase = b'heads' in pullop.remotebundle2caps.get(b'phases', ())
1833 1837 if not legacyphase and hasbinaryphase:
1834 1838 kwargs[b'phases'] = True
1835 1839 pullop.stepsdone.add(b'phases')
1836 1840
1837 1841 if b'listkeys' in pullop.remotebundle2caps:
1838 1842 if b'phases' not in pullop.stepsdone:
1839 1843 kwargs[b'listkeys'] = [b'phases']
1840 1844
1841 1845 bookmarksrequested = False
1842 1846 legacybookmark = b'bookmarks' in ui.configlist(b'devel', b'legacy.exchange')
1843 1847 hasbinarybook = b'bookmarks' in pullop.remotebundle2caps
1844 1848
1845 1849 if pullop.remotebookmarks is not None:
1846 1850 pullop.stepsdone.add(b'request-bookmarks')
1847 1851
1848 1852 if (
1849 1853 b'request-bookmarks' not in pullop.stepsdone
1850 1854 and pullop.remotebookmarks is None
1851 1855 and not legacybookmark
1852 1856 and hasbinarybook
1853 1857 ):
1854 1858 kwargs[b'bookmarks'] = True
1855 1859 bookmarksrequested = True
1856 1860
1857 1861 if b'listkeys' in pullop.remotebundle2caps:
1858 1862 if b'request-bookmarks' not in pullop.stepsdone:
1859 1863 # make sure to always includes bookmark data when migrating
1860 1864 # `hg incoming --bundle` to using this function.
1861 1865 pullop.stepsdone.add(b'request-bookmarks')
1862 1866 kwargs.setdefault(b'listkeys', []).append(b'bookmarks')
1863 1867
1864 1868 # If this is a full pull / clone and the server supports the clone bundles
1865 1869 # feature, tell the server whether we attempted a clone bundle. The
1866 1870 # presence of this flag indicates the client supports clone bundles. This
1867 1871 # will enable the server to treat clients that support clone bundles
1868 1872 # differently from those that don't.
1869 1873 if (
1870 1874 pullop.remote.capable(b'clonebundles')
1871 1875 and pullop.heads is None
1872 1876 and list(pullop.common) == [pullop.repo.nullid]
1873 1877 ):
1874 1878 kwargs[b'cbattempted'] = pullop.clonebundleattempted
1875 1879
1876 1880 if streaming:
1877 1881 pullop.repo.ui.status(_(b'streaming all changes\n'))
1878 1882 elif not pullop.fetch:
1879 1883 pullop.repo.ui.status(_(b"no changes found\n"))
1880 1884 pullop.cgresult = 0
1881 1885 else:
1882 1886 if pullop.heads is None and list(pullop.common) == [pullop.repo.nullid]:
1883 1887 pullop.repo.ui.status(_(b"requesting all changes\n"))
1884 1888 if obsolete.isenabled(pullop.repo, obsolete.exchangeopt):
1885 1889 remoteversions = bundle2.obsmarkersversion(pullop.remotebundle2caps)
1886 1890 if obsolete.commonversion(remoteversions) is not None:
1887 1891 kwargs[b'obsmarkers'] = True
1888 1892 pullop.stepsdone.add(b'obsmarkers')
1889 1893 _pullbundle2extraprepare(pullop, kwargs)
1890 1894
1891 1895 remote_sidedata = bundle2.read_remote_wanted_sidedata(pullop.remote)
1892 1896 if remote_sidedata:
1893 1897 kwargs[b'remote_sidedata'] = remote_sidedata
1894 1898
1895 1899 with pullop.remote.commandexecutor() as e:
1896 1900 args = dict(kwargs)
1897 1901 args[b'source'] = b'pull'
1898 1902 bundle = e.callcommand(b'getbundle', args).result()
1899 1903
1900 1904 try:
1901 1905 op = bundle2.bundleoperation(
1902 1906 pullop.repo, pullop.gettransaction, source=b'pull'
1903 1907 )
1904 1908 op.modes[b'bookmarks'] = b'records'
1905 1909 bundle2.processbundle(pullop.repo, bundle, op=op)
1906 1910 except bundle2.AbortFromPart as exc:
1907 1911 pullop.repo.ui.error(_(b'remote: abort: %s\n') % exc)
1908 1912 raise error.RemoteError(_(b'pull failed on remote'), hint=exc.hint)
1909 1913 except error.BundleValueError as exc:
1910 1914 raise error.RemoteError(_(b'missing support for %s') % exc)
1911 1915
1912 1916 if pullop.fetch:
1913 1917 pullop.cgresult = bundle2.combinechangegroupresults(op)
1914 1918
1915 1919 # processing phases change
1916 1920 for namespace, value in op.records[b'listkeys']:
1917 1921 if namespace == b'phases':
1918 1922 _pullapplyphases(pullop, value)
1919 1923
1920 1924 # processing bookmark update
1921 1925 if bookmarksrequested:
1922 1926 books = {}
1923 1927 for record in op.records[b'bookmarks']:
1924 1928 books[record[b'bookmark']] = record[b"node"]
1925 1929 pullop.remotebookmarks = books
1926 1930 else:
1927 1931 for namespace, value in op.records[b'listkeys']:
1928 1932 if namespace == b'bookmarks':
1929 1933 pullop.remotebookmarks = bookmod.unhexlifybookmarks(value)
1930 1934
1931 1935 # bookmark data were either already there or pulled in the bundle
1932 1936 if pullop.remotebookmarks is not None:
1933 1937 _pullbookmarks(pullop)
1934 1938
1935 1939
1936 1940 def _pullbundle2extraprepare(pullop, kwargs):
1937 1941 """hook function so that extensions can extend the getbundle call"""
1938 1942
1939 1943
1940 1944 def _pullchangeset(pullop):
1941 1945 """pull changeset from unbundle into the local repo"""
1942 1946 # We delay the open of the transaction as late as possible so we
1943 1947 # don't open transaction for nothing or you break future useful
1944 1948 # rollback call
1945 1949 if b'changegroup' in pullop.stepsdone:
1946 1950 return
1947 1951 pullop.stepsdone.add(b'changegroup')
1948 1952 if not pullop.fetch:
1949 1953 pullop.repo.ui.status(_(b"no changes found\n"))
1950 1954 pullop.cgresult = 0
1951 1955 return
1952 1956 tr = pullop.gettransaction()
1953 1957 if pullop.heads is None and list(pullop.common) == [pullop.repo.nullid]:
1954 1958 pullop.repo.ui.status(_(b"requesting all changes\n"))
1955 1959 elif pullop.heads is None and pullop.remote.capable(b'changegroupsubset'):
1956 1960 # issue1320, avoid a race if remote changed after discovery
1957 1961 pullop.heads = pullop.rheads
1958 1962
1959 1963 if pullop.remote.capable(b'getbundle'):
1960 1964 # TODO: get bundlecaps from remote
1961 1965 cg = pullop.remote.getbundle(
1962 1966 b'pull', common=pullop.common, heads=pullop.heads or pullop.rheads
1963 1967 )
1964 1968 elif pullop.heads is None:
1965 1969 with pullop.remote.commandexecutor() as e:
1966 1970 cg = e.callcommand(
1967 1971 b'changegroup',
1968 1972 {
1969 1973 b'nodes': pullop.fetch,
1970 1974 b'source': b'pull',
1971 1975 },
1972 1976 ).result()
1973 1977
1974 1978 elif not pullop.remote.capable(b'changegroupsubset'):
1975 1979 raise error.Abort(
1976 1980 _(
1977 1981 b"partial pull cannot be done because "
1978 1982 b"other repository doesn't support "
1979 1983 b"changegroupsubset."
1980 1984 )
1981 1985 )
1982 1986 else:
1983 1987 with pullop.remote.commandexecutor() as e:
1984 1988 cg = e.callcommand(
1985 1989 b'changegroupsubset',
1986 1990 {
1987 1991 b'bases': pullop.fetch,
1988 1992 b'heads': pullop.heads,
1989 1993 b'source': b'pull',
1990 1994 },
1991 1995 ).result()
1992 1996
1993 1997 bundleop = bundle2.applybundle(
1994 1998 pullop.repo, cg, tr, b'pull', pullop.remote.url()
1995 1999 )
1996 2000 pullop.cgresult = bundle2.combinechangegroupresults(bundleop)
1997 2001
1998 2002
1999 2003 def _pullphase(pullop):
2000 2004 # Get remote phases data from remote
2001 2005 if b'phases' in pullop.stepsdone:
2002 2006 return
2003 2007 remotephases = listkeys(pullop.remote, b'phases')
2004 2008 _pullapplyphases(pullop, remotephases)
2005 2009
2006 2010
2007 2011 def _pullapplyphases(pullop, remotephases):
2008 2012 """apply phase movement from observed remote state"""
2009 2013 if b'phases' in pullop.stepsdone:
2010 2014 return
2011 2015 pullop.stepsdone.add(b'phases')
2012 2016 publishing = bool(remotephases.get(b'publishing', False))
2013 2017 if remotephases and not publishing:
2014 2018 # remote is new and non-publishing
2015 2019 pheads, _dr = phases.analyzeremotephases(
2016 2020 pullop.repo, pullop.pulledsubset, remotephases
2017 2021 )
2018 2022 dheads = pullop.pulledsubset
2019 2023 else:
2020 2024 # Remote is old or publishing all common changesets
2021 2025 # should be seen as public
2022 2026 pheads = pullop.pulledsubset
2023 2027 dheads = []
2024 2028 unfi = pullop.repo.unfiltered()
2025 2029 phase = unfi._phasecache.phase
2026 2030 rev = unfi.changelog.index.get_rev
2027 2031 public = phases.public
2028 2032 draft = phases.draft
2029 2033
2030 2034 # exclude changesets already public locally and update the others
2031 2035 pheads = [pn for pn in pheads if phase(unfi, rev(pn)) > public]
2032 2036 if pheads:
2033 2037 tr = pullop.gettransaction()
2034 2038 phases.advanceboundary(pullop.repo, tr, public, pheads)
2035 2039
2036 2040 # exclude changesets already draft locally and update the others
2037 2041 dheads = [pn for pn in dheads if phase(unfi, rev(pn)) > draft]
2038 2042 if dheads:
2039 2043 tr = pullop.gettransaction()
2040 2044 phases.advanceboundary(pullop.repo, tr, draft, dheads)
2041 2045
2042 2046
2043 2047 def _pullbookmarks(pullop):
2044 2048 """process the remote bookmark information to update the local one"""
2045 2049 if b'bookmarks' in pullop.stepsdone:
2046 2050 return
2047 2051 pullop.stepsdone.add(b'bookmarks')
2048 2052 repo = pullop.repo
2049 2053 remotebookmarks = pullop.remotebookmarks
2050 2054 bookmarks_mode = None
2051 2055 if pullop.remote_path is not None:
2052 2056 bookmarks_mode = pullop.remote_path.bookmarks_mode
2053 2057 bookmod.updatefromremote(
2054 2058 repo.ui,
2055 2059 repo,
2056 2060 remotebookmarks,
2057 2061 pullop.remote.url(),
2058 2062 pullop.gettransaction,
2059 2063 explicit=pullop.explicitbookmarks,
2060 2064 mode=bookmarks_mode,
2061 2065 )
2062 2066
2063 2067
2064 2068 def _pullobsolete(pullop):
2065 2069 """utility function to pull obsolete markers from a remote
2066 2070
2067 2071 The `gettransaction` is function that return the pull transaction, creating
2068 2072 one if necessary. We return the transaction to inform the calling code that
2069 2073 a new transaction have been created (when applicable).
2070 2074
2071 2075 Exists mostly to allow overriding for experimentation purpose"""
2072 2076 if b'obsmarkers' in pullop.stepsdone:
2073 2077 return
2074 2078 pullop.stepsdone.add(b'obsmarkers')
2075 2079 tr = None
2076 2080 if obsolete.isenabled(pullop.repo, obsolete.exchangeopt):
2077 2081 pullop.repo.ui.debug(b'fetching remote obsolete markers\n')
2078 2082 remoteobs = listkeys(pullop.remote, b'obsolete')
2079 2083 if b'dump0' in remoteobs:
2080 2084 tr = pullop.gettransaction()
2081 2085 markers = []
2082 2086 for key in sorted(remoteobs, reverse=True):
2083 2087 if key.startswith(b'dump'):
2084 2088 data = util.b85decode(remoteobs[key])
2085 2089 version, newmarks = obsolete._readmarkers(data)
2086 2090 markers += newmarks
2087 2091 if markers:
2088 2092 pullop.repo.obsstore.add(tr, markers)
2089 2093 pullop.repo.invalidatevolatilesets()
2090 2094 return tr
2091 2095
2092 2096
2093 2097 def applynarrowacl(repo, kwargs):
2094 2098 """Apply narrow fetch access control.
2095 2099
2096 2100 This massages the named arguments for getbundle wire protocol commands
2097 2101 so requested data is filtered through access control rules.
2098 2102 """
2099 2103 ui = repo.ui
2100 2104 # TODO this assumes existence of HTTP and is a layering violation.
2101 2105 username = ui.shortuser(ui.environ.get(b'REMOTE_USER') or ui.username())
2102 2106 user_includes = ui.configlist(
2103 2107 _NARROWACL_SECTION,
2104 2108 username + b'.includes',
2105 2109 ui.configlist(_NARROWACL_SECTION, b'default.includes'),
2106 2110 )
2107 2111 user_excludes = ui.configlist(
2108 2112 _NARROWACL_SECTION,
2109 2113 username + b'.excludes',
2110 2114 ui.configlist(_NARROWACL_SECTION, b'default.excludes'),
2111 2115 )
2112 2116 if not user_includes:
2113 2117 raise error.Abort(
2114 2118 _(b"%s configuration for user %s is empty")
2115 2119 % (_NARROWACL_SECTION, username)
2116 2120 )
2117 2121
2118 2122 user_includes = [
2119 2123 b'path:.' if p == b'*' else b'path:' + p for p in user_includes
2120 2124 ]
2121 2125 user_excludes = [
2122 2126 b'path:.' if p == b'*' else b'path:' + p for p in user_excludes
2123 2127 ]
2124 2128
2125 2129 req_includes = set(kwargs.get('includepats', []))
2126 2130 req_excludes = set(kwargs.get('excludepats', []))
2127 2131
2128 2132 req_includes, req_excludes, invalid_includes = narrowspec.restrictpatterns(
2129 2133 req_includes, req_excludes, user_includes, user_excludes
2130 2134 )
2131 2135
2132 2136 if invalid_includes:
2133 2137 raise error.Abort(
2134 2138 _(b"The following includes are not accessible for %s: %s")
2135 2139 % (username, stringutil.pprint(invalid_includes))
2136 2140 )
2137 2141
2138 2142 new_args = {}
2139 2143 new_args.update(kwargs)
2140 2144 new_args['narrow'] = True
2141 2145 new_args['narrow_acl'] = True
2142 2146 new_args['includepats'] = req_includes
2143 2147 if req_excludes:
2144 2148 new_args['excludepats'] = req_excludes
2145 2149
2146 2150 return new_args
2147 2151
2148 2152
2149 2153 def _computeellipsis(repo, common, heads, known, match, depth=None):
2150 2154 """Compute the shape of a narrowed DAG.
2151 2155
2152 2156 Args:
2153 2157 repo: The repository we're transferring.
2154 2158 common: The roots of the DAG range we're transferring.
2155 2159 May be just [nullid], which means all ancestors of heads.
2156 2160 heads: The heads of the DAG range we're transferring.
2157 2161 match: The narrowmatcher that allows us to identify relevant changes.
2158 2162 depth: If not None, only consider nodes to be full nodes if they are at
2159 2163 most depth changesets away from one of heads.
2160 2164
2161 2165 Returns:
2162 2166 A tuple of (visitnodes, relevant_nodes, ellipsisroots) where:
2163 2167
2164 2168 visitnodes: The list of nodes (either full or ellipsis) which
2165 2169 need to be sent to the client.
2166 2170 relevant_nodes: The set of changelog nodes which change a file inside
2167 2171 the narrowspec. The client needs these as non-ellipsis nodes.
2168 2172 ellipsisroots: A dict of {rev: parents} that is used in
2169 2173 narrowchangegroup to produce ellipsis nodes with the
2170 2174 correct parents.
2171 2175 """
2172 2176 cl = repo.changelog
2173 2177 mfl = repo.manifestlog
2174 2178
2175 2179 clrev = cl.rev
2176 2180
2177 2181 commonrevs = {clrev(n) for n in common} | {nullrev}
2178 2182 headsrevs = {clrev(n) for n in heads}
2179 2183
2180 2184 if depth:
2181 2185 revdepth = {h: 0 for h in headsrevs}
2182 2186
2183 2187 ellipsisheads = collections.defaultdict(set)
2184 2188 ellipsisroots = collections.defaultdict(set)
2185 2189
2186 2190 def addroot(head, curchange):
2187 2191 """Add a root to an ellipsis head, splitting heads with 3 roots."""
2188 2192 ellipsisroots[head].add(curchange)
2189 2193 # Recursively split ellipsis heads with 3 roots by finding the
2190 2194 # roots' youngest common descendant which is an elided merge commit.
2191 2195 # That descendant takes 2 of the 3 roots as its own, and becomes a
2192 2196 # root of the head.
2193 2197 while len(ellipsisroots[head]) > 2:
2194 2198 child, roots = splithead(head)
2195 2199 splitroots(head, child, roots)
2196 2200 head = child # Recurse in case we just added a 3rd root
2197 2201
2198 2202 def splitroots(head, child, roots):
2199 2203 ellipsisroots[head].difference_update(roots)
2200 2204 ellipsisroots[head].add(child)
2201 2205 ellipsisroots[child].update(roots)
2202 2206 ellipsisroots[child].discard(child)
2203 2207
2204 2208 def splithead(head):
2205 2209 r1, r2, r3 = sorted(ellipsisroots[head])
2206 2210 for nr1, nr2 in ((r2, r3), (r1, r3), (r1, r2)):
2207 2211 mid = repo.revs(
2208 2212 b'sort(merge() & %d::%d & %d::%d, -rev)', nr1, head, nr2, head
2209 2213 )
2210 2214 for j in mid:
2211 2215 if j == nr2:
2212 2216 return nr2, (nr1, nr2)
2213 2217 if j not in ellipsisroots or len(ellipsisroots[j]) < 2:
2214 2218 return j, (nr1, nr2)
2215 2219 raise error.Abort(
2216 2220 _(
2217 2221 b'Failed to split up ellipsis node! head: %d, '
2218 2222 b'roots: %d %d %d'
2219 2223 )
2220 2224 % (head, r1, r2, r3)
2221 2225 )
2222 2226
2223 2227 missing = list(cl.findmissingrevs(common=commonrevs, heads=headsrevs))
2224 2228 visit = reversed(missing)
2225 2229 relevant_nodes = set()
2226 2230 visitnodes = [cl.node(m) for m in missing]
2227 2231 required = set(headsrevs) | known
2228 2232 for rev in visit:
2229 2233 clrev = cl.changelogrevision(rev)
2230 2234 ps = [prev for prev in cl.parentrevs(rev) if prev != nullrev]
2231 2235 if depth is not None:
2232 2236 curdepth = revdepth[rev]
2233 2237 for p in ps:
2234 2238 revdepth[p] = min(curdepth + 1, revdepth.get(p, depth + 1))
2235 2239 needed = False
2236 2240 shallow_enough = depth is None or revdepth[rev] <= depth
2237 2241 if shallow_enough:
2238 2242 curmf = mfl[clrev.manifest].read()
2239 2243 if ps:
2240 2244 # We choose to not trust the changed files list in
2241 2245 # changesets because it's not always correct. TODO: could
2242 2246 # we trust it for the non-merge case?
2243 2247 p1mf = mfl[cl.changelogrevision(ps[0]).manifest].read()
2244 2248 needed = bool(curmf.diff(p1mf, match))
2245 2249 if not needed and len(ps) > 1:
2246 2250 # For merge changes, the list of changed files is not
2247 2251 # helpful, since we need to emit the merge if a file
2248 2252 # in the narrow spec has changed on either side of the
2249 2253 # merge. As a result, we do a manifest diff to check.
2250 2254 p2mf = mfl[cl.changelogrevision(ps[1]).manifest].read()
2251 2255 needed = bool(curmf.diff(p2mf, match))
2252 2256 else:
2253 2257 # For a root node, we need to include the node if any
2254 2258 # files in the node match the narrowspec.
2255 2259 needed = any(curmf.walk(match))
2256 2260
2257 2261 if needed:
2258 2262 for head in ellipsisheads[rev]:
2259 2263 addroot(head, rev)
2260 2264 for p in ps:
2261 2265 required.add(p)
2262 2266 relevant_nodes.add(cl.node(rev))
2263 2267 else:
2264 2268 if not ps:
2265 2269 ps = [nullrev]
2266 2270 if rev in required:
2267 2271 for head in ellipsisheads[rev]:
2268 2272 addroot(head, rev)
2269 2273 for p in ps:
2270 2274 ellipsisheads[p].add(rev)
2271 2275 else:
2272 2276 for p in ps:
2273 2277 ellipsisheads[p] |= ellipsisheads[rev]
2274 2278
2275 2279 # add common changesets as roots of their reachable ellipsis heads
2276 2280 for c in commonrevs:
2277 2281 for head in ellipsisheads[c]:
2278 2282 addroot(head, c)
2279 2283 return visitnodes, relevant_nodes, ellipsisroots
2280 2284
2281 2285
2282 2286 def caps20to10(repo, role):
2283 2287 """return a set with appropriate options to use bundle20 during getbundle"""
2284 2288 caps = {b'HG20'}
2285 2289 capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo, role=role))
2286 2290 caps.add(b'bundle2=' + urlreq.quote(capsblob))
2287 2291 return caps
2288 2292
2289 2293
2290 2294 # List of names of steps to perform for a bundle2 for getbundle, order matters.
2291 2295 getbundle2partsorder = []
2292 2296
2293 2297 # Mapping between step name and function
2294 2298 #
2295 2299 # This exists to help extensions wrap steps if necessary
2296 2300 getbundle2partsmapping = {}
2297 2301
2298 2302
2299 2303 def getbundle2partsgenerator(stepname, idx=None):
2300 2304 """decorator for function generating bundle2 part for getbundle
2301 2305
2302 2306 The function is added to the step -> function mapping and appended to the
2303 2307 list of steps. Beware that decorated functions will be added in order
2304 2308 (this may matter).
2305 2309
2306 2310 You can only use this decorator for new steps, if you want to wrap a step
2307 2311 from an extension, attack the getbundle2partsmapping dictionary directly."""
2308 2312
2309 2313 def dec(func):
2310 2314 assert stepname not in getbundle2partsmapping
2311 2315 getbundle2partsmapping[stepname] = func
2312 2316 if idx is None:
2313 2317 getbundle2partsorder.append(stepname)
2314 2318 else:
2315 2319 getbundle2partsorder.insert(idx, stepname)
2316 2320 return func
2317 2321
2318 2322 return dec
2319 2323
2320 2324
2321 2325 def bundle2requested(bundlecaps):
2322 2326 if bundlecaps is not None:
2323 2327 return any(cap.startswith(b'HG2') for cap in bundlecaps)
2324 2328 return False
2325 2329
2326 2330
2327 2331 def getbundlechunks(
2328 2332 repo,
2329 2333 source,
2330 2334 heads=None,
2331 2335 common=None,
2332 2336 bundlecaps=None,
2333 2337 remote_sidedata=None,
2334 2338 **kwargs
2335 2339 ):
2336 2340 """Return chunks constituting a bundle's raw data.
2337 2341
2338 2342 Could be a bundle HG10 or a bundle HG20 depending on bundlecaps
2339 2343 passed.
2340 2344
2341 2345 Returns a 2-tuple of a dict with metadata about the generated bundle
2342 2346 and an iterator over raw chunks (of varying sizes).
2343 2347 """
2344 2348 kwargs = pycompat.byteskwargs(kwargs)
2345 2349 info = {}
2346 2350 usebundle2 = bundle2requested(bundlecaps)
2347 2351 # bundle10 case
2348 2352 if not usebundle2:
2349 2353 if bundlecaps and not kwargs.get(b'cg', True):
2350 2354 raise ValueError(
2351 2355 _(b'request for bundle10 must include changegroup')
2352 2356 )
2353 2357
2354 2358 if kwargs:
2355 2359 raise ValueError(
2356 2360 _(b'unsupported getbundle arguments: %s')
2357 2361 % b', '.join(sorted(kwargs.keys()))
2358 2362 )
2359 2363 outgoing = _computeoutgoing(repo, heads, common)
2360 2364 info[b'bundleversion'] = 1
2361 2365 return (
2362 2366 info,
2363 2367 changegroup.makestream(
2364 2368 repo,
2365 2369 outgoing,
2366 2370 b'01',
2367 2371 source,
2368 2372 bundlecaps=bundlecaps,
2369 2373 remote_sidedata=remote_sidedata,
2370 2374 ),
2371 2375 )
2372 2376
2373 2377 # bundle20 case
2374 2378 info[b'bundleversion'] = 2
2375 2379 b2caps = {}
2376 2380 for bcaps in bundlecaps:
2377 2381 if bcaps.startswith(b'bundle2='):
2378 2382 blob = urlreq.unquote(bcaps[len(b'bundle2=') :])
2379 2383 b2caps.update(bundle2.decodecaps(blob))
2380 2384 bundler = bundle2.bundle20(repo.ui, b2caps)
2381 2385
2382 2386 kwargs[b'heads'] = heads
2383 2387 kwargs[b'common'] = common
2384 2388
2385 2389 for name in getbundle2partsorder:
2386 2390 func = getbundle2partsmapping[name]
2387 2391 func(
2388 2392 bundler,
2389 2393 repo,
2390 2394 source,
2391 2395 bundlecaps=bundlecaps,
2392 2396 b2caps=b2caps,
2393 2397 remote_sidedata=remote_sidedata,
2394 2398 **pycompat.strkwargs(kwargs)
2395 2399 )
2396 2400
2397 2401 info[b'prefercompressed'] = bundler.prefercompressed
2398 2402
2399 2403 return info, bundler.getchunks()
2400 2404
2401 2405
2402 2406 @getbundle2partsgenerator(b'stream2')
2403 2407 def _getbundlestream2(bundler, repo, *args, **kwargs):
2404 2408 return bundle2.addpartbundlestream2(bundler, repo, **kwargs)
2405 2409
2406 2410
2407 2411 @getbundle2partsgenerator(b'changegroup')
2408 2412 def _getbundlechangegrouppart(
2409 2413 bundler,
2410 2414 repo,
2411 2415 source,
2412 2416 bundlecaps=None,
2413 2417 b2caps=None,
2414 2418 heads=None,
2415 2419 common=None,
2416 2420 remote_sidedata=None,
2417 2421 **kwargs
2418 2422 ):
2419 2423 """add a changegroup part to the requested bundle"""
2420 2424 if not kwargs.get('cg', True) or not b2caps:
2421 2425 return
2422 2426
2423 2427 version = b'01'
2424 2428 cgversions = b2caps.get(b'changegroup')
2425 2429 if cgversions: # 3.1 and 3.2 ship with an empty value
2426 2430 cgversions = [
2427 2431 v
2428 2432 for v in cgversions
2429 2433 if v in changegroup.supportedoutgoingversions(repo)
2430 2434 ]
2431 2435 if not cgversions:
2432 2436 raise error.Abort(_(b'no common changegroup version'))
2433 2437 version = max(cgversions)
2434 2438
2435 2439 outgoing = _computeoutgoing(repo, heads, common)
2436 2440 if not outgoing.missing:
2437 2441 return
2438 2442
2439 2443 if kwargs.get('narrow', False):
2440 2444 include = sorted(filter(bool, kwargs.get('includepats', [])))
2441 2445 exclude = sorted(filter(bool, kwargs.get('excludepats', [])))
2442 2446 matcher = narrowspec.match(repo.root, include=include, exclude=exclude)
2443 2447 else:
2444 2448 matcher = None
2445 2449
2446 2450 cgstream = changegroup.makestream(
2447 2451 repo,
2448 2452 outgoing,
2449 2453 version,
2450 2454 source,
2451 2455 bundlecaps=bundlecaps,
2452 2456 matcher=matcher,
2453 2457 remote_sidedata=remote_sidedata,
2454 2458 )
2455 2459
2456 2460 part = bundler.newpart(b'changegroup', data=cgstream)
2457 2461 if cgversions:
2458 2462 part.addparam(b'version', version)
2459 2463
2460 2464 part.addparam(b'nbchanges', b'%d' % len(outgoing.missing), mandatory=False)
2461 2465
2462 2466 if scmutil.istreemanifest(repo):
2463 2467 part.addparam(b'treemanifest', b'1')
2464 2468
2465 2469 if repository.REPO_FEATURE_SIDE_DATA in repo.features:
2466 2470 part.addparam(b'exp-sidedata', b'1')
2467 2471 sidedata = bundle2.format_remote_wanted_sidedata(repo)
2468 2472 part.addparam(b'exp-wanted-sidedata', sidedata)
2469 2473
2470 2474 if (
2471 2475 kwargs.get('narrow', False)
2472 2476 and kwargs.get('narrow_acl', False)
2473 2477 and (include or exclude)
2474 2478 ):
2475 2479 # this is mandatory because otherwise ACL clients won't work
2476 2480 narrowspecpart = bundler.newpart(b'Narrow:responsespec')
2477 2481 narrowspecpart.data = b'%s\0%s' % (
2478 2482 b'\n'.join(include),
2479 2483 b'\n'.join(exclude),
2480 2484 )
2481 2485
2482 2486
2483 2487 @getbundle2partsgenerator(b'bookmarks')
2484 2488 def _getbundlebookmarkpart(
2485 2489 bundler, repo, source, bundlecaps=None, b2caps=None, **kwargs
2486 2490 ):
2487 2491 """add a bookmark part to the requested bundle"""
2488 2492 if not kwargs.get('bookmarks', False):
2489 2493 return
2490 2494 if not b2caps or b'bookmarks' not in b2caps:
2491 2495 raise error.Abort(_(b'no common bookmarks exchange method'))
2492 2496 books = bookmod.listbinbookmarks(repo)
2493 2497 data = bookmod.binaryencode(repo, books)
2494 2498 if data:
2495 2499 bundler.newpart(b'bookmarks', data=data)
2496 2500
2497 2501
2498 2502 @getbundle2partsgenerator(b'listkeys')
2499 2503 def _getbundlelistkeysparts(
2500 2504 bundler, repo, source, bundlecaps=None, b2caps=None, **kwargs
2501 2505 ):
2502 2506 """add parts containing listkeys namespaces to the requested bundle"""
2503 2507 listkeys = kwargs.get('listkeys', ())
2504 2508 for namespace in listkeys:
2505 2509 part = bundler.newpart(b'listkeys')
2506 2510 part.addparam(b'namespace', namespace)
2507 2511 keys = repo.listkeys(namespace).items()
2508 2512 part.data = pushkey.encodekeys(keys)
2509 2513
2510 2514
2511 2515 @getbundle2partsgenerator(b'obsmarkers')
2512 2516 def _getbundleobsmarkerpart(
2513 2517 bundler, repo, source, bundlecaps=None, b2caps=None, heads=None, **kwargs
2514 2518 ):
2515 2519 """add an obsolescence markers part to the requested bundle"""
2516 2520 if kwargs.get('obsmarkers', False):
2517 2521 if heads is None:
2518 2522 heads = repo.heads()
2519 2523 subset = [c.node() for c in repo.set(b'::%ln', heads)]
2520 2524 markers = repo.obsstore.relevantmarkers(subset)
2521 2525 markers = obsutil.sortedmarkers(markers)
2522 2526 bundle2.buildobsmarkerspart(bundler, markers)
2523 2527
2524 2528
2525 2529 @getbundle2partsgenerator(b'phases')
2526 2530 def _getbundlephasespart(
2527 2531 bundler, repo, source, bundlecaps=None, b2caps=None, heads=None, **kwargs
2528 2532 ):
2529 2533 """add phase heads part to the requested bundle"""
2530 2534 if kwargs.get('phases', False):
2531 2535 if not b2caps or b'heads' not in b2caps.get(b'phases'):
2532 2536 raise error.Abort(_(b'no common phases exchange method'))
2533 2537 if heads is None:
2534 2538 heads = repo.heads()
2535 2539
2536 2540 headsbyphase = collections.defaultdict(set)
2537 2541 if repo.publishing():
2538 2542 headsbyphase[phases.public] = heads
2539 2543 else:
2540 2544 # find the appropriate heads to move
2541 2545
2542 2546 phase = repo._phasecache.phase
2543 2547 node = repo.changelog.node
2544 2548 rev = repo.changelog.rev
2545 2549 for h in heads:
2546 2550 headsbyphase[phase(repo, rev(h))].add(h)
2547 2551 seenphases = list(headsbyphase.keys())
2548 2552
2549 2553 # We do not handle anything but public and draft phase for now)
2550 2554 if seenphases:
2551 2555 assert max(seenphases) <= phases.draft
2552 2556
2553 2557 # if client is pulling non-public changesets, we need to find
2554 2558 # intermediate public heads.
2555 2559 draftheads = headsbyphase.get(phases.draft, set())
2556 2560 if draftheads:
2557 2561 publicheads = headsbyphase.get(phases.public, set())
2558 2562
2559 2563 revset = b'heads(only(%ln, %ln) and public())'
2560 2564 extraheads = repo.revs(revset, draftheads, publicheads)
2561 2565 for r in extraheads:
2562 2566 headsbyphase[phases.public].add(node(r))
2563 2567
2564 2568 # transform data in a format used by the encoding function
2565 2569 phasemapping = {
2566 2570 phase: sorted(headsbyphase[phase]) for phase in phases.allphases
2567 2571 }
2568 2572
2569 2573 # generate the actual part
2570 2574 phasedata = phases.binaryencode(phasemapping)
2571 2575 bundler.newpart(b'phase-heads', data=phasedata)
2572 2576
2573 2577
2574 2578 @getbundle2partsgenerator(b'hgtagsfnodes')
2575 2579 def _getbundletagsfnodes(
2576 2580 bundler,
2577 2581 repo,
2578 2582 source,
2579 2583 bundlecaps=None,
2580 2584 b2caps=None,
2581 2585 heads=None,
2582 2586 common=None,
2583 2587 **kwargs
2584 2588 ):
2585 2589 """Transfer the .hgtags filenodes mapping.
2586 2590
2587 2591 Only values for heads in this bundle will be transferred.
2588 2592
2589 2593 The part data consists of pairs of 20 byte changeset node and .hgtags
2590 2594 filenodes raw values.
2591 2595 """
2592 2596 # Don't send unless:
2593 2597 # - changeset are being exchanged,
2594 2598 # - the client supports it.
2595 2599 if not b2caps or not (kwargs.get('cg', True) and b'hgtagsfnodes' in b2caps):
2596 2600 return
2597 2601
2598 2602 outgoing = _computeoutgoing(repo, heads, common)
2599 2603 bundle2.addparttagsfnodescache(repo, bundler, outgoing)
2600 2604
2601 2605
2602 2606 @getbundle2partsgenerator(b'cache:rev-branch-cache')
2603 2607 def _getbundlerevbranchcache(
2604 2608 bundler,
2605 2609 repo,
2606 2610 source,
2607 2611 bundlecaps=None,
2608 2612 b2caps=None,
2609 2613 heads=None,
2610 2614 common=None,
2611 2615 **kwargs
2612 2616 ):
2613 2617 """Transfer the rev-branch-cache mapping
2614 2618
2615 2619 The payload is a series of data related to each branch
2616 2620
2617 2621 1) branch name length
2618 2622 2) number of open heads
2619 2623 3) number of closed heads
2620 2624 4) open heads nodes
2621 2625 5) closed heads nodes
2622 2626 """
2623 2627 # Don't send unless:
2624 2628 # - changeset are being exchanged,
2625 2629 # - the client supports it.
2626 2630 # - narrow bundle isn't in play (not currently compatible).
2627 2631 if (
2628 2632 not kwargs.get('cg', True)
2629 2633 or not b2caps
2630 2634 or b'rev-branch-cache' not in b2caps
2631 2635 or kwargs.get('narrow', False)
2632 2636 or repo.ui.has_section(_NARROWACL_SECTION)
2633 2637 ):
2634 2638 return
2635 2639
2636 2640 outgoing = _computeoutgoing(repo, heads, common)
2637 2641 bundle2.addpartrevbranchcache(repo, bundler, outgoing)
2638 2642
2639 2643
2640 2644 def check_heads(repo, their_heads, context):
2641 2645 """check if the heads of a repo have been modified
2642 2646
2643 2647 Used by peer for unbundling.
2644 2648 """
2645 2649 heads = repo.heads()
2646 2650 heads_hash = hashutil.sha1(b''.join(sorted(heads))).digest()
2647 2651 if not (
2648 2652 their_heads == [b'force']
2649 2653 or their_heads == heads
2650 2654 or their_heads == [b'hashed', heads_hash]
2651 2655 ):
2652 2656 # someone else committed/pushed/unbundled while we
2653 2657 # were transferring data
2654 2658 raise error.PushRaced(
2655 2659 b'repository changed while %s - please try again' % context
2656 2660 )
2657 2661
2658 2662
2659 2663 def unbundle(repo, cg, heads, source, url):
2660 2664 """Apply a bundle to a repo.
2661 2665
2662 2666 this function makes sure the repo is locked during the application and have
2663 2667 mechanism to check that no push race occurred between the creation of the
2664 2668 bundle and its application.
2665 2669
2666 2670 If the push was raced as PushRaced exception is raised."""
2667 2671 r = 0
2668 2672 # need a transaction when processing a bundle2 stream
2669 2673 # [wlock, lock, tr] - needs to be an array so nested functions can modify it
2670 2674 lockandtr = [None, None, None]
2671 2675 recordout = None
2672 2676 # quick fix for output mismatch with bundle2 in 3.4
2673 2677 captureoutput = repo.ui.configbool(
2674 2678 b'experimental', b'bundle2-output-capture'
2675 2679 )
2676 2680 if url.startswith(b'remote:http:') or url.startswith(b'remote:https:'):
2677 2681 captureoutput = True
2678 2682 try:
2679 2683 # note: outside bundle1, 'heads' is expected to be empty and this
2680 2684 # 'check_heads' call wil be a no-op
2681 2685 check_heads(repo, heads, b'uploading changes')
2682 2686 # push can proceed
2683 2687 if not isinstance(cg, bundle2.unbundle20):
2684 2688 # legacy case: bundle1 (changegroup 01)
2685 2689 txnname = b"\n".join([source, urlutil.hidepassword(url)])
2686 2690 with repo.lock(), repo.transaction(txnname) as tr:
2687 2691 op = bundle2.applybundle(repo, cg, tr, source, url)
2688 2692 r = bundle2.combinechangegroupresults(op)
2689 2693 else:
2690 2694 r = None
2691 2695 try:
2692 2696
2693 2697 def gettransaction():
2694 2698 if not lockandtr[2]:
2695 2699 if not bookmod.bookmarksinstore(repo):
2696 2700 lockandtr[0] = repo.wlock()
2697 2701 lockandtr[1] = repo.lock()
2698 2702 lockandtr[2] = repo.transaction(source)
2699 2703 lockandtr[2].hookargs[b'source'] = source
2700 2704 lockandtr[2].hookargs[b'url'] = url
2701 2705 lockandtr[2].hookargs[b'bundle2'] = b'1'
2702 2706 return lockandtr[2]
2703 2707
2704 2708 # Do greedy locking by default until we're satisfied with lazy
2705 2709 # locking.
2706 2710 if not repo.ui.configbool(
2707 2711 b'experimental', b'bundle2lazylocking'
2708 2712 ):
2709 2713 gettransaction()
2710 2714
2711 2715 op = bundle2.bundleoperation(
2712 2716 repo,
2713 2717 gettransaction,
2714 2718 captureoutput=captureoutput,
2715 2719 source=b'push',
2716 2720 )
2717 2721 try:
2718 2722 op = bundle2.processbundle(repo, cg, op=op)
2719 2723 finally:
2720 2724 r = op.reply
2721 2725 if captureoutput and r is not None:
2722 2726 repo.ui.pushbuffer(error=True, subproc=True)
2723 2727
2724 2728 def recordout(output):
2725 2729 r.newpart(b'output', data=output, mandatory=False)
2726 2730
2727 2731 if lockandtr[2] is not None:
2728 2732 lockandtr[2].close()
2729 2733 except BaseException as exc:
2730 2734 exc.duringunbundle2 = True
2731 2735 if captureoutput and r is not None:
2732 2736 parts = exc._bundle2salvagedoutput = r.salvageoutput()
2733 2737
2734 2738 def recordout(output):
2735 2739 part = bundle2.bundlepart(
2736 2740 b'output', data=output, mandatory=False
2737 2741 )
2738 2742 parts.append(part)
2739 2743
2740 2744 raise
2741 2745 finally:
2742 2746 lockmod.release(lockandtr[2], lockandtr[1], lockandtr[0])
2743 2747 if recordout is not None:
2744 2748 recordout(repo.ui.popbuffer())
2745 2749 return r
2746 2750
2747 2751
2748 2752 def _maybeapplyclonebundle(pullop):
2749 2753 """Apply a clone bundle from a remote, if possible."""
2750 2754
2751 2755 repo = pullop.repo
2752 2756 remote = pullop.remote
2753 2757
2754 2758 if not repo.ui.configbool(b'ui', b'clonebundles'):
2755 2759 return
2756 2760
2757 2761 # Only run if local repo is empty.
2758 2762 if len(repo):
2759 2763 return
2760 2764
2761 2765 if pullop.heads:
2762 2766 return
2763 2767
2764 2768 if not remote.capable(b'clonebundles'):
2765 2769 return
2766 2770
2767 2771 with remote.commandexecutor() as e:
2768 2772 res = e.callcommand(b'clonebundles', {}).result()
2769 2773
2770 2774 # If we call the wire protocol command, that's good enough to record the
2771 2775 # attempt.
2772 2776 pullop.clonebundleattempted = True
2773 2777
2774 2778 entries = bundlecaches.parseclonebundlesmanifest(repo, res)
2775 2779 if not entries:
2776 2780 repo.ui.note(
2777 2781 _(
2778 2782 b'no clone bundles available on remote; '
2779 2783 b'falling back to regular clone\n'
2780 2784 )
2781 2785 )
2782 2786 return
2783 2787
2784 2788 entries = bundlecaches.filterclonebundleentries(
2785 2789 repo, entries, streamclonerequested=pullop.streamclonerequested
2786 2790 )
2787 2791
2788 2792 if not entries:
2789 2793 # There is a thundering herd concern here. However, if a server
2790 2794 # operator doesn't advertise bundles appropriate for its clients,
2791 2795 # they deserve what's coming. Furthermore, from a client's
2792 2796 # perspective, no automatic fallback would mean not being able to
2793 2797 # clone!
2794 2798 repo.ui.warn(
2795 2799 _(
2796 2800 b'no compatible clone bundles available on server; '
2797 2801 b'falling back to regular clone\n'
2798 2802 )
2799 2803 )
2800 2804 repo.ui.warn(
2801 2805 _(b'(you may want to report this to the server operator)\n')
2802 2806 )
2803 2807 return
2804 2808
2805 2809 entries = bundlecaches.sortclonebundleentries(repo.ui, entries)
2806 2810
2807 2811 url = entries[0][b'URL']
2808 2812 repo.ui.status(_(b'applying clone bundle from %s\n') % url)
2809 2813 if trypullbundlefromurl(repo.ui, repo, url):
2810 2814 repo.ui.status(_(b'finished applying clone bundle\n'))
2811 2815 # Bundle failed.
2812 2816 #
2813 2817 # We abort by default to avoid the thundering herd of
2814 2818 # clients flooding a server that was expecting expensive
2815 2819 # clone load to be offloaded.
2816 2820 elif repo.ui.configbool(b'ui', b'clonebundlefallback'):
2817 2821 repo.ui.warn(_(b'falling back to normal clone\n'))
2818 2822 else:
2819 2823 raise error.Abort(
2820 2824 _(b'error applying bundle'),
2821 2825 hint=_(
2822 2826 b'if this error persists, consider contacting '
2823 2827 b'the server operator or disable clone '
2824 2828 b'bundles via '
2825 2829 b'"--config ui.clonebundles=false"'
2826 2830 ),
2827 2831 )
2828 2832
2829 2833
2830 2834 def trypullbundlefromurl(ui, repo, url):
2831 2835 """Attempt to apply a bundle from a URL."""
2832 2836 with repo.lock(), repo.transaction(b'bundleurl') as tr:
2833 2837 try:
2834 2838 fh = urlmod.open(ui, url)
2835 2839 cg = readbundle(ui, fh, b'stream')
2836 2840
2837 2841 if isinstance(cg, streamclone.streamcloneapplier):
2838 2842 cg.apply(repo)
2839 2843 else:
2840 2844 bundle2.applybundle(repo, cg, tr, b'clonebundles', url)
2841 2845 return True
2842 2846 except urlerr.httperror as e:
2843 2847 ui.warn(
2844 2848 _(b'HTTP error fetching bundle: %s\n')
2845 2849 % stringutil.forcebytestr(e)
2846 2850 )
2847 2851 except urlerr.urlerror as e:
2848 2852 ui.warn(
2849 2853 _(b'error fetching bundle: %s\n')
2850 2854 % stringutil.forcebytestr(e.reason)
2851 2855 )
2852 2856
2853 2857 return False
@@ -1,1523 +1,1533 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 > [command-templates]
13 13 > # simpler log output
14 14 > log = "{node|short}: {desc}\n"
15 15 >
16 16 > [experimental]
17 17 > # enable evolution
18 18 > evolution=true
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 1 new obsolescence markers
130 130 $ hg debugobsolete `getid 'desc("C-A0")'` a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1
131 131 1 new obsolescence markers
132 132 obsoleted 1 changesets
133 133 $ hg debugobsolete a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 `getid 'desc("C-A1")'`
134 134 1 new obsolescence markers
135 135
136 136 $ hg up 'desc("ROOT")'
137 137 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
138 138 $ hg log --hidden -G
139 139 o cf2c22470d67: C-A1
140 140 |
141 141 | x 84fcb0dfe17b: C-A0
142 142 |/
143 143 @ ea207398892e: ROOT
144 144
145 145 $ hg debugobsolete
146 146 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
147 147 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
148 148 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
149 149
150 150 Actual testing
151 151 --------------
152 152
153 153 $ testrevs 'desc("C-A0")'
154 154 ### Matched revisions###
155 155 84fcb0dfe17b: C-A0
156 156 ### Relevant markers ###
157 157 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
158 158 # bundling: 1 changesets found
159 159 ### Bundled markers ###
160 160 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
161 161 ### diff <relevant> <bundled> ###
162 162 #################################
163 163 ### Exclusive markers ###
164 164 # stripping: saved backup bundle to $TESTTMP/simple-chain/.hg/strip-backup/84fcb0dfe17b-6454bbdc-backup.hg
165 165 ### Backup markers ###
166 166 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
167 167 ### diff <relevant> <backed-up> ###
168 168 #################################
169 169 ### Stripped markers ###
170 170 ### diff <exclusive> <stripped> ###
171 171 #################################
172 172 # unbundling: adding changesets
173 173 # unbundling: adding manifests
174 174 # unbundling: adding file changes
175 175 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
176 176 # unbundling: (1 other changesets obsolete on arrival)
177 177 # unbundling: (run 'hg heads' to see heads)
178 178
179 179 $ testrevs 'desc("C-A1")'
180 180 ### Matched revisions###
181 181 cf2c22470d67: C-A1
182 182 ### Relevant 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 # bundling: 1 changesets found
187 187 ### Bundled markers ###
188 188 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
189 189 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 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 ### diff <relevant> <bundled> ###
192 192 #################################
193 193 ### Exclusive markers ###
194 194 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 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 # stripping: saved backup bundle to $TESTTMP/simple-chain/.hg/strip-backup/cf2c22470d67-fa0f07b0-backup.hg
197 197 ### Backup markers ###
198 198 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
199 199 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 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 <relevant> <backed-up> ###
202 202 #################################
203 203 ### Stripped markers ###
204 204 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
205 205 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
206 206 ### diff <exclusive> <stripped> ###
207 207 #################################
208 208 # unbundling: adding changesets
209 209 # unbundling: adding manifests
210 210 # unbundling: adding file changes
211 211 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
212 212 # unbundling: 2 new obsolescence markers
213 213 # unbundling: obsoleted 1 changesets
214 214 # unbundling: new changesets cf2c22470d67 (1 drafts)
215 215 # unbundling: (run 'hg heads' to see heads)
216 216
217 217 $ testrevs 'desc("C-A")'
218 218 ### Matched revisions###
219 219 84fcb0dfe17b: C-A0
220 220 cf2c22470d67: C-A1
221 221 ### Relevant markers ###
222 222 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
223 223 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
224 224 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
225 225 # bundling: 2 changesets found
226 226 ### Bundled markers ###
227 227 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
228 228 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
229 229 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
230 230 ### diff <relevant> <bundled> ###
231 231 #################################
232 232 ### Exclusive markers ###
233 233 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
234 234 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
235 235 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
236 236 # stripping: saved backup bundle to $TESTTMP/simple-chain/.hg/strip-backup/cf2c22470d67-fce4fc64-backup.hg
237 237 ### Backup markers ###
238 238 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
239 239 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
240 240 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
241 241 ### diff <relevant> <backed-up> ###
242 242 #################################
243 243 ### Stripped markers ###
244 244 84fcb0dfe17b256ebae52e05572993b9194c018a a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
245 245 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
246 246 a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1 cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
247 247 ### diff <exclusive> <stripped> ###
248 248 #################################
249 249 # unbundling: adding changesets
250 250 # unbundling: adding manifests
251 251 # unbundling: adding file changes
252 252 # unbundling: added 2 changesets with 2 changes to 2 files (+1 heads)
253 253 # unbundling: 3 new obsolescence markers
254 254 # unbundling: new changesets cf2c22470d67 (1 drafts)
255 255 # unbundling: (1 other changesets obsolete on arrival)
256 256 # unbundling: (run 'hg heads' to see heads)
257 257
258 258 chain with prune children
259 259 =========================
260 260
261 261 . β‡ βŠ— B0
262 262 . |
263 263 . β‡ ΓΈβ‡ β—” A1
264 264 . |
265 265 . ●
266 266
267 267 setup
268 268 -----
269 269
270 270 $ mktestrepo prune
271 271 $ mkcommit 'C-A0'
272 272 $ mkcommit 'C-B0'
273 273 $ hg up 'desc("ROOT")'
274 274 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
275 275 $ mkcommit 'C-A1'
276 276 created new head
277 277 $ hg debugobsolete a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 `getid 'desc("C-A0")'`
278 278 1 new obsolescence markers
279 279 $ hg debugobsolete `getid 'desc("C-A0")'` `getid 'desc("C-A1")'`
280 280 1 new obsolescence markers
281 281 obsoleted 1 changesets
282 282 1 new orphan changesets
283 283 $ hg debugobsolete --record-parents `getid 'desc("C-B0")'`
284 284 1 new obsolescence markers
285 285 obsoleted 1 changesets
286 286 $ hg up 'desc("ROOT")'
287 287 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
288 288 $ hg log --hidden -G
289 289 o cf2c22470d67: C-A1
290 290 |
291 291 | x 29f93b1df87b: C-B0
292 292 | |
293 293 | x 84fcb0dfe17b: C-A0
294 294 |/
295 295 @ ea207398892e: ROOT
296 296
297 297 $ hg debugobsolete
298 298 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
299 299 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
300 300 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
301 301
302 302 Actual testing
303 303 --------------
304 304
305 305 $ testrevs 'desc("C-A0")'
306 306 ### Matched revisions###
307 307 84fcb0dfe17b: C-A0
308 308 ### Relevant markers ###
309 309 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
310 310 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
311 311 # bundling: 1 changesets found
312 312 ### Bundled markers ###
313 313 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
314 314 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
315 315 ### diff <relevant> <bundled> ###
316 316 #################################
317 317 ### Exclusive markers ###
318 318
319 319 (The strip markers is considered exclusive to the pruned changeset even if it
320 320 is also considered "relevant" to its parent. This allows to strip prune
321 321 markers. This avoid leaving prune markers from dead-end that could be
322 322 problematic)
323 323
324 324 $ testrevs 'desc("C-B0")'
325 325 ### Matched revisions###
326 326 29f93b1df87b: C-B0
327 327 ### Relevant markers ###
328 328 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
329 329 # bundling: 1 changesets found
330 330 ### Bundled markers ###
331 331 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
332 332 ### diff <relevant> <bundled> ###
333 333 #################################
334 334 ### Exclusive markers ###
335 335 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
336 336 # stripping: saved backup bundle to $TESTTMP/prune/.hg/strip-backup/29f93b1df87b-7fb32101-backup.hg
337 337 ### Backup markers ###
338 338 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
339 339 ### diff <relevant> <backed-up> ###
340 340 #################################
341 341 ### Stripped markers ###
342 342 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
343 343 ### diff <exclusive> <stripped> ###
344 344 #################################
345 345 # unbundling: adding changesets
346 346 # unbundling: adding manifests
347 347 # unbundling: adding file changes
348 348 # unbundling: added 1 changesets with 1 changes to 1 files
349 349 # unbundling: 1 new obsolescence markers
350 350 # unbundling: (1 other changesets obsolete on arrival)
351 351 # unbundling: (run 'hg update' to get a working copy)
352 352
353 353 $ testrevs 'desc("C-A1")'
354 354 ### Matched revisions###
355 355 cf2c22470d67: C-A1
356 356 ### Relevant markers ###
357 357 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
358 358 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
359 359 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
360 360 # bundling: 1 changesets found
361 361 ### Bundled markers ###
362 362 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
363 363 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
364 364 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
365 365 ### diff <relevant> <bundled> ###
366 366 #################################
367 367 ### Exclusive markers ###
368 368 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
369 369 # stripping: saved backup bundle to $TESTTMP/prune/.hg/strip-backup/cf2c22470d67-fa0f07b0-backup.hg
370 370 ### Backup markers ###
371 371 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
372 372 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
373 373 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
374 374 ### diff <relevant> <backed-up> ###
375 375 #################################
376 376 ### Stripped markers ###
377 377 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
378 378 ### diff <exclusive> <stripped> ###
379 379 #################################
380 380 # unbundling: adding changesets
381 381 # unbundling: adding manifests
382 382 # unbundling: adding file changes
383 383 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
384 384 # unbundling: 1 new obsolescence markers
385 385 # unbundling: obsoleted 1 changesets
386 386 # unbundling: new changesets cf2c22470d67 (1 drafts)
387 387 # unbundling: (run 'hg heads' to see heads)
388 388
389 389 bundling multiple revisions
390 390
391 391 $ testrevs 'desc("C-A")'
392 392 ### Matched revisions###
393 393 84fcb0dfe17b: C-A0
394 394 cf2c22470d67: C-A1
395 395 ### Relevant markers ###
396 396 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
397 397 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
398 398 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
399 399 # bundling: 2 changesets found
400 400 ### Bundled markers ###
401 401 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
402 402 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
403 403 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
404 404 ### diff <relevant> <bundled> ###
405 405 #################################
406 406 ### Exclusive markers ###
407 407 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
408 408 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
409 409
410 410 $ testrevs 'desc("C-")'
411 411 ### Matched revisions###
412 412 29f93b1df87b: C-B0
413 413 84fcb0dfe17b: C-A0
414 414 cf2c22470d67: C-A1
415 415 ### Relevant markers ###
416 416 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
417 417 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
418 418 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
419 419 # bundling: 3 changesets found
420 420 ### Bundled markers ###
421 421 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
422 422 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
423 423 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
424 424 ### diff <relevant> <bundled> ###
425 425 #################################
426 426 ### Exclusive markers ###
427 427 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
428 428 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
429 429 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
430 430 # stripping: saved backup bundle to $TESTTMP/prune/.hg/strip-backup/cf2c22470d67-884c33b0-backup.hg
431 431 ### Backup markers ###
432 432 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
433 433 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
434 434 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
435 435 ### diff <relevant> <backed-up> ###
436 436 #################################
437 437 ### Stripped markers ###
438 438 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
439 439 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
440 440 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
441 441 ### diff <exclusive> <stripped> ###
442 442 #################################
443 443 # unbundling: adding changesets
444 444 # unbundling: adding manifests
445 445 # unbundling: adding file changes
446 446 # unbundling: added 3 changesets with 3 changes to 3 files (+1 heads)
447 447 # unbundling: 3 new obsolescence markers
448 448 # unbundling: new changesets cf2c22470d67 (1 drafts)
449 449 # unbundling: (2 other changesets obsolete on arrival)
450 450 # unbundling: (run 'hg heads' to see heads)
451 451
452 452 chain with precursors also pruned
453 453 =================================
454 454
455 455 . A0 (also pruned)
456 456 . β‡ ΓΈβ‡ β—” A1
457 457 . |
458 458 . ●
459 459
460 460 setup
461 461 -----
462 462
463 463 $ mktestrepo prune-inline
464 464 $ mkcommit 'C-A0'
465 465 $ hg up 'desc("ROOT")'
466 466 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
467 467 $ mkcommit 'C-A1'
468 468 created new head
469 469 $ hg debugobsolete a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 `getid 'desc("C-A0")'`
470 470 1 new obsolescence markers
471 471 $ hg debugobsolete --record-parents `getid 'desc("C-A0")'`
472 472 1 new obsolescence markers
473 473 obsoleted 1 changesets
474 474 $ hg debugobsolete `getid 'desc("C-A0")'` `getid 'desc("C-A1")'`
475 475 1 new obsolescence markers
476 476 $ hg up 'desc("ROOT")'
477 477 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
478 478 $ hg log --hidden -G
479 479 o cf2c22470d67: C-A1
480 480 |
481 481 | x 84fcb0dfe17b: C-A0
482 482 |/
483 483 @ ea207398892e: ROOT
484 484
485 485 $ hg debugobsolete
486 486 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
487 487 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
488 488 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
489 489
490 490 Actual testing
491 491 --------------
492 492
493 493 $ testrevs 'desc("C-A0")'
494 494 ### Matched revisions###
495 495 84fcb0dfe17b: C-A0
496 496 ### Relevant markers ###
497 497 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
498 498 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
499 499 # bundling: 1 changesets found
500 500 ### Bundled markers ###
501 501 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
502 502 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
503 503 ### diff <relevant> <bundled> ###
504 504 #################################
505 505 ### Exclusive markers ###
506 506 # stripping: saved backup bundle to $TESTTMP/prune-inline/.hg/strip-backup/84fcb0dfe17b-6454bbdc-backup.hg
507 507 ### Backup markers ###
508 508 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
509 509 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
510 510 ### diff <relevant> <backed-up> ###
511 511 #################################
512 512 ### Stripped markers ###
513 513 ### diff <exclusive> <stripped> ###
514 514 #################################
515 515 # unbundling: adding changesets
516 516 # unbundling: adding manifests
517 517 # unbundling: adding file changes
518 518 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
519 519 # unbundling: (1 other changesets obsolete on arrival)
520 520 # unbundling: (run 'hg heads' to see heads)
521 521
522 522 $ testrevs 'desc("C-A1")'
523 523 ### Matched revisions###
524 524 cf2c22470d67: C-A1
525 525 ### Relevant markers ###
526 526 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
527 527 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
528 528 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
529 529 # bundling: 1 changesets found
530 530 ### Bundled markers ###
531 531 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
532 532 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
533 533 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
534 534 ### diff <relevant> <bundled> ###
535 535 #################################
536 536 ### Exclusive markers ###
537 537 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
538 538 # stripping: saved backup bundle to $TESTTMP/prune-inline/.hg/strip-backup/cf2c22470d67-fa0f07b0-backup.hg
539 539 ### Backup markers ###
540 540 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
541 541 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
542 542 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
543 543 ### diff <relevant> <backed-up> ###
544 544 #################################
545 545 ### Stripped markers ###
546 546 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
547 547 ### diff <exclusive> <stripped> ###
548 548 #################################
549 549 # unbundling: adding changesets
550 550 # unbundling: adding manifests
551 551 # unbundling: adding file changes
552 552 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
553 553 # unbundling: 1 new obsolescence markers
554 554 # unbundling: new changesets cf2c22470d67 (1 drafts)
555 555 # unbundling: (run 'hg heads' to see heads)
556 556
557 557 $ testrevs 'desc("C-A")'
558 558 ### Matched revisions###
559 559 84fcb0dfe17b: C-A0
560 560 cf2c22470d67: C-A1
561 561 ### Relevant markers ###
562 562 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
563 563 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
564 564 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
565 565 # bundling: 2 changesets found
566 566 ### Bundled markers ###
567 567 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
568 568 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
569 569 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
570 570 ### diff <relevant> <bundled> ###
571 571 #################################
572 572 ### Exclusive markers ###
573 573 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
574 574 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
575 575 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
576 576 # stripping: saved backup bundle to $TESTTMP/prune-inline/.hg/strip-backup/cf2c22470d67-fce4fc64-backup.hg
577 577 ### Backup markers ###
578 578 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
579 579 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
580 580 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
581 581 ### diff <relevant> <backed-up> ###
582 582 #################################
583 583 ### Stripped markers ###
584 584 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
585 585 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
586 586 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
587 587 ### diff <exclusive> <stripped> ###
588 588 #################################
589 589 # unbundling: adding changesets
590 590 # unbundling: adding manifests
591 591 # unbundling: adding file changes
592 592 # unbundling: added 2 changesets with 2 changes to 2 files (+1 heads)
593 593 # unbundling: 3 new obsolescence markers
594 594 # unbundling: new changesets cf2c22470d67 (1 drafts)
595 595 # unbundling: (1 other changesets obsolete on arrival)
596 596 # unbundling: (run 'hg heads' to see heads)
597 597
598 598 chain with missing prune
599 599 ========================
600 600
601 601 . βŠ— B
602 602 . |
603 603 . β‡ β—Œβ‡ β—” A1
604 604 . |
605 605 . ●
606 606
607 607 setup
608 608 -----
609 609
610 610 $ mktestrepo missing-prune
611 611 $ mkcommit 'C-A0'
612 612 $ mkcommit 'C-B0'
613 613 $ hg up 'desc("ROOT")'
614 614 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
615 615 $ mkcommit 'C-A1'
616 616 created new head
617 617 $ hg debugobsolete a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 `getid 'desc("C-A0")'`
618 618 1 new obsolescence markers
619 619 $ hg debugobsolete `getid 'desc("C-A0")'` `getid 'desc("C-A1")'`
620 620 1 new obsolescence markers
621 621 obsoleted 1 changesets
622 622 1 new orphan changesets
623 623 $ hg debugobsolete --record-parents `getid 'desc("C-B0")'`
624 624 1 new obsolescence markers
625 625 obsoleted 1 changesets
626 626
627 627 (it is annoying to create prune with parent data without the changeset, so we strip it after the fact)
628 628
629 629 $ hg strip --hidden --rev 'desc("C-A0")::' --no-backup --config devel.strip-obsmarkers=no
630 630
631 631 $ hg up 'desc("ROOT")'
632 632 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
633 633 $ hg log --hidden -G
634 634 o cf2c22470d67: C-A1
635 635 |
636 636 @ ea207398892e: ROOT
637 637
638 638 $ hg debugobsolete
639 639 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
640 640 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
641 641 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
642 642
643 643 Actual testing
644 644 --------------
645 645
646 646 $ testrevs 'desc("C-A1")'
647 647 ### Matched revisions###
648 648 cf2c22470d67: C-A1
649 649 ### Relevant markers ###
650 650 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
651 651 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
652 652 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
653 653 # bundling: 1 changesets found
654 654 ### Bundled markers ###
655 655 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
656 656 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
657 657 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
658 658 ### diff <relevant> <bundled> ###
659 659 #################################
660 660 ### Exclusive markers ###
661 661 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
662 662 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
663 663 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
664 664 # stripping: saved backup bundle to $TESTTMP/missing-prune/.hg/strip-backup/cf2c22470d67-fa0f07b0-backup.hg
665 665 ### Backup markers ###
666 666 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
667 667 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
668 668 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
669 669 ### diff <relevant> <backed-up> ###
670 670 #################################
671 671 ### Stripped markers ###
672 672 29f93b1df87baee1824e014080d8adf145f81783 0 {84fcb0dfe17b256ebae52e05572993b9194c018a} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
673 673 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
674 674 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
675 675 ### diff <exclusive> <stripped> ###
676 676 #################################
677 677 # unbundling: adding changesets
678 678 # unbundling: adding manifests
679 679 # unbundling: adding file changes
680 680 # unbundling: added 1 changesets with 1 changes to 1 files
681 681 # unbundling: 3 new obsolescence markers
682 682 # unbundling: new changesets cf2c22470d67 (1 drafts)
683 683 # unbundling: (run 'hg update' to get a working copy)
684 684
685 685 chain with precursors also pruned
686 686 =================================
687 687
688 688 . A0 (also pruned)
689 689 . β‡ β—Œβ‡ β—” A1
690 690 . |
691 691 . ●
692 692
693 693 setup
694 694 -----
695 695
696 696 $ mktestrepo prune-inline-missing
697 697 $ mkcommit 'C-A0'
698 698 $ hg up 'desc("ROOT")'
699 699 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
700 700 $ mkcommit 'C-A1'
701 701 created new head
702 702 $ hg debugobsolete a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 `getid 'desc("C-A0")'`
703 703 1 new obsolescence markers
704 704 $ hg debugobsolete --record-parents `getid 'desc("C-A0")'`
705 705 1 new obsolescence markers
706 706 obsoleted 1 changesets
707 707 $ hg debugobsolete `getid 'desc("C-A0")'` `getid 'desc("C-A1")'`
708 708 1 new obsolescence markers
709 709
710 710 (it is annoying to create prune with parent data without the changeset, so we strip it after the fact)
711 711
712 712 $ hg strip --hidden --rev 'desc("C-A0")::' --no-backup --config devel.strip-obsmarkers=no
713 713
714 714 $ hg up 'desc("ROOT")'
715 715 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
716 716 $ hg log --hidden -G
717 717 o cf2c22470d67: C-A1
718 718 |
719 719 @ ea207398892e: ROOT
720 720
721 721 $ hg debugobsolete
722 722 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
723 723 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
724 724 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
725 725
726 726 Actual testing
727 727 --------------
728 728
729 729 $ testrevs 'desc("C-A1")'
730 730 ### Matched revisions###
731 731 cf2c22470d67: C-A1
732 732 ### Relevant markers ###
733 733 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
734 734 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
735 735 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
736 736 # bundling: 1 changesets found
737 737 ### Bundled markers ###
738 738 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
739 739 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
740 740 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
741 741 ### diff <relevant> <bundled> ###
742 742 #################################
743 743 ### Exclusive markers ###
744 744 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
745 745 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
746 746 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
747 747 # stripping: saved backup bundle to $TESTTMP/prune-inline-missing/.hg/strip-backup/cf2c22470d67-fa0f07b0-backup.hg
748 748 ### Backup markers ###
749 749 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
750 750 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
751 751 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
752 752 ### diff <relevant> <backed-up> ###
753 753 #################################
754 754 ### Stripped markers ###
755 755 84fcb0dfe17b256ebae52e05572993b9194c018a 0 {ea207398892eb49e06441f10dda2a731f0450f20} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
756 756 84fcb0dfe17b256ebae52e05572993b9194c018a cf2c22470d67233004e934a31184ac2b35389914 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
757 757 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 84fcb0dfe17b256ebae52e05572993b9194c018a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
758 758 ### diff <exclusive> <stripped> ###
759 759 #################################
760 760 # unbundling: adding changesets
761 761 # unbundling: adding manifests
762 762 # unbundling: adding file changes
763 763 # unbundling: added 1 changesets with 1 changes to 1 files
764 764 # unbundling: 3 new obsolescence markers
765 765 # unbundling: new changesets cf2c22470d67 (1 drafts)
766 766 # unbundling: (run 'hg update' to get a working copy)
767 767
768 768 Chain with fold and split
769 769 =========================
770 770
771 771 setup
772 772 -----
773 773
774 774 $ mktestrepo split-fold
775 775 $ mkcommit 'C-A'
776 776 $ hg up 'desc("ROOT")'
777 777 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
778 778 $ mkcommit 'C-B'
779 779 created new head
780 780 $ hg up 'desc("ROOT")'
781 781 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
782 782 $ mkcommit 'C-C'
783 783 created new head
784 784 $ hg up 'desc("ROOT")'
785 785 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
786 786 $ mkcommit 'C-D'
787 787 created new head
788 788 $ hg up 'desc("ROOT")'
789 789 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
790 790 $ mkcommit 'C-E'
791 791 created new head
792 792 $ hg debugobsolete a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 `getid 'desc("C-A")'`
793 793 1 new obsolescence markers
794 794 $ hg debugobsolete `getid 'desc("C-A")'` `getid 'desc("C-B")'` `getid 'desc("C-C")'` # record split
795 795 1 new obsolescence markers
796 796 obsoleted 1 changesets
797 797 $ hg debugobsolete `getid 'desc("C-A")'` `getid 'desc("C-D")'` # other divergent
798 798 1 new obsolescence markers
799 799 3 new content-divergent changesets
800 800 $ hg debugobsolete `getid 'desc("C-A")'` b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0
801 801 1 new obsolescence markers
802 802 $ hg debugobsolete b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 `getid 'desc("C-E")'`
803 803 1 new obsolescence markers
804 804 1 new content-divergent changesets
805 805 $ hg debugobsolete `getid 'desc("C-B")'` `getid 'desc("C-E")'`
806 806 1 new obsolescence markers
807 807 obsoleted 1 changesets
808 808 $ hg debugobsolete `getid 'desc("C-C")'` `getid 'desc("C-E")'`
809 809 1 new obsolescence markers
810 810 obsoleted 1 changesets
811 811 $ hg debugobsolete `getid 'desc("C-D")'` `getid 'desc("C-E")'`
812 812 1 new obsolescence markers
813 813 obsoleted 1 changesets
814 814 $ hg debugobsolete c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 `getid 'desc("C-E")'`
815 815 1 new obsolescence markers
816 816
817 817 $ hg up 'desc("ROOT")'
818 818 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
819 819 $ hg log --hidden -G
820 820 o 2f20ff6509f0: C-E
821 821 |
822 822 | x 06dc9da25ef0: C-D
823 823 |/
824 824 | x 27ec657ca21d: C-C
825 825 |/
826 826 | x a9b9da38ed96: C-B
827 827 |/
828 828 | x 9ac430e15fca: C-A
829 829 |/
830 830 @ ea207398892e: ROOT
831 831
832 832 $ hg debugobsolete
833 833 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
834 834 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
835 835 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
836 836 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
837 837 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
838 838 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
839 839 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
840 840 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
841 841 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
842 842
843 843 Actual testing
844 844 --------------
845 845
846 846 $ testrevs 'desc("C-A")'
847 847 ### Matched revisions###
848 848 9ac430e15fca: C-A
849 849 ### Relevant markers ###
850 850 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
851 851 # bundling: 1 changesets found
852 852 ### Bundled markers ###
853 853 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
854 854 ### diff <relevant> <bundled> ###
855 855 #################################
856 856 ### Exclusive markers ###
857 857 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/9ac430e15fca-81204eba-backup.hg
858 858 ### Backup markers ###
859 859 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
860 860 ### diff <relevant> <backed-up> ###
861 861 #################################
862 862 ### Stripped markers ###
863 863 ### diff <exclusive> <stripped> ###
864 864 #################################
865 865 # unbundling: adding changesets
866 866 # unbundling: adding manifests
867 867 # unbundling: adding file changes
868 868 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
869 869 # unbundling: (1 other changesets obsolete on arrival)
870 870 # unbundling: (run 'hg heads' to see heads)
871 871
872 872 $ testrevs 'desc("C-B")'
873 873 ### Matched revisions###
874 874 a9b9da38ed96: C-B
875 875 ### Relevant markers ###
876 876 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
877 877 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
878 878 # bundling: 1 changesets found
879 879 ### Bundled markers ###
880 880 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
881 881 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
882 882 ### diff <relevant> <bundled> ###
883 883 #################################
884 884 ### Exclusive markers ###
885 885 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/a9b9da38ed96-7465d6e9-backup.hg
886 886 ### Backup markers ###
887 887 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
888 888 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
889 889 ### diff <relevant> <backed-up> ###
890 890 #################################
891 891 ### Stripped markers ###
892 892 ### diff <exclusive> <stripped> ###
893 893 #################################
894 894 # unbundling: adding changesets
895 895 # unbundling: adding manifests
896 896 # unbundling: adding file changes
897 897 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
898 898 # unbundling: (1 other changesets obsolete on arrival)
899 899 # unbundling: (run 'hg heads' to see heads)
900 900
901 901 $ testrevs 'desc("C-C")'
902 902 ### Matched revisions###
903 903 27ec657ca21d: C-C
904 904 ### Relevant markers ###
905 905 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
906 906 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
907 907 # bundling: 1 changesets found
908 908 ### Bundled markers ###
909 909 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
910 910 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
911 911 ### diff <relevant> <bundled> ###
912 912 #################################
913 913 ### Exclusive markers ###
914 914 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/27ec657ca21d-d5dd1c7c-backup.hg
915 915 ### Backup markers ###
916 916 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
917 917 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
918 918 ### diff <relevant> <backed-up> ###
919 919 #################################
920 920 ### Stripped markers ###
921 921 ### diff <exclusive> <stripped> ###
922 922 #################################
923 923 # unbundling: adding changesets
924 924 # unbundling: adding manifests
925 925 # unbundling: adding file changes
926 926 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
927 927 # unbundling: (1 other changesets obsolete on arrival)
928 928 # unbundling: (run 'hg heads' to see heads)
929 929
930 930 $ testrevs 'desc("C-D")'
931 931 ### Matched revisions###
932 932 06dc9da25ef0: C-D
933 933 ### Relevant markers ###
934 934 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
935 935 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
936 936 # bundling: 1 changesets found
937 937 ### Bundled markers ###
938 938 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
939 939 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
940 940 ### diff <relevant> <bundled> ###
941 941 #################################
942 942 ### Exclusive markers ###
943 943 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/06dc9da25ef0-9b1c0a91-backup.hg
944 944 ### Backup markers ###
945 945 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
946 946 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
947 947 ### diff <relevant> <backed-up> ###
948 948 #################################
949 949 ### Stripped markers ###
950 950 ### diff <exclusive> <stripped> ###
951 951 #################################
952 952 # unbundling: adding changesets
953 953 # unbundling: adding manifests
954 954 # unbundling: adding file changes
955 955 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
956 956 # unbundling: (1 other changesets obsolete on arrival)
957 957 # unbundling: (run 'hg heads' to see heads)
958 958
959 959 $ testrevs 'desc("C-E")'
960 960 ### Matched revisions###
961 961 2f20ff6509f0: C-E
962 962 ### Relevant markers ###
963 963 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
964 964 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
965 965 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
966 966 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
967 967 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
968 968 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
969 969 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
970 970 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
971 971 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
972 972 # bundling: 1 changesets found
973 973 ### Bundled markers ###
974 974 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
975 975 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
976 976 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
977 977 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
978 978 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
979 979 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
980 980 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
981 981 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
982 982 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
983 983 ### diff <relevant> <bundled> ###
984 984 #################################
985 985 ### Exclusive markers ###
986 986 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
987 987 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
988 988 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
989 989 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
990 990 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
991 991 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
992 992 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/2f20ff6509f0-8adeb22d-backup.hg
993 993 3 new content-divergent changesets
994 994 ### Backup markers ###
995 995 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
996 996 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
997 997 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
998 998 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
999 999 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1000 1000 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1001 1001 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1002 1002 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1003 1003 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1004 1004 ### diff <relevant> <backed-up> ###
1005 1005 #################################
1006 1006 ### Stripped markers ###
1007 1007 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1008 1008 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1009 1009 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1010 1010 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1011 1011 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1012 1012 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1013 1013 ### diff <exclusive> <stripped> ###
1014 1014 #################################
1015 1015 # unbundling: adding changesets
1016 1016 # unbundling: adding manifests
1017 1017 # unbundling: adding file changes
1018 1018 # unbundling: added 1 changesets with 1 changes to 1 files (+1 heads)
1019 1019 # unbundling: 6 new obsolescence markers
1020 1020 # unbundling: obsoleted 3 changesets
1021 1021 # unbundling: new changesets 2f20ff6509f0 (1 drafts)
1022 1022 # unbundling: (run 'hg heads' to see heads)
1023 1023
1024 1024 Bundle multiple revisions
1025 1025
1026 1026 * each part of the split
1027 1027
1028 1028 $ testrevs 'desc("C-B") + desc("C-C")'
1029 1029 ### Matched revisions###
1030 1030 27ec657ca21d: C-C
1031 1031 a9b9da38ed96: C-B
1032 1032 ### Relevant markers ###
1033 1033 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1034 1034 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1035 1035 # bundling: 2 changesets found
1036 1036 ### Bundled markers ###
1037 1037 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1038 1038 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1039 1039 ### diff <relevant> <bundled> ###
1040 1040 #################################
1041 1041 ### Exclusive markers ###
1042 1042 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/a9b9da38ed96-0daf625a-backup.hg
1043 1043 ### Backup markers ###
1044 1044 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1045 1045 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1046 1046 ### diff <relevant> <backed-up> ###
1047 1047 #################################
1048 1048 ### Stripped markers ###
1049 1049 ### diff <exclusive> <stripped> ###
1050 1050 #################################
1051 1051 # unbundling: adding changesets
1052 1052 # unbundling: adding manifests
1053 1053 # unbundling: adding file changes
1054 1054 # unbundling: added 2 changesets with 2 changes to 2 files (+2 heads)
1055 1055 # unbundling: (2 other changesets obsolete on arrival)
1056 1056 # unbundling: (run 'hg heads' to see heads)
1057 1057
1058 1058 * top one and other divergent
1059 1059
1060 1060 $ testrevs 'desc("C-E") + desc("C-D")'
1061 1061 ### Matched revisions###
1062 1062 06dc9da25ef0: C-D
1063 1063 2f20ff6509f0: C-E
1064 1064 ### Relevant markers ###
1065 1065 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1066 1066 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1067 1067 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1068 1068 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1069 1069 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1070 1070 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1071 1071 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1072 1072 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1073 1073 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1074 1074 # bundling: 2 changesets found
1075 1075 ### Bundled markers ###
1076 1076 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1077 1077 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1078 1078 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1079 1079 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1080 1080 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1081 1081 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1082 1082 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1083 1083 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1084 1084 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1085 1085 ### diff <relevant> <bundled> ###
1086 1086 #################################
1087 1087 ### Exclusive markers ###
1088 1088 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1089 1089 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1090 1090 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1091 1091 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1092 1092 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1093 1093 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1094 1094 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1095 1095 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/2f20ff6509f0-bf1b80f4-backup.hg
1096 1096 ### Backup markers ###
1097 1097 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1098 1098 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1099 1099 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1100 1100 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1101 1101 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1102 1102 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1103 1103 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1104 1104 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1105 1105 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1106 1106 ### diff <relevant> <backed-up> ###
1107 1107 #################################
1108 1108 ### Stripped markers ###
1109 1109 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1110 1110 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1111 1111 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1112 1112 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1113 1113 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1114 1114 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1115 1115 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1116 1116 ### diff <exclusive> <stripped> ###
1117 1117 #################################
1118 1118 # unbundling: adding changesets
1119 1119 # unbundling: adding manifests
1120 1120 # unbundling: adding file changes
1121 1121 # unbundling: added 2 changesets with 2 changes to 2 files (+2 heads)
1122 1122 # unbundling: 7 new obsolescence markers
1123 1123 # unbundling: obsoleted 2 changesets
1124 1124 # unbundling: new changesets 2f20ff6509f0 (1 drafts)
1125 1125 # unbundling: (1 other changesets obsolete on arrival)
1126 1126 # unbundling: (run 'hg heads' to see heads)
1127 1127
1128 1128 * top one and initial precursors
1129 1129
1130 1130 $ testrevs 'desc("C-E") + desc("C-A")'
1131 1131 ### Matched revisions###
1132 1132 2f20ff6509f0: C-E
1133 1133 9ac430e15fca: C-A
1134 1134 ### Relevant markers ###
1135 1135 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1136 1136 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1137 1137 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1138 1138 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1139 1139 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1140 1140 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1141 1141 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1142 1142 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1143 1143 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1144 1144 # bundling: 2 changesets found
1145 1145 ### Bundled markers ###
1146 1146 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1147 1147 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1148 1148 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1149 1149 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1150 1150 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1151 1151 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1152 1152 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1153 1153 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1154 1154 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1155 1155 ### diff <relevant> <bundled> ###
1156 1156 #################################
1157 1157 ### Exclusive markers ###
1158 1158 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1159 1159 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1160 1160 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1161 1161 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1162 1162 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1163 1163 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1164 1164 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/9ac430e15fca-36b6476a-backup.hg
1165 1165 3 new content-divergent changesets
1166 1166 ### Backup markers ###
1167 1167 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1168 1168 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1169 1169 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1170 1170 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1171 1171 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1172 1172 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1173 1173 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1174 1174 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1175 1175 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1176 1176 ### diff <relevant> <backed-up> ###
1177 1177 #################################
1178 1178 ### Stripped markers ###
1179 1179 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1180 1180 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1181 1181 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1182 1182 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1183 1183 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1184 1184 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1185 1185 ### diff <exclusive> <stripped> ###
1186 1186 #################################
1187 1187 # unbundling: adding changesets
1188 1188 # unbundling: adding manifests
1189 1189 # unbundling: adding file changes
1190 1190 # unbundling: added 2 changesets with 2 changes to 2 files (+2 heads)
1191 1191 # unbundling: 6 new obsolescence markers
1192 1192 # unbundling: obsoleted 3 changesets
1193 1193 # unbundling: new changesets 2f20ff6509f0 (1 drafts)
1194 1194 # unbundling: (1 other changesets obsolete on arrival)
1195 1195 # unbundling: (run 'hg heads' to see heads)
1196 1196
1197 1197 * top one and one of the split
1198 1198
1199 1199 $ testrevs 'desc("C-E") + desc("C-C")'
1200 1200 ### Matched revisions###
1201 1201 27ec657ca21d: C-C
1202 1202 2f20ff6509f0: C-E
1203 1203 ### Relevant markers ###
1204 1204 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1205 1205 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1206 1206 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1207 1207 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1208 1208 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1209 1209 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1210 1210 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1211 1211 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1212 1212 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1213 1213 # bundling: 2 changesets found
1214 1214 ### Bundled markers ###
1215 1215 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1216 1216 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1217 1217 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1218 1218 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1219 1219 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1220 1220 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1221 1221 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1222 1222 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1223 1223 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1224 1224 ### diff <relevant> <bundled> ###
1225 1225 #################################
1226 1226 ### Exclusive markers ###
1227 1227 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1228 1228 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1229 1229 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1230 1230 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1231 1231 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1232 1232 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1233 1233 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1234 1234 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/2f20ff6509f0-5fdfcd7d-backup.hg
1235 1235 ### Backup markers ###
1236 1236 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1237 1237 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1238 1238 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1239 1239 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1240 1240 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1241 1241 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1242 1242 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1243 1243 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1244 1244 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1245 1245 ### diff <relevant> <backed-up> ###
1246 1246 #################################
1247 1247 ### Stripped markers ###
1248 1248 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1249 1249 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1250 1250 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1251 1251 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1252 1252 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1253 1253 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1254 1254 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1255 1255 ### diff <exclusive> <stripped> ###
1256 1256 #################################
1257 1257 # unbundling: adding changesets
1258 1258 # unbundling: adding manifests
1259 1259 # unbundling: adding file changes
1260 1260 # unbundling: added 2 changesets with 2 changes to 2 files (+2 heads)
1261 1261 # unbundling: 7 new obsolescence markers
1262 1262 # unbundling: obsoleted 2 changesets
1263 1263 # unbundling: new changesets 2f20ff6509f0 (1 drafts)
1264 1264 # unbundling: (1 other changesets obsolete on arrival)
1265 1265 # unbundling: (run 'hg heads' to see heads)
1266 1266
1267 1267 * all
1268 1268
1269 1269 $ testrevs 'desc("C-")'
1270 1270 ### Matched revisions###
1271 1271 06dc9da25ef0: C-D
1272 1272 27ec657ca21d: C-C
1273 1273 2f20ff6509f0: C-E
1274 1274 9ac430e15fca: C-A
1275 1275 a9b9da38ed96: C-B
1276 1276 ### Relevant markers ###
1277 1277 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1278 1278 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1279 1279 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1280 1280 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1281 1281 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1282 1282 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1283 1283 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1284 1284 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1285 1285 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1286 1286 # bundling: 5 changesets found
1287 1287 ### Bundled markers ###
1288 1288 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1289 1289 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1290 1290 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1291 1291 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1292 1292 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1293 1293 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1294 1294 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1295 1295 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1296 1296 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1297 1297 ### diff <relevant> <bundled> ###
1298 1298 #################################
1299 1299 ### Exclusive markers ###
1300 1300 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1301 1301 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1302 1302 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1303 1303 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1304 1304 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1305 1305 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1306 1306 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1307 1307 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1308 1308 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1309 1309 # stripping: saved backup bundle to $TESTTMP/split-fold/.hg/strip-backup/a9b9da38ed96-eeb4258f-backup.hg
1310 1310 ### Backup markers ###
1311 1311 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1312 1312 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1313 1313 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1314 1314 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1315 1315 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1316 1316 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1317 1317 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1318 1318 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1319 1319 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1320 1320 ### diff <relevant> <backed-up> ###
1321 1321 #################################
1322 1322 ### Stripped markers ###
1323 1323 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1324 1324 27ec657ca21dd27c36c99fa75586f72ff0d442f1 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1325 1325 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 06dc9da25ef03e1ff7864dded5fcba42eff2a3f0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1326 1326 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c a9b9da38ed96f8c6c14f429441f625a344eb4696 27ec657ca21dd27c36c99fa75586f72ff0d442f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1327 1327 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1328 1328 a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0 9ac430e15fca923b0ba027ca85d4d75c5c9cb73c 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1329 1329 a9b9da38ed96f8c6c14f429441f625a344eb4696 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1330 1330 b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1331 1331 c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0 2f20ff6509f0e013e90c5c8efd996131c918b0ca 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1332 1332 ### diff <exclusive> <stripped> ###
1333 1333 #################################
1334 1334 # unbundling: adding changesets
1335 1335 # unbundling: adding manifests
1336 1336 # unbundling: adding file changes
1337 1337 # unbundling: added 5 changesets with 5 changes to 5 files (+4 heads)
1338 1338 # unbundling: 9 new obsolescence markers
1339 1339 # unbundling: new changesets 2f20ff6509f0 (1 drafts)
1340 1340 # unbundling: (4 other changesets obsolete on arrival)
1341 1341 # unbundling: (run 'hg heads' to see heads)
1342 1342
1343 1343 changeset pruned on its own
1344 1344 ===========================
1345 1345
1346 1346 . βŠ— B
1347 1347 . |
1348 1348 . β—• A
1349 1349 . |
1350 1350 . ●
1351 1351
1352 1352 setup
1353 1353 -----
1354 1354
1355 1355 $ mktestrepo lonely-prune
1356 1356 $ hg up 'desc("ROOT")'
1357 1357 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1358 1358 $ mkcommit 'C-A'
1359 1359 $ mkcommit 'C-B'
1360 1360 $ hg debugobsolete --record-parent `getid 'desc("C-B")'`
1361 1361 1 new obsolescence markers
1362 1362 obsoleted 1 changesets
1363 1363
1364 1364 $ hg up 'desc("ROOT")'
1365 1365 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1366 1366 $ hg log --hidden -G
1367 1367 x cefb651fc2fd: C-B
1368 1368 |
1369 1369 o 9ac430e15fca: C-A
1370 1370 |
1371 1371 @ ea207398892e: ROOT
1372 1372
1373 1373 $ hg debugobsolete
1374 1374 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1375 1375
1376 1376 Actual testing
1377 1377 --------------
1378 1378 $ testrevs 'desc("C-A")'
1379 1379 ### Matched revisions###
1380 1380 9ac430e15fca: C-A
1381 1381 ### Relevant markers ###
1382 1382 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1383 1383 # bundling: 1 changesets found
1384 1384 ### Bundled markers ###
1385 1385 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1386 1386 ### diff <relevant> <bundled> ###
1387 1387 #################################
1388 1388 ### Exclusive markers ###
1389 1389 $ testrevs 'desc("C-B")'
1390 1390 ### Matched revisions###
1391 1391 cefb651fc2fd: C-B
1392 1392 ### Relevant markers ###
1393 1393 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1394 1394 # bundling: 1 changesets found
1395 1395 ### Bundled markers ###
1396 1396 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1397 1397 ### diff <relevant> <bundled> ###
1398 1398 #################################
1399 1399 ### Exclusive markers ###
1400 1400 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1401 1401 # stripping: saved backup bundle to $TESTTMP/lonely-prune/.hg/strip-backup/cefb651fc2fd-345c8dfa-backup.hg
1402 1402 ### Backup markers ###
1403 1403 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1404 1404 ### diff <relevant> <backed-up> ###
1405 1405 #################################
1406 1406 ### Stripped markers ###
1407 1407 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1408 1408 ### diff <exclusive> <stripped> ###
1409 1409 #################################
1410 1410 # unbundling: adding changesets
1411 1411 # unbundling: adding manifests
1412 1412 # unbundling: adding file changes
1413 1413 # unbundling: added 1 changesets with 1 changes to 1 files
1414 1414 # unbundling: 1 new obsolescence markers
1415 1415 # unbundling: (1 other changesets obsolete on arrival)
1416 1416 # unbundling: (run 'hg update' to get a working copy)
1417 1417 $ testrevs 'desc("C-")'
1418 1418 ### Matched revisions###
1419 1419 9ac430e15fca: C-A
1420 1420 cefb651fc2fd: C-B
1421 1421 ### Relevant markers ###
1422 1422 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1423 1423 # bundling: 2 changesets found
1424 1424 ### Bundled markers ###
1425 1425 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1426 1426 ### diff <relevant> <bundled> ###
1427 1427 #################################
1428 1428 ### Exclusive markers ###
1429 1429 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1430 1430 # stripping: saved backup bundle to $TESTTMP/lonely-prune/.hg/strip-backup/9ac430e15fca-b9855b02-backup.hg
1431 1431 ### Backup markers ###
1432 1432 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1433 1433 ### diff <relevant> <backed-up> ###
1434 1434 #################################
1435 1435 ### Stripped markers ###
1436 1436 cefb651fc2fdc7bb75e588781de5e432c134e8a5 0 {9ac430e15fca923b0ba027ca85d4d75c5c9cb73c} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1437 1437 ### diff <exclusive> <stripped> ###
1438 1438 #################################
1439 1439 # unbundling: adding changesets
1440 1440 # unbundling: adding manifests
1441 1441 # unbundling: adding file changes
1442 1442 # unbundling: added 2 changesets with 2 changes to 2 files
1443 1443 # unbundling: 1 new obsolescence markers
1444 1444 # unbundling: new changesets 9ac430e15fca (1 drafts)
1445 1445 # unbundling: (1 other changesets obsolete on arrival)
1446 1446 # unbundling: (run 'hg update' to get a working copy)
1447 1447
1448 1448 Test that advisory obsolescence markers in bundles are ignored if unsupported
1449 1449 -----------------------------------------------------------------------------
1450 1450
1451 1451 $ hg init repo-with-obs
1452 1452 $ cd repo-with-obs
1453 1453 $ hg debugbuilddag +1
1454 1454 $ hg debugobsolete `getid 0`
1455 1455 1 new obsolescence markers
1456 1456 obsoleted 1 changesets
1457 1457 $ hg bundle --config experimental.evolution.bundle-obsmarker=true --config experimental.evolution.bundle-obsmarker:mandatory=false --all --hidden bundle-with-obs
1458 1458 1 changesets found
1459 1459 $ cd ..
1460 1460 $ hg init repo-without-obs
1461 1461 $ cd repo-without-obs
1462 1462 $ hg --config experimental.evolution=False unbundle ../repo-with-obs/bundle-with-obs --debug
1463 1463 bundle2-input-bundle: 1 params with-transaction
1464 1464 bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
1465 1465 adding changesets
1466 1466 add changeset 1ea73414a91b
1467 1467 adding manifests
1468 1468 adding file changes
1469 1469 bundle2-input-part: total payload size 190
1470 1470 bundle2-input-part: "cache:rev-branch-cache" (advisory) supported
1471 1471 bundle2-input-part: total payload size 39
1472 1472 bundle2-input-part: "obsmarkers" (advisory) supported
1473 1473 bundle2-input-part: total payload size 50
1474 1474 ignoring obsolescence markers, feature not enabled
1475 1475 bundle2-input-bundle: 3 parts total
1476 1476 updating the branch cache
1477 1477 added 1 changesets with 0 changes to 0 files
1478 1478 new changesets 1ea73414a91b (1 drafts)
1479 1479 (run 'hg update' to get a working copy)
1480 1480 $ cd ..
1481 1481
1482 1482 Test bundlespec overwrite default
1483 1483 ---------------------------------
1484 1484
1485 1485 # move back to the default
1486 1486
1487 1487 $ grep -v evolution.bundle-obsmarker $HGRCPATH > a
1488 1488 $ mv a $HGRCPATH
1489 1489
1490 1490 $ hg bundle -R repo-with-obs --type 'v2;obsolescence=yes' --all --hidden bundle-type-with-obs
1491 1491 1 changesets found
1492 $ hg debugbundle --spec bundle-type-with-obs
1493 bzip2-v2;obsolescence=yes
1492 1494 $ hg debugbundle bundle-type-with-obs --part-type obsmarkers
1493 1495 Stream params: {Compression: BZ}
1494 1496 obsmarkers -- {} (mandatory: True)
1495 1497 version: 1 (50 bytes)
1496 1498 1ea73414a91b0920940797d8fc6a11e447f8ea1e 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1497 1499
1498 1500 $ hg bundle -R repo-with-obs --type 'v2;obsolescence=yes;obsolescence-mandatory=no' --all --hidden bundle-type-with-obs-adv
1499 1501 1 changesets found
1502 $ hg debugbundle --spec bundle-type-with-obs-adv
1503 bzip2-v2;obsolescence=yes;obsolescence-mandatory=no
1500 1504 $ hg debugbundle bundle-type-with-obs-adv --part-type obsmarkers
1501 1505 Stream params: {Compression: BZ}
1502 1506 obsmarkers -- {} (mandatory: False)
1503 1507 version: 1 (50 bytes)
1504 1508 1ea73414a91b0920940797d8fc6a11e447f8ea1e 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1505 1509 $ hg bundle -R repo-with-obs --type 'v2;obsolescence=no' --all --hidden bundle-type-without-obs
1506 1510 1 changesets found
1511 $ hg debugbundle --spec bundle-type-without-obs
1512 bzip2-v2
1507 1513 $ hg debugbundle bundle-type-without-obs --part-type obsmarkers
1508 1514 Stream params: {Compression: BZ}
1509 1515
1510 1516 Test bundlespec overwrite local config
1511 1517 --------------------------------------
1512 1518
1513 1519 $ hg bundle -R repo-with-obs --config experimental.evolution.bundle-obsmarker=false --type 'v2;obsolescence=yes' --all --hidden bundle-type-with-obs2
1514 1520 1 changesets found
1521 $ hg debugbundle --spec bundle-type-with-obs2
1522 bzip2-v2;obsolescence=yes
1515 1523 $ hg debugbundle bundle-type-with-obs2 --part-type obsmarkers
1516 1524 Stream params: {Compression: BZ}
1517 1525 obsmarkers -- {} (mandatory: True)
1518 1526 version: 1 (50 bytes)
1519 1527 1ea73414a91b0920940797d8fc6a11e447f8ea1e 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
1520 1528 $ hg bundle -R repo-with-obs --config experimental.evolution.bundle-obsmarker=true --type 'v2;obsolescence=no' --all --hidden bundle-type-without-obs2
1521 1529 1 changesets found
1530 $ hg debugbundle --spec bundle-type-without-obs2
1531 bzip2-v2
1522 1532 $ hg debugbundle bundle-type-without-obs2 --part-type obsmarkers
1523 1533 Stream params: {Compression: BZ}
General Comments 0
You need to be logged in to leave comments. Login now