# HG changeset patch # User Durham Goode # Date 2014-03-25 23:10:07 # Node ID 47d43e2323c5f8c6492d8ce01117424c716ceaea # Parent 5d57b2101ab119bce762025b8d83a00db7263e3b revset: fix generatorset race condition If two things were iterating over a generatorset at the same time, they could miss out on the things the other was generating, resulting in incomplete results. This fixes it by making it possible for two things to iterate at once, by always checking the _genlist at the beginning of each iteration. I was only able to repro it with pending changes from my other commits, but they aren't ready yet. So I'm unable to add a test for now. diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -2624,10 +2624,8 @@ class _generatorset(object): gen: a generator producing the values for the generatorset. """ self._gen = gen - self._iter = iter(gen) self._cache = {} self._genlist = baseset([]) - self._iterated = False self._finished = False def __contains__(self, x): @@ -2639,28 +2637,30 @@ class _generatorset(object): if l == x: return True - self._finished = True self._cache[x] = False return False def __iter__(self): - if self._iterated: - # At least a part of the list should be cached if iteration has - # started over the generatorset. - for l in self._genlist: - yield l - - for item in self._consumegen(): - yield item + if self._finished: + for x in self._genlist: + yield x + return + + i = 0 + genlist = self._genlist + consume = self._consumegen() + while True: + if i < len(genlist): + yield genlist[i] + else: + yield consume.next() + i += 1 def _consumegen(self): - self._iterated = True - for item in self._gen: self._cache[item] = True self._genlist.append(item) yield item - self._finished = True def set(self):