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 |
|
|
1389 | uid_file = os.path.join(_bytes2sys(self._testtmp), 'UID') | |
1390 |
env['HGTEST_ |
|
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