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 |