diff mercurial/obsolete.py @ 18069:f84e731cbd20

obsolete: drop successors sets which are subset of another one If both "(B,)" and "(B, C)" are successors set of "A", "(B,)" is dropped. We won't be interrested in detection such divergence scenario.
author Pierre-Yves David <pierre-yves.david@logilab.fr>
date Sat, 10 Nov 2012 01:56:59 +0100
parents 4bec77e62c00
children af632936d3d9
line wrap: on
line diff
--- a/mercurial/obsolete.py	Thu Dec 13 15:38:43 2012 +0100
+++ b/mercurial/obsolete.py	Sat Nov 10 01:56:59 2012 +0100
@@ -558,11 +558,16 @@
                 # sets. In such a case, the marker will contribute multiple
                 # divergent successors sets. If multiple successors have
                 # divergents successors sets, a cartesian product is used.
+                #
+                # At the end we post-process successors sets to remove
+                # duplicated entry and successors set that are strict subset of
+                # another one.
                 succssets = []
                 for mark in succmarkers[current]:
                     # successors sets contributed by this marker
                     markss = [[]]
                     for suc in mark[1]:
+                        # cardinal product with previous successors
                         productresult = []
                         for prefix in markss:
                             for suffix in cache[suc]:
@@ -575,7 +580,20 @@
                                 productresult.append(newss)
                         markss = productresult
                     succssets.extend(markss)
-                cache[current] = list(set(tuple(r) for r in succssets if r))
+                # remove duplicated and subset
+                seen = []
+                final = []
+                candidate = sorted(((set(s), s) for s in succssets if s),
+                                   key=lambda x: len(x[1]), reverse=True)
+                for setversion, listversion in candidate:
+                    for seenset in seen:
+                        if setversion.issubset(seenset):
+                            break
+                    else:
+                        final.append(listversion)
+                        seen.append(setversion)
+                final.reverse() # put small successors set first
+                cache[current] = final
     return cache[initialnode]
 
 def _knownrevs(repo, nodes):