mercurial/revlogutils/deltas.py
changeset 39493 3ca144f1c8dd
parent 39492 a33f394b2bfd
child 39494 e72130f58f5d
--- a/mercurial/revlogutils/deltas.py	Fri Sep 07 11:17:29 2018 -0400
+++ b/mercurial/revlogutils/deltas.py	Fri Sep 07 11:17:30 2018 -0400
@@ -9,6 +9,7 @@
 
 from __future__ import absolute_import
 
+import collections
 import heapq
 import struct
 
@@ -607,8 +608,18 @@
                 continue
             group.append(rev)
         if group:
+            # XXX: in the sparse revlog case, group can become large,
+            #      impacting performances. Some bounding or slicing mecanism
+            #      would help to reduce this impact.
             yield tuple(group)
 
+def _findsnapshots(revlog, cache, start_rev):
+    """find snapshot from start_rev to tip"""
+    deltaparent = revlog.deltaparent
+    for rev in revlog.revs(start_rev):
+        if deltaparent(rev) == nullrev:
+            cache[nullrev].append(rev)
+
 def _rawgroups(revlog, p1, p2, cachedelta):
     """Provides group of revision to be tested as delta base
 
@@ -656,6 +667,18 @@
         for p in parents:
             bases.append(deltachain(p)[0])
         yield tuple(sorted(bases))
+        # No suitable base found in the parent chain, search if any full
+        # snapshots emitted since parent's base would be a suitable base for an
+        # intermediate snapshot.
+        #
+        # It give a chance to reuse a delta chain unrelated to the current
+        # revisions instead of starting our own. Without such re-use,
+        # topological branches would keep reopening new full chains. Creating
+        # more and more snapshot as the repository grow.
+        snapfloor = min(bases) + 1
+        snapshots = collections.defaultdict(list)
+        _findsnapshots(revlog, snapshots, snapfloor)
+        yield tuple(snapshots[nullrev])
 
     # other approach failed try against prev to hopefully save us a
     # fulltext.