##// END OF EJS Templates
persistent-nodemap: properly delete all nodemap files on downgrade...
marmoute -
r49539:d55c4472 default
parent child Browse files
Show More
@@ -1,657 +1,659 b''
1 # nodemap.py - nodemap related code and utilities
1 # nodemap.py - nodemap related code and utilities
2 #
2 #
3 # Copyright 2019 Pierre-Yves David <pierre-yves.david@octobus.net>
3 # Copyright 2019 Pierre-Yves David <pierre-yves.david@octobus.net>
4 # Copyright 2019 George Racinet <georges.racinet@octobus.net>
4 # Copyright 2019 George Racinet <georges.racinet@octobus.net>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
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 re
12 import re
13 import struct
13 import struct
14
14
15 from ..node import hex
15 from ..node import hex
16
16
17 from .. import (
17 from .. import (
18 error,
18 error,
19 util,
19 util,
20 )
20 )
21 from . import docket as docket_mod
21 from . import docket as docket_mod
22
22
23
23
24 class NodeMap(dict):
24 class NodeMap(dict):
25 def __missing__(self, x):
25 def __missing__(self, x):
26 raise error.RevlogError(b'unknown node: %s' % x)
26 raise error.RevlogError(b'unknown node: %s' % x)
27
27
28
28
29 def test_race_hook_1():
29 def test_race_hook_1():
30 """hook point for test
30 """hook point for test
31
31
32 This let tests to have things happens between the docket reading and the
32 This let tests to have things happens between the docket reading and the
33 data reading"""
33 data reading"""
34 pass
34 pass
35
35
36
36
37 def persisted_data(revlog):
37 def persisted_data(revlog):
38 """read the nodemap for a revlog from disk"""
38 """read the nodemap for a revlog from disk"""
39 if revlog._nodemap_file is None:
39 if revlog._nodemap_file is None:
40 return None
40 return None
41 pdata = revlog.opener.tryread(revlog._nodemap_file)
41 pdata = revlog.opener.tryread(revlog._nodemap_file)
42 if not pdata:
42 if not pdata:
43 return None
43 return None
44 offset = 0
44 offset = 0
45 (version,) = S_VERSION.unpack(pdata[offset : offset + S_VERSION.size])
45 (version,) = S_VERSION.unpack(pdata[offset : offset + S_VERSION.size])
46 if version != ONDISK_VERSION:
46 if version != ONDISK_VERSION:
47 return None
47 return None
48 offset += S_VERSION.size
48 offset += S_VERSION.size
49 headers = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size])
49 headers = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size])
50 uid_size, tip_rev, data_length, data_unused, tip_node_size = headers
50 uid_size, tip_rev, data_length, data_unused, tip_node_size = headers
51 offset += S_HEADER.size
51 offset += S_HEADER.size
52 docket = NodeMapDocket(pdata[offset : offset + uid_size])
52 docket = NodeMapDocket(pdata[offset : offset + uid_size])
53 offset += uid_size
53 offset += uid_size
54 docket.tip_rev = tip_rev
54 docket.tip_rev = tip_rev
55 docket.tip_node = pdata[offset : offset + tip_node_size]
55 docket.tip_node = pdata[offset : offset + tip_node_size]
56 docket.data_length = data_length
56 docket.data_length = data_length
57 docket.data_unused = data_unused
57 docket.data_unused = data_unused
58
58
59 filename = _rawdata_filepath(revlog, docket)
59 filename = _rawdata_filepath(revlog, docket)
60 use_mmap = revlog.opener.options.get(b"persistent-nodemap.mmap")
60 use_mmap = revlog.opener.options.get(b"persistent-nodemap.mmap")
61
61
62 test_race_hook_1()
62 test_race_hook_1()
63 try:
63 try:
64 with revlog.opener(filename) as fd:
64 with revlog.opener(filename) as fd:
65 if use_mmap:
65 if use_mmap:
66 try:
66 try:
67 data = util.buffer(util.mmapread(fd, data_length))
67 data = util.buffer(util.mmapread(fd, data_length))
68 except ValueError:
68 except ValueError:
69 # raised when the read file is too small
69 # raised when the read file is too small
70 data = b''
70 data = b''
71 else:
71 else:
72 data = fd.read(data_length)
72 data = fd.read(data_length)
73 except (IOError, OSError) as e:
73 except (IOError, OSError) as e:
74 if e.errno == errno.ENOENT:
74 if e.errno == errno.ENOENT:
75 return None
75 return None
76 else:
76 else:
77 raise
77 raise
78 if len(data) < data_length:
78 if len(data) < data_length:
79 return None
79 return None
80 return docket, data
80 return docket, data
81
81
82
82
83 def setup_persistent_nodemap(tr, revlog):
83 def setup_persistent_nodemap(tr, revlog):
84 """Install whatever is needed transaction side to persist a nodemap on disk
84 """Install whatever is needed transaction side to persist a nodemap on disk
85
85
86 (only actually persist the nodemap if this is relevant for this revlog)
86 (only actually persist the nodemap if this is relevant for this revlog)
87 """
87 """
88 if revlog._inline:
88 if revlog._inline:
89 return # inlined revlog are too small for this to be relevant
89 return # inlined revlog are too small for this to be relevant
90 if revlog._nodemap_file is None:
90 if revlog._nodemap_file is None:
91 return # we do not use persistent_nodemap on this revlog
91 return # we do not use persistent_nodemap on this revlog
92
92
93 # we need to happen after the changelog finalization, in that use "cl-"
93 # we need to happen after the changelog finalization, in that use "cl-"
94 callback_id = b"nm-revlog-persistent-nodemap-%s" % revlog._nodemap_file
94 callback_id = b"nm-revlog-persistent-nodemap-%s" % revlog._nodemap_file
95 if tr.hasfinalize(callback_id):
95 if tr.hasfinalize(callback_id):
96 return # no need to register again
96 return # no need to register again
97 tr.addpending(
97 tr.addpending(
98 callback_id, lambda tr: persist_nodemap(tr, revlog, pending=True)
98 callback_id, lambda tr: persist_nodemap(tr, revlog, pending=True)
99 )
99 )
100 tr.addfinalize(callback_id, lambda tr: persist_nodemap(tr, revlog))
100 tr.addfinalize(callback_id, lambda tr: persist_nodemap(tr, revlog))
101
101
102
102
103 class _NoTransaction(object):
103 class _NoTransaction(object):
104 """transaction like object to update the nodemap outside a transaction"""
104 """transaction like object to update the nodemap outside a transaction"""
105
105
106 def __init__(self):
106 def __init__(self):
107 self._postclose = {}
107 self._postclose = {}
108
108
109 def addpostclose(self, callback_id, callback_func):
109 def addpostclose(self, callback_id, callback_func):
110 self._postclose[callback_id] = callback_func
110 self._postclose[callback_id] = callback_func
111
111
112 def registertmp(self, *args, **kwargs):
112 def registertmp(self, *args, **kwargs):
113 pass
113 pass
114
114
115 def addbackup(self, *args, **kwargs):
115 def addbackup(self, *args, **kwargs):
116 pass
116 pass
117
117
118 def add(self, *args, **kwargs):
118 def add(self, *args, **kwargs):
119 pass
119 pass
120
120
121 def addabort(self, *args, **kwargs):
121 def addabort(self, *args, **kwargs):
122 pass
122 pass
123
123
124 def _report(self, *args):
124 def _report(self, *args):
125 pass
125 pass
126
126
127
127
128 def update_persistent_nodemap(revlog):
128 def update_persistent_nodemap(revlog):
129 """update the persistent nodemap right now
129 """update the persistent nodemap right now
130
130
131 To be used for updating the nodemap on disk outside of a normal transaction
131 To be used for updating the nodemap on disk outside of a normal transaction
132 setup (eg, `debugupdatecache`).
132 setup (eg, `debugupdatecache`).
133 """
133 """
134 if revlog._inline:
134 if revlog._inline:
135 return # inlined revlog are too small for this to be relevant
135 return # inlined revlog are too small for this to be relevant
136 if revlog._nodemap_file is None:
136 if revlog._nodemap_file is None:
137 return # we do not use persistent_nodemap on this revlog
137 return # we do not use persistent_nodemap on this revlog
138
138
139 notr = _NoTransaction()
139 notr = _NoTransaction()
140 persist_nodemap(notr, revlog)
140 persist_nodemap(notr, revlog)
141 for k in sorted(notr._postclose):
141 for k in sorted(notr._postclose):
142 notr._postclose[k](None)
142 notr._postclose[k](None)
143
143
144
144
145 def delete_nodemap(tr, repo, revlog):
145 def delete_nodemap(tr, repo, revlog):
146 """Delete nodemap data on disk for a given revlog"""
146 """Delete nodemap data on disk for a given revlog"""
147 if revlog._nodemap_file is None:
147 prefix = revlog.radix
148 msg = "calling persist nodemap on a revlog without the feature enabled"
148 pattern = re.compile(br"(^|/)%s(-[0-9a-f]+\.nd|\.n(\.a)?)$" % prefix)
149 raise error.ProgrammingError(msg)
149 dirpath = revlog.opener.dirname(revlog._indexfile)
150 repo.svfs.tryunlink(revlog._nodemap_file)
150 for f in revlog.opener.listdir(dirpath):
151 if pattern.match(f):
152 repo.svfs.tryunlink(f)
151
153
152
154
153 def persist_nodemap(tr, revlog, pending=False, force=False):
155 def persist_nodemap(tr, revlog, pending=False, force=False):
154 """Write nodemap data on disk for a given revlog"""
156 """Write nodemap data on disk for a given revlog"""
155 if getattr(revlog, 'filteredrevs', ()):
157 if getattr(revlog, 'filteredrevs', ()):
156 raise error.ProgrammingError(
158 raise error.ProgrammingError(
157 "cannot persist nodemap of a filtered changelog"
159 "cannot persist nodemap of a filtered changelog"
158 )
160 )
159 if revlog._nodemap_file is None:
161 if revlog._nodemap_file is None:
160 if force:
162 if force:
161 revlog._nodemap_file = get_nodemap_file(revlog)
163 revlog._nodemap_file = get_nodemap_file(revlog)
162 else:
164 else:
163 msg = "calling persist nodemap on a revlog without the feature enabled"
165 msg = "calling persist nodemap on a revlog without the feature enabled"
164 raise error.ProgrammingError(msg)
166 raise error.ProgrammingError(msg)
165
167
166 can_incremental = util.safehasattr(revlog.index, "nodemap_data_incremental")
168 can_incremental = util.safehasattr(revlog.index, "nodemap_data_incremental")
167 ondisk_docket = revlog._nodemap_docket
169 ondisk_docket = revlog._nodemap_docket
168 feed_data = util.safehasattr(revlog.index, "update_nodemap_data")
170 feed_data = util.safehasattr(revlog.index, "update_nodemap_data")
169 use_mmap = revlog.opener.options.get(b"persistent-nodemap.mmap")
171 use_mmap = revlog.opener.options.get(b"persistent-nodemap.mmap")
170
172
171 data = None
173 data = None
172 # first attemp an incremental update of the data
174 # first attemp an incremental update of the data
173 if can_incremental and ondisk_docket is not None:
175 if can_incremental and ondisk_docket is not None:
174 target_docket = revlog._nodemap_docket.copy()
176 target_docket = revlog._nodemap_docket.copy()
175 (
177 (
176 src_docket,
178 src_docket,
177 data_changed_count,
179 data_changed_count,
178 data,
180 data,
179 ) = revlog.index.nodemap_data_incremental()
181 ) = revlog.index.nodemap_data_incremental()
180 new_length = target_docket.data_length + len(data)
182 new_length = target_docket.data_length + len(data)
181 new_unused = target_docket.data_unused + data_changed_count
183 new_unused = target_docket.data_unused + data_changed_count
182 if src_docket != target_docket:
184 if src_docket != target_docket:
183 data = None
185 data = None
184 elif new_length <= (new_unused * 10): # under 10% of unused data
186 elif new_length <= (new_unused * 10): # under 10% of unused data
185 data = None
187 data = None
186 else:
188 else:
187 datafile = _rawdata_filepath(revlog, target_docket)
189 datafile = _rawdata_filepath(revlog, target_docket)
188 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
190 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
189 # store vfs
191 # store vfs
190 tr.add(datafile, target_docket.data_length)
192 tr.add(datafile, target_docket.data_length)
191 with revlog.opener(datafile, b'r+') as fd:
193 with revlog.opener(datafile, b'r+') as fd:
192 fd.seek(target_docket.data_length)
194 fd.seek(target_docket.data_length)
193 fd.write(data)
195 fd.write(data)
194 if feed_data:
196 if feed_data:
195 if use_mmap:
197 if use_mmap:
196 fd.seek(0)
198 fd.seek(0)
197 new_data = fd.read(new_length)
199 new_data = fd.read(new_length)
198 else:
200 else:
199 fd.flush()
201 fd.flush()
200 new_data = util.buffer(util.mmapread(fd, new_length))
202 new_data = util.buffer(util.mmapread(fd, new_length))
201 target_docket.data_length = new_length
203 target_docket.data_length = new_length
202 target_docket.data_unused = new_unused
204 target_docket.data_unused = new_unused
203
205
204 if data is None:
206 if data is None:
205 # otherwise fallback to a full new export
207 # otherwise fallback to a full new export
206 target_docket = NodeMapDocket()
208 target_docket = NodeMapDocket()
207 datafile = _rawdata_filepath(revlog, target_docket)
209 datafile = _rawdata_filepath(revlog, target_docket)
208 if util.safehasattr(revlog.index, "nodemap_data_all"):
210 if util.safehasattr(revlog.index, "nodemap_data_all"):
209 data = revlog.index.nodemap_data_all()
211 data = revlog.index.nodemap_data_all()
210 else:
212 else:
211 data = persistent_data(revlog.index)
213 data = persistent_data(revlog.index)
212 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
214 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
213 # store vfs
215 # store vfs
214
216
215 tryunlink = revlog.opener.tryunlink
217 tryunlink = revlog.opener.tryunlink
216
218
217 def abortck(tr):
219 def abortck(tr):
218 tryunlink(datafile)
220 tryunlink(datafile)
219
221
220 callback_id = b"delete-%s" % datafile
222 callback_id = b"delete-%s" % datafile
221
223
222 # some flavor of the transaction abort does not cleanup new file, it
224 # some flavor of the transaction abort does not cleanup new file, it
223 # simply empty them.
225 # simply empty them.
224 tr.addabort(callback_id, abortck)
226 tr.addabort(callback_id, abortck)
225 with revlog.opener(datafile, b'w+') as fd:
227 with revlog.opener(datafile, b'w+') as fd:
226 fd.write(data)
228 fd.write(data)
227 if feed_data:
229 if feed_data:
228 if use_mmap:
230 if use_mmap:
229 new_data = data
231 new_data = data
230 else:
232 else:
231 fd.flush()
233 fd.flush()
232 new_data = util.buffer(util.mmapread(fd, len(data)))
234 new_data = util.buffer(util.mmapread(fd, len(data)))
233 target_docket.data_length = len(data)
235 target_docket.data_length = len(data)
234 target_docket.tip_rev = revlog.tiprev()
236 target_docket.tip_rev = revlog.tiprev()
235 target_docket.tip_node = revlog.node(target_docket.tip_rev)
237 target_docket.tip_node = revlog.node(target_docket.tip_rev)
236 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
238 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
237 # store vfs
239 # store vfs
238 file_path = revlog._nodemap_file
240 file_path = revlog._nodemap_file
239 if pending:
241 if pending:
240 file_path += b'.a'
242 file_path += b'.a'
241 tr.registertmp(file_path)
243 tr.registertmp(file_path)
242 else:
244 else:
243 tr.addbackup(file_path)
245 tr.addbackup(file_path)
244
246
245 with revlog.opener(file_path, b'w', atomictemp=True) as fp:
247 with revlog.opener(file_path, b'w', atomictemp=True) as fp:
246 fp.write(target_docket.serialize())
248 fp.write(target_docket.serialize())
247 revlog._nodemap_docket = target_docket
249 revlog._nodemap_docket = target_docket
248 if feed_data:
250 if feed_data:
249 revlog.index.update_nodemap_data(target_docket, new_data)
251 revlog.index.update_nodemap_data(target_docket, new_data)
250
252
251 # search for old index file in all cases, some older process might have
253 # search for old index file in all cases, some older process might have
252 # left one behind.
254 # left one behind.
253 olds = _other_rawdata_filepath(revlog, target_docket)
255 olds = _other_rawdata_filepath(revlog, target_docket)
254 if olds:
256 if olds:
255 realvfs = getattr(revlog, '_realopener', revlog.opener)
257 realvfs = getattr(revlog, '_realopener', revlog.opener)
256
258
257 def cleanup(tr):
259 def cleanup(tr):
258 for oldfile in olds:
260 for oldfile in olds:
259 realvfs.tryunlink(oldfile)
261 realvfs.tryunlink(oldfile)
260
262
261 callback_id = b"revlog-cleanup-nodemap-%s" % revlog._nodemap_file
263 callback_id = b"revlog-cleanup-nodemap-%s" % revlog._nodemap_file
262 tr.addpostclose(callback_id, cleanup)
264 tr.addpostclose(callback_id, cleanup)
263
265
264
266
265 ### Nodemap docket file
267 ### Nodemap docket file
266 #
268 #
267 # The nodemap data are stored on disk using 2 files:
269 # The nodemap data are stored on disk using 2 files:
268 #
270 #
269 # * a raw data files containing a persistent nodemap
271 # * a raw data files containing a persistent nodemap
270 # (see `Nodemap Trie` section)
272 # (see `Nodemap Trie` section)
271 #
273 #
272 # * a small "docket" file containing medatadata
274 # * a small "docket" file containing medatadata
273 #
275 #
274 # While the nodemap data can be multiple tens of megabytes, the "docket" is
276 # While the nodemap data can be multiple tens of megabytes, the "docket" is
275 # small, it is easy to update it automatically or to duplicated its content
277 # small, it is easy to update it automatically or to duplicated its content
276 # during a transaction.
278 # during a transaction.
277 #
279 #
278 # Multiple raw data can exist at the same time (The currently valid one and a
280 # Multiple raw data can exist at the same time (The currently valid one and a
279 # new one beind used by an in progress transaction). To accomodate this, the
281 # new one beind used by an in progress transaction). To accomodate this, the
280 # filename hosting the raw data has a variable parts. The exact filename is
282 # filename hosting the raw data has a variable parts. The exact filename is
281 # specified inside the "docket" file.
283 # specified inside the "docket" file.
282 #
284 #
283 # The docket file contains information to find, qualify and validate the raw
285 # The docket file contains information to find, qualify and validate the raw
284 # data. Its content is currently very light, but it will expand as the on disk
286 # data. Its content is currently very light, but it will expand as the on disk
285 # nodemap gains the necessary features to be used in production.
287 # nodemap gains the necessary features to be used in production.
286
288
287 ONDISK_VERSION = 1
289 ONDISK_VERSION = 1
288 S_VERSION = struct.Struct(">B")
290 S_VERSION = struct.Struct(">B")
289 S_HEADER = struct.Struct(">BQQQQ")
291 S_HEADER = struct.Struct(">BQQQQ")
290
292
291
293
292 class NodeMapDocket(object):
294 class NodeMapDocket(object):
293 """metadata associated with persistent nodemap data
295 """metadata associated with persistent nodemap data
294
296
295 The persistent data may come from disk or be on their way to disk.
297 The persistent data may come from disk or be on their way to disk.
296 """
298 """
297
299
298 def __init__(self, uid=None):
300 def __init__(self, uid=None):
299 if uid is None:
301 if uid is None:
300 uid = docket_mod.make_uid()
302 uid = docket_mod.make_uid()
301 # a unique identifier for the data file:
303 # a unique identifier for the data file:
302 # - When new data are appended, it is preserved.
304 # - When new data are appended, it is preserved.
303 # - When a new data file is created, a new identifier is generated.
305 # - When a new data file is created, a new identifier is generated.
304 self.uid = uid
306 self.uid = uid
305 # the tipmost revision stored in the data file. This revision and all
307 # the tipmost revision stored in the data file. This revision and all
306 # revision before it are expected to be encoded in the data file.
308 # revision before it are expected to be encoded in the data file.
307 self.tip_rev = None
309 self.tip_rev = None
308 # the node of that tipmost revision, if it mismatch the current index
310 # the node of that tipmost revision, if it mismatch the current index
309 # data the docket is not valid for the current index and should be
311 # data the docket is not valid for the current index and should be
310 # discarded.
312 # discarded.
311 #
313 #
312 # note: this method is not perfect as some destructive operation could
314 # note: this method is not perfect as some destructive operation could
313 # preserve the same tip_rev + tip_node while altering lower revision.
315 # preserve the same tip_rev + tip_node while altering lower revision.
314 # However this multiple other caches have the same vulnerability (eg:
316 # However this multiple other caches have the same vulnerability (eg:
315 # brancmap cache).
317 # brancmap cache).
316 self.tip_node = None
318 self.tip_node = None
317 # the size (in bytes) of the persisted data to encode the nodemap valid
319 # the size (in bytes) of the persisted data to encode the nodemap valid
318 # for `tip_rev`.
320 # for `tip_rev`.
319 # - data file shorter than this are corrupted,
321 # - data file shorter than this are corrupted,
320 # - any extra data should be ignored.
322 # - any extra data should be ignored.
321 self.data_length = None
323 self.data_length = None
322 # the amount (in bytes) of "dead" data, still in the data file but no
324 # the amount (in bytes) of "dead" data, still in the data file but no
323 # longer used for the nodemap.
325 # longer used for the nodemap.
324 self.data_unused = 0
326 self.data_unused = 0
325
327
326 def copy(self):
328 def copy(self):
327 new = NodeMapDocket(uid=self.uid)
329 new = NodeMapDocket(uid=self.uid)
328 new.tip_rev = self.tip_rev
330 new.tip_rev = self.tip_rev
329 new.tip_node = self.tip_node
331 new.tip_node = self.tip_node
330 new.data_length = self.data_length
332 new.data_length = self.data_length
331 new.data_unused = self.data_unused
333 new.data_unused = self.data_unused
332 return new
334 return new
333
335
334 def __cmp__(self, other):
336 def __cmp__(self, other):
335 if self.uid < other.uid:
337 if self.uid < other.uid:
336 return -1
338 return -1
337 if self.uid > other.uid:
339 if self.uid > other.uid:
338 return 1
340 return 1
339 elif self.data_length < other.data_length:
341 elif self.data_length < other.data_length:
340 return -1
342 return -1
341 elif self.data_length > other.data_length:
343 elif self.data_length > other.data_length:
342 return 1
344 return 1
343 return 0
345 return 0
344
346
345 def __eq__(self, other):
347 def __eq__(self, other):
346 return self.uid == other.uid and self.data_length == other.data_length
348 return self.uid == other.uid and self.data_length == other.data_length
347
349
348 def serialize(self):
350 def serialize(self):
349 """return serialized bytes for a docket using the passed uid"""
351 """return serialized bytes for a docket using the passed uid"""
350 data = []
352 data = []
351 data.append(S_VERSION.pack(ONDISK_VERSION))
353 data.append(S_VERSION.pack(ONDISK_VERSION))
352 headers = (
354 headers = (
353 len(self.uid),
355 len(self.uid),
354 self.tip_rev,
356 self.tip_rev,
355 self.data_length,
357 self.data_length,
356 self.data_unused,
358 self.data_unused,
357 len(self.tip_node),
359 len(self.tip_node),
358 )
360 )
359 data.append(S_HEADER.pack(*headers))
361 data.append(S_HEADER.pack(*headers))
360 data.append(self.uid)
362 data.append(self.uid)
361 data.append(self.tip_node)
363 data.append(self.tip_node)
362 return b''.join(data)
364 return b''.join(data)
363
365
364
366
365 def _rawdata_filepath(revlog, docket):
367 def _rawdata_filepath(revlog, docket):
366 """The (vfs relative) nodemap's rawdata file for a given uid"""
368 """The (vfs relative) nodemap's rawdata file for a given uid"""
367 prefix = revlog.radix
369 prefix = revlog.radix
368 return b"%s-%s.nd" % (prefix, docket.uid)
370 return b"%s-%s.nd" % (prefix, docket.uid)
369
371
370
372
371 def _other_rawdata_filepath(revlog, docket):
373 def _other_rawdata_filepath(revlog, docket):
372 prefix = revlog.radix
374 prefix = revlog.radix
373 pattern = re.compile(br"(^|/)%s-[0-9a-f]+\.nd$" % prefix)
375 pattern = re.compile(br"(^|/)%s-[0-9a-f]+\.nd$" % prefix)
374 new_file_path = _rawdata_filepath(revlog, docket)
376 new_file_path = _rawdata_filepath(revlog, docket)
375 new_file_name = revlog.opener.basename(new_file_path)
377 new_file_name = revlog.opener.basename(new_file_path)
376 dirpath = revlog.opener.dirname(new_file_path)
378 dirpath = revlog.opener.dirname(new_file_path)
377 others = []
379 others = []
378 for f in revlog.opener.listdir(dirpath):
380 for f in revlog.opener.listdir(dirpath):
379 if pattern.match(f) and f != new_file_name:
381 if pattern.match(f) and f != new_file_name:
380 others.append(f)
382 others.append(f)
381 return others
383 return others
382
384
383
385
384 ### Nodemap Trie
386 ### Nodemap Trie
385 #
387 #
386 # This is a simple reference implementation to compute and persist a nodemap
388 # This is a simple reference implementation to compute and persist a nodemap
387 # trie. This reference implementation is write only. The python version of this
389 # trie. This reference implementation is write only. The python version of this
388 # is not expected to be actually used, since it wont provide performance
390 # is not expected to be actually used, since it wont provide performance
389 # improvement over existing non-persistent C implementation.
391 # improvement over existing non-persistent C implementation.
390 #
392 #
391 # The nodemap is persisted as Trie using 4bits-address/16-entries block. each
393 # The nodemap is persisted as Trie using 4bits-address/16-entries block. each
392 # revision can be adressed using its node shortest prefix.
394 # revision can be adressed using its node shortest prefix.
393 #
395 #
394 # The trie is stored as a sequence of block. Each block contains 16 entries
396 # The trie is stored as a sequence of block. Each block contains 16 entries
395 # (signed 64bit integer, big endian). Each entry can be one of the following:
397 # (signed 64bit integer, big endian). Each entry can be one of the following:
396 #
398 #
397 # * value >= 0 -> index of sub-block
399 # * value >= 0 -> index of sub-block
398 # * value == -1 -> no value
400 # * value == -1 -> no value
399 # * value < -1 -> encoded revision: rev = -(value+2)
401 # * value < -1 -> encoded revision: rev = -(value+2)
400 #
402 #
401 # See REV_OFFSET and _transform_rev below.
403 # See REV_OFFSET and _transform_rev below.
402 #
404 #
403 # The implementation focus on simplicity, not on performance. A Rust
405 # The implementation focus on simplicity, not on performance. A Rust
404 # implementation should provide a efficient version of the same binary
406 # implementation should provide a efficient version of the same binary
405 # persistence. This reference python implementation is never meant to be
407 # persistence. This reference python implementation is never meant to be
406 # extensively use in production.
408 # extensively use in production.
407
409
408
410
409 def persistent_data(index):
411 def persistent_data(index):
410 """return the persistent binary form for a nodemap for a given index"""
412 """return the persistent binary form for a nodemap for a given index"""
411 trie = _build_trie(index)
413 trie = _build_trie(index)
412 return _persist_trie(trie)
414 return _persist_trie(trie)
413
415
414
416
415 def update_persistent_data(index, root, max_idx, last_rev):
417 def update_persistent_data(index, root, max_idx, last_rev):
416 """return the incremental update for persistent nodemap from a given index"""
418 """return the incremental update for persistent nodemap from a given index"""
417 changed_block, trie = _update_trie(index, root, last_rev)
419 changed_block, trie = _update_trie(index, root, last_rev)
418 return (
420 return (
419 changed_block * S_BLOCK.size,
421 changed_block * S_BLOCK.size,
420 _persist_trie(trie, existing_idx=max_idx),
422 _persist_trie(trie, existing_idx=max_idx),
421 )
423 )
422
424
423
425
424 S_BLOCK = struct.Struct(">" + ("l" * 16))
426 S_BLOCK = struct.Struct(">" + ("l" * 16))
425
427
426 NO_ENTRY = -1
428 NO_ENTRY = -1
427 # rev 0 need to be -2 because 0 is used by block, -1 is a special value.
429 # rev 0 need to be -2 because 0 is used by block, -1 is a special value.
428 REV_OFFSET = 2
430 REV_OFFSET = 2
429
431
430
432
431 def _transform_rev(rev):
433 def _transform_rev(rev):
432 """Return the number used to represent the rev in the tree.
434 """Return the number used to represent the rev in the tree.
433
435
434 (or retrieve a rev number from such representation)
436 (or retrieve a rev number from such representation)
435
437
436 Note that this is an involution, a function equal to its inverse (i.e.
438 Note that this is an involution, a function equal to its inverse (i.e.
437 which gives the identity when applied to itself).
439 which gives the identity when applied to itself).
438 """
440 """
439 return -(rev + REV_OFFSET)
441 return -(rev + REV_OFFSET)
440
442
441
443
442 def _to_int(hex_digit):
444 def _to_int(hex_digit):
443 """turn an hexadecimal digit into a proper integer"""
445 """turn an hexadecimal digit into a proper integer"""
444 return int(hex_digit, 16)
446 return int(hex_digit, 16)
445
447
446
448
447 class Block(dict):
449 class Block(dict):
448 """represent a block of the Trie
450 """represent a block of the Trie
449
451
450 contains up to 16 entry indexed from 0 to 15"""
452 contains up to 16 entry indexed from 0 to 15"""
451
453
452 def __init__(self):
454 def __init__(self):
453 super(Block, self).__init__()
455 super(Block, self).__init__()
454 # If this block exist on disk, here is its ID
456 # If this block exist on disk, here is its ID
455 self.ondisk_id = None
457 self.ondisk_id = None
456
458
457 def __iter__(self):
459 def __iter__(self):
458 return iter(self.get(i) for i in range(16))
460 return iter(self.get(i) for i in range(16))
459
461
460
462
461 def _build_trie(index):
463 def _build_trie(index):
462 """build a nodemap trie
464 """build a nodemap trie
463
465
464 The nodemap stores revision number for each unique prefix.
466 The nodemap stores revision number for each unique prefix.
465
467
466 Each block is a dictionary with keys in `[0, 15]`. Values are either
468 Each block is a dictionary with keys in `[0, 15]`. Values are either
467 another block or a revision number.
469 another block or a revision number.
468 """
470 """
469 root = Block()
471 root = Block()
470 for rev in range(len(index)):
472 for rev in range(len(index)):
471 current_hex = hex(index[rev][7])
473 current_hex = hex(index[rev][7])
472 _insert_into_block(index, 0, root, rev, current_hex)
474 _insert_into_block(index, 0, root, rev, current_hex)
473 return root
475 return root
474
476
475
477
476 def _update_trie(index, root, last_rev):
478 def _update_trie(index, root, last_rev):
477 """consume"""
479 """consume"""
478 changed = 0
480 changed = 0
479 for rev in range(last_rev + 1, len(index)):
481 for rev in range(last_rev + 1, len(index)):
480 current_hex = hex(index[rev][7])
482 current_hex = hex(index[rev][7])
481 changed += _insert_into_block(index, 0, root, rev, current_hex)
483 changed += _insert_into_block(index, 0, root, rev, current_hex)
482 return changed, root
484 return changed, root
483
485
484
486
485 def _insert_into_block(index, level, block, current_rev, current_hex):
487 def _insert_into_block(index, level, block, current_rev, current_hex):
486 """insert a new revision in a block
488 """insert a new revision in a block
487
489
488 index: the index we are adding revision for
490 index: the index we are adding revision for
489 level: the depth of the current block in the trie
491 level: the depth of the current block in the trie
490 block: the block currently being considered
492 block: the block currently being considered
491 current_rev: the revision number we are adding
493 current_rev: the revision number we are adding
492 current_hex: the hexadecimal representation of the of that revision
494 current_hex: the hexadecimal representation of the of that revision
493 """
495 """
494 changed = 1
496 changed = 1
495 if block.ondisk_id is not None:
497 if block.ondisk_id is not None:
496 block.ondisk_id = None
498 block.ondisk_id = None
497 hex_digit = _to_int(current_hex[level : level + 1])
499 hex_digit = _to_int(current_hex[level : level + 1])
498 entry = block.get(hex_digit)
500 entry = block.get(hex_digit)
499 if entry is None:
501 if entry is None:
500 # no entry, simply store the revision number
502 # no entry, simply store the revision number
501 block[hex_digit] = current_rev
503 block[hex_digit] = current_rev
502 elif isinstance(entry, dict):
504 elif isinstance(entry, dict):
503 # need to recurse to an underlying block
505 # need to recurse to an underlying block
504 changed += _insert_into_block(
506 changed += _insert_into_block(
505 index, level + 1, entry, current_rev, current_hex
507 index, level + 1, entry, current_rev, current_hex
506 )
508 )
507 else:
509 else:
508 # collision with a previously unique prefix, inserting new
510 # collision with a previously unique prefix, inserting new
509 # vertices to fit both entry.
511 # vertices to fit both entry.
510 other_hex = hex(index[entry][7])
512 other_hex = hex(index[entry][7])
511 other_rev = entry
513 other_rev = entry
512 new = Block()
514 new = Block()
513 block[hex_digit] = new
515 block[hex_digit] = new
514 _insert_into_block(index, level + 1, new, other_rev, other_hex)
516 _insert_into_block(index, level + 1, new, other_rev, other_hex)
515 _insert_into_block(index, level + 1, new, current_rev, current_hex)
517 _insert_into_block(index, level + 1, new, current_rev, current_hex)
516 return changed
518 return changed
517
519
518
520
519 def _persist_trie(root, existing_idx=None):
521 def _persist_trie(root, existing_idx=None):
520 """turn a nodemap trie into persistent binary data
522 """turn a nodemap trie into persistent binary data
521
523
522 See `_build_trie` for nodemap trie structure"""
524 See `_build_trie` for nodemap trie structure"""
523 block_map = {}
525 block_map = {}
524 if existing_idx is not None:
526 if existing_idx is not None:
525 base_idx = existing_idx + 1
527 base_idx = existing_idx + 1
526 else:
528 else:
527 base_idx = 0
529 base_idx = 0
528 chunks = []
530 chunks = []
529 for tn in _walk_trie(root):
531 for tn in _walk_trie(root):
530 if tn.ondisk_id is not None:
532 if tn.ondisk_id is not None:
531 block_map[id(tn)] = tn.ondisk_id
533 block_map[id(tn)] = tn.ondisk_id
532 else:
534 else:
533 block_map[id(tn)] = len(chunks) + base_idx
535 block_map[id(tn)] = len(chunks) + base_idx
534 chunks.append(_persist_block(tn, block_map))
536 chunks.append(_persist_block(tn, block_map))
535 return b''.join(chunks)
537 return b''.join(chunks)
536
538
537
539
538 def _walk_trie(block):
540 def _walk_trie(block):
539 """yield all the block in a trie
541 """yield all the block in a trie
540
542
541 Children blocks are always yield before their parent block.
543 Children blocks are always yield before their parent block.
542 """
544 """
543 for (__, item) in sorted(block.items()):
545 for (__, item) in sorted(block.items()):
544 if isinstance(item, dict):
546 if isinstance(item, dict):
545 for sub_block in _walk_trie(item):
547 for sub_block in _walk_trie(item):
546 yield sub_block
548 yield sub_block
547 yield block
549 yield block
548
550
549
551
550 def _persist_block(block_node, block_map):
552 def _persist_block(block_node, block_map):
551 """produce persistent binary data for a single block
553 """produce persistent binary data for a single block
552
554
553 Children block are assumed to be already persisted and present in
555 Children block are assumed to be already persisted and present in
554 block_map.
556 block_map.
555 """
557 """
556 data = tuple(_to_value(v, block_map) for v in block_node)
558 data = tuple(_to_value(v, block_map) for v in block_node)
557 return S_BLOCK.pack(*data)
559 return S_BLOCK.pack(*data)
558
560
559
561
560 def _to_value(item, block_map):
562 def _to_value(item, block_map):
561 """persist any value as an integer"""
563 """persist any value as an integer"""
562 if item is None:
564 if item is None:
563 return NO_ENTRY
565 return NO_ENTRY
564 elif isinstance(item, dict):
566 elif isinstance(item, dict):
565 return block_map[id(item)]
567 return block_map[id(item)]
566 else:
568 else:
567 return _transform_rev(item)
569 return _transform_rev(item)
568
570
569
571
570 def parse_data(data):
572 def parse_data(data):
571 """parse parse nodemap data into a nodemap Trie"""
573 """parse parse nodemap data into a nodemap Trie"""
572 if (len(data) % S_BLOCK.size) != 0:
574 if (len(data) % S_BLOCK.size) != 0:
573 msg = b"nodemap data size is not a multiple of block size (%d): %d"
575 msg = b"nodemap data size is not a multiple of block size (%d): %d"
574 raise error.Abort(msg % (S_BLOCK.size, len(data)))
576 raise error.Abort(msg % (S_BLOCK.size, len(data)))
575 if not data:
577 if not data:
576 return Block(), None
578 return Block(), None
577 block_map = {}
579 block_map = {}
578 new_blocks = []
580 new_blocks = []
579 for i in range(0, len(data), S_BLOCK.size):
581 for i in range(0, len(data), S_BLOCK.size):
580 block = Block()
582 block = Block()
581 block.ondisk_id = len(block_map)
583 block.ondisk_id = len(block_map)
582 block_map[block.ondisk_id] = block
584 block_map[block.ondisk_id] = block
583 block_data = data[i : i + S_BLOCK.size]
585 block_data = data[i : i + S_BLOCK.size]
584 values = S_BLOCK.unpack(block_data)
586 values = S_BLOCK.unpack(block_data)
585 new_blocks.append((block, values))
587 new_blocks.append((block, values))
586 for b, values in new_blocks:
588 for b, values in new_blocks:
587 for idx, v in enumerate(values):
589 for idx, v in enumerate(values):
588 if v == NO_ENTRY:
590 if v == NO_ENTRY:
589 continue
591 continue
590 elif v >= 0:
592 elif v >= 0:
591 b[idx] = block_map[v]
593 b[idx] = block_map[v]
592 else:
594 else:
593 b[idx] = _transform_rev(v)
595 b[idx] = _transform_rev(v)
594 return block, i // S_BLOCK.size
596 return block, i // S_BLOCK.size
595
597
596
598
597 # debug utility
599 # debug utility
598
600
599
601
600 def check_data(ui, index, data):
602 def check_data(ui, index, data):
601 """verify that the provided nodemap data are valid for the given idex"""
603 """verify that the provided nodemap data are valid for the given idex"""
602 ret = 0
604 ret = 0
603 ui.status((b"revision in index: %d\n") % len(index))
605 ui.status((b"revision in index: %d\n") % len(index))
604 root, __ = parse_data(data)
606 root, __ = parse_data(data)
605 all_revs = set(_all_revisions(root))
607 all_revs = set(_all_revisions(root))
606 ui.status((b"revision in nodemap: %d\n") % len(all_revs))
608 ui.status((b"revision in nodemap: %d\n") % len(all_revs))
607 for r in range(len(index)):
609 for r in range(len(index)):
608 if r not in all_revs:
610 if r not in all_revs:
609 msg = b" revision missing from nodemap: %d\n" % r
611 msg = b" revision missing from nodemap: %d\n" % r
610 ui.write_err(msg)
612 ui.write_err(msg)
611 ret = 1
613 ret = 1
612 else:
614 else:
613 all_revs.remove(r)
615 all_revs.remove(r)
614 nm_rev = _find_node(root, hex(index[r][7]))
616 nm_rev = _find_node(root, hex(index[r][7]))
615 if nm_rev is None:
617 if nm_rev is None:
616 msg = b" revision node does not match any entries: %d\n" % r
618 msg = b" revision node does not match any entries: %d\n" % r
617 ui.write_err(msg)
619 ui.write_err(msg)
618 ret = 1
620 ret = 1
619 elif nm_rev != r:
621 elif nm_rev != r:
620 msg = (
622 msg = (
621 b" revision node does not match the expected revision: "
623 b" revision node does not match the expected revision: "
622 b"%d != %d\n" % (r, nm_rev)
624 b"%d != %d\n" % (r, nm_rev)
623 )
625 )
624 ui.write_err(msg)
626 ui.write_err(msg)
625 ret = 1
627 ret = 1
626
628
627 if all_revs:
629 if all_revs:
628 for r in sorted(all_revs):
630 for r in sorted(all_revs):
629 msg = b" extra revision in nodemap: %d\n" % r
631 msg = b" extra revision in nodemap: %d\n" % r
630 ui.write_err(msg)
632 ui.write_err(msg)
631 ret = 1
633 ret = 1
632 return ret
634 return ret
633
635
634
636
635 def _all_revisions(root):
637 def _all_revisions(root):
636 """return all revisions stored in a Trie"""
638 """return all revisions stored in a Trie"""
637 for block in _walk_trie(root):
639 for block in _walk_trie(root):
638 for v in block:
640 for v in block:
639 if v is None or isinstance(v, Block):
641 if v is None or isinstance(v, Block):
640 continue
642 continue
641 yield v
643 yield v
642
644
643
645
644 def _find_node(block, node):
646 def _find_node(block, node):
645 """find the revision associated with a given node"""
647 """find the revision associated with a given node"""
646 entry = block.get(_to_int(node[0:1]))
648 entry = block.get(_to_int(node[0:1]))
647 if isinstance(entry, dict):
649 if isinstance(entry, dict):
648 return _find_node(entry, node[1:])
650 return _find_node(entry, node[1:])
649 return entry
651 return entry
650
652
651
653
652 def get_nodemap_file(revlog):
654 def get_nodemap_file(revlog):
653 if revlog._trypending:
655 if revlog._trypending:
654 pending_path = revlog.radix + b".n.a"
656 pending_path = revlog.radix + b".n.a"
655 if revlog.opener.exists(pending_path):
657 if revlog.opener.exists(pending_path):
656 return pending_path
658 return pending_path
657 return revlog.radix + b".n"
659 return revlog.radix + b".n"
@@ -1,1262 +1,1260 b''
1 ===================================
1 ===================================
2 Test the persistent on-disk nodemap
2 Test the persistent on-disk nodemap
3 ===================================
3 ===================================
4
4
5
5
6 $ cat << EOF >> $HGRCPATH
6 $ cat << EOF >> $HGRCPATH
7 > [format]
7 > [format]
8 > use-share-safe=yes
8 > use-share-safe=yes
9 > [extensions]
9 > [extensions]
10 > share=
10 > share=
11 > EOF
11 > EOF
12
12
13 #if no-rust
13 #if no-rust
14
14
15 $ cat << EOF >> $HGRCPATH
15 $ cat << EOF >> $HGRCPATH
16 > [format]
16 > [format]
17 > use-persistent-nodemap=yes
17 > use-persistent-nodemap=yes
18 > [devel]
18 > [devel]
19 > persistent-nodemap=yes
19 > persistent-nodemap=yes
20 > EOF
20 > EOF
21
21
22 #endif
22 #endif
23
23
24 $ hg init test-repo --config storage.revlog.persistent-nodemap.slow-path=allow
24 $ hg init test-repo --config storage.revlog.persistent-nodemap.slow-path=allow
25 $ cd test-repo
25 $ cd test-repo
26
26
27 Check handling of the default slow-path value
27 Check handling of the default slow-path value
28
28
29 #if no-pure no-rust
29 #if no-pure no-rust
30
30
31 $ hg id
31 $ hg id
32 abort: accessing `persistent-nodemap` repository without associated fast implementation.
32 abort: accessing `persistent-nodemap` repository without associated fast implementation.
33 (check `hg help config.format.use-persistent-nodemap` for details)
33 (check `hg help config.format.use-persistent-nodemap` for details)
34 [255]
34 [255]
35
35
36 Unlock further check (we are here to test the feature)
36 Unlock further check (we are here to test the feature)
37
37
38 $ cat << EOF >> $HGRCPATH
38 $ cat << EOF >> $HGRCPATH
39 > [storage]
39 > [storage]
40 > # to avoid spamming the test
40 > # to avoid spamming the test
41 > revlog.persistent-nodemap.slow-path=allow
41 > revlog.persistent-nodemap.slow-path=allow
42 > EOF
42 > EOF
43
43
44 #endif
44 #endif
45
45
46 #if rust
46 #if rust
47
47
48 Regression test for a previous bug in Rust/C FFI for the `Revlog_CAPI` capsule:
48 Regression test for a previous bug in Rust/C FFI for the `Revlog_CAPI` capsule:
49 in places where `mercurial/cext/revlog.c` function signatures use `Py_ssize_t`
49 in places where `mercurial/cext/revlog.c` function signatures use `Py_ssize_t`
50 (64 bits on Linux x86_64), corresponding declarations in `rust/hg-cpython/src/cindex.rs`
50 (64 bits on Linux x86_64), corresponding declarations in `rust/hg-cpython/src/cindex.rs`
51 incorrectly used `libc::c_int` (32 bits).
51 incorrectly used `libc::c_int` (32 bits).
52 As a result, -1 passed from Rust for the null revision became 4294967295 in C.
52 As a result, -1 passed from Rust for the null revision became 4294967295 in C.
53
53
54 $ hg log -r 00000000
54 $ hg log -r 00000000
55 changeset: -1:000000000000
55 changeset: -1:000000000000
56 tag: tip
56 tag: tip
57 user:
57 user:
58 date: Thu Jan 01 00:00:00 1970 +0000
58 date: Thu Jan 01 00:00:00 1970 +0000
59
59
60
60
61 #endif
61 #endif
62
62
63
63
64 $ hg debugformat
64 $ hg debugformat
65 format-variant repo
65 format-variant repo
66 fncache: yes
66 fncache: yes
67 dirstate-v2: no
67 dirstate-v2: no
68 dotencode: yes
68 dotencode: yes
69 generaldelta: yes
69 generaldelta: yes
70 share-safe: yes
70 share-safe: yes
71 sparserevlog: yes
71 sparserevlog: yes
72 persistent-nodemap: yes
72 persistent-nodemap: yes
73 copies-sdc: no
73 copies-sdc: no
74 revlog-v2: no
74 revlog-v2: no
75 changelog-v2: no
75 changelog-v2: no
76 plain-cl-delta: yes
76 plain-cl-delta: yes
77 compression: zlib (no-zstd !)
77 compression: zlib (no-zstd !)
78 compression: zstd (zstd !)
78 compression: zstd (zstd !)
79 compression-level: default
79 compression-level: default
80 $ hg debugbuilddag .+5000 --new-file
80 $ hg debugbuilddag .+5000 --new-file
81
81
82 $ hg debugnodemap --metadata
82 $ hg debugnodemap --metadata
83 uid: ???????? (glob)
83 uid: ???????? (glob)
84 tip-rev: 5000
84 tip-rev: 5000
85 tip-node: 6b02b8c7b96654c25e86ba69eda198d7e6ad8b3c
85 tip-node: 6b02b8c7b96654c25e86ba69eda198d7e6ad8b3c
86 data-length: 121088
86 data-length: 121088
87 data-unused: 0
87 data-unused: 0
88 data-unused: 0.000%
88 data-unused: 0.000%
89 $ f --size .hg/store/00changelog.n
89 $ f --size .hg/store/00changelog.n
90 .hg/store/00changelog.n: size=62
90 .hg/store/00changelog.n: size=62
91
91
92 Simple lookup works
92 Simple lookup works
93
93
94 $ ANYNODE=`hg log --template '{node|short}\n' --rev tip`
94 $ ANYNODE=`hg log --template '{node|short}\n' --rev tip`
95 $ hg log -r "$ANYNODE" --template '{rev}\n'
95 $ hg log -r "$ANYNODE" --template '{rev}\n'
96 5000
96 5000
97
97
98
98
99 #if rust
99 #if rust
100
100
101 $ f --sha256 .hg/store/00changelog-*.nd
101 $ f --sha256 .hg/store/00changelog-*.nd
102 .hg/store/00changelog-????????.nd: sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd (glob)
102 .hg/store/00changelog-????????.nd: sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd (glob)
103
103
104 $ f --sha256 .hg/store/00manifest-*.nd
104 $ f --sha256 .hg/store/00manifest-*.nd
105 .hg/store/00manifest-????????.nd: sha256=97117b1c064ea2f86664a124589e47db0e254e8d34739b5c5cc5bf31c9da2b51 (glob)
105 .hg/store/00manifest-????????.nd: sha256=97117b1c064ea2f86664a124589e47db0e254e8d34739b5c5cc5bf31c9da2b51 (glob)
106 $ hg debugnodemap --dump-new | f --sha256 --size
106 $ hg debugnodemap --dump-new | f --sha256 --size
107 size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd
107 size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd
108 $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
108 $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
109 size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd
109 size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd
110 0000: 00 00 00 91 00 00 00 20 00 00 00 bb 00 00 00 e7 |....... ........|
110 0000: 00 00 00 91 00 00 00 20 00 00 00 bb 00 00 00 e7 |....... ........|
111 0010: 00 00 00 66 00 00 00 a1 00 00 01 13 00 00 01 22 |...f..........."|
111 0010: 00 00 00 66 00 00 00 a1 00 00 01 13 00 00 01 22 |...f..........."|
112 0020: 00 00 00 23 00 00 00 fc 00 00 00 ba 00 00 00 5e |...#...........^|
112 0020: 00 00 00 23 00 00 00 fc 00 00 00 ba 00 00 00 5e |...#...........^|
113 0030: 00 00 00 df 00 00 01 4e 00 00 01 65 00 00 00 ab |.......N...e....|
113 0030: 00 00 00 df 00 00 01 4e 00 00 01 65 00 00 00 ab |.......N...e....|
114 0040: 00 00 00 a9 00 00 00 95 00 00 00 73 00 00 00 38 |...........s...8|
114 0040: 00 00 00 a9 00 00 00 95 00 00 00 73 00 00 00 38 |...........s...8|
115 0050: 00 00 00 cc 00 00 00 92 00 00 00 90 00 00 00 69 |...............i|
115 0050: 00 00 00 cc 00 00 00 92 00 00 00 90 00 00 00 69 |...............i|
116 0060: 00 00 00 ec 00 00 00 8d 00 00 01 4f 00 00 00 12 |...........O....|
116 0060: 00 00 00 ec 00 00 00 8d 00 00 01 4f 00 00 00 12 |...........O....|
117 0070: 00 00 02 0c 00 00 00 77 00 00 00 9c 00 00 00 8f |.......w........|
117 0070: 00 00 02 0c 00 00 00 77 00 00 00 9c 00 00 00 8f |.......w........|
118 0080: 00 00 00 d5 00 00 00 6b 00 00 00 48 00 00 00 b3 |.......k...H....|
118 0080: 00 00 00 d5 00 00 00 6b 00 00 00 48 00 00 00 b3 |.......k...H....|
119 0090: 00 00 00 e5 00 00 00 b5 00 00 00 8e 00 00 00 ad |................|
119 0090: 00 00 00 e5 00 00 00 b5 00 00 00 8e 00 00 00 ad |................|
120 00a0: 00 00 00 7b 00 00 00 7c 00 00 00 0b 00 00 00 2b |...{...|.......+|
120 00a0: 00 00 00 7b 00 00 00 7c 00 00 00 0b 00 00 00 2b |...{...|.......+|
121 00b0: 00 00 00 c6 00 00 00 1e 00 00 01 08 00 00 00 11 |................|
121 00b0: 00 00 00 c6 00 00 00 1e 00 00 01 08 00 00 00 11 |................|
122 00c0: 00 00 01 30 00 00 00 26 00 00 01 9c 00 00 00 35 |...0...&.......5|
122 00c0: 00 00 01 30 00 00 00 26 00 00 01 9c 00 00 00 35 |...0...&.......5|
123 00d0: 00 00 00 b8 00 00 01 31 00 00 00 2c 00 00 00 55 |.......1...,...U|
123 00d0: 00 00 00 b8 00 00 01 31 00 00 00 2c 00 00 00 55 |.......1...,...U|
124 00e0: 00 00 00 8a 00 00 00 9a 00 00 00 0c 00 00 01 1e |................|
124 00e0: 00 00 00 8a 00 00 00 9a 00 00 00 0c 00 00 01 1e |................|
125 00f0: 00 00 00 a4 00 00 00 83 00 00 00 c9 00 00 00 8c |................|
125 00f0: 00 00 00 a4 00 00 00 83 00 00 00 c9 00 00 00 8c |................|
126
126
127
127
128 #else
128 #else
129
129
130 $ f --sha256 .hg/store/00changelog-*.nd
130 $ f --sha256 .hg/store/00changelog-*.nd
131 .hg/store/00changelog-????????.nd: sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 (glob)
131 .hg/store/00changelog-????????.nd: sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 (glob)
132 $ hg debugnodemap --dump-new | f --sha256 --size
132 $ hg debugnodemap --dump-new | f --sha256 --size
133 size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79
133 size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79
134 $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
134 $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
135 size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79
135 size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79
136 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
136 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
137 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
137 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
138 0020: ff ff ff ff ff ff f5 06 ff ff ff ff ff ff f3 e7 |................|
138 0020: ff ff ff ff ff ff f5 06 ff ff ff ff ff ff f3 e7 |................|
139 0030: ff ff ef ca ff ff ff ff ff ff ff ff ff ff ff ff |................|
139 0030: ff ff ef ca ff ff ff ff ff ff ff ff ff ff ff ff |................|
140 0040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
140 0040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
141 0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ed 08 |................|
141 0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ed 08 |................|
142 0060: ff ff ed 66 ff ff ff ff ff ff ff ff ff ff ff ff |...f............|
142 0060: ff ff ed 66 ff ff ff ff ff ff ff ff ff ff ff ff |...f............|
143 0070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
143 0070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
144 0080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
144 0080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
145 0090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f6 ed |................|
145 0090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f6 ed |................|
146 00a0: ff ff ff ff ff ff fe 61 ff ff ff ff ff ff ff ff |.......a........|
146 00a0: ff ff ff ff ff ff fe 61 ff ff ff ff ff ff ff ff |.......a........|
147 00b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
147 00b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
148 00c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
148 00c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
149 00d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
149 00d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
150 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f1 02 |................|
150 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f1 02 |................|
151 00f0: ff ff ff ff ff ff ed 1b ff ff ff ff ff ff ff ff |................|
151 00f0: ff ff ff ff ff ff ed 1b ff ff ff ff ff ff ff ff |................|
152
152
153 #endif
153 #endif
154
154
155 $ hg debugnodemap --check
155 $ hg debugnodemap --check
156 revision in index: 5001
156 revision in index: 5001
157 revision in nodemap: 5001
157 revision in nodemap: 5001
158
158
159 add a new commit
159 add a new commit
160
160
161 $ hg up
161 $ hg up
162 5001 files updated, 0 files merged, 0 files removed, 0 files unresolved
162 5001 files updated, 0 files merged, 0 files removed, 0 files unresolved
163 $ echo foo > foo
163 $ echo foo > foo
164 $ hg add foo
164 $ hg add foo
165
165
166
166
167 Check slow-path config value handling
167 Check slow-path config value handling
168 -------------------------------------
168 -------------------------------------
169
169
170 #if no-pure no-rust
170 #if no-pure no-rust
171
171
172 $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value"
172 $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value"
173 unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value"
173 unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value"
174 falling back to default value: abort
174 falling back to default value: abort
175 abort: accessing `persistent-nodemap` repository without associated fast implementation.
175 abort: accessing `persistent-nodemap` repository without associated fast implementation.
176 (check `hg help config.format.use-persistent-nodemap` for details)
176 (check `hg help config.format.use-persistent-nodemap` for details)
177 [255]
177 [255]
178
178
179 $ hg log -r . --config "storage.revlog.persistent-nodemap.slow-path=warn"
179 $ hg log -r . --config "storage.revlog.persistent-nodemap.slow-path=warn"
180 warning: accessing `persistent-nodemap` repository without associated fast implementation.
180 warning: accessing `persistent-nodemap` repository without associated fast implementation.
181 (check `hg help config.format.use-persistent-nodemap` for details)
181 (check `hg help config.format.use-persistent-nodemap` for details)
182 changeset: 5000:6b02b8c7b966
182 changeset: 5000:6b02b8c7b966
183 tag: tip
183 tag: tip
184 user: debugbuilddag
184 user: debugbuilddag
185 date: Thu Jan 01 01:23:20 1970 +0000
185 date: Thu Jan 01 01:23:20 1970 +0000
186 summary: r5000
186 summary: r5000
187
187
188 $ hg ci -m 'foo' --config "storage.revlog.persistent-nodemap.slow-path=abort"
188 $ hg ci -m 'foo' --config "storage.revlog.persistent-nodemap.slow-path=abort"
189 abort: accessing `persistent-nodemap` repository without associated fast implementation.
189 abort: accessing `persistent-nodemap` repository without associated fast implementation.
190 (check `hg help config.format.use-persistent-nodemap` for details)
190 (check `hg help config.format.use-persistent-nodemap` for details)
191 [255]
191 [255]
192
192
193 #else
193 #else
194
194
195 $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value"
195 $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value"
196 unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value"
196 unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value"
197 falling back to default value: abort
197 falling back to default value: abort
198 6b02b8c7b966+ tip
198 6b02b8c7b966+ tip
199
199
200 #endif
200 #endif
201
201
202 $ hg ci -m 'foo'
202 $ hg ci -m 'foo'
203
203
204 #if no-pure no-rust
204 #if no-pure no-rust
205 $ hg debugnodemap --metadata
205 $ hg debugnodemap --metadata
206 uid: ???????? (glob)
206 uid: ???????? (glob)
207 tip-rev: 5001
207 tip-rev: 5001
208 tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c
208 tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c
209 data-length: 121088
209 data-length: 121088
210 data-unused: 0
210 data-unused: 0
211 data-unused: 0.000%
211 data-unused: 0.000%
212 #else
212 #else
213 $ hg debugnodemap --metadata
213 $ hg debugnodemap --metadata
214 uid: ???????? (glob)
214 uid: ???????? (glob)
215 tip-rev: 5001
215 tip-rev: 5001
216 tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c
216 tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c
217 data-length: 121344
217 data-length: 121344
218 data-unused: 256
218 data-unused: 256
219 data-unused: 0.211%
219 data-unused: 0.211%
220 #endif
220 #endif
221
221
222 $ f --size .hg/store/00changelog.n
222 $ f --size .hg/store/00changelog.n
223 .hg/store/00changelog.n: size=62
223 .hg/store/00changelog.n: size=62
224
224
225 (The pure code use the debug code that perform incremental update, the C code reencode from scratch)
225 (The pure code use the debug code that perform incremental update, the C code reencode from scratch)
226
226
227 #if pure
227 #if pure
228 $ f --sha256 .hg/store/00changelog-*.nd --size
228 $ f --sha256 .hg/store/00changelog-*.nd --size
229 .hg/store/00changelog-????????.nd: size=121344, sha256=cce54c5da5bde3ad72a4938673ed4064c86231b9c64376b082b163fdb20f8f66 (glob)
229 .hg/store/00changelog-????????.nd: size=121344, sha256=cce54c5da5bde3ad72a4938673ed4064c86231b9c64376b082b163fdb20f8f66 (glob)
230 #endif
230 #endif
231
231
232 #if rust
232 #if rust
233 $ f --sha256 .hg/store/00changelog-*.nd --size
233 $ f --sha256 .hg/store/00changelog-*.nd --size
234 .hg/store/00changelog-????????.nd: size=121344, sha256=952b042fcf614ceb37b542b1b723e04f18f83efe99bee4e0f5ccd232ef470e58 (glob)
234 .hg/store/00changelog-????????.nd: size=121344, sha256=952b042fcf614ceb37b542b1b723e04f18f83efe99bee4e0f5ccd232ef470e58 (glob)
235 #endif
235 #endif
236
236
237 #if no-pure no-rust
237 #if no-pure no-rust
238 $ f --sha256 .hg/store/00changelog-*.nd --size
238 $ f --sha256 .hg/store/00changelog-*.nd --size
239 .hg/store/00changelog-????????.nd: size=121088, sha256=df7c06a035b96cb28c7287d349d603baef43240be7736fe34eea419a49702e17 (glob)
239 .hg/store/00changelog-????????.nd: size=121088, sha256=df7c06a035b96cb28c7287d349d603baef43240be7736fe34eea419a49702e17 (glob)
240 #endif
240 #endif
241
241
242 $ hg debugnodemap --check
242 $ hg debugnodemap --check
243 revision in index: 5002
243 revision in index: 5002
244 revision in nodemap: 5002
244 revision in nodemap: 5002
245
245
246 Test code path without mmap
246 Test code path without mmap
247 ---------------------------
247 ---------------------------
248
248
249 $ echo bar > bar
249 $ echo bar > bar
250 $ hg add bar
250 $ hg add bar
251 $ hg ci -m 'bar' --config storage.revlog.persistent-nodemap.mmap=no
251 $ hg ci -m 'bar' --config storage.revlog.persistent-nodemap.mmap=no
252
252
253 $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=yes
253 $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=yes
254 revision in index: 5003
254 revision in index: 5003
255 revision in nodemap: 5003
255 revision in nodemap: 5003
256 $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=no
256 $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=no
257 revision in index: 5003
257 revision in index: 5003
258 revision in nodemap: 5003
258 revision in nodemap: 5003
259
259
260
260
261 #if pure
261 #if pure
262 $ hg debugnodemap --metadata
262 $ hg debugnodemap --metadata
263 uid: ???????? (glob)
263 uid: ???????? (glob)
264 tip-rev: 5002
264 tip-rev: 5002
265 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
265 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
266 data-length: 121600
266 data-length: 121600
267 data-unused: 512
267 data-unused: 512
268 data-unused: 0.421%
268 data-unused: 0.421%
269 $ f --sha256 .hg/store/00changelog-*.nd --size
269 $ f --sha256 .hg/store/00changelog-*.nd --size
270 .hg/store/00changelog-????????.nd: size=121600, sha256=def52503d049ccb823974af313a98a935319ba61f40f3aa06a8be4d35c215054 (glob)
270 .hg/store/00changelog-????????.nd: size=121600, sha256=def52503d049ccb823974af313a98a935319ba61f40f3aa06a8be4d35c215054 (glob)
271 #endif
271 #endif
272 #if rust
272 #if rust
273 $ hg debugnodemap --metadata
273 $ hg debugnodemap --metadata
274 uid: ???????? (glob)
274 uid: ???????? (glob)
275 tip-rev: 5002
275 tip-rev: 5002
276 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
276 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
277 data-length: 121600
277 data-length: 121600
278 data-unused: 512
278 data-unused: 512
279 data-unused: 0.421%
279 data-unused: 0.421%
280 $ f --sha256 .hg/store/00changelog-*.nd --size
280 $ f --sha256 .hg/store/00changelog-*.nd --size
281 .hg/store/00changelog-????????.nd: size=121600, sha256=dacf5b5f1d4585fee7527d0e67cad5b1ba0930e6a0928f650f779aefb04ce3fb (glob)
281 .hg/store/00changelog-????????.nd: size=121600, sha256=dacf5b5f1d4585fee7527d0e67cad5b1ba0930e6a0928f650f779aefb04ce3fb (glob)
282 #endif
282 #endif
283 #if no-pure no-rust
283 #if no-pure no-rust
284 $ hg debugnodemap --metadata
284 $ hg debugnodemap --metadata
285 uid: ???????? (glob)
285 uid: ???????? (glob)
286 tip-rev: 5002
286 tip-rev: 5002
287 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
287 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
288 data-length: 121088
288 data-length: 121088
289 data-unused: 0
289 data-unused: 0
290 data-unused: 0.000%
290 data-unused: 0.000%
291 $ f --sha256 .hg/store/00changelog-*.nd --size
291 $ f --sha256 .hg/store/00changelog-*.nd --size
292 .hg/store/00changelog-????????.nd: size=121088, sha256=59fcede3e3cc587755916ceed29e3c33748cd1aa7d2f91828ac83e7979d935e8 (glob)
292 .hg/store/00changelog-????????.nd: size=121088, sha256=59fcede3e3cc587755916ceed29e3c33748cd1aa7d2f91828ac83e7979d935e8 (glob)
293 #endif
293 #endif
294
294
295 Test force warming the cache
295 Test force warming the cache
296
296
297 $ rm .hg/store/00changelog.n
297 $ rm .hg/store/00changelog.n
298 $ hg debugnodemap --metadata
298 $ hg debugnodemap --metadata
299 $ hg debugupdatecache
299 $ hg debugupdatecache
300 #if pure
300 #if pure
301 $ hg debugnodemap --metadata
301 $ hg debugnodemap --metadata
302 uid: ???????? (glob)
302 uid: ???????? (glob)
303 tip-rev: 5002
303 tip-rev: 5002
304 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
304 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
305 data-length: 121088
305 data-length: 121088
306 data-unused: 0
306 data-unused: 0
307 data-unused: 0.000%
307 data-unused: 0.000%
308 #else
308 #else
309 $ hg debugnodemap --metadata
309 $ hg debugnodemap --metadata
310 uid: ???????? (glob)
310 uid: ???????? (glob)
311 tip-rev: 5002
311 tip-rev: 5002
312 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
312 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
313 data-length: 121088
313 data-length: 121088
314 data-unused: 0
314 data-unused: 0
315 data-unused: 0.000%
315 data-unused: 0.000%
316 #endif
316 #endif
317
317
318 Check out of sync nodemap
318 Check out of sync nodemap
319 =========================
319 =========================
320
320
321 First copy old data on the side.
321 First copy old data on the side.
322
322
323 $ mkdir ../tmp-copies
323 $ mkdir ../tmp-copies
324 $ cp .hg/store/00changelog-????????.nd .hg/store/00changelog.n ../tmp-copies
324 $ cp .hg/store/00changelog-????????.nd .hg/store/00changelog.n ../tmp-copies
325
325
326 Nodemap lagging behind
326 Nodemap lagging behind
327 ----------------------
327 ----------------------
328
328
329 make a new commit
329 make a new commit
330
330
331 $ echo bar2 > bar
331 $ echo bar2 > bar
332 $ hg ci -m 'bar2'
332 $ hg ci -m 'bar2'
333 $ NODE=`hg log -r tip -T '{node}\n'`
333 $ NODE=`hg log -r tip -T '{node}\n'`
334 $ hg log -r "$NODE" -T '{rev}\n'
334 $ hg log -r "$NODE" -T '{rev}\n'
335 5003
335 5003
336
336
337 If the nodemap is lagging behind, it can catch up fine
337 If the nodemap is lagging behind, it can catch up fine
338
338
339 $ hg debugnodemap --metadata
339 $ hg debugnodemap --metadata
340 uid: ???????? (glob)
340 uid: ???????? (glob)
341 tip-rev: 5003
341 tip-rev: 5003
342 tip-node: c9329770f979ade2d16912267c38ba5f82fd37b3
342 tip-node: c9329770f979ade2d16912267c38ba5f82fd37b3
343 data-length: 121344 (pure !)
343 data-length: 121344 (pure !)
344 data-length: 121344 (rust !)
344 data-length: 121344 (rust !)
345 data-length: 121152 (no-rust no-pure !)
345 data-length: 121152 (no-rust no-pure !)
346 data-unused: 192 (pure !)
346 data-unused: 192 (pure !)
347 data-unused: 192 (rust !)
347 data-unused: 192 (rust !)
348 data-unused: 0 (no-rust no-pure !)
348 data-unused: 0 (no-rust no-pure !)
349 data-unused: 0.158% (pure !)
349 data-unused: 0.158% (pure !)
350 data-unused: 0.158% (rust !)
350 data-unused: 0.158% (rust !)
351 data-unused: 0.000% (no-rust no-pure !)
351 data-unused: 0.000% (no-rust no-pure !)
352 $ cp -f ../tmp-copies/* .hg/store/
352 $ cp -f ../tmp-copies/* .hg/store/
353 $ hg debugnodemap --metadata
353 $ hg debugnodemap --metadata
354 uid: ???????? (glob)
354 uid: ???????? (glob)
355 tip-rev: 5002
355 tip-rev: 5002
356 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
356 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
357 data-length: 121088
357 data-length: 121088
358 data-unused: 0
358 data-unused: 0
359 data-unused: 0.000%
359 data-unused: 0.000%
360 $ hg log -r "$NODE" -T '{rev}\n'
360 $ hg log -r "$NODE" -T '{rev}\n'
361 5003
361 5003
362
362
363 changelog altered
363 changelog altered
364 -----------------
364 -----------------
365
365
366 If the nodemap is not gated behind a requirements, an unaware client can alter
366 If the nodemap is not gated behind a requirements, an unaware client can alter
367 the repository so the revlog used to generate the nodemap is not longer
367 the repository so the revlog used to generate the nodemap is not longer
368 compatible with the persistent nodemap. We need to detect that.
368 compatible with the persistent nodemap. We need to detect that.
369
369
370 $ hg up "$NODE~5"
370 $ hg up "$NODE~5"
371 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
371 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
372 $ echo bar > babar
372 $ echo bar > babar
373 $ hg add babar
373 $ hg add babar
374 $ hg ci -m 'babar'
374 $ hg ci -m 'babar'
375 created new head
375 created new head
376 $ OTHERNODE=`hg log -r tip -T '{node}\n'`
376 $ OTHERNODE=`hg log -r tip -T '{node}\n'`
377 $ hg log -r "$OTHERNODE" -T '{rev}\n'
377 $ hg log -r "$OTHERNODE" -T '{rev}\n'
378 5004
378 5004
379
379
380 $ hg --config extensions.strip= strip --rev "$NODE~1" --no-backup
380 $ hg --config extensions.strip= strip --rev "$NODE~1" --no-backup
381
381
382 the nodemap should detect the changelog have been tampered with and recover.
382 the nodemap should detect the changelog have been tampered with and recover.
383
383
384 $ hg debugnodemap --metadata
384 $ hg debugnodemap --metadata
385 uid: ???????? (glob)
385 uid: ???????? (glob)
386 tip-rev: 5002
386 tip-rev: 5002
387 tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944
387 tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944
388 data-length: 121536 (pure !)
388 data-length: 121536 (pure !)
389 data-length: 121088 (rust !)
389 data-length: 121088 (rust !)
390 data-length: 121088 (no-pure no-rust !)
390 data-length: 121088 (no-pure no-rust !)
391 data-unused: 448 (pure !)
391 data-unused: 448 (pure !)
392 data-unused: 0 (rust !)
392 data-unused: 0 (rust !)
393 data-unused: 0 (no-pure no-rust !)
393 data-unused: 0 (no-pure no-rust !)
394 data-unused: 0.000% (rust !)
394 data-unused: 0.000% (rust !)
395 data-unused: 0.369% (pure !)
395 data-unused: 0.369% (pure !)
396 data-unused: 0.000% (no-pure no-rust !)
396 data-unused: 0.000% (no-pure no-rust !)
397
397
398 $ cp -f ../tmp-copies/* .hg/store/
398 $ cp -f ../tmp-copies/* .hg/store/
399 $ hg debugnodemap --metadata
399 $ hg debugnodemap --metadata
400 uid: ???????? (glob)
400 uid: ???????? (glob)
401 tip-rev: 5002
401 tip-rev: 5002
402 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
402 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
403 data-length: 121088
403 data-length: 121088
404 data-unused: 0
404 data-unused: 0
405 data-unused: 0.000%
405 data-unused: 0.000%
406 $ hg log -r "$OTHERNODE" -T '{rev}\n'
406 $ hg log -r "$OTHERNODE" -T '{rev}\n'
407 5002
407 5002
408
408
409 missing data file
409 missing data file
410 -----------------
410 -----------------
411
411
412 $ UUID=`hg debugnodemap --metadata| grep 'uid:' | \
412 $ UUID=`hg debugnodemap --metadata| grep 'uid:' | \
413 > sed 's/uid: //'`
413 > sed 's/uid: //'`
414 $ FILE=.hg/store/00changelog-"${UUID}".nd
414 $ FILE=.hg/store/00changelog-"${UUID}".nd
415 $ mv $FILE ../tmp-data-file
415 $ mv $FILE ../tmp-data-file
416 $ cp .hg/store/00changelog.n ../tmp-docket
416 $ cp .hg/store/00changelog.n ../tmp-docket
417
417
418 mercurial don't crash
418 mercurial don't crash
419
419
420 $ hg log -r .
420 $ hg log -r .
421 changeset: 5002:b355ef8adce0
421 changeset: 5002:b355ef8adce0
422 tag: tip
422 tag: tip
423 parent: 4998:d918ad6d18d3
423 parent: 4998:d918ad6d18d3
424 user: test
424 user: test
425 date: Thu Jan 01 00:00:00 1970 +0000
425 date: Thu Jan 01 00:00:00 1970 +0000
426 summary: babar
426 summary: babar
427
427
428 $ hg debugnodemap --metadata
428 $ hg debugnodemap --metadata
429
429
430 $ hg debugupdatecache
430 $ hg debugupdatecache
431 $ hg debugnodemap --metadata
431 $ hg debugnodemap --metadata
432 uid: * (glob)
432 uid: * (glob)
433 tip-rev: 5002
433 tip-rev: 5002
434 tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944
434 tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944
435 data-length: 121088
435 data-length: 121088
436 data-unused: 0
436 data-unused: 0
437 data-unused: 0.000%
437 data-unused: 0.000%
438 $ mv ../tmp-data-file $FILE
438 $ mv ../tmp-data-file $FILE
439 $ mv ../tmp-docket .hg/store/00changelog.n
439 $ mv ../tmp-docket .hg/store/00changelog.n
440
440
441 Check transaction related property
441 Check transaction related property
442 ==================================
442 ==================================
443
443
444 An up to date nodemap should be available to shell hooks,
444 An up to date nodemap should be available to shell hooks,
445
445
446 $ echo dsljfl > a
446 $ echo dsljfl > a
447 $ hg add a
447 $ hg add a
448 $ hg ci -m a
448 $ hg ci -m a
449 $ hg debugnodemap --metadata
449 $ hg debugnodemap --metadata
450 uid: ???????? (glob)
450 uid: ???????? (glob)
451 tip-rev: 5003
451 tip-rev: 5003
452 tip-node: a52c5079765b5865d97b993b303a18740113bbb2
452 tip-node: a52c5079765b5865d97b993b303a18740113bbb2
453 data-length: 121088
453 data-length: 121088
454 data-unused: 0
454 data-unused: 0
455 data-unused: 0.000%
455 data-unused: 0.000%
456 $ echo babar2 > babar
456 $ echo babar2 > babar
457 $ hg ci -m 'babar2' --config "hooks.pretxnclose.nodemap-test=hg debugnodemap --metadata"
457 $ hg ci -m 'babar2' --config "hooks.pretxnclose.nodemap-test=hg debugnodemap --metadata"
458 uid: ???????? (glob)
458 uid: ???????? (glob)
459 tip-rev: 5004
459 tip-rev: 5004
460 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
460 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
461 data-length: 121280 (pure !)
461 data-length: 121280 (pure !)
462 data-length: 121280 (rust !)
462 data-length: 121280 (rust !)
463 data-length: 121088 (no-pure no-rust !)
463 data-length: 121088 (no-pure no-rust !)
464 data-unused: 192 (pure !)
464 data-unused: 192 (pure !)
465 data-unused: 192 (rust !)
465 data-unused: 192 (rust !)
466 data-unused: 0 (no-pure no-rust !)
466 data-unused: 0 (no-pure no-rust !)
467 data-unused: 0.158% (pure !)
467 data-unused: 0.158% (pure !)
468 data-unused: 0.158% (rust !)
468 data-unused: 0.158% (rust !)
469 data-unused: 0.000% (no-pure no-rust !)
469 data-unused: 0.000% (no-pure no-rust !)
470 $ hg debugnodemap --metadata
470 $ hg debugnodemap --metadata
471 uid: ???????? (glob)
471 uid: ???????? (glob)
472 tip-rev: 5004
472 tip-rev: 5004
473 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
473 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
474 data-length: 121280 (pure !)
474 data-length: 121280 (pure !)
475 data-length: 121280 (rust !)
475 data-length: 121280 (rust !)
476 data-length: 121088 (no-pure no-rust !)
476 data-length: 121088 (no-pure no-rust !)
477 data-unused: 192 (pure !)
477 data-unused: 192 (pure !)
478 data-unused: 192 (rust !)
478 data-unused: 192 (rust !)
479 data-unused: 0 (no-pure no-rust !)
479 data-unused: 0 (no-pure no-rust !)
480 data-unused: 0.158% (pure !)
480 data-unused: 0.158% (pure !)
481 data-unused: 0.158% (rust !)
481 data-unused: 0.158% (rust !)
482 data-unused: 0.000% (no-pure no-rust !)
482 data-unused: 0.000% (no-pure no-rust !)
483
483
484 Another process does not see the pending nodemap content during run.
484 Another process does not see the pending nodemap content during run.
485
485
486 $ echo qpoasp > a
486 $ echo qpoasp > a
487 $ hg ci -m a2 \
487 $ hg ci -m a2 \
488 > --config "hooks.pretxnclose=sh \"$RUNTESTDIR/testlib/wait-on-file\" 20 sync-repo-read sync-txn-pending" \
488 > --config "hooks.pretxnclose=sh \"$RUNTESTDIR/testlib/wait-on-file\" 20 sync-repo-read sync-txn-pending" \
489 > --config "hooks.txnclose=touch sync-txn-close" > output.txt 2>&1 &
489 > --config "hooks.txnclose=touch sync-txn-close" > output.txt 2>&1 &
490
490
491 (read the repository while the commit transaction is pending)
491 (read the repository while the commit transaction is pending)
492
492
493 $ sh "$RUNTESTDIR/testlib/wait-on-file" 20 sync-txn-pending && \
493 $ sh "$RUNTESTDIR/testlib/wait-on-file" 20 sync-txn-pending && \
494 > hg debugnodemap --metadata && \
494 > hg debugnodemap --metadata && \
495 > sh "$RUNTESTDIR/testlib/wait-on-file" 20 sync-txn-close sync-repo-read
495 > sh "$RUNTESTDIR/testlib/wait-on-file" 20 sync-txn-close sync-repo-read
496 uid: ???????? (glob)
496 uid: ???????? (glob)
497 tip-rev: 5004
497 tip-rev: 5004
498 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
498 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
499 data-length: 121280 (pure !)
499 data-length: 121280 (pure !)
500 data-length: 121280 (rust !)
500 data-length: 121280 (rust !)
501 data-length: 121088 (no-pure no-rust !)
501 data-length: 121088 (no-pure no-rust !)
502 data-unused: 192 (pure !)
502 data-unused: 192 (pure !)
503 data-unused: 192 (rust !)
503 data-unused: 192 (rust !)
504 data-unused: 0 (no-pure no-rust !)
504 data-unused: 0 (no-pure no-rust !)
505 data-unused: 0.158% (pure !)
505 data-unused: 0.158% (pure !)
506 data-unused: 0.158% (rust !)
506 data-unused: 0.158% (rust !)
507 data-unused: 0.000% (no-pure no-rust !)
507 data-unused: 0.000% (no-pure no-rust !)
508 $ hg debugnodemap --metadata
508 $ hg debugnodemap --metadata
509 uid: ???????? (glob)
509 uid: ???????? (glob)
510 tip-rev: 5005
510 tip-rev: 5005
511 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
511 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
512 data-length: 121536 (pure !)
512 data-length: 121536 (pure !)
513 data-length: 121536 (rust !)
513 data-length: 121536 (rust !)
514 data-length: 121088 (no-pure no-rust !)
514 data-length: 121088 (no-pure no-rust !)
515 data-unused: 448 (pure !)
515 data-unused: 448 (pure !)
516 data-unused: 448 (rust !)
516 data-unused: 448 (rust !)
517 data-unused: 0 (no-pure no-rust !)
517 data-unused: 0 (no-pure no-rust !)
518 data-unused: 0.369% (pure !)
518 data-unused: 0.369% (pure !)
519 data-unused: 0.369% (rust !)
519 data-unused: 0.369% (rust !)
520 data-unused: 0.000% (no-pure no-rust !)
520 data-unused: 0.000% (no-pure no-rust !)
521
521
522 $ cat output.txt
522 $ cat output.txt
523
523
524 Check that a failing transaction will properly revert the data
524 Check that a failing transaction will properly revert the data
525
525
526 $ echo plakfe > a
526 $ echo plakfe > a
527 $ f --size --sha256 .hg/store/00changelog-*.nd
527 $ f --size --sha256 .hg/store/00changelog-*.nd
528 .hg/store/00changelog-????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
528 .hg/store/00changelog-????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
529 .hg/store/00changelog-????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
529 .hg/store/00changelog-????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
530 .hg/store/00changelog-????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !)
530 .hg/store/00changelog-????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !)
531 $ hg ci -m a3 --config "extensions.abort=$RUNTESTDIR/testlib/crash_transaction_late.py"
531 $ hg ci -m a3 --config "extensions.abort=$RUNTESTDIR/testlib/crash_transaction_late.py"
532 transaction abort!
532 transaction abort!
533 rollback completed
533 rollback completed
534 abort: This is a late abort
534 abort: This is a late abort
535 [255]
535 [255]
536 $ hg debugnodemap --metadata
536 $ hg debugnodemap --metadata
537 uid: ???????? (glob)
537 uid: ???????? (glob)
538 tip-rev: 5005
538 tip-rev: 5005
539 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
539 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
540 data-length: 121536 (pure !)
540 data-length: 121536 (pure !)
541 data-length: 121536 (rust !)
541 data-length: 121536 (rust !)
542 data-length: 121088 (no-pure no-rust !)
542 data-length: 121088 (no-pure no-rust !)
543 data-unused: 448 (pure !)
543 data-unused: 448 (pure !)
544 data-unused: 448 (rust !)
544 data-unused: 448 (rust !)
545 data-unused: 0 (no-pure no-rust !)
545 data-unused: 0 (no-pure no-rust !)
546 data-unused: 0.369% (pure !)
546 data-unused: 0.369% (pure !)
547 data-unused: 0.369% (rust !)
547 data-unused: 0.369% (rust !)
548 data-unused: 0.000% (no-pure no-rust !)
548 data-unused: 0.000% (no-pure no-rust !)
549 $ f --size --sha256 .hg/store/00changelog-*.nd
549 $ f --size --sha256 .hg/store/00changelog-*.nd
550 .hg/store/00changelog-????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
550 .hg/store/00changelog-????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
551 .hg/store/00changelog-????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
551 .hg/store/00changelog-????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
552 .hg/store/00changelog-????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !)
552 .hg/store/00changelog-????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !)
553
553
554 Check that removing content does not confuse the nodemap
554 Check that removing content does not confuse the nodemap
555 --------------------------------------------------------
555 --------------------------------------------------------
556
556
557 removing data with rollback
557 removing data with rollback
558
558
559 $ echo aso > a
559 $ echo aso > a
560 $ hg ci -m a4
560 $ hg ci -m a4
561 $ hg rollback
561 $ hg rollback
562 repository tip rolled back to revision 5005 (undo commit)
562 repository tip rolled back to revision 5005 (undo commit)
563 working directory now based on revision 5005
563 working directory now based on revision 5005
564 $ hg id -r .
564 $ hg id -r .
565 90d5d3ba2fc4 tip
565 90d5d3ba2fc4 tip
566
566
567 removing data with strip
567 removing data with strip
568
568
569 $ echo aso > a
569 $ echo aso > a
570 $ hg ci -m a4
570 $ hg ci -m a4
571 $ hg --config extensions.strip= strip -r . --no-backup
571 $ hg --config extensions.strip= strip -r . --no-backup
572 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
572 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
573 $ hg id -r . --traceback
573 $ hg id -r . --traceback
574 90d5d3ba2fc4 tip
574 90d5d3ba2fc4 tip
575
575
576 (be a good citizen and regenerate the nodemap)
576 (be a good citizen and regenerate the nodemap)
577 $ hg debugupdatecaches
577 $ hg debugupdatecaches
578 $ hg debugnodemap --metadata
578 $ hg debugnodemap --metadata
579 uid: * (glob)
579 uid: * (glob)
580 tip-rev: 5005
580 tip-rev: 5005
581 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
581 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
582 data-length: 121088
582 data-length: 121088
583 data-unused: 0
583 data-unused: 0
584 data-unused: 0.000%
584 data-unused: 0.000%
585
585
586 Check race condition when multiple process write new data to the repository
586 Check race condition when multiple process write new data to the repository
587 ---------------------------------------------------------------------------
587 ---------------------------------------------------------------------------
588
588
589 In this test, we check that two writers touching the repositories will not
589 In this test, we check that two writers touching the repositories will not
590 overwrite each other data. This test is prompted by the existent of issue6554.
590 overwrite each other data. This test is prompted by the existent of issue6554.
591 Where a writer ended up using and outdated docket to update the repository. See
591 Where a writer ended up using and outdated docket to update the repository. See
592 the dedicated extension for details on the race windows and read/write schedule
592 the dedicated extension for details on the race windows and read/write schedule
593 necessary to end up in this situation: testlib/persistent-nodemap-race-ext.py
593 necessary to end up in this situation: testlib/persistent-nodemap-race-ext.py
594
594
595 The issue was initially observed on a server with a high push trafic, but it
595 The issue was initially observed on a server with a high push trafic, but it
596 can be reproduced using a share and two commiting process which seems simpler.
596 can be reproduced using a share and two commiting process which seems simpler.
597
597
598 The test is Rust only as the other implementation does not use the same
598 The test is Rust only as the other implementation does not use the same
599 read/write patterns.
599 read/write patterns.
600
600
601 $ cd ..
601 $ cd ..
602
602
603 #if rust
603 #if rust
604
604
605 $ cp -R test-repo race-repo
605 $ cp -R test-repo race-repo
606 $ hg share race-repo ./other-wc --config format.use-share-safe=yes
606 $ hg share race-repo ./other-wc --config format.use-share-safe=yes
607 updating working directory
607 updating working directory
608 5001 files updated, 0 files merged, 0 files removed, 0 files unresolved
608 5001 files updated, 0 files merged, 0 files removed, 0 files unresolved
609 $ hg debugformat -R ./race-repo | egrep 'share-safe|persistent-nodemap'
609 $ hg debugformat -R ./race-repo | egrep 'share-safe|persistent-nodemap'
610 share-safe: yes
610 share-safe: yes
611 persistent-nodemap: yes
611 persistent-nodemap: yes
612 $ hg debugformat -R ./other-wc/ | egrep 'share-safe|persistent-nodemap'
612 $ hg debugformat -R ./other-wc/ | egrep 'share-safe|persistent-nodemap'
613 share-safe: yes
613 share-safe: yes
614 persistent-nodemap: yes
614 persistent-nodemap: yes
615 $ hg -R ./other-wc update 'min(head())'
615 $ hg -R ./other-wc update 'min(head())'
616 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
616 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
617 $ hg -R ./race-repo debugnodemap --metadata
617 $ hg -R ./race-repo debugnodemap --metadata
618 uid: 43c37dde
618 uid: 43c37dde
619 tip-rev: 5005
619 tip-rev: 5005
620 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
620 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
621 data-length: 121088
621 data-length: 121088
622 data-unused: 0
622 data-unused: 0
623 data-unused: 0.000%
623 data-unused: 0.000%
624 $ hg -R ./race-repo log -G -r 'head()'
624 $ hg -R ./race-repo log -G -r 'head()'
625 @ changeset: 5005:90d5d3ba2fc4
625 @ changeset: 5005:90d5d3ba2fc4
626 | tag: tip
626 | tag: tip
627 ~ user: test
627 ~ user: test
628 date: Thu Jan 01 00:00:00 1970 +0000
628 date: Thu Jan 01 00:00:00 1970 +0000
629 summary: a2
629 summary: a2
630
630
631 o changeset: 5001:16395c3cf7e2
631 o changeset: 5001:16395c3cf7e2
632 | user: test
632 | user: test
633 ~ date: Thu Jan 01 00:00:00 1970 +0000
633 ~ date: Thu Jan 01 00:00:00 1970 +0000
634 summary: foo
634 summary: foo
635
635
636 $ hg -R ./other-wc log -G -r 'head()'
636 $ hg -R ./other-wc log -G -r 'head()'
637 o changeset: 5005:90d5d3ba2fc4
637 o changeset: 5005:90d5d3ba2fc4
638 | tag: tip
638 | tag: tip
639 ~ user: test
639 ~ user: test
640 date: Thu Jan 01 00:00:00 1970 +0000
640 date: Thu Jan 01 00:00:00 1970 +0000
641 summary: a2
641 summary: a2
642
642
643 @ changeset: 5001:16395c3cf7e2
643 @ changeset: 5001:16395c3cf7e2
644 | user: test
644 | user: test
645 ~ date: Thu Jan 01 00:00:00 1970 +0000
645 ~ date: Thu Jan 01 00:00:00 1970 +0000
646 summary: foo
646 summary: foo
647
647
648 $ echo left-side-race > race-repo/left-side-race
648 $ echo left-side-race > race-repo/left-side-race
649 $ hg -R ./race-repo/ add race-repo/left-side-race
649 $ hg -R ./race-repo/ add race-repo/left-side-race
650
650
651 $ echo right-side-race > ./other-wc/right-side-race
651 $ echo right-side-race > ./other-wc/right-side-race
652 $ hg -R ./other-wc/ add ./other-wc/right-side-race
652 $ hg -R ./other-wc/ add ./other-wc/right-side-race
653
653
654 $ mkdir sync-files
654 $ mkdir sync-files
655 $ mkdir outputs
655 $ mkdir outputs
656 $ (
656 $ (
657 > hg -R ./race-repo/ commit -m left-side-commit \
657 > hg -R ./race-repo/ commit -m left-side-commit \
658 > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \
658 > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \
659 > --config 'devel.nodemap-race.role=left';
659 > --config 'devel.nodemap-race.role=left';
660 > touch sync-files/left-done
660 > touch sync-files/left-done
661 > ) > outputs/left.txt 2>&1 &
661 > ) > outputs/left.txt 2>&1 &
662 $ (
662 $ (
663 > hg -R ./other-wc/ commit -m right-side-commit \
663 > hg -R ./other-wc/ commit -m right-side-commit \
664 > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \
664 > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \
665 > --config 'devel.nodemap-race.role=right';
665 > --config 'devel.nodemap-race.role=right';
666 > touch sync-files/right-done
666 > touch sync-files/right-done
667 > ) > outputs/right.txt 2>&1 &
667 > ) > outputs/right.txt 2>&1 &
668 $ (
668 $ (
669 > hg -R ./race-repo/ check-nodemap-race \
669 > hg -R ./race-repo/ check-nodemap-race \
670 > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \
670 > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \
671 > --config 'devel.nodemap-race.role=reader';
671 > --config 'devel.nodemap-race.role=reader';
672 > touch sync-files/reader-done
672 > touch sync-files/reader-done
673 > ) > outputs/reader.txt 2>&1 &
673 > ) > outputs/reader.txt 2>&1 &
674 $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/left-done
674 $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/left-done
675 $ cat outputs/left.txt
675 $ cat outputs/left.txt
676 docket-details:
676 docket-details:
677 uid: 43c37dde
677 uid: 43c37dde
678 actual-tip: 5005
678 actual-tip: 5005
679 tip-rev: 5005
679 tip-rev: 5005
680 data-length: 121088
680 data-length: 121088
681 nodemap-race: left side locked and ready to commit
681 nodemap-race: left side locked and ready to commit
682 docket-details:
682 docket-details:
683 uid: 43c37dde
683 uid: 43c37dde
684 actual-tip: 5005
684 actual-tip: 5005
685 tip-rev: 5005
685 tip-rev: 5005
686 data-length: 121088
686 data-length: 121088
687 finalized changelog write
687 finalized changelog write
688 persisting changelog nodemap
688 persisting changelog nodemap
689 new data start at 121088
689 new data start at 121088
690 persisted changelog nodemap
690 persisted changelog nodemap
691 docket-details:
691 docket-details:
692 uid: 43c37dde
692 uid: 43c37dde
693 actual-tip: 5006
693 actual-tip: 5006
694 tip-rev: 5006
694 tip-rev: 5006
695 data-length: 121280
695 data-length: 121280
696 $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/right-done
696 $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/right-done
697 $ cat outputs/right.txt
697 $ cat outputs/right.txt
698 nodemap-race: right side start of the locking sequence
698 nodemap-race: right side start of the locking sequence
699 nodemap-race: right side reading changelog
699 nodemap-race: right side reading changelog
700 nodemap-race: right side reading of changelog is done
700 nodemap-race: right side reading of changelog is done
701 docket-details:
701 docket-details:
702 uid: 43c37dde
702 uid: 43c37dde
703 actual-tip: 5006
703 actual-tip: 5006
704 tip-rev: 5005
704 tip-rev: 5005
705 data-length: 121088
705 data-length: 121088
706 nodemap-race: right side ready to wait for the lock
706 nodemap-race: right side ready to wait for the lock
707 nodemap-race: right side locked and ready to commit
707 nodemap-race: right side locked and ready to commit
708 docket-details:
708 docket-details:
709 uid: 43c37dde
709 uid: 43c37dde
710 actual-tip: 5006
710 actual-tip: 5006
711 tip-rev: 5006
711 tip-rev: 5006
712 data-length: 121280
712 data-length: 121280
713 right ready to write, waiting for reader
713 right ready to write, waiting for reader
714 right proceeding with writing its changelog index and nodemap
714 right proceeding with writing its changelog index and nodemap
715 finalized changelog write
715 finalized changelog write
716 persisting changelog nodemap
716 persisting changelog nodemap
717 new data start at 121280
717 new data start at 121280
718 persisted changelog nodemap
718 persisted changelog nodemap
719 docket-details:
719 docket-details:
720 uid: 43c37dde
720 uid: 43c37dde
721 actual-tip: 5007
721 actual-tip: 5007
722 tip-rev: 5007
722 tip-rev: 5007
723 data-length: 121536
723 data-length: 121536
724 $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/reader-done
724 $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/reader-done
725 $ cat outputs/reader.txt
725 $ cat outputs/reader.txt
726 reader: reading changelog
726 reader: reading changelog
727 reader ready to read the changelog, waiting for right
727 reader ready to read the changelog, waiting for right
728 reader: nodemap docket read
728 reader: nodemap docket read
729 record-data-length: 121280
729 record-data-length: 121280
730 actual-data-length: 121280
730 actual-data-length: 121280
731 file-actual-length: 121536
731 file-actual-length: 121536
732 reader: changelog read
732 reader: changelog read
733 docket-details:
733 docket-details:
734 uid: 43c37dde
734 uid: 43c37dde
735 actual-tip: 5006
735 actual-tip: 5006
736 tip-rev: 5006
736 tip-rev: 5006
737 data-length: 121280
737 data-length: 121280
738 tip-rev: 5006
738 tip-rev: 5006
739 tip-node: 492901161367
739 tip-node: 492901161367
740 node-rev: 5006
740 node-rev: 5006
741
741
742 $ hg -R ./race-repo log -G -r 'head()'
742 $ hg -R ./race-repo log -G -r 'head()'
743 o changeset: 5007:ac4a2abde241
743 o changeset: 5007:ac4a2abde241
744 | tag: tip
744 | tag: tip
745 ~ parent: 5001:16395c3cf7e2
745 ~ parent: 5001:16395c3cf7e2
746 user: test
746 user: test
747 date: Thu Jan 01 00:00:00 1970 +0000
747 date: Thu Jan 01 00:00:00 1970 +0000
748 summary: right-side-commit
748 summary: right-side-commit
749
749
750 @ changeset: 5006:492901161367
750 @ changeset: 5006:492901161367
751 | user: test
751 | user: test
752 ~ date: Thu Jan 01 00:00:00 1970 +0000
752 ~ date: Thu Jan 01 00:00:00 1970 +0000
753 summary: left-side-commit
753 summary: left-side-commit
754
754
755 $ hg -R ./other-wc log -G -r 'head()'
755 $ hg -R ./other-wc log -G -r 'head()'
756 @ changeset: 5007:ac4a2abde241
756 @ changeset: 5007:ac4a2abde241
757 | tag: tip
757 | tag: tip
758 ~ parent: 5001:16395c3cf7e2
758 ~ parent: 5001:16395c3cf7e2
759 user: test
759 user: test
760 date: Thu Jan 01 00:00:00 1970 +0000
760 date: Thu Jan 01 00:00:00 1970 +0000
761 summary: right-side-commit
761 summary: right-side-commit
762
762
763 o changeset: 5006:492901161367
763 o changeset: 5006:492901161367
764 | user: test
764 | user: test
765 ~ date: Thu Jan 01 00:00:00 1970 +0000
765 ~ date: Thu Jan 01 00:00:00 1970 +0000
766 summary: left-side-commit
766 summary: left-side-commit
767
767
768 #endif
768 #endif
769
769
770 Test upgrade / downgrade
770 Test upgrade / downgrade
771 ========================
771 ========================
772
772
773 $ cd ./test-repo/
773 $ cd ./test-repo/
774
774
775 downgrading
775 downgrading
776
776
777 $ cat << EOF >> .hg/hgrc
777 $ cat << EOF >> .hg/hgrc
778 > [format]
778 > [format]
779 > use-persistent-nodemap=no
779 > use-persistent-nodemap=no
780 > EOF
780 > EOF
781 $ hg debugformat -v
781 $ hg debugformat -v
782 format-variant repo config default
782 format-variant repo config default
783 fncache: yes yes yes
783 fncache: yes yes yes
784 dirstate-v2: no no no
784 dirstate-v2: no no no
785 dotencode: yes yes yes
785 dotencode: yes yes yes
786 generaldelta: yes yes yes
786 generaldelta: yes yes yes
787 share-safe: yes yes yes
787 share-safe: yes yes yes
788 sparserevlog: yes yes yes
788 sparserevlog: yes yes yes
789 persistent-nodemap: yes no no
789 persistent-nodemap: yes no no
790 copies-sdc: no no no
790 copies-sdc: no no no
791 revlog-v2: no no no
791 revlog-v2: no no no
792 changelog-v2: no no no
792 changelog-v2: no no no
793 plain-cl-delta: yes yes yes
793 plain-cl-delta: yes yes yes
794 compression: zlib zlib zlib (no-zstd !)
794 compression: zlib zlib zlib (no-zstd !)
795 compression: zstd zstd zstd (zstd !)
795 compression: zstd zstd zstd (zstd !)
796 compression-level: default default default
796 compression-level: default default default
797 $ hg debugupgraderepo --run --no-backup --quiet
797 $ hg debugupgraderepo --run --no-backup --quiet
798 upgrade will perform the following actions:
798 upgrade will perform the following actions:
799
799
800 requirements
800 requirements
801 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-zstd no-dirstate-v2 !)
801 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-zstd no-dirstate-v2 !)
802 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd no-dirstate-v2 !)
802 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd no-dirstate-v2 !)
803 preserved: dotencode, use-dirstate-v2, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !)
803 preserved: dotencode, use-dirstate-v2, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !)
804 removed: persistent-nodemap
804 removed: persistent-nodemap
805
805
806 processed revlogs:
806 processed revlogs:
807 - all-filelogs
807 - all-filelogs
808 - changelog
808 - changelog
809 - manifest
809 - manifest
810
810
811 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
811 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
812 00changelog-*.nd (glob)
813 00manifest-*.nd (glob)
814 undo.backup.00changelog.n
812 undo.backup.00changelog.n
815 undo.backup.00manifest.n
813 undo.backup.00manifest.n
816 $ hg debugnodemap --metadata
814 $ hg debugnodemap --metadata
817
815
818
816
819 upgrading
817 upgrading
820
818
821 $ cat << EOF >> .hg/hgrc
819 $ cat << EOF >> .hg/hgrc
822 > [format]
820 > [format]
823 > use-persistent-nodemap=yes
821 > use-persistent-nodemap=yes
824 > EOF
822 > EOF
825 $ hg debugformat -v
823 $ hg debugformat -v
826 format-variant repo config default
824 format-variant repo config default
827 fncache: yes yes yes
825 fncache: yes yes yes
828 dirstate-v2: no no no
826 dirstate-v2: no no no
829 dotencode: yes yes yes
827 dotencode: yes yes yes
830 generaldelta: yes yes yes
828 generaldelta: yes yes yes
831 share-safe: yes yes yes
829 share-safe: yes yes yes
832 sparserevlog: yes yes yes
830 sparserevlog: yes yes yes
833 persistent-nodemap: no yes no
831 persistent-nodemap: no yes no
834 copies-sdc: no no no
832 copies-sdc: no no no
835 revlog-v2: no no no
833 revlog-v2: no no no
836 changelog-v2: no no no
834 changelog-v2: no no no
837 plain-cl-delta: yes yes yes
835 plain-cl-delta: yes yes yes
838 compression: zlib zlib zlib (no-zstd !)
836 compression: zlib zlib zlib (no-zstd !)
839 compression: zstd zstd zstd (zstd !)
837 compression: zstd zstd zstd (zstd !)
840 compression-level: default default default
838 compression-level: default default default
841 $ hg debugupgraderepo --run --no-backup --quiet
839 $ hg debugupgraderepo --run --no-backup --quiet
842 upgrade will perform the following actions:
840 upgrade will perform the following actions:
843
841
844 requirements
842 requirements
845 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-zstd no-dirstate-v2 !)
843 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-zstd no-dirstate-v2 !)
846 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd no-dirstate-v2 !)
844 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd no-dirstate-v2 !)
847 preserved: dotencode, use-dirstate-v2, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !)
845 preserved: dotencode, use-dirstate-v2, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !)
848 added: persistent-nodemap
846 added: persistent-nodemap
849
847
850 processed revlogs:
848 processed revlogs:
851 - all-filelogs
849 - all-filelogs
852 - changelog
850 - changelog
853 - manifest
851 - manifest
854
852
855 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
853 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
856 00changelog-*.nd (glob)
854 00changelog-*.nd (glob)
857 00changelog.n
855 00changelog.n
858 00manifest-*.nd (glob)
856 00manifest-*.nd (glob)
859 00manifest.n
857 00manifest.n
860 undo.backup.00changelog.n
858 undo.backup.00changelog.n
861 undo.backup.00manifest.n
859 undo.backup.00manifest.n
862
860
863 $ hg debugnodemap --metadata
861 $ hg debugnodemap --metadata
864 uid: * (glob)
862 uid: * (glob)
865 tip-rev: 5005
863 tip-rev: 5005
866 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
864 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
867 data-length: 121088
865 data-length: 121088
868 data-unused: 0
866 data-unused: 0
869 data-unused: 0.000%
867 data-unused: 0.000%
870
868
871 Running unrelated upgrade
869 Running unrelated upgrade
872
870
873 $ hg debugupgraderepo --run --no-backup --quiet --optimize re-delta-all
871 $ hg debugupgraderepo --run --no-backup --quiet --optimize re-delta-all
874 upgrade will perform the following actions:
872 upgrade will perform the following actions:
875
873
876 requirements
874 requirements
877 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (no-zstd no-dirstate-v2 !)
875 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (no-zstd no-dirstate-v2 !)
878 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd no-dirstate-v2 !)
876 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd no-dirstate-v2 !)
879 preserved: dotencode, use-dirstate-v2, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !)
877 preserved: dotencode, use-dirstate-v2, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !)
880
878
881 optimisations: re-delta-all
879 optimisations: re-delta-all
882
880
883 processed revlogs:
881 processed revlogs:
884 - all-filelogs
882 - all-filelogs
885 - changelog
883 - changelog
886 - manifest
884 - manifest
887
885
888 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
886 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
889 00changelog-*.nd (glob)
887 00changelog-*.nd (glob)
890 00changelog.n
888 00changelog.n
891 00manifest-*.nd (glob)
889 00manifest-*.nd (glob)
892 00manifest.n
890 00manifest.n
893
891
894 $ hg debugnodemap --metadata
892 $ hg debugnodemap --metadata
895 uid: * (glob)
893 uid: * (glob)
896 tip-rev: 5005
894 tip-rev: 5005
897 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
895 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
898 data-length: 121088
896 data-length: 121088
899 data-unused: 0
897 data-unused: 0
900 data-unused: 0.000%
898 data-unused: 0.000%
901
899
902 Persistent nodemap and local/streaming clone
900 Persistent nodemap and local/streaming clone
903 ============================================
901 ============================================
904
902
905 $ cd ..
903 $ cd ..
906
904
907 standard clone
905 standard clone
908 --------------
906 --------------
909
907
910 The persistent nodemap should exist after a streaming clone
908 The persistent nodemap should exist after a streaming clone
911
909
912 $ hg clone --pull --quiet -U test-repo standard-clone
910 $ hg clone --pull --quiet -U test-repo standard-clone
913 $ ls -1 standard-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
911 $ ls -1 standard-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
914 00changelog-*.nd (glob)
912 00changelog-*.nd (glob)
915 00changelog.n
913 00changelog.n
916 00manifest-*.nd (glob)
914 00manifest-*.nd (glob)
917 00manifest.n
915 00manifest.n
918 $ hg -R standard-clone debugnodemap --metadata
916 $ hg -R standard-clone debugnodemap --metadata
919 uid: * (glob)
917 uid: * (glob)
920 tip-rev: 5005
918 tip-rev: 5005
921 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
919 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
922 data-length: 121088
920 data-length: 121088
923 data-unused: 0
921 data-unused: 0
924 data-unused: 0.000%
922 data-unused: 0.000%
925
923
926
924
927 local clone
925 local clone
928 ------------
926 ------------
929
927
930 The persistent nodemap should exist after a streaming clone
928 The persistent nodemap should exist after a streaming clone
931
929
932 $ hg clone -U test-repo local-clone
930 $ hg clone -U test-repo local-clone
933 $ ls -1 local-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
931 $ ls -1 local-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
934 00changelog-*.nd (glob)
932 00changelog-*.nd (glob)
935 00changelog.n
933 00changelog.n
936 00manifest-*.nd (glob)
934 00manifest-*.nd (glob)
937 00manifest.n
935 00manifest.n
938 $ hg -R local-clone debugnodemap --metadata
936 $ hg -R local-clone debugnodemap --metadata
939 uid: * (glob)
937 uid: * (glob)
940 tip-rev: 5005
938 tip-rev: 5005
941 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
939 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
942 data-length: 121088
940 data-length: 121088
943 data-unused: 0
941 data-unused: 0
944 data-unused: 0.000%
942 data-unused: 0.000%
945
943
946 Test various corruption case
944 Test various corruption case
947 ============================
945 ============================
948
946
949 Missing datafile
947 Missing datafile
950 ----------------
948 ----------------
951
949
952 Test behavior with a missing datafile
950 Test behavior with a missing datafile
953
951
954 $ hg clone --quiet --pull test-repo corruption-test-repo
952 $ hg clone --quiet --pull test-repo corruption-test-repo
955 $ ls -1 corruption-test-repo/.hg/store/00changelog*
953 $ ls -1 corruption-test-repo/.hg/store/00changelog*
956 corruption-test-repo/.hg/store/00changelog-*.nd (glob)
954 corruption-test-repo/.hg/store/00changelog-*.nd (glob)
957 corruption-test-repo/.hg/store/00changelog.d
955 corruption-test-repo/.hg/store/00changelog.d
958 corruption-test-repo/.hg/store/00changelog.i
956 corruption-test-repo/.hg/store/00changelog.i
959 corruption-test-repo/.hg/store/00changelog.n
957 corruption-test-repo/.hg/store/00changelog.n
960 $ rm corruption-test-repo/.hg/store/00changelog*.nd
958 $ rm corruption-test-repo/.hg/store/00changelog*.nd
961 $ hg log -R corruption-test-repo -r .
959 $ hg log -R corruption-test-repo -r .
962 changeset: 5005:90d5d3ba2fc4
960 changeset: 5005:90d5d3ba2fc4
963 tag: tip
961 tag: tip
964 user: test
962 user: test
965 date: Thu Jan 01 00:00:00 1970 +0000
963 date: Thu Jan 01 00:00:00 1970 +0000
966 summary: a2
964 summary: a2
967
965
968 $ ls -1 corruption-test-repo/.hg/store/00changelog*
966 $ ls -1 corruption-test-repo/.hg/store/00changelog*
969 corruption-test-repo/.hg/store/00changelog.d
967 corruption-test-repo/.hg/store/00changelog.d
970 corruption-test-repo/.hg/store/00changelog.i
968 corruption-test-repo/.hg/store/00changelog.i
971 corruption-test-repo/.hg/store/00changelog.n
969 corruption-test-repo/.hg/store/00changelog.n
972
970
973 Truncated data file
971 Truncated data file
974 -------------------
972 -------------------
975
973
976 Test behavior with a too short datafile
974 Test behavior with a too short datafile
977
975
978 rebuild the missing data
976 rebuild the missing data
979 $ hg -R corruption-test-repo debugupdatecache
977 $ hg -R corruption-test-repo debugupdatecache
980 $ ls -1 corruption-test-repo/.hg/store/00changelog*
978 $ ls -1 corruption-test-repo/.hg/store/00changelog*
981 corruption-test-repo/.hg/store/00changelog-*.nd (glob)
979 corruption-test-repo/.hg/store/00changelog-*.nd (glob)
982 corruption-test-repo/.hg/store/00changelog.d
980 corruption-test-repo/.hg/store/00changelog.d
983 corruption-test-repo/.hg/store/00changelog.i
981 corruption-test-repo/.hg/store/00changelog.i
984 corruption-test-repo/.hg/store/00changelog.n
982 corruption-test-repo/.hg/store/00changelog.n
985
983
986 truncate the file
984 truncate the file
987
985
988 $ datafilepath=`ls corruption-test-repo/.hg/store/00changelog*.nd`
986 $ datafilepath=`ls corruption-test-repo/.hg/store/00changelog*.nd`
989 $ f -s $datafilepath
987 $ f -s $datafilepath
990 corruption-test-repo/.hg/store/00changelog-*.nd: size=121088 (glob)
988 corruption-test-repo/.hg/store/00changelog-*.nd: size=121088 (glob)
991 $ dd if=$datafilepath bs=1000 count=10 of=$datafilepath-tmp
989 $ dd if=$datafilepath bs=1000 count=10 of=$datafilepath-tmp
992 10+0 records in
990 10+0 records in
993 10+0 records out
991 10+0 records out
994 * bytes * (glob)
992 * bytes * (glob)
995 $ mv $datafilepath-tmp $datafilepath
993 $ mv $datafilepath-tmp $datafilepath
996 $ f -s $datafilepath
994 $ f -s $datafilepath
997 corruption-test-repo/.hg/store/00changelog-*.nd: size=10000 (glob)
995 corruption-test-repo/.hg/store/00changelog-*.nd: size=10000 (glob)
998
996
999 Check that Mercurial reaction to this event
997 Check that Mercurial reaction to this event
1000
998
1001 $ hg -R corruption-test-repo log -r . --traceback
999 $ hg -R corruption-test-repo log -r . --traceback
1002 changeset: 5005:90d5d3ba2fc4
1000 changeset: 5005:90d5d3ba2fc4
1003 tag: tip
1001 tag: tip
1004 user: test
1002 user: test
1005 date: Thu Jan 01 00:00:00 1970 +0000
1003 date: Thu Jan 01 00:00:00 1970 +0000
1006 summary: a2
1004 summary: a2
1007
1005
1008
1006
1009
1007
1010 stream clone
1008 stream clone
1011 ============
1009 ============
1012
1010
1013 The persistent nodemap should exist after a streaming clone
1011 The persistent nodemap should exist after a streaming clone
1014
1012
1015 Simple case
1013 Simple case
1016 -----------
1014 -----------
1017
1015
1018 No race condition
1016 No race condition
1019
1017
1020 $ hg clone -U --stream ssh://user@dummy/test-repo stream-clone --debug | egrep '00(changelog|manifest)'
1018 $ hg clone -U --stream ssh://user@dummy/test-repo stream-clone --debug | egrep '00(changelog|manifest)'
1021 adding [s] 00manifest.n (62 bytes)
1019 adding [s] 00manifest.n (62 bytes)
1022 adding [s] 00manifest-*.nd (118 KB) (glob)
1020 adding [s] 00manifest-*.nd (118 KB) (glob)
1023 adding [s] 00changelog.n (62 bytes)
1021 adding [s] 00changelog.n (62 bytes)
1024 adding [s] 00changelog-*.nd (118 KB) (glob)
1022 adding [s] 00changelog-*.nd (118 KB) (glob)
1025 adding [s] 00manifest.d (452 KB) (no-zstd !)
1023 adding [s] 00manifest.d (452 KB) (no-zstd !)
1026 adding [s] 00manifest.d (491 KB) (zstd no-bigendian !)
1024 adding [s] 00manifest.d (491 KB) (zstd no-bigendian !)
1027 adding [s] 00manifest.d (492 KB) (zstd bigendian !)
1025 adding [s] 00manifest.d (492 KB) (zstd bigendian !)
1028 adding [s] 00changelog.d (360 KB) (no-zstd !)
1026 adding [s] 00changelog.d (360 KB) (no-zstd !)
1029 adding [s] 00changelog.d (368 KB) (zstd !)
1027 adding [s] 00changelog.d (368 KB) (zstd !)
1030 adding [s] 00manifest.i (313 KB)
1028 adding [s] 00manifest.i (313 KB)
1031 adding [s] 00changelog.i (313 KB)
1029 adding [s] 00changelog.i (313 KB)
1032 $ ls -1 stream-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
1030 $ ls -1 stream-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
1033 00changelog-*.nd (glob)
1031 00changelog-*.nd (glob)
1034 00changelog.n
1032 00changelog.n
1035 00manifest-*.nd (glob)
1033 00manifest-*.nd (glob)
1036 00manifest.n
1034 00manifest.n
1037 $ hg -R stream-clone debugnodemap --metadata
1035 $ hg -R stream-clone debugnodemap --metadata
1038 uid: * (glob)
1036 uid: * (glob)
1039 tip-rev: 5005
1037 tip-rev: 5005
1040 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1038 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1041 data-length: 121088
1039 data-length: 121088
1042 data-unused: 0
1040 data-unused: 0
1043 data-unused: 0.000%
1041 data-unused: 0.000%
1044
1042
1045 new data appened
1043 new data appened
1046 -----------------
1044 -----------------
1047
1045
1048 Other commit happening on the server during the stream clone
1046 Other commit happening on the server during the stream clone
1049
1047
1050 setup the step-by-step stream cloning
1048 setup the step-by-step stream cloning
1051
1049
1052 $ HG_TEST_STREAM_WALKED_FILE_1="$TESTTMP/sync_file_walked_1"
1050 $ HG_TEST_STREAM_WALKED_FILE_1="$TESTTMP/sync_file_walked_1"
1053 $ export HG_TEST_STREAM_WALKED_FILE_1
1051 $ export HG_TEST_STREAM_WALKED_FILE_1
1054 $ HG_TEST_STREAM_WALKED_FILE_2="$TESTTMP/sync_file_walked_2"
1052 $ HG_TEST_STREAM_WALKED_FILE_2="$TESTTMP/sync_file_walked_2"
1055 $ export HG_TEST_STREAM_WALKED_FILE_2
1053 $ export HG_TEST_STREAM_WALKED_FILE_2
1056 $ HG_TEST_STREAM_WALKED_FILE_3="$TESTTMP/sync_file_walked_3"
1054 $ HG_TEST_STREAM_WALKED_FILE_3="$TESTTMP/sync_file_walked_3"
1057 $ export HG_TEST_STREAM_WALKED_FILE_3
1055 $ export HG_TEST_STREAM_WALKED_FILE_3
1058 $ cat << EOF >> test-repo/.hg/hgrc
1056 $ cat << EOF >> test-repo/.hg/hgrc
1059 > [extensions]
1057 > [extensions]
1060 > steps=$RUNTESTDIR/testlib/ext-stream-clone-steps.py
1058 > steps=$RUNTESTDIR/testlib/ext-stream-clone-steps.py
1061 > EOF
1059 > EOF
1062
1060
1063 Check and record file state beforehand
1061 Check and record file state beforehand
1064
1062
1065 $ f --size test-repo/.hg/store/00changelog*
1063 $ f --size test-repo/.hg/store/00changelog*
1066 test-repo/.hg/store/00changelog-*.nd: size=121088 (glob)
1064 test-repo/.hg/store/00changelog-*.nd: size=121088 (glob)
1067 test-repo/.hg/store/00changelog.d: size=376891 (zstd no-bigendian !)
1065 test-repo/.hg/store/00changelog.d: size=376891 (zstd no-bigendian !)
1068 test-repo/.hg/store/00changelog.d: size=376889 (zstd bigendian !)
1066 test-repo/.hg/store/00changelog.d: size=376889 (zstd bigendian !)
1069 test-repo/.hg/store/00changelog.d: size=368890 (no-zstd !)
1067 test-repo/.hg/store/00changelog.d: size=368890 (no-zstd !)
1070 test-repo/.hg/store/00changelog.i: size=320384
1068 test-repo/.hg/store/00changelog.i: size=320384
1071 test-repo/.hg/store/00changelog.n: size=62
1069 test-repo/.hg/store/00changelog.n: size=62
1072 $ hg -R test-repo debugnodemap --metadata | tee server-metadata.txt
1070 $ hg -R test-repo debugnodemap --metadata | tee server-metadata.txt
1073 uid: * (glob)
1071 uid: * (glob)
1074 tip-rev: 5005
1072 tip-rev: 5005
1075 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1073 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1076 data-length: 121088
1074 data-length: 121088
1077 data-unused: 0
1075 data-unused: 0
1078 data-unused: 0.000%
1076 data-unused: 0.000%
1079
1077
1080 Prepare a commit
1078 Prepare a commit
1081
1079
1082 $ echo foo >> test-repo/foo
1080 $ echo foo >> test-repo/foo
1083 $ hg -R test-repo/ add test-repo/foo
1081 $ hg -R test-repo/ add test-repo/foo
1084
1082
1085 Do a mix of clone and commit at the same time so that the file listed on disk differ at actual transfer time.
1083 Do a mix of clone and commit at the same time so that the file listed on disk differ at actual transfer time.
1086
1084
1087 $ (hg clone -U --stream ssh://user@dummy/test-repo stream-clone-race-1 --debug 2>> clone-output | egrep '00(changelog|manifest)' >> clone-output; touch $HG_TEST_STREAM_WALKED_FILE_3) &
1085 $ (hg clone -U --stream ssh://user@dummy/test-repo stream-clone-race-1 --debug 2>> clone-output | egrep '00(changelog|manifest)' >> clone-output; touch $HG_TEST_STREAM_WALKED_FILE_3) &
1088 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1
1086 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1
1089 $ hg -R test-repo/ commit -m foo
1087 $ hg -R test-repo/ commit -m foo
1090 $ touch $HG_TEST_STREAM_WALKED_FILE_2
1088 $ touch $HG_TEST_STREAM_WALKED_FILE_2
1091 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3
1089 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3
1092 $ cat clone-output
1090 $ cat clone-output
1093 adding [s] 00manifest.n (62 bytes)
1091 adding [s] 00manifest.n (62 bytes)
1094 adding [s] 00manifest-*.nd (118 KB) (glob)
1092 adding [s] 00manifest-*.nd (118 KB) (glob)
1095 adding [s] 00changelog.n (62 bytes)
1093 adding [s] 00changelog.n (62 bytes)
1096 adding [s] 00changelog-*.nd (118 KB) (glob)
1094 adding [s] 00changelog-*.nd (118 KB) (glob)
1097 adding [s] 00manifest.d (452 KB) (no-zstd !)
1095 adding [s] 00manifest.d (452 KB) (no-zstd !)
1098 adding [s] 00manifest.d (491 KB) (zstd no-bigendian !)
1096 adding [s] 00manifest.d (491 KB) (zstd no-bigendian !)
1099 adding [s] 00manifest.d (492 KB) (zstd bigendian !)
1097 adding [s] 00manifest.d (492 KB) (zstd bigendian !)
1100 adding [s] 00changelog.d (360 KB) (no-zstd !)
1098 adding [s] 00changelog.d (360 KB) (no-zstd !)
1101 adding [s] 00changelog.d (368 KB) (zstd !)
1099 adding [s] 00changelog.d (368 KB) (zstd !)
1102 adding [s] 00manifest.i (313 KB)
1100 adding [s] 00manifest.i (313 KB)
1103 adding [s] 00changelog.i (313 KB)
1101 adding [s] 00changelog.i (313 KB)
1104
1102
1105 Check the result state
1103 Check the result state
1106
1104
1107 $ f --size stream-clone-race-1/.hg/store/00changelog*
1105 $ f --size stream-clone-race-1/.hg/store/00changelog*
1108 stream-clone-race-1/.hg/store/00changelog-*.nd: size=121088 (glob)
1106 stream-clone-race-1/.hg/store/00changelog-*.nd: size=121088 (glob)
1109 stream-clone-race-1/.hg/store/00changelog.d: size=368890 (no-zstd !)
1107 stream-clone-race-1/.hg/store/00changelog.d: size=368890 (no-zstd !)
1110 stream-clone-race-1/.hg/store/00changelog.d: size=376891 (zstd no-bigendian !)
1108 stream-clone-race-1/.hg/store/00changelog.d: size=376891 (zstd no-bigendian !)
1111 stream-clone-race-1/.hg/store/00changelog.d: size=376889 (zstd bigendian !)
1109 stream-clone-race-1/.hg/store/00changelog.d: size=376889 (zstd bigendian !)
1112 stream-clone-race-1/.hg/store/00changelog.i: size=320384
1110 stream-clone-race-1/.hg/store/00changelog.i: size=320384
1113 stream-clone-race-1/.hg/store/00changelog.n: size=62
1111 stream-clone-race-1/.hg/store/00changelog.n: size=62
1114
1112
1115 $ hg -R stream-clone-race-1 debugnodemap --metadata | tee client-metadata.txt
1113 $ hg -R stream-clone-race-1 debugnodemap --metadata | tee client-metadata.txt
1116 uid: * (glob)
1114 uid: * (glob)
1117 tip-rev: 5005
1115 tip-rev: 5005
1118 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1116 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1119 data-length: 121088
1117 data-length: 121088
1120 data-unused: 0
1118 data-unused: 0
1121 data-unused: 0.000%
1119 data-unused: 0.000%
1122
1120
1123 We get a usable nodemap, so no rewrite would be needed and the metadata should be identical
1121 We get a usable nodemap, so no rewrite would be needed and the metadata should be identical
1124 (ie: the following diff should be empty)
1122 (ie: the following diff should be empty)
1125
1123
1126 This isn't the case for the `no-rust` `no-pure` implementation as it use a very minimal nodemap implementation that unconditionnaly rewrite the nodemap "all the time".
1124 This isn't the case for the `no-rust` `no-pure` implementation as it use a very minimal nodemap implementation that unconditionnaly rewrite the nodemap "all the time".
1127
1125
1128 #if no-rust no-pure
1126 #if no-rust no-pure
1129 $ diff -u server-metadata.txt client-metadata.txt
1127 $ diff -u server-metadata.txt client-metadata.txt
1130 --- server-metadata.txt * (glob)
1128 --- server-metadata.txt * (glob)
1131 +++ client-metadata.txt * (glob)
1129 +++ client-metadata.txt * (glob)
1132 @@ -1,4 +1,4 @@
1130 @@ -1,4 +1,4 @@
1133 -uid: * (glob)
1131 -uid: * (glob)
1134 +uid: * (glob)
1132 +uid: * (glob)
1135 tip-rev: 5005
1133 tip-rev: 5005
1136 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1134 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1137 data-length: 121088
1135 data-length: 121088
1138 [1]
1136 [1]
1139 #else
1137 #else
1140 $ diff -u server-metadata.txt client-metadata.txt
1138 $ diff -u server-metadata.txt client-metadata.txt
1141 #endif
1139 #endif
1142
1140
1143
1141
1144 Clean up after the test.
1142 Clean up after the test.
1145
1143
1146 $ rm -f "$HG_TEST_STREAM_WALKED_FILE_1"
1144 $ rm -f "$HG_TEST_STREAM_WALKED_FILE_1"
1147 $ rm -f "$HG_TEST_STREAM_WALKED_FILE_2"
1145 $ rm -f "$HG_TEST_STREAM_WALKED_FILE_2"
1148 $ rm -f "$HG_TEST_STREAM_WALKED_FILE_3"
1146 $ rm -f "$HG_TEST_STREAM_WALKED_FILE_3"
1149
1147
1150 full regeneration
1148 full regeneration
1151 -----------------
1149 -----------------
1152
1150
1153 A full nodemap is generated
1151 A full nodemap is generated
1154
1152
1155 (ideally this test would append enough data to make sure the nodemap data file
1153 (ideally this test would append enough data to make sure the nodemap data file
1156 get changed, however to make thing simpler we will force the regeneration for
1154 get changed, however to make thing simpler we will force the regeneration for
1157 this test.
1155 this test.
1158
1156
1159 Check the initial state
1157 Check the initial state
1160
1158
1161 $ f --size test-repo/.hg/store/00changelog*
1159 $ f --size test-repo/.hg/store/00changelog*
1162 test-repo/.hg/store/00changelog-*.nd: size=121344 (glob) (rust !)
1160 test-repo/.hg/store/00changelog-*.nd: size=121344 (glob) (rust !)
1163 test-repo/.hg/store/00changelog-*.nd: size=121344 (glob) (pure !)
1161 test-repo/.hg/store/00changelog-*.nd: size=121344 (glob) (pure !)
1164 test-repo/.hg/store/00changelog-*.nd: size=121152 (glob) (no-rust no-pure !)
1162 test-repo/.hg/store/00changelog-*.nd: size=121152 (glob) (no-rust no-pure !)
1165 test-repo/.hg/store/00changelog.d: size=376950 (zstd no-bigendian !)
1163 test-repo/.hg/store/00changelog.d: size=376950 (zstd no-bigendian !)
1166 test-repo/.hg/store/00changelog.d: size=376948 (zstd bigendian !)
1164 test-repo/.hg/store/00changelog.d: size=376948 (zstd bigendian !)
1167 test-repo/.hg/store/00changelog.d: size=368949 (no-zstd !)
1165 test-repo/.hg/store/00changelog.d: size=368949 (no-zstd !)
1168 test-repo/.hg/store/00changelog.i: size=320448
1166 test-repo/.hg/store/00changelog.i: size=320448
1169 test-repo/.hg/store/00changelog.n: size=62
1167 test-repo/.hg/store/00changelog.n: size=62
1170 $ hg -R test-repo debugnodemap --metadata | tee server-metadata-2.txt
1168 $ hg -R test-repo debugnodemap --metadata | tee server-metadata-2.txt
1171 uid: * (glob)
1169 uid: * (glob)
1172 tip-rev: 5006
1170 tip-rev: 5006
1173 tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b
1171 tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b
1174 data-length: 121344 (rust !)
1172 data-length: 121344 (rust !)
1175 data-length: 121344 (pure !)
1173 data-length: 121344 (pure !)
1176 data-length: 121152 (no-rust no-pure !)
1174 data-length: 121152 (no-rust no-pure !)
1177 data-unused: 192 (rust !)
1175 data-unused: 192 (rust !)
1178 data-unused: 192 (pure !)
1176 data-unused: 192 (pure !)
1179 data-unused: 0 (no-rust no-pure !)
1177 data-unused: 0 (no-rust no-pure !)
1180 data-unused: 0.158% (rust !)
1178 data-unused: 0.158% (rust !)
1181 data-unused: 0.158% (pure !)
1179 data-unused: 0.158% (pure !)
1182 data-unused: 0.000% (no-rust no-pure !)
1180 data-unused: 0.000% (no-rust no-pure !)
1183
1181
1184 Performe the mix of clone and full refresh of the nodemap, so that the files
1182 Performe the mix of clone and full refresh of the nodemap, so that the files
1185 (and filenames) are different between listing time and actual transfer time.
1183 (and filenames) are different between listing time and actual transfer time.
1186
1184
1187 $ (hg clone -U --stream ssh://user@dummy/test-repo stream-clone-race-2 --debug 2>> clone-output-2 | egrep '00(changelog|manifest)' >> clone-output-2; touch $HG_TEST_STREAM_WALKED_FILE_3) &
1185 $ (hg clone -U --stream ssh://user@dummy/test-repo stream-clone-race-2 --debug 2>> clone-output-2 | egrep '00(changelog|manifest)' >> clone-output-2; touch $HG_TEST_STREAM_WALKED_FILE_3) &
1188 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1
1186 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1
1189 $ rm test-repo/.hg/store/00changelog.n
1187 $ rm test-repo/.hg/store/00changelog.n
1190 $ rm test-repo/.hg/store/00changelog-*.nd
1188 $ rm test-repo/.hg/store/00changelog-*.nd
1191 $ hg -R test-repo/ debugupdatecache
1189 $ hg -R test-repo/ debugupdatecache
1192 $ touch $HG_TEST_STREAM_WALKED_FILE_2
1190 $ touch $HG_TEST_STREAM_WALKED_FILE_2
1193 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3
1191 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3
1194
1192
1195 (note: the stream clone code wronly pick the `undo.` files)
1193 (note: the stream clone code wronly pick the `undo.` files)
1196
1194
1197 $ cat clone-output-2
1195 $ cat clone-output-2
1198 adding [s] undo.backup.00manifest.n (62 bytes) (known-bad-output !)
1196 adding [s] undo.backup.00manifest.n (62 bytes) (known-bad-output !)
1199 adding [s] undo.backup.00changelog.n (62 bytes) (known-bad-output !)
1197 adding [s] undo.backup.00changelog.n (62 bytes) (known-bad-output !)
1200 adding [s] 00manifest.n (62 bytes)
1198 adding [s] 00manifest.n (62 bytes)
1201 adding [s] 00manifest-*.nd (118 KB) (glob)
1199 adding [s] 00manifest-*.nd (118 KB) (glob)
1202 adding [s] 00changelog.n (62 bytes)
1200 adding [s] 00changelog.n (62 bytes)
1203 adding [s] 00changelog-*.nd (118 KB) (glob)
1201 adding [s] 00changelog-*.nd (118 KB) (glob)
1204 adding [s] 00manifest.d (492 KB) (zstd !)
1202 adding [s] 00manifest.d (492 KB) (zstd !)
1205 adding [s] 00manifest.d (452 KB) (no-zstd !)
1203 adding [s] 00manifest.d (452 KB) (no-zstd !)
1206 adding [s] 00changelog.d (360 KB) (no-zstd !)
1204 adding [s] 00changelog.d (360 KB) (no-zstd !)
1207 adding [s] 00changelog.d (368 KB) (zstd !)
1205 adding [s] 00changelog.d (368 KB) (zstd !)
1208 adding [s] 00manifest.i (313 KB)
1206 adding [s] 00manifest.i (313 KB)
1209 adding [s] 00changelog.i (313 KB)
1207 adding [s] 00changelog.i (313 KB)
1210
1208
1211 Check the result.
1209 Check the result.
1212
1210
1213 $ f --size stream-clone-race-2/.hg/store/00changelog*
1211 $ f --size stream-clone-race-2/.hg/store/00changelog*
1214 stream-clone-race-2/.hg/store/00changelog-*.nd: size=121344 (glob) (rust !)
1212 stream-clone-race-2/.hg/store/00changelog-*.nd: size=121344 (glob) (rust !)
1215 stream-clone-race-2/.hg/store/00changelog-*.nd: size=121344 (glob) (pure !)
1213 stream-clone-race-2/.hg/store/00changelog-*.nd: size=121344 (glob) (pure !)
1216 stream-clone-race-2/.hg/store/00changelog-*.nd: size=121152 (glob) (no-rust no-pure !)
1214 stream-clone-race-2/.hg/store/00changelog-*.nd: size=121152 (glob) (no-rust no-pure !)
1217 stream-clone-race-2/.hg/store/00changelog.d: size=376950 (zstd no-bigendian !)
1215 stream-clone-race-2/.hg/store/00changelog.d: size=376950 (zstd no-bigendian !)
1218 stream-clone-race-2/.hg/store/00changelog.d: size=376948 (zstd bigendian !)
1216 stream-clone-race-2/.hg/store/00changelog.d: size=376948 (zstd bigendian !)
1219 stream-clone-race-2/.hg/store/00changelog.d: size=368949 (no-zstd !)
1217 stream-clone-race-2/.hg/store/00changelog.d: size=368949 (no-zstd !)
1220 stream-clone-race-2/.hg/store/00changelog.i: size=320448
1218 stream-clone-race-2/.hg/store/00changelog.i: size=320448
1221 stream-clone-race-2/.hg/store/00changelog.n: size=62
1219 stream-clone-race-2/.hg/store/00changelog.n: size=62
1222
1220
1223 $ hg -R stream-clone-race-2 debugnodemap --metadata | tee client-metadata-2.txt
1221 $ hg -R stream-clone-race-2 debugnodemap --metadata | tee client-metadata-2.txt
1224 uid: * (glob)
1222 uid: * (glob)
1225 tip-rev: 5006
1223 tip-rev: 5006
1226 tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b
1224 tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b
1227 data-length: 121344 (rust !)
1225 data-length: 121344 (rust !)
1228 data-unused: 192 (rust !)
1226 data-unused: 192 (rust !)
1229 data-unused: 0.158% (rust !)
1227 data-unused: 0.158% (rust !)
1230 data-length: 121152 (no-rust no-pure !)
1228 data-length: 121152 (no-rust no-pure !)
1231 data-unused: 0 (no-rust no-pure !)
1229 data-unused: 0 (no-rust no-pure !)
1232 data-unused: 0.000% (no-rust no-pure !)
1230 data-unused: 0.000% (no-rust no-pure !)
1233 data-length: 121344 (pure !)
1231 data-length: 121344 (pure !)
1234 data-unused: 192 (pure !)
1232 data-unused: 192 (pure !)
1235 data-unused: 0.158% (pure !)
1233 data-unused: 0.158% (pure !)
1236
1234
1237 We get a usable nodemap, so no rewrite would be needed and the metadata should be identical
1235 We get a usable nodemap, so no rewrite would be needed and the metadata should be identical
1238 (ie: the following diff should be empty)
1236 (ie: the following diff should be empty)
1239
1237
1240 This isn't the case for the `no-rust` `no-pure` implementation as it use a very minimal nodemap implementation that unconditionnaly rewrite the nodemap "all the time".
1238 This isn't the case for the `no-rust` `no-pure` implementation as it use a very minimal nodemap implementation that unconditionnaly rewrite the nodemap "all the time".
1241
1239
1242 #if no-rust no-pure
1240 #if no-rust no-pure
1243 $ diff -u server-metadata-2.txt client-metadata-2.txt
1241 $ diff -u server-metadata-2.txt client-metadata-2.txt
1244 --- server-metadata-2.txt * (glob)
1242 --- server-metadata-2.txt * (glob)
1245 +++ client-metadata-2.txt * (glob)
1243 +++ client-metadata-2.txt * (glob)
1246 @@ -1,4 +1,4 @@
1244 @@ -1,4 +1,4 @@
1247 -uid: * (glob)
1245 -uid: * (glob)
1248 +uid: * (glob)
1246 +uid: * (glob)
1249 tip-rev: 5006
1247 tip-rev: 5006
1250 tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b
1248 tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b
1251 data-length: 121152
1249 data-length: 121152
1252 [1]
1250 [1]
1253 #else
1251 #else
1254 $ diff -u server-metadata-2.txt client-metadata-2.txt
1252 $ diff -u server-metadata-2.txt client-metadata-2.txt
1255 #endif
1253 #endif
1256
1254
1257 Clean up after the test
1255 Clean up after the test
1258
1256
1259 $ rm -f $HG_TEST_STREAM_WALKED_FILE_1
1257 $ rm -f $HG_TEST_STREAM_WALKED_FILE_1
1260 $ rm -f $HG_TEST_STREAM_WALKED_FILE_2
1258 $ rm -f $HG_TEST_STREAM_WALKED_FILE_2
1261 $ rm -f $HG_TEST_STREAM_WALKED_FILE_3
1259 $ rm -f $HG_TEST_STREAM_WALKED_FILE_3
1262
1260
General Comments 0
You need to be logged in to leave comments. Login now