[PATCH 2 of 4 stable] rbc: fix invalid rbc-revs entries caused by missing cache growth

Mads Kiilerich mads at kiilerich.com
Mon Jul 18 16:27:02 EDT 2016


# HG changeset patch
# User Mads Kiilerich <madski at unity3d.com>
# Date 1468873358 -7200
#      Mon Jul 18 22:22:38 2016 +0200
# Branch stable
# Node ID 28a03a9dc85d869d5a64edf99bb6f0e8eb0e616e
# Parent  33738ab96d61001a660395cd0e2c5416222ec842
rbc: fix invalid rbc-revs entries caused by missing cache growth

It was in some cases possible to end up writing to the cache file without
growing it first. The range assignment in _setcachedata would append instead of
writing at the requested position and thus write the new record in the wrong
place.

To fix this, we avoid looking up in too small caches, and when growing the
cache, do it right before writing the new record to it so we know it has been
done correctly.

diff --git a/mercurial/branchmap.py b/mercurial/branchmap.py
--- a/mercurial/branchmap.py
+++ b/mercurial/branchmap.py
@@ -402,10 +402,9 @@ class revbranchcache(object):
         if rev == nullrev:
             return changelog.branchinfo(rev)
 
-        # if requested rev is missing, add and populate all missing revs
+        # if requested rev isn't allocated, grow and cache the rev info
         if len(self._rbcrevs) < rbcrevidx + _rbcrecsize:
-            self._rbcrevs.extend('\0' * (len(changelog) * _rbcrecsize -
-                                         len(self._rbcrevs)))
+            return self._branchinfo(rev)
 
         # fast path: extract data from cache, use it if node is matching
         reponode = changelog.node(rev)[:_rbcnodelen]
@@ -452,6 +451,10 @@ class revbranchcache(object):
         rbcrevidx = rev * _rbcrecsize
         rec = array('c')
         rec.fromstring(pack(_rbcrecfmt, node, branchidx))
+        if len(self._rbcrevs) < rbcrevidx + _rbcrecsize:
+            self._rbcrevs.extend('\0' *
+                                 (len(self._repo.changelog) * _rbcrecsize -
+                                  len(self._rbcrevs)))
         self._rbcrevs[rbcrevidx:rbcrevidx + _rbcrecsize] = rec
         self._rbcrevslen = min(self._rbcrevslen, rev)
 
diff --git a/tests/test-branches.t b/tests/test-branches.t
--- a/tests/test-branches.t
+++ b/tests/test-branches.t
@@ -655,12 +655,16 @@ Test that cache files are created and gr
   $ rm .hg/cache/rbc*
   $ hg log -r "5 & branch(5)" -T "{rev}\n"
   5
-BUG: rbc-revs should have an entry as 5th record but has it misplaced as the
-first:
   $ f --size --hexdump .hg/cache/rbc-*
   .hg/cache/rbc-names-v1: size=1
   0000: 61                                              |a|
-  .hg/cache/rbc-revs-v1: size=8
-  0000: d8 cb c6 1d 00 00 00 00                         |........|
+  .hg/cache/rbc-revs-v1: size=112
+  0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+  0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+  0020: 00 00 00 00 00 00 00 00 d8 cb c6 1d 00 00 00 00 |................|
+  0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+  0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+  0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+  0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
 
   $ cd ..


More information about the Mercurial-devel mailing list