[PATCH] rebase: turn rebase revs into set before filtering obsolete

Simon Farnsworth simonfar at fb.com
Tue Jul 19 06:39:43 EDT 2016


# HG changeset patch
# User Simon Farnsworth <simonfar at fb.com>
# Date 1468924193 25200
#      Tue Jul 19 03:29:53 2016 -0700
# Branch stable
# Node ID 39ca6ff7183e4a42fea832e0fedfe65de9b70ffa
# Parent  02a8fea4289b51992b2495a06d4b12cbda876cf1
rebase: turn rebase revs into set before filtering obsolete

When the inhibit extension from mutable-history is enabled, it attempts to
iterate over the rebaseset to prevent the nodes being rebased from being
marked obsolete. This happens at the same time as rebase's
_filterobsoleterevs function trying to iterate over the rebaseset to figure
out which ones are obsolete. The two of these iterating over the same
revset generatorset cause a 'generator already executing' exception. This is
probably a flaw in the revset implementation, since iterating over the same
set twice should be supported.

This regression was introduced in 5d16ebe7b14, since it changed
_filterobsoleterevs to be called before the rebaseset was turned into a
set(). For now let’s just make the rebaseset an actual set again before
calling that function. This was caught by the inhibit tests.

The relevant call stack from test-inhibit.t:

   File "/tmp/hgtests.jgjrN5/install/lib/python/hgext/rebase.py", line 285, in _preparenewrebase
     obsrevs = _filterobsoleterevs(self.repo, rebaseset)
   File "/data/hgbuild/facebook-hg-rpms/mutable-history/hgext/inhibit.py", line 197, in _filterobsoleterevswrap
     r = orig(repo, rebasesetrevs, *args, **kwargs)
   File "/tmp/hgtests.jgjrN5/install/lib/python/hgext/rebase.py", line 1380, in _filterobsoleterevs
     return set(r for r in revs if repo[r].obsolete())
   File "/tmp/hgtests.jgjrN5/install/lib/python/hgext/rebase.py", line 1380, in <genexpr>
     return set(r for r in revs if repo[r].obsolete())
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/revset.py", line 3079, in _iterordered
     val2 = next(iter2)
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/revset.py", line 3417, in gen
     yield nextrev()
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/revset.py", line 3424, in _consumegen
     for item in self._gen:
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/revset.py", line 71, in iterate
     cl = repo.changelog
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/repoview.py", line 319, in changelog
     revs = filterrevs(unfi, self.filtername)
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/repoview.py", line 261, in filterrevs
     repo.filteredrevcache[filtername] = func(repo.unfiltered())
   File "/data/hgbuild/facebook-hg-rpms/mutable-history/hgext/directaccess.py", line 65, in _computehidden
     hidden = repoview.filterrevs(repo, 'visible')
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/repoview.py", line 261, in filterrevs
     repo.filteredrevcache[filtername] = func(repo.unfiltered())
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/repoview.py", line 175, in computehidden
     hideable = hideablerevs(repo)
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/repoview.py", line 33, in hideablerevs
     return obsolete.getrevs(repo, 'obsolete')
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/obsolete.py", line 1097, in getrevs
     repo.obsstore.caches[name] = cachefuncs[name](repo)
   File "/data/hgbuild/facebook-hg-rpms/mutable-history/hgext/inhibit.py", line 255, in _computeobsoleteset
     if getrev(n) not in blacklist:
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/revset.py", line 3264, in __contains__
     return x in self._r1 or x in self._r2
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/revset.py", line 3348, in __contains__
     for l in self._consumegen():
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/revset.py", line 3424, in _consumegen
     for item in self._gen:
 ValueError: generator already executing

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -281,7 +281,7 @@
                   " unrebased descendants"),
                 hint=_('use --keep to keep original changesets'))
 
-        obsrevs = _filterobsoleterevs(self.repo, rebaseset)
+        obsrevs = _filterobsoleterevs(self.repo, set(rebaseset))
         self._handleskippingobsolete(rebaseset, obsrevs, dest)
 
         result = buildstate(self.repo, dest, rebaseset, self.collapsef,


More information about the Mercurial-devel mailing list