hgext/rebase.py
changeset 26587 56b2bcea2529
parent 26496 b885ab9ca182
child 26669 07db7e95c464
equal deleted inserted replaced
26586:d51c658d3f04 26587:56b2bcea2529
   223             except KeyError:
   223             except KeyError:
   224                 enablehistedit = " --config extensions.histedit="
   224                 enablehistedit = " --config extensions.histedit="
   225             help = "hg%s help -e histedit" % enablehistedit
   225             help = "hg%s help -e histedit" % enablehistedit
   226             msg = _("interactive history editing is supported by the "
   226             msg = _("interactive history editing is supported by the "
   227                     "'histedit' extension (see \"%s\")") % help
   227                     "'histedit' extension (see \"%s\")") % help
   228             raise util.Abort(msg)
   228             raise error.Abort(msg)
   229 
   229 
   230         if collapsemsg and not collapsef:
   230         if collapsemsg and not collapsef:
   231             raise util.Abort(
   231             raise error.Abort(
   232                 _('message can only be specified with collapse'))
   232                 _('message can only be specified with collapse'))
   233 
   233 
   234         if contf or abortf:
   234         if contf or abortf:
   235             if contf and abortf:
   235             if contf and abortf:
   236                 raise util.Abort(_('cannot use both abort and continue'))
   236                 raise error.Abort(_('cannot use both abort and continue'))
   237             if collapsef:
   237             if collapsef:
   238                 raise util.Abort(
   238                 raise error.Abort(
   239                     _('cannot use collapse with continue or abort'))
   239                     _('cannot use collapse with continue or abort'))
   240             if srcf or basef or destf:
   240             if srcf or basef or destf:
   241                 raise util.Abort(
   241                 raise error.Abort(
   242                     _('abort and continue do not allow specifying revisions'))
   242                     _('abort and continue do not allow specifying revisions'))
   243             if abortf and opts.get('tool', False):
   243             if abortf and opts.get('tool', False):
   244                 ui.warn(_('tool option will be ignored\n'))
   244                 ui.warn(_('tool option will be ignored\n'))
   245 
   245 
   246             try:
   246             try:
   253                                    ' only broken state is cleared)\n'))
   253                                    ' only broken state is cleared)\n'))
   254                     return 0
   254                     return 0
   255                 else:
   255                 else:
   256                     msg = _('cannot continue inconsistent rebase')
   256                     msg = _('cannot continue inconsistent rebase')
   257                     hint = _('use "hg rebase --abort" to clear broken state')
   257                     hint = _('use "hg rebase --abort" to clear broken state')
   258                     raise util.Abort(msg, hint=hint)
   258                     raise error.Abort(msg, hint=hint)
   259             if abortf:
   259             if abortf:
   260                 return abort(repo, originalwd, target, state,
   260                 return abort(repo, originalwd, target, state,
   261                              activebookmark=activebookmark)
   261                              activebookmark=activebookmark)
   262         else:
   262         else:
   263             if srcf and basef:
   263             if srcf and basef:
   264                 raise util.Abort(_('cannot specify both a '
   264                 raise error.Abort(_('cannot specify both a '
   265                                    'source and a base'))
   265                                    'source and a base'))
   266             if revf and basef:
   266             if revf and basef:
   267                 raise util.Abort(_('cannot specify both a '
   267                 raise error.Abort(_('cannot specify both a '
   268                                    'revision and a base'))
   268                                    'revision and a base'))
   269             if revf and srcf:
   269             if revf and srcf:
   270                 raise util.Abort(_('cannot specify both a '
   270                 raise error.Abort(_('cannot specify both a '
   271                                    'revision and a source'))
   271                                    'revision and a source'))
   272 
   272 
   273             cmdutil.checkunfinished(repo)
   273             cmdutil.checkunfinished(repo)
   274             cmdutil.bailifchanged(repo)
   274             cmdutil.bailifchanged(repo)
   275 
   275 
   333 
   333 
   334             allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
   334             allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
   335             if (not (keepf or allowunstable)
   335             if (not (keepf or allowunstable)
   336                   and repo.revs('first(children(%ld) - %ld)',
   336                   and repo.revs('first(children(%ld) - %ld)',
   337                                 rebaseset, rebaseset)):
   337                                 rebaseset, rebaseset)):
   338                 raise util.Abort(
   338                 raise error.Abort(
   339                     _("can't remove original changesets with"
   339                     _("can't remove original changesets with"
   340                       " unrebased descendants"),
   340                       " unrebased descendants"),
   341                     hint=_('use --keep to keep original changesets'))
   341                     hint=_('use --keep to keep original changesets'))
   342 
   342 
   343             obsoletenotrebased = {}
   343             obsoletenotrebased = {}
   359                 ui.status(_('nothing to rebase\n'))
   359                 ui.status(_('nothing to rebase\n'))
   360                 return 1
   360                 return 1
   361 
   361 
   362             root = min(rebaseset)
   362             root = min(rebaseset)
   363             if not keepf and not repo[root].mutable():
   363             if not keepf and not repo[root].mutable():
   364                 raise util.Abort(_("can't rebase public changeset %s")
   364                 raise error.Abort(_("can't rebase public changeset %s")
   365                                  % repo[root],
   365                                  % repo[root],
   366                                  hint=_('see "hg help phases" for details'))
   366                                  hint=_('see "hg help phases" for details'))
   367 
   367 
   368             originalwd, target, state = result
   368             originalwd, target, state = result
   369             if collapsef:
   369             if collapsef:
   382             if collapsef:
   382             if collapsef:
   383                 branches = set()
   383                 branches = set()
   384                 for rev in state:
   384                 for rev in state:
   385                     branches.add(repo[rev].branch())
   385                     branches.add(repo[rev].branch())
   386                     if len(branches) > 1:
   386                     if len(branches) > 1:
   387                         raise util.Abort(_('cannot collapse multiple named '
   387                         raise error.Abort(_('cannot collapse multiple named '
   388                             'branches'))
   388                             'branches'))
   389 
   389 
   390         # Rebase
   390         # Rebase
   391         if not targetancestors:
   391         if not targetancestors:
   392             targetancestors = repo.changelog.ancestors([target], inclusive=True)
   392             targetancestors = repo.changelog.ancestors([target], inclusive=True)
   562                 parents.add(p.rev())
   562                 parents.add(p.rev())
   563     if not parents:
   563     if not parents:
   564         return nullrev
   564         return nullrev
   565     if len(parents) == 1:
   565     if len(parents) == 1:
   566         return parents.pop()
   566         return parents.pop()
   567     raise util.Abort(_('unable to collapse on top of %s, there is more '
   567     raise error.Abort(_('unable to collapse on top of %s, there is more '
   568                        'than one external parent: %s') %
   568                        'than one external parent: %s') %
   569                      (max(targetancestors),
   569                      (max(targetancestors),
   570                       ', '.join(str(p) for p in sorted(parents))))
   570                       ', '.join(str(p) for p in sorted(parents))))
   571 
   571 
   572 def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None,
   572 def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None,
   675                     p2 = target
   675                     p2 = target
   676             else:
   676             else:
   677                 p2 = state[p2n]
   677                 p2 = state[p2n]
   678         else: # p2n external
   678         else: # p2n external
   679             if p2 != nullrev: # p1n external too => rev is a merged revision
   679             if p2 != nullrev: # p1n external too => rev is a merged revision
   680                 raise util.Abort(_('cannot use revision %d as base, result '
   680                 raise error.Abort(_('cannot use revision %d as base, result '
   681                         'would have 3 parents') % rev)
   681                         'would have 3 parents') % rev)
   682             p2 = p2n
   682             p2 = p2n
   683     repo.ui.debug(" future parents are %d and %d\n" %
   683     repo.ui.debug(" future parents are %d and %d\n" %
   684                             (repo[p1].rev(), repo[p2].rev()))
   684                             (repo[p1].rev(), repo[p2].rev()))
   685 
   685 
   864                     # Legacy compat special case
   864                     # Legacy compat special case
   865                 else:
   865                 else:
   866                     state[repo[oldrev].rev()] = repo[newrev].rev()
   866                     state[repo[oldrev].rev()] = repo[newrev].rev()
   867 
   867 
   868         if keepbranches is None:
   868         if keepbranches is None:
   869             raise util.Abort(_('.hg/rebasestate is incomplete'))
   869             raise error.Abort(_('.hg/rebasestate is incomplete'))
   870 
   870 
   871         skipped = set()
   871         skipped = set()
   872         # recompute the set of skipped revs
   872         # recompute the set of skipped revs
   873         if not collapse:
   873         if not collapse:
   874             seen = set([target])
   874             seen = set([target])
   883         return (originalwd, target, state, skipped,
   883         return (originalwd, target, state, skipped,
   884                 collapse, keep, keepbranches, external, activebookmark)
   884                 collapse, keep, keepbranches, external, activebookmark)
   885     except IOError as err:
   885     except IOError as err:
   886         if err.errno != errno.ENOENT:
   886         if err.errno != errno.ENOENT:
   887             raise
   887             raise
   888         raise util.Abort(_('no rebase in progress'))
   888         raise error.Abort(_('no rebase in progress'))
   889 
   889 
   890 def needupdate(repo, state):
   890 def needupdate(repo, state):
   891     '''check whether we should `update --clean` away from a merge, or if
   891     '''check whether we should `update --clean` away from a merge, or if
   892     somehow the working dir got forcibly updated, e.g. by older hg'''
   892     somehow the working dir got forcibly updated, e.g. by older hg'''
   893     parents = [p.rev() for p in repo.parents()]
   893     parents = [p.rev() for p in repo.parents()]
   957     # This check isn't strictly necessary, since mq detects commits over an
   957     # This check isn't strictly necessary, since mq detects commits over an
   958     # applied patch. But it prevents messing up the working directory when
   958     # applied patch. But it prevents messing up the working directory when
   959     # a partially completed rebase is blocked by mq.
   959     # a partially completed rebase is blocked by mq.
   960     if 'qtip' in repo.tags() and (dest.node() in
   960     if 'qtip' in repo.tags() and (dest.node() in
   961                             [s.node for s in repo.mq.applied]):
   961                             [s.node for s in repo.mq.applied]):
   962         raise util.Abort(_('cannot rebase onto an applied mq patch'))
   962         raise error.Abort(_('cannot rebase onto an applied mq patch'))
   963 
   963 
   964     roots = list(repo.set('roots(%ld)', rebaseset))
   964     roots = list(repo.set('roots(%ld)', rebaseset))
   965     if not roots:
   965     if not roots:
   966         raise util.Abort(_('no matching revisions'))
   966         raise error.Abort(_('no matching revisions'))
   967     roots.sort()
   967     roots.sort()
   968     state = {}
   968     state = {}
   969     detachset = set()
   969     detachset = set()
   970     for root in roots:
   970     for root in roots:
   971         commonbase = root.ancestor(dest)
   971         commonbase = root.ancestor(dest)
   972         if commonbase == root:
   972         if commonbase == root:
   973             raise util.Abort(_('source is ancestor of destination'))
   973             raise error.Abort(_('source is ancestor of destination'))
   974         if commonbase == dest:
   974         if commonbase == dest:
   975             samebranch = root.branch() == dest.branch()
   975             samebranch = root.branch() == dest.branch()
   976             if not collapse and samebranch and root in dest.children():
   976             if not collapse and samebranch and root in dest.children():
   977                 repo.ui.debug('source is a child of destination\n')
   977                 repo.ui.debug('source is a child of destination\n')
   978                 return None
   978                 return None
  1112                                   % repo._activebookmark)
  1112                                   % repo._activebookmark)
  1113         finally:
  1113         finally:
  1114             release(lock, wlock)
  1114             release(lock, wlock)
  1115     else:
  1115     else:
  1116         if opts.get('tool'):
  1116         if opts.get('tool'):
  1117             raise util.Abort(_('--tool can only be used with --rebase'))
  1117             raise error.Abort(_('--tool can only be used with --rebase'))
  1118         orig(ui, repo, *args, **opts)
  1118         orig(ui, repo, *args, **opts)
  1119 
  1119 
  1120 def _setrebasesetvisibility(repo, revs):
  1120 def _setrebasesetvisibility(repo, revs):
  1121     """store the currently rebased set on the repo object
  1121     """store the currently rebased set on the repo object
  1122 
  1122