comparison mercurial/revlogutils/nodemap.py @ 47310:9a3aa54774ff

persistent-nodemap: add a way to make the picked uid predictable This will make the test less volatile and therefore easier to maintain. I am setting this is for the persistent nodemap docket first, but my target is to use similar logic for the revlogv2 (and co) test. For persisent nodemap, they are too many different in how each test variants (with rust, without rust, etc) needs new uid for this be really useful (right now). However it will be directly useful for the revlogv2 logic. Differential Revision: https://phab.mercurial-scm.org/D10753
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 19 May 2021 17:19:46 +0200
parents 4f38ada3fc26
children 5bc6d2fc1cfc
comparison
equal deleted inserted replaced
47309:af4d1a177548 47310:9a3aa54774ff
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 12 import os
13 import random
13 import re 14 import re
14 import struct 15 import struct
15 16
16 from ..node import hex 17 from ..node import hex
17 18
18 from .. import ( 19 from .. import (
20 encoding,
19 error, 21 error,
22 pycompat,
20 util, 23 util,
21 ) 24 )
22 25
23 26
24 class NodeMap(dict): 27 class NodeMap(dict):
284 def _make_uid(): 287 def _make_uid():
285 """return a new unique identifier. 288 """return a new unique identifier.
286 289
287 The identifier is random and composed of ascii characters.""" 290 The identifier is random and composed of ascii characters."""
288 return hex(os.urandom(ID_SIZE)) 291 return hex(os.urandom(ID_SIZE))
292
293
294 # some special test logic to avoid anoying random output in the test
295 stable_docket_file = encoding.environ.get(b'HGTEST_DOCKETIDFILE')
296
297 if stable_docket_file:
298
299 def _make_uid():
300 try:
301 with open(stable_docket_file, mode='rb') as f:
302 seed = f.read().strip()
303 except IOError as inst:
304 if inst.errno != errno.ENOENT:
305 raise
306 seed = b'4' # chosen by a fair dice roll. garanteed to be random
307 if pycompat.ispy3:
308 iter_seed = iter(seed)
309 else:
310 iter_seed = (ord(c) for c in seed)
311 # some basic circular sum hashing on 64 bits
312 int_seed = 0
313 low_mask = int('1' * 35, 2)
314 for i in iter_seed:
315 high_part = int_seed >> 35
316 low_part = (int_seed & low_mask) << 28
317 int_seed = high_part + low_part + i
318 r = random.Random()
319 if pycompat.ispy3:
320 r.seed(int_seed, version=1)
321 else:
322 r.seed(int_seed)
323 # once we drop python 3.8 support we can simply use r.randbytes
324 raw = r.getrandbits(ID_SIZE * 8)
325 assert ID_SIZE == 8
326 p = struct.pack('>Q', raw)
327 new = hex(p)
328 with open(stable_docket_file, 'wb') as f:
329 f.write(new)
330 return new
289 331
290 332
291 class NodeMapDocket(object): 333 class NodeMapDocket(object):
292 """metadata associated with persistent nodemap data 334 """metadata associated with persistent nodemap data
293 335