comparison mercurial/revlogutils/docket.py @ 47312:7ea39d633cf3

docket: move the uid logic in the `revlogutils.docket` module We want to use it for revlog-v2 (& Co), it seems more logical to have the logic lives inside the `docket` file than the `nodemap` file. Differential Revision: https://phab.mercurial-scm.org/D10755
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 19 May 2021 19:57:55 +0200
parents 921648d31553
children f612db768c7a
comparison
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