obsutil: move 'exclusivemarkers' to the new modules
authorPierre-Yves David <pierre-yves.david@octobus.net>
Tue, 27 Jun 2017 01:11:56 +0200
changeset 33143 d09ae850296d
parent 33142 4f49810a1011
child 33144 d0e5bf12f314
obsutil: move 'exclusivemarkers' to the new modules We have a new 'obsutil' module now. We move the high level utility there to bring 'obsolete.py' back to a more reasonable size.
mercurial/obsolete.py
mercurial/obsutil.py
mercurial/repair.py
--- a/mercurial/obsolete.py	Tue Jun 27 01:03:01 2017 +0200
+++ b/mercurial/obsolete.py	Tue Jun 27 01:11:56 2017 +0200
@@ -771,131 +771,6 @@
                 % len(list(store)))
     return store
 
-def _filterprunes(markers):
-    """return a set with no prune markers"""
-    return set(m for m in markers if m[1])
-
-def exclusivemarkers(repo, nodes):
-    """set of markers relevant to "nodes" but no other locally-known nodes
-
-    This function compute the set of markers "exclusive" to a locally-known
-    node. This means we walk the markers starting from <nodes> until we reach a
-    locally-known precursors outside of <nodes>. Element of <nodes> with
-    locally-known successors outside of <nodes> are ignored (since their
-    precursors markers are also relevant to these successors).
-
-    For example:
-
-        # (A0 rewritten as A1)
-        #
-        # A0 <-1- A1 # Marker "1" is exclusive to A1
-
-        or
-
-        # (A0 rewritten as AX; AX rewritten as A1; AX is unkown locally)
-        #
-        # <-1- A0 <-2- AX <-3- A1 # Marker "2,3" are exclusive to A1
-
-        or
-
-        # (A0 has unknown precursors, A0 rewritten as A1 and A2 (divergence))
-        #
-        #          <-2- A1 # Marker "2" is exclusive to A0,A1
-        #        /
-        # <-1- A0
-        #        \
-        #         <-3- A2 # Marker "3" is exclusive to A0,A2
-        #
-        # in addition:
-        #
-        #  Markers "2,3" are exclusive to A1,A2
-        #  Markers "1,2,3" are exclusive to A0,A1,A2
-
-        See test/test-obsolete-bundle-strip.t for more examples.
-
-    An example usage is strip. When stripping a changeset, we also want to
-    strip the markers exclusive to this changeset. Otherwise we would have
-    "dangling"" obsolescence markers from its precursors: Obsolescence markers
-    marking a node as obsolete without any successors available locally.
-
-    As for relevant markers, the prune markers for children will be followed.
-    Of course, they will only be followed if the pruned children is
-    locally-known. Since the prune markers are relevant to the pruned node.
-    However, while prune markers are considered relevant to the parent of the
-    pruned changesets, prune markers for locally-known changeset (with no
-    successors) are considered exclusive to the pruned nodes. This allows
-    to strip the prune markers (with the rest of the exclusive chain) alongside
-    the pruned changesets.
-    """
-    # running on a filtered repository would be dangerous as markers could be
-    # reported as exclusive when they are relevant for other filtered nodes.
-    unfi = repo.unfiltered()
-
-    # shortcut to various useful item
-    nm = unfi.changelog.nodemap
-    precursorsmarkers = unfi.obsstore.precursors
-    successormarkers = unfi.obsstore.successors
-    childrenmarkers = unfi.obsstore.children
-
-    # exclusive markers (return of the function)
-    exclmarkers = set()
-    # we need fast membership testing
-    nodes = set(nodes)
-    # looking for head in the obshistory
-    #
-    # XXX we are ignoring all issues in regard with cycle for now.
-    stack = [n for n in nodes if not _filterprunes(successormarkers.get(n, ()))]
-    stack.sort()
-    # nodes already stacked
-    seennodes = set(stack)
-    while stack:
-        current = stack.pop()
-        # fetch precursors markers
-        markers = list(precursorsmarkers.get(current, ()))
-        # extend the list with prune markers
-        for mark in successormarkers.get(current, ()):
-            if not mark[1]:
-                markers.append(mark)
-        # and markers from children (looking for prune)
-        for mark in childrenmarkers.get(current, ()):
-            if not mark[1]:
-                markers.append(mark)
-        # traverse the markers
-        for mark in markers:
-            if mark in exclmarkers:
-                # markers already selected
-                continue
-
-            # If the markers is about the current node, select it
-            #
-            # (this delay the addition of markers from children)
-            if mark[1] or mark[0] == current:
-                exclmarkers.add(mark)
-
-            # should we keep traversing through the precursors?
-            prec = mark[0]
-
-            # nodes in the stack or already processed
-            if prec in seennodes:
-                continue
-
-            # is this a locally known node ?
-            known = prec in nm
-            # if locally-known and not in the <nodes> set the traversal
-            # stop here.
-            if known and prec not in nodes:
-                continue
-
-            # do not keep going if there are unselected markers pointing to this
-            # nodes. If we end up traversing these unselected markers later the
-            # node will be taken care of at that point.
-            precmarkers = _filterprunes(successormarkers.get(prec))
-            if precmarkers.issubset(exclmarkers):
-                seennodes.add(prec)
-                stack.append(prec)
-
-    return exclmarkers
-
 def commonversion(versions):
     """Return the newest version listed in both versions and our local formats.
 
@@ -971,7 +846,7 @@
     if nodes is None:
         rawmarkers = repo.obsstore
     elif exclusive:
-        rawmarkers = exclusivemarkers(repo, nodes)
+        rawmarkers = obsutil.exclusivemarkers(repo, nodes)
     else:
         rawmarkers = repo.obsstore.relevantmarkers(nodes)
 
@@ -1063,6 +938,11 @@
             foreground = set(repo.set('%ln::', known))
     return set(c.node() for c in foreground)
 
+def exclusivemarkers(repo, nodes):
+    movemsg = 'obsolete.exclusivemarkers moved to obsutil.exclusivemarkers'
+    repo.ui.deprecwarn(movemsg, '4.3')
+    return obsutil.exclusivemarkers(repo, nodes)
+
 def successorssets(repo, initialnode, cache=None):
     movemsg = 'obsolete.successorssets moved to obsutil.successorssets'
     repo.ui.deprecwarn(movemsg, '4.3')
--- a/mercurial/obsutil.py	Tue Jun 27 01:03:01 2017 +0200
+++ b/mercurial/obsutil.py	Tue Jun 27 01:11:56 2017 +0200
@@ -35,6 +35,131 @@
             else:
                 stack.append(precnodeid)
 
+def _filterprunes(markers):
+    """return a set with no prune markers"""
+    return set(m for m in markers if m[1])
+
+def exclusivemarkers(repo, nodes):
+    """set of markers relevant to "nodes" but no other locally-known nodes
+
+    This function compute the set of markers "exclusive" to a locally-known
+    node. This means we walk the markers starting from <nodes> until we reach a
+    locally-known precursors outside of <nodes>. Element of <nodes> with
+    locally-known successors outside of <nodes> are ignored (since their
+    precursors markers are also relevant to these successors).
+
+    For example:
+
+        # (A0 rewritten as A1)
+        #
+        # A0 <-1- A1 # Marker "1" is exclusive to A1
+
+        or
+
+        # (A0 rewritten as AX; AX rewritten as A1; AX is unkown locally)
+        #
+        # <-1- A0 <-2- AX <-3- A1 # Marker "2,3" are exclusive to A1
+
+        or
+
+        # (A0 has unknown precursors, A0 rewritten as A1 and A2 (divergence))
+        #
+        #          <-2- A1 # Marker "2" is exclusive to A0,A1
+        #        /
+        # <-1- A0
+        #        \
+        #         <-3- A2 # Marker "3" is exclusive to A0,A2
+        #
+        # in addition:
+        #
+        #  Markers "2,3" are exclusive to A1,A2
+        #  Markers "1,2,3" are exclusive to A0,A1,A2
+
+        See test/test-obsolete-bundle-strip.t for more examples.
+
+    An example usage is strip. When stripping a changeset, we also want to
+    strip the markers exclusive to this changeset. Otherwise we would have
+    "dangling"" obsolescence markers from its precursors: Obsolescence markers
+    marking a node as obsolete without any successors available locally.
+
+    As for relevant markers, the prune markers for children will be followed.
+    Of course, they will only be followed if the pruned children is
+    locally-known. Since the prune markers are relevant to the pruned node.
+    However, while prune markers are considered relevant to the parent of the
+    pruned changesets, prune markers for locally-known changeset (with no
+    successors) are considered exclusive to the pruned nodes. This allows
+    to strip the prune markers (with the rest of the exclusive chain) alongside
+    the pruned changesets.
+    """
+    # running on a filtered repository would be dangerous as markers could be
+    # reported as exclusive when they are relevant for other filtered nodes.
+    unfi = repo.unfiltered()
+
+    # shortcut to various useful item
+    nm = unfi.changelog.nodemap
+    precursorsmarkers = unfi.obsstore.precursors
+    successormarkers = unfi.obsstore.successors
+    childrenmarkers = unfi.obsstore.children
+
+    # exclusive markers (return of the function)
+    exclmarkers = set()
+    # we need fast membership testing
+    nodes = set(nodes)
+    # looking for head in the obshistory
+    #
+    # XXX we are ignoring all issues in regard with cycle for now.
+    stack = [n for n in nodes if not _filterprunes(successormarkers.get(n, ()))]
+    stack.sort()
+    # nodes already stacked
+    seennodes = set(stack)
+    while stack:
+        current = stack.pop()
+        # fetch precursors markers
+        markers = list(precursorsmarkers.get(current, ()))
+        # extend the list with prune markers
+        for mark in successormarkers.get(current, ()):
+            if not mark[1]:
+                markers.append(mark)
+        # and markers from children (looking for prune)
+        for mark in childrenmarkers.get(current, ()):
+            if not mark[1]:
+                markers.append(mark)
+        # traverse the markers
+        for mark in markers:
+            if mark in exclmarkers:
+                # markers already selected
+                continue
+
+            # If the markers is about the current node, select it
+            #
+            # (this delay the addition of markers from children)
+            if mark[1] or mark[0] == current:
+                exclmarkers.add(mark)
+
+            # should we keep traversing through the precursors?
+            prec = mark[0]
+
+            # nodes in the stack or already processed
+            if prec in seennodes:
+                continue
+
+            # is this a locally known node ?
+            known = prec in nm
+            # if locally-known and not in the <nodes> set the traversal
+            # stop here.
+            if known and prec not in nodes:
+                continue
+
+            # do not keep going if there are unselected markers pointing to this
+            # nodes. If we end up traversing these unselected markers later the
+            # node will be taken care of at that point.
+            precmarkers = _filterprunes(successormarkers.get(prec))
+            if precmarkers.issubset(exclmarkers):
+                seennodes.add(prec)
+                stack.append(prec)
+
+    return exclmarkers
+
 def successorssets(repo, initialnode, cache=None):
     """Return set of all latest successors of initial nodes
 
--- a/mercurial/repair.py	Tue Jun 27 01:03:01 2017 +0200
+++ b/mercurial/repair.py	Tue Jun 27 01:11:56 2017 +0200
@@ -20,6 +20,7 @@
     error,
     exchange,
     obsolete,
+    obsutil,
     util,
 )
 
@@ -132,7 +133,7 @@
 
     stripobsidx = obsmarkers = ()
     if repo.ui.configbool('devel', 'strip-obsmarkers', True):
-        obsmarkers = obsolete.exclusivemarkers(repo, stripbases)
+        obsmarkers = obsutil.exclusivemarkers(repo, stripbases)
     if obsmarkers:
         stripobsidx = [i for i, m in enumerate(repo.obsstore)
                        if m in obsmarkers]