##// END OF EJS Templates
docket: move the uid logic in the `revlogutils.docket` module...
marmoute -
r48093:7ea39d63 default
parent child Browse files
Show More
@@ -17,10 +17,16 b''
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
@@ -28,6 +34,55 b' from . import ('
28 constants,
34 constants,
29 )
35 )
30
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
85
31 # Docket format
86 # Docket format
32 #
87 #
33 # * 4 bytes: revlog version
88 # * 4 bytes: revlog version
@@ -9,19 +9,16 b''
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):
@@ -281,56 +278,6 b' 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
@@ -340,7 +287,7 b' class NodeMapDocket(object):'
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.
@@ -1386,8 +1386,8 b' class Test(unittest.TestCase):'
1386 env['PYTHONUSERBASE'] = sysconfig.get_config_var('userbase') or ''
1386 env['PYTHONUSERBASE'] = sysconfig.get_config_var('userbase') or ''
1387 env['HGEMITWARNINGS'] = '1'
1387 env['HGEMITWARNINGS'] = '1'
1388 env['TESTTMP'] = _bytes2sys(self._testtmp)
1388 env['TESTTMP'] = _bytes2sys(self._testtmp)
1389 docket_id_file = os.path.join(_bytes2sys(self._testtmp), 'DOCKETID')
1389 uid_file = os.path.join(_bytes2sys(self._testtmp), 'UID')
1390 env['HGTEST_DOCKETIDFILE'] = docket_id_file
1390 env['HGTEST_UUIDFILE'] = uid_file
1391 env['TESTNAME'] = self.name
1391 env['TESTNAME'] = self.name
1392 env['HOME'] = _bytes2sys(self._testtmp)
1392 env['HOME'] = _bytes2sys(self._testtmp)
1393 if os.name == 'nt':
1393 if os.name == 'nt':
General Comments 0
You need to be logged in to leave comments. Login now