hgext/rebase.py
changeset 35058 a68c3420be41
parent 35002 1a07f9187831
child 35125 f56a30b844aa
equal deleted inserted replaced
35057:0564e7c7f4cd 35058:a68c3420be41
   177         self.keepbranchesf = opts.get('keepbranches', False)
   177         self.keepbranchesf = opts.get('keepbranches', False)
   178         # keepopen is not meant for use on the command line, but by
   178         # keepopen is not meant for use on the command line, but by
   179         # other extensions
   179         # other extensions
   180         self.keepopen = opts.get('keepopen', False)
   180         self.keepopen = opts.get('keepopen', False)
   181         self.obsoletenotrebased = {}
   181         self.obsoletenotrebased = {}
       
   182         self.obsoletewithoutsuccessorindestination = set()
   182 
   183 
   183     @property
   184     @property
   184     def repo(self):
   185     def repo(self):
   185         if self.prepared:
   186         if self.prepared:
   186             return self._repo.unfiltered()
   187             return self._repo.unfiltered()
   309         """
   310         """
   310         self.obsoletenotrebased = {}
   311         self.obsoletenotrebased = {}
   311         if not self.ui.configbool('experimental', 'rebaseskipobsolete'):
   312         if not self.ui.configbool('experimental', 'rebaseskipobsolete'):
   312             return
   313             return
   313         obsoleteset = set(obsoleterevs)
   314         obsoleteset = set(obsoleterevs)
   314         self.obsoletenotrebased = _computeobsoletenotrebased(self.repo,
   315         self.obsoletenotrebased, self.obsoletewithoutsuccessorindestination = \
   315                                     obsoleteset, destmap)
   316             _computeobsoletenotrebased(self.repo, obsoleteset, destmap)
   316         skippedset = set(self.obsoletenotrebased)
   317         skippedset = set(self.obsoletenotrebased)
       
   318         skippedset.update(self.obsoletewithoutsuccessorindestination)
   317         _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset)
   319         _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset)
   318 
   320 
   319     def _prepareabortorcontinue(self, isabort):
   321     def _prepareabortorcontinue(self, isabort):
   320         try:
   322         try:
   321             self.restorestatus()
   323             self.restorestatus()
   417         ui.note(_('rebase merging completed\n'))
   419         ui.note(_('rebase merging completed\n'))
   418 
   420 
   419     def _performrebasesubset(self, tr, subset, pos, total):
   421     def _performrebasesubset(self, tr, subset, pos, total):
   420         repo, ui, opts = self.repo, self.ui, self.opts
   422         repo, ui, opts = self.repo, self.ui, self.opts
   421         sortedrevs = repo.revs('sort(%ld, -topo)', subset)
   423         sortedrevs = repo.revs('sort(%ld, -topo)', subset)
       
   424         allowdivergence = self.ui.configbool(
       
   425             'experimental', 'evolution.allowdivergence')
       
   426         if not allowdivergence:
       
   427             sortedrevs -= repo.revs(
       
   428                 'descendants(%ld) and not %ld',
       
   429                 self.obsoletewithoutsuccessorindestination,
       
   430                 self.obsoletewithoutsuccessorindestination,
       
   431             )
   422         for rev in sortedrevs:
   432         for rev in sortedrevs:
   423             dest = self.destmap[rev]
   433             dest = self.destmap[rev]
   424             ctx = repo[rev]
   434             ctx = repo[rev]
   425             desc = _ctxdesc(ctx)
   435             desc = _ctxdesc(ctx)
   426             if self.state[rev] == rev:
   436             if self.state[rev] == rev:
   427                 ui.status(_('already rebased %s\n') % desc)
   437                 ui.status(_('already rebased %s\n') % desc)
       
   438             elif (not allowdivergence
       
   439                   and rev in self.obsoletewithoutsuccessorindestination):
       
   440                 msg = _('note: not rebasing %s and its descendants as '
       
   441                         'this would cause divergence\n') % desc
       
   442                 repo.ui.status(msg)
       
   443                 self.skipped.add(rev)
   428             elif rev in self.obsoletenotrebased:
   444             elif rev in self.obsoletenotrebased:
   429                 succ = self.obsoletenotrebased[rev]
   445                 succ = self.obsoletenotrebased[rev]
   430                 if succ is None:
   446                 if succ is None:
   431                     msg = _('note: not rebasing %s, it has no '
   447                     msg = _('note: not rebasing %s, it has no '
   432                             'successor\n') % desc
   448                             'successor\n') % desc
  1614 def _filterobsoleterevs(repo, revs):
  1630 def _filterobsoleterevs(repo, revs):
  1615     """returns a set of the obsolete revisions in revs"""
  1631     """returns a set of the obsolete revisions in revs"""
  1616     return set(r for r in revs if repo[r].obsolete())
  1632     return set(r for r in revs if repo[r].obsolete())
  1617 
  1633 
  1618 def _computeobsoletenotrebased(repo, rebaseobsrevs, destmap):
  1634 def _computeobsoletenotrebased(repo, rebaseobsrevs, destmap):
  1619     """return a mapping obsolete => successor for all obsolete nodes to be
  1635     """Return (obsoletenotrebased, obsoletewithoutsuccessorindestination).
  1620     rebased that have a successors in the destination
  1636 
  1621 
  1637     `obsoletenotrebased` is a mapping mapping obsolete => successor for all
  1622     obsolete => None entries in the mapping indicate nodes with no successor"""
  1638     obsolete nodes to be rebased given in `rebaseobsrevs`.
       
  1639 
       
  1640     `obsoletewithoutsuccessorindestination` is a set with obsolete revisions
       
  1641     without a successor in destination.
       
  1642     """
  1623     obsoletenotrebased = {}
  1643     obsoletenotrebased = {}
       
  1644     obsoletewithoutsuccessorindestination = set([])
  1624 
  1645 
  1625     assert repo.filtername is None
  1646     assert repo.filtername is None
  1626     cl = repo.changelog
  1647     cl = repo.changelog
  1627     nodemap = cl.nodemap
  1648     nodemap = cl.nodemap
  1628     for srcrev in rebaseobsrevs:
  1649     for srcrev in rebaseobsrevs:
  1639                 if succnode == srcnode or succnode not in nodemap:
  1660                 if succnode == srcnode or succnode not in nodemap:
  1640                     continue
  1661                     continue
  1641                 if cl.isancestor(succnode, destnode):
  1662                 if cl.isancestor(succnode, destnode):
  1642                     obsoletenotrebased[srcrev] = nodemap[succnode]
  1663                     obsoletenotrebased[srcrev] = nodemap[succnode]
  1643                     break
  1664                     break
  1644 
  1665             else:
  1645     return obsoletenotrebased
  1666                 # If 'srcrev' has a successor in rebase set but none in
       
  1667                 # destination (which would be catched above), we shall skip it
       
  1668                 # and its descendants to avoid divergence.
       
  1669                 if any(nodemap[s] in destmap
       
  1670                        for s in successors if s != srcnode):
       
  1671                     obsoletewithoutsuccessorindestination.add(srcrev)
       
  1672 
       
  1673     return obsoletenotrebased, obsoletewithoutsuccessorindestination
  1646 
  1674 
  1647 def summaryhook(ui, repo):
  1675 def summaryhook(ui, repo):
  1648     if not repo.vfs.exists('rebasestate'):
  1676     if not repo.vfs.exists('rebasestate'):
  1649         return
  1677         return
  1650     try:
  1678     try: