309 else: |
316 else: |
310 msg = _('cannot continue inconsistent rebase') |
317 msg = _('cannot continue inconsistent rebase') |
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) |
329 else: |
335 else: |
330 dest, rebaseset = _definesets(ui, repo, destf, srcf, basef, revf, |
336 dest, rebaseset = _definesets(ui, repo, destf, srcf, basef, revf, |
394 if not targetancestors: |
401 if not targetancestors: |
395 targetancestors = repo.changelog.ancestors([target], inclusive=True) |
402 targetancestors = repo.changelog.ancestors([target], inclusive=True) |
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: |
409 ctx = repo[rev] |
416 ctx = repo[rev] |
410 desc = '%d:%s "%s"' % (ctx.rev(), ctx, |
417 desc = '%d:%s "%s"' % (ctx.rev(), ctx, |
411 ctx.description().split('\n', 1)[0]) |
418 ctx.description().split('\n', 1)[0]) |
412 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node()) |
419 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node()) |
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') |
428 else: |
436 else: |
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( |
436 _('unresolved conflicts (see hg ' |
444 _('unresolved conflicts (see hg ' |
437 'resolve, then hg rebase --continue)')) |
445 'resolve, then hg rebase --continue)')) |
451 repo.setparents(repo[p1].node()) |
459 repo.setparents(repo[p1].node()) |
452 repo.dirstate.endparentchange() |
460 repo.dirstate.endparentchange() |
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' |
491 if collapsemsg: |
499 if collapsemsg: |
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) |
504 if newnode is None: |
514 if newnode is None: |
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 -- |
522 # this should probably be cleaned up |
532 # this should probably be cleaned up |
523 targetnode = repo[target].node() |
533 targetnode = repo[target].node() |
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) |
534 |
544 |
535 if not keepf: |
545 if not keepf: |
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 |
550 ui.note(_("rebase completed\n")) |
560 ui.note(_("rebase completed\n")) |
551 util.unlinkpath(repo.sjoin('undo'), ignoremissing=True) |
561 util.unlinkpath(repo.sjoin('undo'), ignoremissing=True) |
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) |
561 |
571 |
562 def _definesets(ui, repo, destf=None, srcf=None, basef=None, revf=[], |
572 def _definesets(ui, repo, destf=None, srcf=None, basef=None, revf=[], |