##// END OF EJS Templates
rebase: introduce a rebaseruntime (RR) class...
Kostia Balytskyi -
r29358:6e83f5bb default
parent child Browse files
Show More
@@ -119,6 +119,17 def _revsetdestrebase(repo, subset, x):
119 sourceset = revset.getset(repo, revset.fullreposet(repo), x)
119 sourceset = revset.getset(repo, revset.fullreposet(repo), x)
120 return subset & revset.baseset([_destrebase(repo, sourceset)])
120 return subset & revset.baseset([_destrebase(repo, sourceset)])
121
121
122 class rebaseruntime(object):
123 """This class is a container for rebase runtime state"""
124 def __init__(self):
125 self.originalwd = None
126 self.external = nullrev
127 # Mapping between the old revision id and either what is the new rebased
128 # revision or what needs to be done with the old revision. The state
129 # dict will be what contains most of the rebase progress state.
130 self.state = {}
131 self.activebookmark = None
132
122 @command('rebase',
133 @command('rebase',
123 [('s', 'source', '',
134 [('s', 'source', '',
124 _('rebase the specified changeset and descendants'), _('REV')),
135 _('rebase the specified changeset and descendants'), _('REV')),
@@ -229,13 +240,8 def rebase(ui, repo, **opts):
229 unresolved conflicts.
240 unresolved conflicts.
230
241
231 """
242 """
232 originalwd = target = None
243 rbsrt = rebaseruntime()
233 activebookmark = None
244 target = None
234 external = nullrev
235 # Mapping between the old revision id and either what is the new rebased
236 # revision or what needs to be done with the old revision. The state dict
237 # will be what contains most of the rebase progress state.
238 state = {}
239 skipped = set()
245 skipped = set()
240 targetancestors = set()
246 targetancestors = set()
241
247
@@ -296,8 +302,9 def rebase(ui, repo, **opts):
296 ui.warn(_('tool option will be ignored\n'))
302 ui.warn(_('tool option will be ignored\n'))
297
303
298 try:
304 try:
299 (originalwd, target, state, skipped, collapsef, keepf,
305 (rbsrt.originalwd, target, rbsrt.state, skipped,
300 keepbranchesf, external, activebookmark) = restorestatus(repo)
306 collapsef, keepf, keepbranchesf, rbsrt.external,
307 rbsrt.activebookmark) = restorestatus(repo)
301 collapsemsg = restorecollapsemsg(repo)
308 collapsemsg = restorecollapsemsg(repo)
302 except error.RepoLookupError:
309 except error.RepoLookupError:
303 if abortf:
310 if abortf:
@@ -311,18 +318,17 def rebase(ui, repo, **opts):
311 hint = _('use "hg rebase --abort" to clear broken state')
318 hint = _('use "hg rebase --abort" to clear broken state')
312 raise error.Abort(msg, hint=hint)
319 raise error.Abort(msg, hint=hint)
313 if abortf:
320 if abortf:
314 return abort(repo, originalwd, target, state,
321 return abort(repo, rbsrt.originalwd, target, rbsrt.state,
315 activebookmark=activebookmark)
322 activebookmark=rbsrt.activebookmark)
316
323
317 obsoletenotrebased = {}
324 obsoletenotrebased = {}
318 if ui.configbool('experimental', 'rebaseskipobsolete',
325 if ui.configbool('experimental', 'rebaseskipobsolete',
319 default=True):
326 default=True):
320 rebaseobsrevs = set([r for r, status in state.items()
327 rebaseobsrevs = set([r for r, st in rbsrt.state.items()
321 if status == revprecursor])
328 if st == revprecursor])
322 rebasesetrevs = set(state.keys())
329 rebasesetrevs = set(rbsrt.state.keys())
323 obsoletenotrebased = _computeobsoletenotrebased(repo,
330 obsoletenotrebased = _computeobsoletenotrebased(repo,
324 rebaseobsrevs,
331 rebaseobsrevs, target)
325 target)
326 rebaseobsskipped = set(obsoletenotrebased)
332 rebaseobsskipped = set(obsoletenotrebased)
327 _checkobsrebase(repo, ui, rebaseobsrevs, rebasesetrevs,
333 _checkobsrebase(repo, ui, rebaseobsrevs, rebasesetrevs,
328 rebaseobsskipped)
334 rebaseobsskipped)
@@ -368,11 +374,12 def rebase(ui, repo, **opts):
368 % repo[root],
374 % repo[root],
369 hint=_('see "hg help phases" for details'))
375 hint=_('see "hg help phases" for details'))
370
376
371 originalwd, target, state = result
377 (rbsrt.originalwd, target, rbsrt.state) = result
372 if collapsef:
378 if collapsef:
373 targetancestors = repo.changelog.ancestors([target],
379 targetancestors = repo.changelog.ancestors([target],
374 inclusive=True)
380 inclusive=True)
375 external = externalparent(repo, state, targetancestors)
381 rbsrt.external = externalparent(repo, rbsrt.state,
382 targetancestors)
376
383
377 if dest.closesbranch() and not keepbranchesf:
384 if dest.closesbranch() and not keepbranchesf:
378 ui.status(_('reopening closed branch head %s\n') % dest)
385 ui.status(_('reopening closed branch head %s\n') % dest)
@@ -384,7 +391,7 def rebase(ui, repo, **opts):
384 extrafns.insert(0, _savebranch)
391 extrafns.insert(0, _savebranch)
385 if collapsef:
392 if collapsef:
386 branches = set()
393 branches = set()
387 for rev in state:
394 for rev in rbsrt.state:
388 branches.add(repo[rev].branch())
395 branches.add(repo[rev].branch())
389 if len(branches) > 1:
396 if len(branches) > 1:
390 raise error.Abort(_('cannot collapse multiple named '
397 raise error.Abort(_('cannot collapse multiple named '
@@ -396,13 +403,13 def rebase(ui, repo, **opts):
396
403
397 # Keep track of the current bookmarks in order to reset them later
404 # Keep track of the current bookmarks in order to reset them later
398 currentbookmarks = repo._bookmarks.copy()
405 currentbookmarks = repo._bookmarks.copy()
399 activebookmark = activebookmark or repo._activebookmark
406 rbsrt.activebookmark = rbsrt.activebookmark or repo._activebookmark
400 if activebookmark:
407 if rbsrt.activebookmark:
401 bookmarks.deactivate(repo)
408 bookmarks.deactivate(repo)
402
409
403 extrafn = _makeextrafn(extrafns)
410 extrafn = _makeextrafn(extrafns)
404
411
405 sortedstate = sorted(state)
412 sortedstate = sorted(rbsrt.state)
406 total = len(sortedstate)
413 total = len(sortedstate)
407 pos = 0
414 pos = 0
408 for rev in sortedstate:
415 for rev in sortedstate:
@@ -413,15 +420,16 def rebase(ui, repo, **opts):
413 if names:
420 if names:
414 desc += ' (%s)' % ' '.join(names)
421 desc += ' (%s)' % ' '.join(names)
415 pos += 1
422 pos += 1
416 if state[rev] == revtodo:
423 if rbsrt.state[rev] == revtodo:
417 ui.status(_('rebasing %s\n') % desc)
424 ui.status(_('rebasing %s\n') % desc)
418 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)),
425 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)),
419 _('changesets'), total)
426 _('changesets'), total)
420 p1, p2, base = defineparents(repo, rev, target, state,
427 p1, p2, base = defineparents(repo, rev, target, rbsrt.state,
421 targetancestors,
428 targetancestors,
422 obsoletenotrebased)
429 obsoletenotrebased)
423 storestatus(repo, originalwd, target, state, collapsef, keepf,
430 storestatus(repo, rbsrt.originalwd, target, rbsrt.state,
424 keepbranchesf, external, activebookmark)
431 collapsef, keepf, keepbranchesf,
432 rbsrt.external, rbsrt.activebookmark)
425 storecollapsemsg(repo, collapsemsg)
433 storecollapsemsg(repo, collapsemsg)
426 if len(repo[None].parents()) == 2:
434 if len(repo[None].parents()) == 2:
427 repo.ui.debug('resuming interrupted rebase\n')
435 repo.ui.debug('resuming interrupted rebase\n')
@@ -429,7 +437,7 def rebase(ui, repo, **opts):
429 try:
437 try:
430 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
438 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
431 'rebase')
439 'rebase')
432 stats = rebasenode(repo, rev, p1, base, state,
440 stats = rebasenode(repo, rev, p1, base, rbsrt.state,
433 collapsef, target)
441 collapsef, target)
434 if stats and stats[3] > 0:
442 if stats and stats[3] > 0:
435 raise error.InterventionRequired(
443 raise error.InterventionRequired(
@@ -453,38 +461,38 def rebase(ui, repo, **opts):
453 newnode = None
461 newnode = None
454 # Update the state
462 # Update the state
455 if newnode is not None:
463 if newnode is not None:
456 state[rev] = repo[newnode].rev()
464 rbsrt.state[rev] = repo[newnode].rev()
457 ui.debug('rebased as %s\n' % short(newnode))
465 ui.debug('rebased as %s\n' % short(newnode))
458 else:
466 else:
459 if not collapsef:
467 if not collapsef:
460 ui.warn(_('note: rebase of %d:%s created no changes '
468 ui.warn(_('note: rebase of %d:%s created no changes '
461 'to commit\n') % (rev, ctx))
469 'to commit\n') % (rev, ctx))
462 skipped.add(rev)
470 skipped.add(rev)
463 state[rev] = p1
471 rbsrt.state[rev] = p1
464 ui.debug('next revision set to %s\n' % p1)
472 ui.debug('next revision set to %s\n' % p1)
465 elif state[rev] == nullmerge:
473 elif rbsrt.state[rev] == nullmerge:
466 ui.debug('ignoring null merge rebase of %s\n' % rev)
474 ui.debug('ignoring null merge rebase of %s\n' % rev)
467 elif state[rev] == revignored:
475 elif rbsrt.state[rev] == revignored:
468 ui.status(_('not rebasing ignored %s\n') % desc)
476 ui.status(_('not rebasing ignored %s\n') % desc)
469 elif state[rev] == revprecursor:
477 elif rbsrt.state[rev] == revprecursor:
470 targetctx = repo[obsoletenotrebased[rev]]
478 targetctx = repo[obsoletenotrebased[rev]]
471 desctarget = '%d:%s "%s"' % (targetctx.rev(), targetctx,
479 desctarget = '%d:%s "%s"' % (targetctx.rev(), targetctx,
472 targetctx.description().split('\n', 1)[0])
480 targetctx.description().split('\n', 1)[0])
473 msg = _('note: not rebasing %s, already in destination as %s\n')
481 msg = _('note: not rebasing %s, already in destination as %s\n')
474 ui.status(msg % (desc, desctarget))
482 ui.status(msg % (desc, desctarget))
475 elif state[rev] == revpruned:
483 elif rbsrt.state[rev] == revpruned:
476 msg = _('note: not rebasing %s, it has no successor\n')
484 msg = _('note: not rebasing %s, it has no successor\n')
477 ui.status(msg % desc)
485 ui.status(msg % desc)
478 else:
486 else:
479 ui.status(_('already rebased %s as %s\n') %
487 ui.status(_('already rebased %s as %s\n') %
480 (desc, repo[state[rev]]))
488 (desc, repo[rbsrt.state[rev]]))
481
489
482 ui.progress(_('rebasing'), None)
490 ui.progress(_('rebasing'), None)
483 ui.note(_('rebase merging completed\n'))
491 ui.note(_('rebase merging completed\n'))
484
492
485 if collapsef and not keepopen:
493 if collapsef and not keepopen:
486 p1, p2, _base = defineparents(repo, min(state), target,
494 p1, p2, _base = defineparents(repo, min(rbsrt.state), target,
487 state, targetancestors,
495 rbsrt.state, targetancestors,
488 obsoletenotrebased)
496 obsoletenotrebased)
489 editopt = opts.get('edit')
497 editopt = opts.get('edit')
490 editform = 'rebase.collapse'
498 editform = 'rebase.collapse'
@@ -492,12 +500,14 def rebase(ui, repo, **opts):
492 commitmsg = collapsemsg
500 commitmsg = collapsemsg
493 else:
501 else:
494 commitmsg = 'Collapsed revision'
502 commitmsg = 'Collapsed revision'
495 for rebased in state:
503 for rebased in rbsrt.state:
496 if rebased not in skipped and state[rebased] > nullmerge:
504 if rebased not in skipped and\
505 rbsrt.state[rebased] > nullmerge:
497 commitmsg += '\n* %s' % repo[rebased].description()
506 commitmsg += '\n* %s' % repo[rebased].description()
498 editopt = True
507 editopt = True
499 editor = cmdutil.getcommiteditor(edit=editopt, editform=editform)
508 editor = cmdutil.getcommiteditor(edit=editopt, editform=editform)
500 newnode = concludenode(repo, rev, p1, external, commitmsg=commitmsg,
509 newnode = concludenode(repo, rev, p1, rbsrt.external,
510 commitmsg=commitmsg,
501 extrafn=extrafn, editor=editor,
511 extrafn=extrafn, editor=editor,
502 keepbranches=keepbranchesf,
512 keepbranches=keepbranchesf,
503 date=date)
513 date=date)
@@ -505,17 +515,17 def rebase(ui, repo, **opts):
505 newrev = target
515 newrev = target
506 else:
516 else:
507 newrev = repo[newnode].rev()
517 newrev = repo[newnode].rev()
508 for oldrev in state.iterkeys():
518 for oldrev in rbsrt.state.iterkeys():
509 if state[oldrev] > nullmerge:
519 if rbsrt.state[oldrev] > nullmerge:
510 state[oldrev] = newrev
520 rbsrt.state[oldrev] = newrev
511
521
512 if 'qtip' in repo.tags():
522 if 'qtip' in repo.tags():
513 updatemq(repo, state, skipped, **opts)
523 updatemq(repo, rbsrt.state, skipped, **opts)
514
524
515 if currentbookmarks:
525 if currentbookmarks:
516 # Nodeids are needed to reset bookmarks
526 # Nodeids are needed to reset bookmarks
517 nstate = {}
527 nstate = {}
518 for k, v in state.iteritems():
528 for k, v in rbsrt.state.iteritems():
519 if v > nullmerge:
529 if v > nullmerge:
520 nstate[repo[k].node()] = repo[v].node()
530 nstate[repo[k].node()] = repo[v].node()
521 # XXX this is the same as dest.node() for the non-continue path --
531 # XXX this is the same as dest.node() for the non-continue path --
@@ -524,10 +534,10 def rebase(ui, repo, **opts):
524
534
525 # restore original working directory
535 # restore original working directory
526 # (we do this before stripping)
536 # (we do this before stripping)
527 newwd = state.get(originalwd, originalwd)
537 newwd = rbsrt.state.get(rbsrt.originalwd, rbsrt.originalwd)
528 if newwd < 0:
538 if newwd < 0:
529 # original directory is a parent of rebase set root or ignored
539 # original directory is a parent of rebase set root or ignored
530 newwd = originalwd
540 newwd = rbsrt.originalwd
531 if newwd not in [c.rev() for c in repo[None].parents()]:
541 if newwd not in [c.rev() for c in repo[None].parents()]:
532 ui.note(_("update back to initial working directory parent\n"))
542 ui.note(_("update back to initial working directory parent\n"))
533 hg.updaterepo(repo, newwd, False)
543 hg.updaterepo(repo, newwd, False)
@@ -536,14 +546,14 def rebase(ui, repo, **opts):
536 collapsedas = None
546 collapsedas = None
537 if collapsef:
547 if collapsef:
538 collapsedas = newnode
548 collapsedas = newnode
539 clearrebased(ui, repo, state, skipped, collapsedas)
549 clearrebased(ui, repo, rbsrt.state, skipped, collapsedas)
540
550
541 with repo.transaction('bookmark') as tr:
551 with repo.transaction('bookmark') as tr:
542 if currentbookmarks:
552 if currentbookmarks:
543 updatebookmarks(repo, targetnode, nstate, currentbookmarks, tr)
553 updatebookmarks(repo, targetnode, nstate, currentbookmarks, tr)
544 if activebookmark not in repo._bookmarks:
554 if rbsrt.activebookmark not in repo._bookmarks:
545 # active bookmark was divergent one and has been deleted
555 # active bookmark was divergent one and has been deleted
546 activebookmark = None
556 rbsrt.activebookmark = None
547 clearstatus(repo)
557 clearstatus(repo)
548 clearcollapsemsg(repo)
558 clearcollapsemsg(repo)
549
559
@@ -552,9 +562,9 def rebase(ui, repo, **opts):
552 if skipped:
562 if skipped:
553 ui.note(_("%d revisions have been skipped\n") % len(skipped))
563 ui.note(_("%d revisions have been skipped\n") % len(skipped))
554
564
555 if (activebookmark and
565 if (rbsrt.activebookmark and
556 repo['.'].node() == repo._bookmarks[activebookmark]):
566 repo['.'].node() == repo._bookmarks[rbsrt.activebookmark]):
557 bookmarks.activate(repo, activebookmark)
567 bookmarks.activate(repo, rbsrt.activebookmark)
558
568
559 finally:
569 finally:
560 release(lock, wlock)
570 release(lock, wlock)
General Comments 0
You need to be logged in to leave comments. Login now