hgext/rebase.py
changeset 36931 28f988093911
parent 36930 36de8a3c429c
child 36932 437f80436186
equal deleted inserted replaced
36930:36de8a3c429c 36931:28f988093911
   428             pos = self._performrebasesubset(tr, subset, pos, total)
   428             pos = self._performrebasesubset(tr, subset, pos, total)
   429         ui.progress(_('rebasing'), None)
   429         ui.progress(_('rebasing'), None)
   430         ui.note(_('rebase merging completed\n'))
   430         ui.note(_('rebase merging completed\n'))
   431 
   431 
   432     def _performrebasesubset(self, tr, subset, pos, total):
   432     def _performrebasesubset(self, tr, subset, pos, total):
   433         repo, ui, opts = self.repo, self.ui, self.opts
   433         sortedrevs = self.repo.revs('sort(%ld, -topo)', subset)
   434         sortedrevs = repo.revs('sort(%ld, -topo)', subset)
       
   435         allowdivergence = self.ui.configbool(
   434         allowdivergence = self.ui.configbool(
   436             'experimental', 'evolution.allowdivergence')
   435             'experimental', 'evolution.allowdivergence')
   437         if not allowdivergence:
   436         if not allowdivergence:
   438             sortedrevs -= repo.revs(
   437             sortedrevs -= self.repo.revs(
   439                 'descendants(%ld) and not %ld',
   438                 'descendants(%ld) and not %ld',
   440                 self.obsoletewithoutsuccessorindestination,
   439                 self.obsoletewithoutsuccessorindestination,
   441                 self.obsoletewithoutsuccessorindestination,
   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         for rev in sortedrevs:
   448         for rev in sortedrevs:
   444             dest = self.destmap[rev]
   449             self._rebasenode(tr, rev, allowdivergence, progress)
   445             ctx = repo[rev]
   450         return posholder[0]
   446             desc = _ctxdesc(ctx)
   451 
   447             if self.state[rev] == rev:
   452     def _rebasenode(self, tr, rev, allowdivergence, progressfn):
   448                 ui.status(_('already rebased %s\n') % desc)
   453         repo, ui, opts = self.repo, self.ui, self.opts
   449             elif (not allowdivergence
   454         dest = self.destmap[rev]
   450                   and rev in self.obsoletewithoutsuccessorindestination):
   455         ctx = repo[rev]
   451                 msg = _('note: not rebasing %s and its descendants as '
   456         desc = _ctxdesc(ctx)
   452                         'this would cause divergence\n') % desc
   457         if self.state[rev] == rev:
   453                 repo.ui.status(msg)
   458             ui.status(_('already rebased %s\n') % desc)
   454                 self.skipped.add(rev)
   459         elif (not allowdivergence
   455             elif rev in self.obsoletenotrebased:
   460               and rev in self.obsoletewithoutsuccessorindestination):
   456                 succ = self.obsoletenotrebased[rev]
   461             msg = _('note: not rebasing %s and its descendants as '
   457                 if succ is None:
   462                     'this would cause divergence\n') % desc
   458                     msg = _('note: not rebasing %s, it has no '
   463             repo.ui.status(msg)
   459                             'successor\n') % desc
   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)
   460                 else:
   516                 else:
   461                     succdesc = _ctxdesc(repo[succ])
   517                     newnode = concludenode(repo, rev, p1, p2,
   462                     msg = (_('note: not rebasing %s, already in '
   518                         extrafn=_makeextrafn(self.extrafns),
   463                              'destination as %s\n') % (desc, succdesc))
   519                         editor=editor,
   464                 repo.ui.status(msg)
   520                         keepbranches=self.keepbranchesf,
   465                 # Make clearrebased aware state[rev] is not a true successor
   521                         date=self.date)
   466                 self.skipped.add(rev)
   522 
   467                 # Record rev as moved to its desired destination in self.state.
   523                 if newnode is None:
   468                 # This helps bookmark and working parent movement.
   524                     # If it ended up being a no-op commit, then the normal
   469                 dest = max(adjustdest(repo, rev, self.destmap, self.state,
   525                     # merge state clean-up path doesn't happen, so do it
   470                                       self.skipped))
   526                     # here. Fix issue5494
   471                 self.state[rev] = dest
   527                     mergemod.mergestate.clean(repo)
   472             elif self.state[rev] == revtodo:
   528             else:
   473                 pos += 1
   529                 # Skip commit if we are collapsing
   474                 ui.status(_('rebasing %s\n') % desc)
   530                 if self.wctx.isinmemory():
   475                 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)),
   531                     self.wctx.setbase(repo[p1])
   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')
       
   483                 else:
   532                 else:
   484                     overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
   533                     repo.setparents(repo[p1].node())
   485                     with ui.configoverride(overrides, 'rebase'):
   534                 newnode = None
   486                         stats = rebasenode(repo, rev, p1, base, self.collapsef,
   535             # Update the state
   487                                            dest, wctx=self.wctx)
   536             if newnode is not None:
   488                         if stats and stats[3] > 0:
   537                 self.state[rev] = repo[newnode].rev()
   489                             if self.wctx.isinmemory():
   538                 ui.debug('rebased as %s\n' % short(newnode))
   490                                 raise error.InMemoryMergeConflictsError()
   539             else:
   491                             else:
       
   492                                 raise error.InterventionRequired(
       
   493                                     _('unresolved conflicts (see hg '
       
   494                                       'resolve, then hg rebase --continue)'))
       
   495                 if not self.collapsef:
   540                 if not self.collapsef:
   496                     merging = p2 != nullrev
   541                     ui.warn(_('note: rebase of %d:%s created no changes '
   497                     editform = cmdutil.mergeeditform(merging, 'rebase')
   542                               'to commit\n') % (rev, ctx))
   498                     editor = cmdutil.getcommiteditor(editform=editform,
   543                     self.skipped.add(rev)
   499                                                      **pycompat.strkwargs(opts))
   544                 self.state[rev] = p1
   500                     if self.wctx.isinmemory():
   545                 ui.debug('next revision set to %d\n' % p1)
   501                         newnode = concludememorynode(repo, rev, p1, p2,
   546         else:
   502                             wctx=self.wctx,
   547             ui.status(_('already rebased %s as %s\n') %
   503                             extrafn=_makeextrafn(self.extrafns),
   548                       (desc, repo[self.state[rev]]))
   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
       
   542 
   549 
   543     def _finishrebase(self):
   550     def _finishrebase(self):
   544         repo, ui, opts = self.repo, self.ui, self.opts
   551         repo, ui, opts = self.repo, self.ui, self.opts
   545         fm = ui.formatter('rebase', opts)
   552         fm = ui.formatter('rebase', opts)
   546         fm.startitem()
   553         fm.startitem()