Patchwork [2,of,2,STABLE,V2,STABLE] revlog: make sure we never use sparserevlog without general delta (issue6056)

login
register
mail settings
Submitter Boris Feld
Date Jan. 31, 2019, 3:50 a.m.
Message ID <8e4137a7d6715c554f36.1548906654@localhost.localdomain>
Download mbox | patch
Permalink /patch/38251/
State Accepted
Headers show

Comments

Boris Feld - Jan. 31, 2019, 3:50 a.m.
# HG changeset patch
# User Boris Feld <boris.feld@octobus.net>
# Date 1548372167 18000
#      Thu Jan 24 18:22:47 2019 -0500
# Branch stable
# Node ID 8e4137a7d6715c554f3689d48fd1c4b3101985ff
# Parent  cf5421ca2bea707ce52fc96f5ca68cf8f4894e8c
# EXP-Topic issue6056
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 8e4137a7d671
revlog: make sure we never use sparserevlog without general delta (issue6056)

We are getting user report where the delta code tries to use `sparse-revlog`
logic on repository where `generaldelta` is disabled. This can't work so we
ensure the two booleans have a consistent value.

Creating this kind of repository is not expected to be possible the current bug
report point at a clonebundle related bug that is still to be properly isolated
(Yuya Nishihara seems to a have done it).

Corrupting a repository to reproduce the issue is possible. A test using this
method is included in this fix.

Patch

diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -497,6 +497,9 @@  class revlog(object):
         else:
             raise error.RevlogError(_('unknown version (%d) in revlog %s') %
                                     (fmt, self.indexfile))
+        # sparse-revlog can't be on without general-delta (issue6056)
+        if not self._generaldelta:
+            self._sparserevlog = False
 
         self._storedeltachains = True
 
diff --git a/mercurial/revlogutils/deltas.py b/mercurial/revlogutils/deltas.py
--- a/mercurial/revlogutils/deltas.py
+++ b/mercurial/revlogutils/deltas.py
@@ -755,7 +755,8 @@  def _rawgroups(revlog, p1, p2, cachedelt
     The group order aims at providing fast or small candidates first.
     """
     gdelta = revlog._generaldelta
-    sparse = revlog._sparserevlog
+    # gate sparse behind general-delta because of issue-6056
+    sparse = gdelta and revlog._sparserevlog
     curr = len(revlog)
     prev = curr - 1
     deltachain = lambda rev: revlog._deltachain(rev)[0]
diff --git a/tests/test-init.t b/tests/test-init.t
--- a/tests/test-init.t
+++ b/tests/test-init.t
@@ -268,3 +268,26 @@  clone bookmarks
   exporting bookmark test
   $ hg -R remote-bookmarks bookmarks
      test                      0:08b9e9f63b32
+
+Check format constraint
+-----------------------
+
+
+  $ hg init issue6056 --config format.usegeneraldelta=0 --config format.sparse-revlog=0
+  $ cd issue6056
+  $ echo foo > 1
+  $ echo foo > 2
+  $ echo foo > 3
+  $ echo foo > 4
+  $ echo foo > 5
+  $ hg add *
+
+Build a bogus repository (sparserevlog without general delta)
+
+  $ hg commit -m 'initial changesets'
+  $ echo 'sparserevlog' >> .hg/requires
+  $ for x in `$TESTDIR/seq.py 100`; do
+  >     echo $x >> `expr $x % 5 + 1`
+  >     hg commit -m $x
+  > done
+  $ cd ..