hgext/rebase.py
changeset 46833 47c251a14525
parent 46832 d95edcbe5c99
child 46834 535de0e34a79
equal deleted inserted replaced
46832:d95edcbe5c99 46833:47c251a14525
   203         self.keepf = opts.get(b'keep', False)
   203         self.keepf = opts.get(b'keep', False)
   204         self.keepbranchesf = opts.get(b'keepbranches', False)
   204         self.keepbranchesf = opts.get(b'keepbranches', False)
   205         self.skipemptysuccessorf = rewriteutil.skip_empty_successor(
   205         self.skipemptysuccessorf = rewriteutil.skip_empty_successor(
   206             repo.ui, b'rebase'
   206             repo.ui, b'rebase'
   207         )
   207         )
   208         self.obsoletenotrebased = {}
   208         self.obsolete_with_successor_in_destination = {}
   209         self.obsoletewithoutsuccessorindestination = set()
   209         self.obsolete_with_successor_in_rebase_set = set()
   210         self.inmemory = inmemory
   210         self.inmemory = inmemory
   211         self.dryrun = dryrun
   211         self.dryrun = dryrun
   212         self.stateobj = statemod.cmdstate(repo, b'rebasestate')
   212         self.stateobj = statemod.cmdstate(repo, b'rebasestate')
   213 
   213 
   214     @property
   214     @property
   348 
   348 
   349         return data
   349         return data
   350 
   350 
   351     def _handleskippingobsolete(self):
   351     def _handleskippingobsolete(self):
   352         """Compute structures necessary for skipping obsolete revisions"""
   352         """Compute structures necessary for skipping obsolete revisions"""
   353         self.obsoletenotrebased = {}
   353         self.obsolete_with_successor_in_destination = {}
   354         if not self.ui.configbool(b'experimental', b'rebaseskipobsolete'):
   354         if not self.ui.configbool(b'experimental', b'rebaseskipobsolete'):
   355             return
   355             return
   356         obsoleteset = {r for r in self.state if self.repo[r].obsolete()}
   356         obsoleteset = {r for r in self.state if self.repo[r].obsolete()}
   357         (
   357         (
   358             self.obsoletenotrebased,
   358             self.obsolete_with_successor_in_destination,
   359             self.obsoletewithoutsuccessorindestination,
   359             self.obsolete_with_successor_in_rebase_set,
   360         ) = _computeobsoletenotrebased(self.repo, obsoleteset, self.destmap)
   360         ) = _compute_obsolete_sets(self.repo, obsoleteset, self.destmap)
   361         skippedset = set(self.obsoletenotrebased)
   361         skippedset = set(self.obsolete_with_successor_in_destination)
   362         skippedset.update(self.obsoletewithoutsuccessorindestination)
   362         skippedset.update(self.obsolete_with_successor_in_rebase_set)
   363         _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset)
   363         _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset)
   364 
   364 
   365     def _prepareabortorcontinue(
   365     def _prepareabortorcontinue(
   366         self, isabort, backup=True, suppwarns=False, dryrun=False, confirm=False
   366         self, isabort, backup=True, suppwarns=False, dryrun=False, confirm=False
   367     ):
   367     ):
   368         self.resume = True
   368         self.resume = True
   369         try:
   369         try:
   370             self.restorestatus()
   370             self.restorestatus()
   371             # Calculate self.obsoletenotrebased
   371             # Calculate self.obsolete_* sets
   372             self._handleskippingobsolete()
   372             self._handleskippingobsolete()
   373             self.collapsemsg = restorecollapsemsg(self.repo, isabort)
   373             self.collapsemsg = restorecollapsemsg(self.repo, isabort)
   374         except error.RepoLookupError:
   374         except error.RepoLookupError:
   375             if isabort:
   375             if isabort:
   376                 clearstatus(self.repo)
   376                 clearstatus(self.repo)
   434             if dest.closesbranch() and not self.keepbranchesf:
   434             if dest.closesbranch() and not self.keepbranchesf:
   435                 self.ui.status(_(b'reopening closed branch head %s\n') % dest)
   435                 self.ui.status(_(b'reopening closed branch head %s\n') % dest)
   436 
   436 
   437         self.prepared = True
   437         self.prepared = True
   438 
   438 
   439         # Calculate self.obsoletenotrebased
   439         # Calculate self.obsolete_* sets
   440         self._handleskippingobsolete()
   440         self._handleskippingobsolete()
   441 
   441 
   442     def _assignworkingcopy(self):
   442     def _assignworkingcopy(self):
   443         if self.inmemory:
   443         if self.inmemory:
   444             from mercurial.context import overlayworkingctx
   444             from mercurial.context import overlayworkingctx
   499         for subset in sortsource(self.destmap):
   499         for subset in sortsource(self.destmap):
   500             sortedrevs = self.repo.revs(b'sort(%ld, -topo)', subset)
   500             sortedrevs = self.repo.revs(b'sort(%ld, -topo)', subset)
   501             if not allowdivergence:
   501             if not allowdivergence:
   502                 sortedrevs -= self.repo.revs(
   502                 sortedrevs -= self.repo.revs(
   503                     b'descendants(%ld) and not %ld',
   503                     b'descendants(%ld) and not %ld',
   504                     self.obsoletewithoutsuccessorindestination,
   504                     self.obsolete_with_successor_in_rebase_set,
   505                     self.obsoletewithoutsuccessorindestination,
   505                     self.obsolete_with_successor_in_rebase_set,
   506                 )
   506                 )
   507             for rev in sortedrevs:
   507             for rev in sortedrevs:
   508                 self._rebasenode(tr, rev, allowdivergence, progress)
   508                 self._rebasenode(tr, rev, allowdivergence, progress)
   509         p.complete()
   509         p.complete()
   510         ui.note(_(b'rebase merging completed\n'))
   510         ui.note(_(b'rebase merging completed\n'))
   573         desc = _ctxdesc(ctx)
   573         desc = _ctxdesc(ctx)
   574         if self.state[rev] == rev:
   574         if self.state[rev] == rev:
   575             ui.status(_(b'already rebased %s\n') % desc)
   575             ui.status(_(b'already rebased %s\n') % desc)
   576         elif (
   576         elif (
   577             not allowdivergence
   577             not allowdivergence
   578             and rev in self.obsoletewithoutsuccessorindestination
   578             and rev in self.obsolete_with_successor_in_rebase_set
   579         ):
   579         ):
   580             msg = (
   580             msg = (
   581                 _(
   581                 _(
   582                     b'note: not rebasing %s and its descendants as '
   582                     b'note: not rebasing %s and its descendants as '
   583                     b'this would cause divergence\n'
   583                     b'this would cause divergence\n'
   584                 )
   584                 )
   585                 % desc
   585                 % desc
   586             )
   586             )
   587             repo.ui.status(msg)
   587             repo.ui.status(msg)
   588             self.skipped.add(rev)
   588             self.skipped.add(rev)
   589         elif rev in self.obsoletenotrebased:
   589         elif rev in self.obsolete_with_successor_in_destination:
   590             succ = self.obsoletenotrebased[rev]
   590             succ = self.obsolete_with_successor_in_destination[rev]
   591             if succ is None:
   591             if succ is None:
   592                 msg = _(b'note: not rebasing %s, it has no successor\n') % desc
   592                 msg = _(b'note: not rebasing %s, it has no successor\n') % desc
   593             else:
   593             else:
   594                 succdesc = _ctxdesc(repo[succ])
   594                 succdesc = _ctxdesc(repo[succ])
   595                 msg = _(
   595                 msg = _(
   611                 repo,
   611                 repo,
   612                 rev,
   612                 rev,
   613                 self.destmap,
   613                 self.destmap,
   614                 self.state,
   614                 self.state,
   615                 self.skipped,
   615                 self.skipped,
   616                 self.obsoletenotrebased,
   616                 self.obsolete_with_successor_in_destination,
   617             )
   617             )
   618             if self.resume and self.wctx.p1().rev() == p1:
   618             if self.resume and self.wctx.p1().rev() == p1:
   619                 repo.ui.debug(b'resuming interrupted rebase\n')
   619                 repo.ui.debug(b'resuming interrupted rebase\n')
   620                 self.resume = False
   620                 self.resume = False
   621             else:
   621             else:
   723                 repo,
   723                 repo,
   724                 min(self.state),
   724                 min(self.state),
   725                 self.destmap,
   725                 self.destmap,
   726                 self.state,
   726                 self.state,
   727                 self.skipped,
   727                 self.skipped,
   728                 self.obsoletenotrebased,
   728                 self.obsolete_with_successor_in_destination,
   729             )
   729             )
   730             editopt = opts.get(b'edit')
   730             editopt = opts.get(b'edit')
   731             editform = b'rebase.collapse'
   731             editform = b'rebase.collapse'
   732             if self.collapsemsg:
   732             if self.collapsemsg:
   733                 commitmsg = self.collapsemsg
   733                 commitmsg = self.collapsemsg
  2177         ret = orig(ui, repo, *args, **opts)
  2177         ret = orig(ui, repo, *args, **opts)
  2178 
  2178 
  2179     return ret
  2179     return ret
  2180 
  2180 
  2181 
  2181 
  2182 def _computeobsoletenotrebased(repo, rebaseobsrevs, destmap):
  2182 def _compute_obsolete_sets(repo, rebaseobsrevs, destmap):
  2183     """Return (obsoletenotrebased, obsoletewithoutsuccessorindestination).
  2183     """Figure out what to do about about obsolete revisions
  2184 
  2184 
  2185     `obsoletenotrebased` is a mapping mapping obsolete => successor for all
  2185     `obsolete_with_successor_in_destination` is a mapping mapping obsolete => successor for all
  2186     obsolete nodes to be rebased given in `rebaseobsrevs`.
  2186     obsolete nodes to be rebased given in `rebaseobsrevs`.
  2187 
  2187 
  2188     `obsoletewithoutsuccessorindestination` is a set with obsolete revisions
  2188     `obsolete_with_successor_in_rebase_set` is a set with obsolete revisions,
  2189     without a successor in destination.
  2189     without a successor in destination, that would cause divergence.
  2190     """
  2190     """
  2191     obsoletenotrebased = {}
  2191     obsolete_with_successor_in_destination = {}
  2192     obsoletewithoutsuccessorindestination = set()
  2192     obsolete_with_successor_in_rebase_set = set()
  2193 
  2193 
  2194     assert repo.filtername is None
  2194     assert repo.filtername is None
  2195     cl = repo.changelog
  2195     cl = repo.changelog
  2196     get_rev = cl.index.get_rev
  2196     get_rev = cl.index.get_rev
  2197     extinctrevs = set(repo.revs(b'extinct()'))
  2197     extinctrevs = set(repo.revs(b'extinct()'))
  2203         successors.remove(srcnode)
  2203         successors.remove(srcnode)
  2204         succrevs = {get_rev(s) for s in successors}
  2204         succrevs = {get_rev(s) for s in successors}
  2205         succrevs.discard(None)
  2205         succrevs.discard(None)
  2206         if not successors or succrevs.issubset(extinctrevs):
  2206         if not successors or succrevs.issubset(extinctrevs):
  2207             # no successor, or all successors are extinct
  2207             # no successor, or all successors are extinct
  2208             obsoletenotrebased[srcrev] = None
  2208             obsolete_with_successor_in_destination[srcrev] = None
  2209         else:
  2209         else:
  2210             dstrev = destmap[srcrev]
  2210             dstrev = destmap[srcrev]
  2211             for succrev in succrevs:
  2211             for succrev in succrevs:
  2212                 if cl.isancestorrev(succrev, dstrev):
  2212                 if cl.isancestorrev(succrev, dstrev):
  2213                     obsoletenotrebased[srcrev] = succrev
  2213                     obsolete_with_successor_in_destination[srcrev] = succrev
  2214                     break
  2214                     break
  2215             else:
  2215             else:
  2216                 # If 'srcrev' has a successor in rebase set but none in
  2216                 # If 'srcrev' has a successor in rebase set but none in
  2217                 # destination (which would be catched above), we shall skip it
  2217                 # destination (which would be catched above), we shall skip it
  2218                 # and its descendants to avoid divergence.
  2218                 # and its descendants to avoid divergence.
  2219                 if srcrev in extinctrevs or any(s in destmap for s in succrevs):
  2219                 if srcrev in extinctrevs or any(s in destmap for s in succrevs):
  2220                     obsoletewithoutsuccessorindestination.add(srcrev)
  2220                     obsolete_with_successor_in_rebase_set.add(srcrev)
  2221 
  2221 
  2222     return obsoletenotrebased, obsoletewithoutsuccessorindestination
  2222     return (
       
  2223         obsolete_with_successor_in_destination,
       
  2224         obsolete_with_successor_in_rebase_set,
       
  2225     )
  2223 
  2226 
  2224 
  2227 
  2225 def abortrebase(ui, repo):
  2228 def abortrebase(ui, repo):
  2226     with repo.wlock(), repo.lock():
  2229     with repo.wlock(), repo.lock():
  2227         rbsrt = rebaseruntime(repo, ui)
  2230         rbsrt = rebaseruntime(repo, ui)