Patchwork [4,of,7] obsstore: add relevant markers method

login
register
mail settings
Submitter Pierre-Yves David
Date Aug. 21, 2014, 3:20 a.m.
Message ID <06e61fc68d923f5d99dc.1408591254@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/5541/
State Accepted
Headers show

Comments

Pierre-Yves David - Aug. 21, 2014, 3:20 a.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1408492990 25200
#      Tue Aug 19 17:03:10 2014 -0700
# Node ID 06e61fc68d923f5d99dc1960ee278a1aaf3aa5f1
# Parent  0e700b1c54043586d946b33202da450dc46f9c06
obsstore: add relevant markers method

We add a ``relevantmarkers`` methods to fetch all markers that seems relevant to a
set of node. See function documentation about how this set is computed. This
will let us exchange only the markers that seems "relevant" to the set of
changeset related to a push or a pull.

The approach used to define "relevant" have been successfully tested in evolve
for 6 months.

Patch

diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
--- a/mercurial/obsolete.py
+++ b/mercurial/obsolete.py
@@ -383,10 +383,37 @@  class obsstore(object):
                 for p in parents:
                     self.children.setdefault(p, set()).add(mark)
         if node.nullid in self.precursors:
             raise util.Abort(_('bad obsolescence marker detected: '
                                'invalid successors nullid'))
+    def relevantmarkers(self, nodes):
+        """return a set of all obsolescence markers relevant to a set of node.
+
+        "relevant" to a set of node mean:
+
+        - marker that use this changeset as successors
+        - prune marker of direct children on this changeset.
+        - recursive application of the two rules on precursors of these markers
+
+        It is a set so you cannot rely on order"""
+        pendingnodes = set(nodes)
+        seenmarkers = set()
+        seennodes = set(pendingnodes)
+        precursorsmarkers = self.precursors
+        children = self.children
+        while pendingnodes:
+            direct = set()
+            for current in pendingnodes:
+                direct.update(precursorsmarkers.get(current, ()))
+                pruned = [m for m in children.get(current, ()) if not m[1]]
+                direct.update(pruned)
+            direct -= seenmarkers
+            pendingnodes = set([m[0] for m in direct])
+            seenmarkers |= direct
+            pendingnodes -= seennodes
+            seennodes |= pendingnodes
+        return seenmarkers
 
 def _encodemarkers(markers, addheader=False):
     # Kept separate from flushmarkers(), it will be reused for
     # markers exchange.
     if addheader: