mercurial/revlogutils/nodemap.py
changeset 47312 7ea39d633cf3
parent 47311 5bc6d2fc1cfc
child 47451 f70ca39d0ab8
equal deleted inserted replaced
47311:5bc6d2fc1cfc 47312:7ea39d633cf3
     7 # GNU General Public License version 2 or any later version.
     7 # GNU General Public License version 2 or any later version.
     8 
     8 
     9 from __future__ import absolute_import
     9 from __future__ import absolute_import
    10 
    10 
    11 import errno
    11 import errno
    12 import os
       
    13 import random
       
    14 import re
    12 import re
    15 import struct
    13 import struct
    16 
    14 
    17 from ..node import hex
    15 from ..node import hex
    18 
    16 
    19 from .. import (
    17 from .. import (
    20     encoding,
       
    21     error,
    18     error,
    22     pycompat,
       
    23     util,
    19     util,
    24 )
    20 )
       
    21 from . import docket as docket_mod
    25 
    22 
    26 
    23 
    27 class NodeMap(dict):
    24 class NodeMap(dict):
    28     def __missing__(self, x):
    25     def __missing__(self, x):
    29         raise error.RevlogError(b'unknown node: %s' % x)
    26         raise error.RevlogError(b'unknown node: %s' % x)
   279 
   276 
   280 ONDISK_VERSION = 1
   277 ONDISK_VERSION = 1
   281 S_VERSION = struct.Struct(">B")
   278 S_VERSION = struct.Struct(">B")
   282 S_HEADER = struct.Struct(">BQQQQ")
   279 S_HEADER = struct.Struct(">BQQQQ")
   283 
   280 
   284 ID_SIZE = 8
       
   285 
       
   286 
       
   287 def _make_uid():
       
   288     """return a new unique identifier.
       
   289 
       
   290     The identifier is random and composed of ascii characters."""
       
   291     # size we "hex" the result we need half the number of bits to have a final
       
   292     # uuid of size ID_SIZE
       
   293     return hex(os.urandom(ID_SIZE // 2))
       
   294 
       
   295 
       
   296 # some special test logic to avoid anoying random output in the test
       
   297 stable_docket_file = encoding.environ.get(b'HGTEST_DOCKETIDFILE')
       
   298 
       
   299 if stable_docket_file:
       
   300 
       
   301     def _make_uid():
       
   302         try:
       
   303             with open(stable_docket_file, mode='rb') as f:
       
   304                 seed = f.read().strip()
       
   305         except IOError as inst:
       
   306             if inst.errno != errno.ENOENT:
       
   307                 raise
       
   308             seed = b'4'  # chosen by a fair dice roll. garanteed to be random
       
   309         if pycompat.ispy3:
       
   310             iter_seed = iter(seed)
       
   311         else:
       
   312             iter_seed = (ord(c) for c in seed)
       
   313         # some basic circular sum hashing on 64 bits
       
   314         int_seed = 0
       
   315         low_mask = int('1' * 35, 2)
       
   316         for i in iter_seed:
       
   317             high_part = int_seed >> 35
       
   318             low_part = (int_seed & low_mask) << 28
       
   319             int_seed = high_part + low_part + i
       
   320         r = random.Random()
       
   321         if pycompat.ispy3:
       
   322             r.seed(int_seed, version=1)
       
   323         else:
       
   324             r.seed(int_seed)
       
   325         # once we drop python 3.8 support we can simply use r.randbytes
       
   326         raw = r.getrandbits(ID_SIZE * 4)
       
   327         assert ID_SIZE == 8
       
   328         p = struct.pack('>L', raw)
       
   329         new = hex(p)
       
   330         with open(stable_docket_file, 'wb') as f:
       
   331             f.write(new)
       
   332         return new
       
   333 
       
   334 
   281 
   335 class NodeMapDocket(object):
   282 class NodeMapDocket(object):
   336     """metadata associated with persistent nodemap data
   283     """metadata associated with persistent nodemap data
   337 
   284 
   338     The persistent data may come from disk or be on their way to disk.
   285     The persistent data may come from disk or be on their way to disk.
   339     """
   286     """
   340 
   287 
   341     def __init__(self, uid=None):
   288     def __init__(self, uid=None):
   342         if uid is None:
   289         if uid is None:
   343             uid = _make_uid()
   290             uid = docket_mod.make_uid()
   344         # a unique identifier for the data file:
   291         # a unique identifier for the data file:
   345         #   - When new data are appended, it is preserved.
   292         #   - When new data are appended, it is preserved.
   346         #   - When a new data file is created, a new identifier is generated.
   293         #   - When a new data file is created, a new identifier is generated.
   347         self.uid = uid
   294         self.uid = uid
   348         # the tipmost revision stored in the data file. This revision and all
   295         # the tipmost revision stored in the data file. This revision and all