##// END OF EJS Templates
rebase: extract function for rebasing a single node...
Martin von Zweigbergk -
r36949:28f98809 default
parent child Browse files
Show More
@@ -430,115 +430,122 b' class rebaseruntime(object):'
430 430 ui.note(_('rebase merging completed\n'))
431 431
432 432 def _performrebasesubset(self, tr, subset, pos, total):
433 repo, ui, opts = self.repo, self.ui, self.opts
434 sortedrevs = repo.revs('sort(%ld, -topo)', subset)
433 sortedrevs = self.repo.revs('sort(%ld, -topo)', subset)
435 434 allowdivergence = self.ui.configbool(
436 435 'experimental', 'evolution.allowdivergence')
437 436 if not allowdivergence:
438 sortedrevs -= repo.revs(
437 sortedrevs -= self.repo.revs(
439 438 'descendants(%ld) and not %ld',
440 439 self.obsoletewithoutsuccessorindestination,
441 440 self.obsoletewithoutsuccessorindestination,
442 441 )
442 posholder = [pos]
443 def progress(ctx):
444 posholder[0] += 1
445 self.repo.ui.progress(_("rebasing"), posholder[0],
446 ("%d:%s" % (ctx.rev(), ctx)), _('changesets'),
447 total)
443 448 for rev in sortedrevs:
444 dest = self.destmap[rev]
445 ctx = repo[rev]
446 desc = _ctxdesc(ctx)
447 if self.state[rev] == rev:
448 ui.status(_('already rebased %s\n') % desc)
449 elif (not allowdivergence
450 and rev in self.obsoletewithoutsuccessorindestination):
451 msg = _('note: not rebasing %s and its descendants as '
452 'this would cause divergence\n') % desc
453 repo.ui.status(msg)
454 self.skipped.add(rev)
455 elif rev in self.obsoletenotrebased:
456 succ = self.obsoletenotrebased[rev]
457 if succ is None:
458 msg = _('note: not rebasing %s, it has no '
459 'successor\n') % desc
460 else:
461 succdesc = _ctxdesc(repo[succ])
462 msg = (_('note: not rebasing %s, already in '
463 'destination as %s\n') % (desc, succdesc))
464 repo.ui.status(msg)
465 # Make clearrebased aware state[rev] is not a true successor
466 self.skipped.add(rev)
467 # Record rev as moved to its desired destination in self.state.
468 # This helps bookmark and working parent movement.
469 dest = max(adjustdest(repo, rev, self.destmap, self.state,
470 self.skipped))
471 self.state[rev] = dest
472 elif self.state[rev] == revtodo:
473 pos += 1
474 ui.status(_('rebasing %s\n') % desc)
475 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)),
476 _('changesets'), total)
477 p1, p2, base = defineparents(repo, rev, self.destmap,
478 self.state, self.skipped,
479 self.obsoletenotrebased)
480 self.storestatus(tr=tr)
481 if len(repo[None].parents()) == 2:
482 repo.ui.debug('resuming interrupted rebase\n')
449 self._rebasenode(tr, rev, allowdivergence, progress)
450 return posholder[0]
451
452 def _rebasenode(self, tr, rev, allowdivergence, progressfn):
453 repo, ui, opts = self.repo, self.ui, self.opts
454 dest = self.destmap[rev]
455 ctx = repo[rev]
456 desc = _ctxdesc(ctx)
457 if self.state[rev] == rev:
458 ui.status(_('already rebased %s\n') % desc)
459 elif (not allowdivergence
460 and rev in self.obsoletewithoutsuccessorindestination):
461 msg = _('note: not rebasing %s and its descendants as '
462 'this would cause divergence\n') % desc
463 repo.ui.status(msg)
464 self.skipped.add(rev)
465 elif rev in self.obsoletenotrebased:
466 succ = self.obsoletenotrebased[rev]
467 if succ is None:
468 msg = _('note: not rebasing %s, it has no '
469 'successor\n') % desc
470 else:
471 succdesc = _ctxdesc(repo[succ])
472 msg = (_('note: not rebasing %s, already in '
473 'destination as %s\n') % (desc, succdesc))
474 repo.ui.status(msg)
475 # Make clearrebased aware state[rev] is not a true successor
476 self.skipped.add(rev)
477 # Record rev as moved to its desired destination in self.state.
478 # This helps bookmark and working parent movement.
479 dest = max(adjustdest(repo, rev, self.destmap, self.state,
480 self.skipped))
481 self.state[rev] = dest
482 elif self.state[rev] == revtodo:
483 ui.status(_('rebasing %s\n') % desc)
484 progressfn(ctx)
485 p1, p2, base = defineparents(repo, rev, self.destmap,
486 self.state, self.skipped,
487 self.obsoletenotrebased)
488 self.storestatus(tr=tr)
489 if len(repo[None].parents()) == 2:
490 repo.ui.debug('resuming interrupted rebase\n')
491 else:
492 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
493 with ui.configoverride(overrides, 'rebase'):
494 stats = rebasenode(repo, rev, p1, base, self.collapsef,
495 dest, wctx=self.wctx)
496 if stats and stats[3] > 0:
497 if self.wctx.isinmemory():
498 raise error.InMemoryMergeConflictsError()
499 else:
500 raise error.InterventionRequired(
501 _('unresolved conflicts (see hg '
502 'resolve, then hg rebase --continue)'))
503 if not self.collapsef:
504 merging = p2 != nullrev
505 editform = cmdutil.mergeeditform(merging, 'rebase')
506 editor = cmdutil.getcommiteditor(editform=editform,
507 **pycompat.strkwargs(opts))
508 if self.wctx.isinmemory():
509 newnode = concludememorynode(repo, rev, p1, p2,
510 wctx=self.wctx,
511 extrafn=_makeextrafn(self.extrafns),
512 editor=editor,
513 keepbranches=self.keepbranchesf,
514 date=self.date)
515 mergemod.mergestate.clean(repo)
483 516 else:
484 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
485 with ui.configoverride(overrides, 'rebase'):
486 stats = rebasenode(repo, rev, p1, base, self.collapsef,
487 dest, wctx=self.wctx)
488 if stats and stats[3] > 0:
489 if self.wctx.isinmemory():
490 raise error.InMemoryMergeConflictsError()
491 else:
492 raise error.InterventionRequired(
493 _('unresolved conflicts (see hg '
494 'resolve, then hg rebase --continue)'))
517 newnode = concludenode(repo, rev, p1, p2,
518 extrafn=_makeextrafn(self.extrafns),
519 editor=editor,
520 keepbranches=self.keepbranchesf,
521 date=self.date)
522
523 if newnode is None:
524 # If it ended up being a no-op commit, then the normal
525 # merge state clean-up path doesn't happen, so do it
526 # here. Fix issue5494
527 mergemod.mergestate.clean(repo)
528 else:
529 # Skip commit if we are collapsing
530 if self.wctx.isinmemory():
531 self.wctx.setbase(repo[p1])
532 else:
533 repo.setparents(repo[p1].node())
534 newnode = None
535 # Update the state
536 if newnode is not None:
537 self.state[rev] = repo[newnode].rev()
538 ui.debug('rebased as %s\n' % short(newnode))
539 else:
495 540 if not self.collapsef:
496 merging = p2 != nullrev
497 editform = cmdutil.mergeeditform(merging, 'rebase')
498 editor = cmdutil.getcommiteditor(editform=editform,
499 **pycompat.strkwargs(opts))
500 if self.wctx.isinmemory():
501 newnode = concludememorynode(repo, rev, p1, p2,
502 wctx=self.wctx,
503 extrafn=_makeextrafn(self.extrafns),
504 editor=editor,
505 keepbranches=self.keepbranchesf,
506 date=self.date)
507 mergemod.mergestate.clean(repo)
508 else:
509 newnode = concludenode(repo, rev, p1, p2,
510 extrafn=_makeextrafn(self.extrafns),
511 editor=editor,
512 keepbranches=self.keepbranchesf,
513 date=self.date)
514
515 if newnode is None:
516 # If it ended up being a no-op commit, then the normal
517 # merge state clean-up path doesn't happen, so do it
518 # here. Fix issue5494
519 mergemod.mergestate.clean(repo)
520 else:
521 # Skip commit if we are collapsing
522 if self.wctx.isinmemory():
523 self.wctx.setbase(repo[p1])
524 else:
525 repo.setparents(repo[p1].node())
526 newnode = None
527 # Update the state
528 if newnode is not None:
529 self.state[rev] = repo[newnode].rev()
530 ui.debug('rebased as %s\n' % short(newnode))
531 else:
532 if not self.collapsef:
533 ui.warn(_('note: rebase of %d:%s created no changes '
534 'to commit\n') % (rev, ctx))
535 self.skipped.add(rev)
536 self.state[rev] = p1
537 ui.debug('next revision set to %d\n' % p1)
538 else:
539 ui.status(_('already rebased %s as %s\n') %
540 (desc, repo[self.state[rev]]))
541 return pos
541 ui.warn(_('note: rebase of %d:%s created no changes '
542 'to commit\n') % (rev, ctx))
543 self.skipped.add(rev)
544 self.state[rev] = p1
545 ui.debug('next revision set to %d\n' % p1)
546 else:
547 ui.status(_('already rebased %s as %s\n') %
548 (desc, repo[self.state[rev]]))
542 549
543 550 def _finishrebase(self):
544 551 repo, ui, opts = self.repo, self.ui, self.opts
General Comments 0
You need to be logged in to leave comments. Login now