mercurial/revlogutils/docket.py
changeset 47312 7ea39d633cf3
parent 47266 921648d31553
child 47323 f612db768c7a
equal deleted inserted replaced
47311:5bc6d2fc1cfc 47312:7ea39d633cf3
    15 #
    15 #
    16 # * a data file, containing variable width data for these revisions,
    16 # * a data file, containing variable width data for these revisions,
    17 
    17 
    18 from __future__ import absolute_import
    18 from __future__ import absolute_import
    19 
    19 
       
    20 import errno
       
    21 import os
       
    22 import random
    20 import struct
    23 import struct
    21 
    24 
    22 from .. import (
    25 from .. import (
       
    26     encoding,
    23     error,
    27     error,
       
    28     node,
       
    29     pycompat,
    24     util,
    30     util,
    25 )
    31 )
    26 
    32 
    27 from . import (
    33 from . import (
    28     constants,
    34     constants,
    29 )
    35 )
       
    36 
       
    37 
       
    38 def make_uid(id_size=8):
       
    39     """return a new unique identifier.
       
    40 
       
    41     The identifier is random and composed of ascii characters."""
       
    42     # size we "hex" the result we need half the number of bits to have a final
       
    43     # uuid of size ID_SIZE
       
    44     return node.hex(os.urandom(id_size // 2))
       
    45 
       
    46 
       
    47 # some special test logic to avoid anoying random output in the test
       
    48 stable_docket_file = encoding.environ.get(b'HGTEST_UUIDFILE')
       
    49 
       
    50 if stable_docket_file:
       
    51 
       
    52     def make_uid(id_size=8):
       
    53         try:
       
    54             with open(stable_docket_file, mode='rb') as f:
       
    55                 seed = f.read().strip()
       
    56         except IOError as inst:
       
    57             if inst.errno != errno.ENOENT:
       
    58                 raise
       
    59             seed = b'04'  # chosen by a fair dice roll. garanteed to be random
       
    60         if pycompat.ispy3:
       
    61             iter_seed = iter(seed)
       
    62         else:
       
    63             iter_seed = (ord(c) for c in seed)
       
    64         # some basic circular sum hashing on 64 bits
       
    65         int_seed = 0
       
    66         low_mask = int('1' * 35, 2)
       
    67         for i in iter_seed:
       
    68             high_part = int_seed >> 35
       
    69             low_part = (int_seed & low_mask) << 28
       
    70             int_seed = high_part + low_part + i
       
    71         r = random.Random()
       
    72         if pycompat.ispy3:
       
    73             r.seed(int_seed, version=1)
       
    74         else:
       
    75             r.seed(int_seed)
       
    76         # once we drop python 3.8 support we can simply use r.randbytes
       
    77         raw = r.getrandbits(id_size * 4)
       
    78         assert id_size == 8
       
    79         p = struct.pack('>L', raw)
       
    80         new = node.hex(p)
       
    81         with open(stable_docket_file, 'wb') as f:
       
    82             f.write(new)
       
    83         return new
       
    84 
    30 
    85 
    31 # Docket format
    86 # Docket format
    32 #
    87 #
    33 # * 4 bytes: revlog version
    88 # * 4 bytes: revlog version
    34 #          |   This is mandatory as docket must be compatible with the previous
    89 #          |   This is mandatory as docket must be compatible with the previous