Mercurial > public > mercurial-scm > hg
comparison mercurial/revlogutils/nodemap.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 | 5bc6d2fc1cfc |
children | f70ca39d0ab8 |
comparison
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 |