##// END OF EJS Templates
rust-nodemap: backed out mitigation for issue 6554...
Georges Racinet -
r49090:aa88fb60 stable
parent child Browse files
Show More
@@ -1,529 +1,512
1 // revlog.rs
1 // revlog.rs
2 //
2 //
3 // Copyright 2019-2020 Georges Racinet <georges.racinet@octobus.net>
3 // Copyright 2019-2020 Georges Racinet <georges.racinet@octobus.net>
4 //
4 //
5 // This software may be used and distributed according to the terms of the
5 // This software may be used and distributed according to the terms of the
6 // GNU General Public License version 2 or any later version.
6 // GNU General Public License version 2 or any later version.
7
7
8 use crate::{
8 use crate::{
9 cindex,
9 cindex,
10 utils::{node_from_py_bytes, node_from_py_object},
10 utils::{node_from_py_bytes, node_from_py_object},
11 };
11 };
12 use cpython::{
12 use cpython::{
13 buffer::{Element, PyBuffer},
13 buffer::{Element, PyBuffer},
14 exc::{IndexError, ValueError},
14 exc::{IndexError, ValueError},
15 ObjectProtocol, PyBytes, PyClone, PyDict, PyErr, PyInt, PyModule,
15 ObjectProtocol, PyBytes, PyClone, PyDict, PyErr, PyInt, PyModule,
16 PyObject, PyResult, PyString, PyTuple, Python, PythonObject, ToPyObject,
16 PyObject, PyResult, PyString, PyTuple, Python, PythonObject, ToPyObject,
17 };
17 };
18 use hg::{
18 use hg::{
19 nodemap::{Block, NodeMapError, NodeTree},
19 nodemap::{Block, NodeMapError, NodeTree},
20 revlog::{nodemap::NodeMap, NodePrefix, RevlogIndex},
20 revlog::{nodemap::NodeMap, NodePrefix, RevlogIndex},
21 Revision,
21 Revision,
22 };
22 };
23 use std::cell::RefCell;
23 use std::cell::RefCell;
24
24
25 /// Return a Struct implementing the Graph trait
25 /// Return a Struct implementing the Graph trait
26 pub(crate) fn pyindex_to_graph(
26 pub(crate) fn pyindex_to_graph(
27 py: Python,
27 py: Python,
28 index: PyObject,
28 index: PyObject,
29 ) -> PyResult<cindex::Index> {
29 ) -> PyResult<cindex::Index> {
30 match index.extract::<MixedIndex>(py) {
30 match index.extract::<MixedIndex>(py) {
31 Ok(midx) => Ok(midx.clone_cindex(py)),
31 Ok(midx) => Ok(midx.clone_cindex(py)),
32 Err(_) => cindex::Index::new(py, index),
32 Err(_) => cindex::Index::new(py, index),
33 }
33 }
34 }
34 }
35
35
36 py_class!(pub class MixedIndex |py| {
36 py_class!(pub class MixedIndex |py| {
37 data cindex: RefCell<cindex::Index>;
37 data cindex: RefCell<cindex::Index>;
38 data nt: RefCell<Option<NodeTree>>;
38 data nt: RefCell<Option<NodeTree>>;
39 data docket: RefCell<Option<PyObject>>;
39 data docket: RefCell<Option<PyObject>>;
40 // Holds a reference to the mmap'ed persistent nodemap data
40 // Holds a reference to the mmap'ed persistent nodemap data
41 data mmap: RefCell<Option<PyBuffer>>;
41 data mmap: RefCell<Option<PyBuffer>>;
42
42
43 def __new__(_cls, cindex: PyObject) -> PyResult<MixedIndex> {
43 def __new__(_cls, cindex: PyObject) -> PyResult<MixedIndex> {
44 Self::new(py, cindex)
44 Self::new(py, cindex)
45 }
45 }
46
46
47 /// Compatibility layer used for Python consumers needing access to the C index
47 /// Compatibility layer used for Python consumers needing access to the C index
48 ///
48 ///
49 /// Only use case so far is `scmutil.shortesthexnodeidprefix`,
49 /// Only use case so far is `scmutil.shortesthexnodeidprefix`,
50 /// that may need to build a custom `nodetree`, based on a specified revset.
50 /// that may need to build a custom `nodetree`, based on a specified revset.
51 /// With a Rust implementation of the nodemap, we will be able to get rid of
51 /// With a Rust implementation of the nodemap, we will be able to get rid of
52 /// this, by exposing our own standalone nodemap class,
52 /// this, by exposing our own standalone nodemap class,
53 /// ready to accept `MixedIndex`.
53 /// ready to accept `MixedIndex`.
54 def get_cindex(&self) -> PyResult<PyObject> {
54 def get_cindex(&self) -> PyResult<PyObject> {
55 Ok(self.cindex(py).borrow().inner().clone_ref(py))
55 Ok(self.cindex(py).borrow().inner().clone_ref(py))
56 }
56 }
57
57
58 // Index API involving nodemap, as defined in mercurial/pure/parsers.py
58 // Index API involving nodemap, as defined in mercurial/pure/parsers.py
59
59
60 /// Return Revision if found, raises a bare `error.RevlogError`
60 /// Return Revision if found, raises a bare `error.RevlogError`
61 /// in case of ambiguity, same as C version does
61 /// in case of ambiguity, same as C version does
62 def get_rev(&self, pynode: PyBytes) -> PyResult<Option<Revision>> {
62 def get_rev(&self, node: PyBytes) -> PyResult<Option<Revision>> {
63 let opt = self.get_nodetree(py)?.borrow();
63 let opt = self.get_nodetree(py)?.borrow();
64 let nt = opt.as_ref().unwrap();
64 let nt = opt.as_ref().unwrap();
65 let idx = &*self.cindex(py).borrow();
65 let idx = &*self.cindex(py).borrow();
66 let node = node_from_py_bytes(py, &pynode)?;
66 let node = node_from_py_bytes(py, &node)?;
67 match nt.find_bin(idx, node.into())
67 nt.find_bin(idx, node.into()).map_err(|e| nodemap_error(py, e))
68 {
69 Ok(None) =>
70 // fallback to C implementation, remove once
71 // https://bz.mercurial-scm.org/show_bug.cgi?id=6554
72 // is fixed (a simple backout should do)
73 self.call_cindex(py, "get_rev", &PyTuple::new(py, &[pynode.into_object()]), None)?
74 .extract(py),
75 Ok(Some(rev)) => Ok(Some(rev)),
76 Err(e) => Err(nodemap_error(py, e)),
77 }
78 }
68 }
79
69
80 /// same as `get_rev()` but raises a bare `error.RevlogError` if node
70 /// same as `get_rev()` but raises a bare `error.RevlogError` if node
81 /// is not found.
71 /// is not found.
82 ///
72 ///
83 /// No need to repeat `node` in the exception, `mercurial/revlog.py`
73 /// No need to repeat `node` in the exception, `mercurial/revlog.py`
84 /// will catch and rewrap with it
74 /// will catch and rewrap with it
85 def rev(&self, node: PyBytes) -> PyResult<Revision> {
75 def rev(&self, node: PyBytes) -> PyResult<Revision> {
86 self.get_rev(py, node)?.ok_or_else(|| revlog_error(py))
76 self.get_rev(py, node)?.ok_or_else(|| revlog_error(py))
87 }
77 }
88
78
89 /// return True if the node exist in the index
79 /// return True if the node exist in the index
90 def has_node(&self, node: PyBytes) -> PyResult<bool> {
80 def has_node(&self, node: PyBytes) -> PyResult<bool> {
91 self.get_rev(py, node).map(|opt| opt.is_some())
81 self.get_rev(py, node).map(|opt| opt.is_some())
92 }
82 }
93
83
94 /// find length of shortest hex nodeid of a binary ID
84 /// find length of shortest hex nodeid of a binary ID
95 def shortest(&self, node: PyBytes) -> PyResult<usize> {
85 def shortest(&self, node: PyBytes) -> PyResult<usize> {
96 let opt = self.get_nodetree(py)?.borrow();
86 let opt = self.get_nodetree(py)?.borrow();
97 let nt = opt.as_ref().unwrap();
87 let nt = opt.as_ref().unwrap();
98 let idx = &*self.cindex(py).borrow();
88 let idx = &*self.cindex(py).borrow();
99 match nt.unique_prefix_len_node(idx, &node_from_py_bytes(py, &node)?)
89 match nt.unique_prefix_len_node(idx, &node_from_py_bytes(py, &node)?)
100 {
90 {
101 Ok(Some(l)) => Ok(l),
91 Ok(Some(l)) => Ok(l),
102 Ok(None) => Err(revlog_error(py)),
92 Ok(None) => Err(revlog_error(py)),
103 Err(e) => Err(nodemap_error(py, e)),
93 Err(e) => Err(nodemap_error(py, e)),
104 }
94 }
105 }
95 }
106
96
107 def partialmatch(&self, pynode: PyObject) -> PyResult<Option<PyBytes>> {
97 def partialmatch(&self, node: PyObject) -> PyResult<Option<PyBytes>> {
108 let opt = self.get_nodetree(py)?.borrow();
98 let opt = self.get_nodetree(py)?.borrow();
109 let nt = opt.as_ref().unwrap();
99 let nt = opt.as_ref().unwrap();
110 let idx = &*self.cindex(py).borrow();
100 let idx = &*self.cindex(py).borrow();
111
101
112 let node_as_string = if cfg!(feature = "python3-sys") {
102 let node_as_string = if cfg!(feature = "python3-sys") {
113 pynode.cast_as::<PyString>(py)?.to_string(py)?.to_string()
103 node.cast_as::<PyString>(py)?.to_string(py)?.to_string()
114 }
104 }
115 else {
105 else {
116 let node = pynode.extract::<PyBytes>(py)?;
106 let node = node.extract::<PyBytes>(py)?;
117 String::from_utf8_lossy(node.data(py)).to_string()
107 String::from_utf8_lossy(node.data(py)).to_string()
118 };
108 };
119
109
120 let prefix = NodePrefix::from_hex(&node_as_string).map_err(|_| PyErr::new::<ValueError, _>(py, "Invalid node or prefix"))?;
110 let prefix = NodePrefix::from_hex(&node_as_string).map_err(|_| PyErr::new::<ValueError, _>(py, "Invalid node or prefix"))?;
121
111
122 match nt.find_bin(idx, prefix) {
112 nt.find_bin(idx, prefix)
123 Ok(None) =>
113 // TODO make an inner API returning the node directly
124 // fallback to C implementation, remove once
114 .map(|opt| opt.map(
125 // https://bz.mercurial-scm.org/show_bug.cgi?id=6554
115 |rev| PyBytes::new(py, idx.node(rev).unwrap().as_bytes())))
126 // is fixed (a simple backout should do)
116 .map_err(|e| nodemap_error(py, e))
127 self.call_cindex(
117
128 py, "partialmatch",
129 &PyTuple::new(py, &[pynode]), None
130 )?.extract(py),
131 Ok(Some(rev)) =>
132 Ok(Some(PyBytes::new(py, idx.node(rev).unwrap().as_bytes()))),
133 Err(e) => Err(nodemap_error(py, e)),
134 }
135 }
118 }
136
119
137 /// append an index entry
120 /// append an index entry
138 def append(&self, tup: PyTuple) -> PyResult<PyObject> {
121 def append(&self, tup: PyTuple) -> PyResult<PyObject> {
139 if tup.len(py) < 8 {
122 if tup.len(py) < 8 {
140 // this is better than the panic promised by tup.get_item()
123 // this is better than the panic promised by tup.get_item()
141 return Err(
124 return Err(
142 PyErr::new::<IndexError, _>(py, "tuple index out of range"))
125 PyErr::new::<IndexError, _>(py, "tuple index out of range"))
143 }
126 }
144 let node_bytes = tup.get_item(py, 7).extract(py)?;
127 let node_bytes = tup.get_item(py, 7).extract(py)?;
145 let node = node_from_py_object(py, &node_bytes)?;
128 let node = node_from_py_object(py, &node_bytes)?;
146
129
147 let mut idx = self.cindex(py).borrow_mut();
130 let mut idx = self.cindex(py).borrow_mut();
148 let rev = idx.len() as Revision;
131 let rev = idx.len() as Revision;
149
132
150 idx.append(py, tup)?;
133 idx.append(py, tup)?;
151 self.get_nodetree(py)?.borrow_mut().as_mut().unwrap()
134 self.get_nodetree(py)?.borrow_mut().as_mut().unwrap()
152 .insert(&*idx, &node, rev)
135 .insert(&*idx, &node, rev)
153 .map_err(|e| nodemap_error(py, e))?;
136 .map_err(|e| nodemap_error(py, e))?;
154 Ok(py.None())
137 Ok(py.None())
155 }
138 }
156
139
157 def __delitem__(&self, key: PyObject) -> PyResult<()> {
140 def __delitem__(&self, key: PyObject) -> PyResult<()> {
158 // __delitem__ is both for `del idx[r]` and `del idx[r1:r2]`
141 // __delitem__ is both for `del idx[r]` and `del idx[r1:r2]`
159 self.cindex(py).borrow().inner().del_item(py, key)?;
142 self.cindex(py).borrow().inner().del_item(py, key)?;
160 let mut opt = self.get_nodetree(py)?.borrow_mut();
143 let mut opt = self.get_nodetree(py)?.borrow_mut();
161 let mut nt = opt.as_mut().unwrap();
144 let mut nt = opt.as_mut().unwrap();
162 nt.invalidate_all();
145 nt.invalidate_all();
163 self.fill_nodemap(py, &mut nt)?;
146 self.fill_nodemap(py, &mut nt)?;
164 Ok(())
147 Ok(())
165 }
148 }
166
149
167 //
150 //
168 // Reforwarded C index API
151 // Reforwarded C index API
169 //
152 //
170
153
171 // index_methods (tp_methods). Same ordering as in revlog.c
154 // index_methods (tp_methods). Same ordering as in revlog.c
172
155
173 /// return the gca set of the given revs
156 /// return the gca set of the given revs
174 def ancestors(&self, *args, **kw) -> PyResult<PyObject> {
157 def ancestors(&self, *args, **kw) -> PyResult<PyObject> {
175 self.call_cindex(py, "ancestors", args, kw)
158 self.call_cindex(py, "ancestors", args, kw)
176 }
159 }
177
160
178 /// return the heads of the common ancestors of the given revs
161 /// return the heads of the common ancestors of the given revs
179 def commonancestorsheads(&self, *args, **kw) -> PyResult<PyObject> {
162 def commonancestorsheads(&self, *args, **kw) -> PyResult<PyObject> {
180 self.call_cindex(py, "commonancestorsheads", args, kw)
163 self.call_cindex(py, "commonancestorsheads", args, kw)
181 }
164 }
182
165
183 /// Clear the index caches and inner py_class data.
166 /// Clear the index caches and inner py_class data.
184 /// It is Python's responsibility to call `update_nodemap_data` again.
167 /// It is Python's responsibility to call `update_nodemap_data` again.
185 def clearcaches(&self, *args, **kw) -> PyResult<PyObject> {
168 def clearcaches(&self, *args, **kw) -> PyResult<PyObject> {
186 self.nt(py).borrow_mut().take();
169 self.nt(py).borrow_mut().take();
187 self.docket(py).borrow_mut().take();
170 self.docket(py).borrow_mut().take();
188 self.mmap(py).borrow_mut().take();
171 self.mmap(py).borrow_mut().take();
189 self.call_cindex(py, "clearcaches", args, kw)
172 self.call_cindex(py, "clearcaches", args, kw)
190 }
173 }
191
174
192 /// return the raw binary string representing a revision
175 /// return the raw binary string representing a revision
193 def entry_binary(&self, *args, **kw) -> PyResult<PyObject> {
176 def entry_binary(&self, *args, **kw) -> PyResult<PyObject> {
194 self.call_cindex(py, "entry_binary", args, kw)
177 self.call_cindex(py, "entry_binary", args, kw)
195 }
178 }
196
179
197 /// return a binary packed version of the header
180 /// return a binary packed version of the header
198 def pack_header(&self, *args, **kw) -> PyResult<PyObject> {
181 def pack_header(&self, *args, **kw) -> PyResult<PyObject> {
199 self.call_cindex(py, "pack_header", args, kw)
182 self.call_cindex(py, "pack_header", args, kw)
200 }
183 }
201
184
202 /// get an index entry
185 /// get an index entry
203 def get(&self, *args, **kw) -> PyResult<PyObject> {
186 def get(&self, *args, **kw) -> PyResult<PyObject> {
204 self.call_cindex(py, "get", args, kw)
187 self.call_cindex(py, "get", args, kw)
205 }
188 }
206
189
207 /// compute phases
190 /// compute phases
208 def computephasesmapsets(&self, *args, **kw) -> PyResult<PyObject> {
191 def computephasesmapsets(&self, *args, **kw) -> PyResult<PyObject> {
209 self.call_cindex(py, "computephasesmapsets", args, kw)
192 self.call_cindex(py, "computephasesmapsets", args, kw)
210 }
193 }
211
194
212 /// reachableroots
195 /// reachableroots
213 def reachableroots2(&self, *args, **kw) -> PyResult<PyObject> {
196 def reachableroots2(&self, *args, **kw) -> PyResult<PyObject> {
214 self.call_cindex(py, "reachableroots2", args, kw)
197 self.call_cindex(py, "reachableroots2", args, kw)
215 }
198 }
216
199
217 /// get head revisions
200 /// get head revisions
218 def headrevs(&self, *args, **kw) -> PyResult<PyObject> {
201 def headrevs(&self, *args, **kw) -> PyResult<PyObject> {
219 self.call_cindex(py, "headrevs", args, kw)
202 self.call_cindex(py, "headrevs", args, kw)
220 }
203 }
221
204
222 /// get filtered head revisions
205 /// get filtered head revisions
223 def headrevsfiltered(&self, *args, **kw) -> PyResult<PyObject> {
206 def headrevsfiltered(&self, *args, **kw) -> PyResult<PyObject> {
224 self.call_cindex(py, "headrevsfiltered", args, kw)
207 self.call_cindex(py, "headrevsfiltered", args, kw)
225 }
208 }
226
209
227 /// True if the object is a snapshot
210 /// True if the object is a snapshot
228 def issnapshot(&self, *args, **kw) -> PyResult<PyObject> {
211 def issnapshot(&self, *args, **kw) -> PyResult<PyObject> {
229 self.call_cindex(py, "issnapshot", args, kw)
212 self.call_cindex(py, "issnapshot", args, kw)
230 }
213 }
231
214
232 /// Gather snapshot data in a cache dict
215 /// Gather snapshot data in a cache dict
233 def findsnapshots(&self, *args, **kw) -> PyResult<PyObject> {
216 def findsnapshots(&self, *args, **kw) -> PyResult<PyObject> {
234 self.call_cindex(py, "findsnapshots", args, kw)
217 self.call_cindex(py, "findsnapshots", args, kw)
235 }
218 }
236
219
237 /// determine revisions with deltas to reconstruct fulltext
220 /// determine revisions with deltas to reconstruct fulltext
238 def deltachain(&self, *args, **kw) -> PyResult<PyObject> {
221 def deltachain(&self, *args, **kw) -> PyResult<PyObject> {
239 self.call_cindex(py, "deltachain", args, kw)
222 self.call_cindex(py, "deltachain", args, kw)
240 }
223 }
241
224
242 /// slice planned chunk read to reach a density threshold
225 /// slice planned chunk read to reach a density threshold
243 def slicechunktodensity(&self, *args, **kw) -> PyResult<PyObject> {
226 def slicechunktodensity(&self, *args, **kw) -> PyResult<PyObject> {
244 self.call_cindex(py, "slicechunktodensity", args, kw)
227 self.call_cindex(py, "slicechunktodensity", args, kw)
245 }
228 }
246
229
247 /// stats for the index
230 /// stats for the index
248 def stats(&self, *args, **kw) -> PyResult<PyObject> {
231 def stats(&self, *args, **kw) -> PyResult<PyObject> {
249 self.call_cindex(py, "stats", args, kw)
232 self.call_cindex(py, "stats", args, kw)
250 }
233 }
251
234
252 // index_sequence_methods and index_mapping_methods.
235 // index_sequence_methods and index_mapping_methods.
253 //
236 //
254 // Since we call back through the high level Python API,
237 // Since we call back through the high level Python API,
255 // there's no point making a distinction between index_get
238 // there's no point making a distinction between index_get
256 // and index_getitem.
239 // and index_getitem.
257
240
258 def __len__(&self) -> PyResult<usize> {
241 def __len__(&self) -> PyResult<usize> {
259 self.cindex(py).borrow().inner().len(py)
242 self.cindex(py).borrow().inner().len(py)
260 }
243 }
261
244
262 def __getitem__(&self, key: PyObject) -> PyResult<PyObject> {
245 def __getitem__(&self, key: PyObject) -> PyResult<PyObject> {
263 // this conversion seems needless, but that's actually because
246 // this conversion seems needless, but that's actually because
264 // `index_getitem` does not handle conversion from PyLong,
247 // `index_getitem` does not handle conversion from PyLong,
265 // which expressions such as [e for e in index] internally use.
248 // which expressions such as [e for e in index] internally use.
266 // Note that we don't seem to have a direct way to call
249 // Note that we don't seem to have a direct way to call
267 // PySequence_GetItem (does the job), which would possibly be better
250 // PySequence_GetItem (does the job), which would possibly be better
268 // for performance
251 // for performance
269 let key = match key.extract::<Revision>(py) {
252 let key = match key.extract::<Revision>(py) {
270 Ok(rev) => rev.to_py_object(py).into_object(),
253 Ok(rev) => rev.to_py_object(py).into_object(),
271 Err(_) => key,
254 Err(_) => key,
272 };
255 };
273 self.cindex(py).borrow().inner().get_item(py, key)
256 self.cindex(py).borrow().inner().get_item(py, key)
274 }
257 }
275
258
276 def __setitem__(&self, key: PyObject, value: PyObject) -> PyResult<()> {
259 def __setitem__(&self, key: PyObject, value: PyObject) -> PyResult<()> {
277 self.cindex(py).borrow().inner().set_item(py, key, value)
260 self.cindex(py).borrow().inner().set_item(py, key, value)
278 }
261 }
279
262
280 def __contains__(&self, item: PyObject) -> PyResult<bool> {
263 def __contains__(&self, item: PyObject) -> PyResult<bool> {
281 // ObjectProtocol does not seem to provide contains(), so
264 // ObjectProtocol does not seem to provide contains(), so
282 // this is an equivalent implementation of the index_contains()
265 // this is an equivalent implementation of the index_contains()
283 // defined in revlog.c
266 // defined in revlog.c
284 let cindex = self.cindex(py).borrow();
267 let cindex = self.cindex(py).borrow();
285 match item.extract::<Revision>(py) {
268 match item.extract::<Revision>(py) {
286 Ok(rev) => {
269 Ok(rev) => {
287 Ok(rev >= -1 && rev < cindex.inner().len(py)? as Revision)
270 Ok(rev >= -1 && rev < cindex.inner().len(py)? as Revision)
288 }
271 }
289 Err(_) => {
272 Err(_) => {
290 cindex.inner().call_method(
273 cindex.inner().call_method(
291 py,
274 py,
292 "has_node",
275 "has_node",
293 PyTuple::new(py, &[item]),
276 PyTuple::new(py, &[item]),
294 None)?
277 None)?
295 .extract(py)
278 .extract(py)
296 }
279 }
297 }
280 }
298 }
281 }
299
282
300 def nodemap_data_all(&self) -> PyResult<PyBytes> {
283 def nodemap_data_all(&self) -> PyResult<PyBytes> {
301 self.inner_nodemap_data_all(py)
284 self.inner_nodemap_data_all(py)
302 }
285 }
303
286
304 def nodemap_data_incremental(&self) -> PyResult<PyObject> {
287 def nodemap_data_incremental(&self) -> PyResult<PyObject> {
305 self.inner_nodemap_data_incremental(py)
288 self.inner_nodemap_data_incremental(py)
306 }
289 }
307 def update_nodemap_data(
290 def update_nodemap_data(
308 &self,
291 &self,
309 docket: PyObject,
292 docket: PyObject,
310 nm_data: PyObject
293 nm_data: PyObject
311 ) -> PyResult<PyObject> {
294 ) -> PyResult<PyObject> {
312 self.inner_update_nodemap_data(py, docket, nm_data)
295 self.inner_update_nodemap_data(py, docket, nm_data)
313 }
296 }
314
297
315 @property
298 @property
316 def entry_size(&self) -> PyResult<PyInt> {
299 def entry_size(&self) -> PyResult<PyInt> {
317 self.cindex(py).borrow().inner().getattr(py, "entry_size")?.extract::<PyInt>(py)
300 self.cindex(py).borrow().inner().getattr(py, "entry_size")?.extract::<PyInt>(py)
318 }
301 }
319
302
320 @property
303 @property
321 def rust_ext_compat(&self) -> PyResult<PyInt> {
304 def rust_ext_compat(&self) -> PyResult<PyInt> {
322 self.cindex(py).borrow().inner().getattr(py, "rust_ext_compat")?.extract::<PyInt>(py)
305 self.cindex(py).borrow().inner().getattr(py, "rust_ext_compat")?.extract::<PyInt>(py)
323 }
306 }
324
307
325 });
308 });
326
309
327 impl MixedIndex {
310 impl MixedIndex {
328 fn new(py: Python, cindex: PyObject) -> PyResult<MixedIndex> {
311 fn new(py: Python, cindex: PyObject) -> PyResult<MixedIndex> {
329 Self::create_instance(
312 Self::create_instance(
330 py,
313 py,
331 RefCell::new(cindex::Index::new(py, cindex)?),
314 RefCell::new(cindex::Index::new(py, cindex)?),
332 RefCell::new(None),
315 RefCell::new(None),
333 RefCell::new(None),
316 RefCell::new(None),
334 RefCell::new(None),
317 RefCell::new(None),
335 )
318 )
336 }
319 }
337
320
338 /// This is scaffolding at this point, but it could also become
321 /// This is scaffolding at this point, but it could also become
339 /// a way to start a persistent nodemap or perform a
322 /// a way to start a persistent nodemap or perform a
340 /// vacuum / repack operation
323 /// vacuum / repack operation
341 fn fill_nodemap(
324 fn fill_nodemap(
342 &self,
325 &self,
343 py: Python,
326 py: Python,
344 nt: &mut NodeTree,
327 nt: &mut NodeTree,
345 ) -> PyResult<PyObject> {
328 ) -> PyResult<PyObject> {
346 let index = self.cindex(py).borrow();
329 let index = self.cindex(py).borrow();
347 for r in 0..index.len() {
330 for r in 0..index.len() {
348 let rev = r as Revision;
331 let rev = r as Revision;
349 // in this case node() won't ever return None
332 // in this case node() won't ever return None
350 nt.insert(&*index, index.node(rev).unwrap(), rev)
333 nt.insert(&*index, index.node(rev).unwrap(), rev)
351 .map_err(|e| nodemap_error(py, e))?
334 .map_err(|e| nodemap_error(py, e))?
352 }
335 }
353 Ok(py.None())
336 Ok(py.None())
354 }
337 }
355
338
356 fn get_nodetree<'a>(
339 fn get_nodetree<'a>(
357 &'a self,
340 &'a self,
358 py: Python<'a>,
341 py: Python<'a>,
359 ) -> PyResult<&'a RefCell<Option<NodeTree>>> {
342 ) -> PyResult<&'a RefCell<Option<NodeTree>>> {
360 if self.nt(py).borrow().is_none() {
343 if self.nt(py).borrow().is_none() {
361 let readonly = Box::new(Vec::new());
344 let readonly = Box::new(Vec::new());
362 let mut nt = NodeTree::load_bytes(readonly, 0);
345 let mut nt = NodeTree::load_bytes(readonly, 0);
363 self.fill_nodemap(py, &mut nt)?;
346 self.fill_nodemap(py, &mut nt)?;
364 self.nt(py).borrow_mut().replace(nt);
347 self.nt(py).borrow_mut().replace(nt);
365 }
348 }
366 Ok(self.nt(py))
349 Ok(self.nt(py))
367 }
350 }
368
351
369 /// forward a method call to the underlying C index
352 /// forward a method call to the underlying C index
370 fn call_cindex(
353 fn call_cindex(
371 &self,
354 &self,
372 py: Python,
355 py: Python,
373 name: &str,
356 name: &str,
374 args: &PyTuple,
357 args: &PyTuple,
375 kwargs: Option<&PyDict>,
358 kwargs: Option<&PyDict>,
376 ) -> PyResult<PyObject> {
359 ) -> PyResult<PyObject> {
377 self.cindex(py)
360 self.cindex(py)
378 .borrow()
361 .borrow()
379 .inner()
362 .inner()
380 .call_method(py, name, args, kwargs)
363 .call_method(py, name, args, kwargs)
381 }
364 }
382
365
383 pub fn clone_cindex(&self, py: Python) -> cindex::Index {
366 pub fn clone_cindex(&self, py: Python) -> cindex::Index {
384 self.cindex(py).borrow().clone_ref(py)
367 self.cindex(py).borrow().clone_ref(py)
385 }
368 }
386
369
387 /// Returns the full nodemap bytes to be written as-is to disk
370 /// Returns the full nodemap bytes to be written as-is to disk
388 fn inner_nodemap_data_all(&self, py: Python) -> PyResult<PyBytes> {
371 fn inner_nodemap_data_all(&self, py: Python) -> PyResult<PyBytes> {
389 let nodemap = self.get_nodetree(py)?.borrow_mut().take().unwrap();
372 let nodemap = self.get_nodetree(py)?.borrow_mut().take().unwrap();
390 let (readonly, bytes) = nodemap.into_readonly_and_added_bytes();
373 let (readonly, bytes) = nodemap.into_readonly_and_added_bytes();
391
374
392 // If there's anything readonly, we need to build the data again from
375 // If there's anything readonly, we need to build the data again from
393 // scratch
376 // scratch
394 let bytes = if readonly.len() > 0 {
377 let bytes = if readonly.len() > 0 {
395 let mut nt = NodeTree::load_bytes(Box::new(vec![]), 0);
378 let mut nt = NodeTree::load_bytes(Box::new(vec![]), 0);
396 self.fill_nodemap(py, &mut nt)?;
379 self.fill_nodemap(py, &mut nt)?;
397
380
398 let (readonly, bytes) = nt.into_readonly_and_added_bytes();
381 let (readonly, bytes) = nt.into_readonly_and_added_bytes();
399 assert_eq!(readonly.len(), 0);
382 assert_eq!(readonly.len(), 0);
400
383
401 bytes
384 bytes
402 } else {
385 } else {
403 bytes
386 bytes
404 };
387 };
405
388
406 let bytes = PyBytes::new(py, &bytes);
389 let bytes = PyBytes::new(py, &bytes);
407 Ok(bytes)
390 Ok(bytes)
408 }
391 }
409
392
410 /// Returns the last saved docket along with the size of any changed data
393 /// Returns the last saved docket along with the size of any changed data
411 /// (in number of blocks), and said data as bytes.
394 /// (in number of blocks), and said data as bytes.
412 fn inner_nodemap_data_incremental(
395 fn inner_nodemap_data_incremental(
413 &self,
396 &self,
414 py: Python,
397 py: Python,
415 ) -> PyResult<PyObject> {
398 ) -> PyResult<PyObject> {
416 let docket = self.docket(py).borrow();
399 let docket = self.docket(py).borrow();
417 let docket = match docket.as_ref() {
400 let docket = match docket.as_ref() {
418 Some(d) => d,
401 Some(d) => d,
419 None => return Ok(py.None()),
402 None => return Ok(py.None()),
420 };
403 };
421
404
422 let node_tree = self.get_nodetree(py)?.borrow_mut().take().unwrap();
405 let node_tree = self.get_nodetree(py)?.borrow_mut().take().unwrap();
423 let masked_blocks = node_tree.masked_readonly_blocks();
406 let masked_blocks = node_tree.masked_readonly_blocks();
424 let (_, data) = node_tree.into_readonly_and_added_bytes();
407 let (_, data) = node_tree.into_readonly_and_added_bytes();
425 let changed = masked_blocks * std::mem::size_of::<Block>();
408 let changed = masked_blocks * std::mem::size_of::<Block>();
426
409
427 Ok((docket, changed, PyBytes::new(py, &data))
410 Ok((docket, changed, PyBytes::new(py, &data))
428 .to_py_object(py)
411 .to_py_object(py)
429 .into_object())
412 .into_object())
430 }
413 }
431
414
432 /// Update the nodemap from the new (mmaped) data.
415 /// Update the nodemap from the new (mmaped) data.
433 /// The docket is kept as a reference for later incremental calls.
416 /// The docket is kept as a reference for later incremental calls.
434 fn inner_update_nodemap_data(
417 fn inner_update_nodemap_data(
435 &self,
418 &self,
436 py: Python,
419 py: Python,
437 docket: PyObject,
420 docket: PyObject,
438 nm_data: PyObject,
421 nm_data: PyObject,
439 ) -> PyResult<PyObject> {
422 ) -> PyResult<PyObject> {
440 let buf = PyBuffer::get(py, &nm_data)?;
423 let buf = PyBuffer::get(py, &nm_data)?;
441 let len = buf.item_count();
424 let len = buf.item_count();
442
425
443 // Build a slice from the mmap'ed buffer data
426 // Build a slice from the mmap'ed buffer data
444 let cbuf = buf.buf_ptr();
427 let cbuf = buf.buf_ptr();
445 let bytes = if std::mem::size_of::<u8>() == buf.item_size()
428 let bytes = if std::mem::size_of::<u8>() == buf.item_size()
446 && buf.is_c_contiguous()
429 && buf.is_c_contiguous()
447 && u8::is_compatible_format(buf.format())
430 && u8::is_compatible_format(buf.format())
448 {
431 {
449 unsafe { std::slice::from_raw_parts(cbuf as *const u8, len) }
432 unsafe { std::slice::from_raw_parts(cbuf as *const u8, len) }
450 } else {
433 } else {
451 return Err(PyErr::new::<ValueError, _>(
434 return Err(PyErr::new::<ValueError, _>(
452 py,
435 py,
453 "Nodemap data buffer has an invalid memory representation"
436 "Nodemap data buffer has an invalid memory representation"
454 .to_string(),
437 .to_string(),
455 ));
438 ));
456 };
439 };
457
440
458 // Keep a reference to the mmap'ed buffer, otherwise we get a dangling
441 // Keep a reference to the mmap'ed buffer, otherwise we get a dangling
459 // pointer.
442 // pointer.
460 self.mmap(py).borrow_mut().replace(buf);
443 self.mmap(py).borrow_mut().replace(buf);
461
444
462 let mut nt = NodeTree::load_bytes(Box::new(bytes), len);
445 let mut nt = NodeTree::load_bytes(Box::new(bytes), len);
463
446
464 let data_tip =
447 let data_tip =
465 docket.getattr(py, "tip_rev")?.extract::<Revision>(py)?;
448 docket.getattr(py, "tip_rev")?.extract::<Revision>(py)?;
466 self.docket(py).borrow_mut().replace(docket.clone_ref(py));
449 self.docket(py).borrow_mut().replace(docket.clone_ref(py));
467 let idx = self.cindex(py).borrow();
450 let idx = self.cindex(py).borrow();
468 let current_tip = idx.len();
451 let current_tip = idx.len();
469
452
470 for r in (data_tip + 1)..current_tip as Revision {
453 for r in (data_tip + 1)..current_tip as Revision {
471 let rev = r as Revision;
454 let rev = r as Revision;
472 // in this case node() won't ever return None
455 // in this case node() won't ever return None
473 nt.insert(&*idx, idx.node(rev).unwrap(), rev)
456 nt.insert(&*idx, idx.node(rev).unwrap(), rev)
474 .map_err(|e| nodemap_error(py, e))?
457 .map_err(|e| nodemap_error(py, e))?
475 }
458 }
476
459
477 *self.nt(py).borrow_mut() = Some(nt);
460 *self.nt(py).borrow_mut() = Some(nt);
478
461
479 Ok(py.None())
462 Ok(py.None())
480 }
463 }
481 }
464 }
482
465
483 fn revlog_error(py: Python) -> PyErr {
466 fn revlog_error(py: Python) -> PyErr {
484 match py
467 match py
485 .import("mercurial.error")
468 .import("mercurial.error")
486 .and_then(|m| m.get(py, "RevlogError"))
469 .and_then(|m| m.get(py, "RevlogError"))
487 {
470 {
488 Err(e) => e,
471 Err(e) => e,
489 Ok(cls) => PyErr::from_instance(
472 Ok(cls) => PyErr::from_instance(
490 py,
473 py,
491 cls.call(py, (py.None(),), None).ok().into_py_object(py),
474 cls.call(py, (py.None(),), None).ok().into_py_object(py),
492 ),
475 ),
493 }
476 }
494 }
477 }
495
478
496 fn rev_not_in_index(py: Python, rev: Revision) -> PyErr {
479 fn rev_not_in_index(py: Python, rev: Revision) -> PyErr {
497 PyErr::new::<ValueError, _>(
480 PyErr::new::<ValueError, _>(
498 py,
481 py,
499 format!(
482 format!(
500 "Inconsistency: Revision {} found in nodemap \
483 "Inconsistency: Revision {} found in nodemap \
501 is not in revlog index",
484 is not in revlog index",
502 rev
485 rev
503 ),
486 ),
504 )
487 )
505 }
488 }
506
489
507 /// Standard treatment of NodeMapError
490 /// Standard treatment of NodeMapError
508 fn nodemap_error(py: Python, err: NodeMapError) -> PyErr {
491 fn nodemap_error(py: Python, err: NodeMapError) -> PyErr {
509 match err {
492 match err {
510 NodeMapError::MultipleResults => revlog_error(py),
493 NodeMapError::MultipleResults => revlog_error(py),
511 NodeMapError::RevisionNotInIndex(r) => rev_not_in_index(py, r),
494 NodeMapError::RevisionNotInIndex(r) => rev_not_in_index(py, r),
512 }
495 }
513 }
496 }
514
497
515 /// Create the module, with __package__ given from parent
498 /// Create the module, with __package__ given from parent
516 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
499 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
517 let dotted_name = &format!("{}.revlog", package);
500 let dotted_name = &format!("{}.revlog", package);
518 let m = PyModule::new(py, dotted_name)?;
501 let m = PyModule::new(py, dotted_name)?;
519 m.add(py, "__package__", package)?;
502 m.add(py, "__package__", package)?;
520 m.add(py, "__doc__", "RevLog - Rust implementations")?;
503 m.add(py, "__doc__", "RevLog - Rust implementations")?;
521
504
522 m.add_class::<MixedIndex>(py)?;
505 m.add_class::<MixedIndex>(py)?;
523
506
524 let sys = PyModule::import(py, "sys")?;
507 let sys = PyModule::import(py, "sys")?;
525 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
508 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
526 sys_modules.set_item(py, dotted_name, &m)?;
509 sys_modules.set_item(py, dotted_name, &m)?;
527
510
528 Ok(m)
511 Ok(m)
529 }
512 }
@@ -1,1295 +1,1255
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
439 Sub-case: fallback for corrupted data file
440 ------------------------------------------
441
442 Sabotaging the data file so that nodemap resolutions fail, triggering fallback to
443 (non-persistent) C implementation.
444
445
446 $ UUID=`hg debugnodemap --metadata| grep 'uid:' | \
447 > sed 's/uid: //'`
448 $ FILE=.hg/store/00changelog-"${UUID}".nd
449 $ python -c "fobj = open('$FILE', 'r+b'); fobj.write(b'\xff' * 121088); fobj.close()"
450
451 The nodemap data file is still considered in sync with the docket. This
452 would fail without the fallback to the (non-persistent) C implementation:
453
454 $ hg log -r b355ef8adce0949b8bdf6afc72ca853740d65944 -T '{rev}\n' --traceback
455 5002
456
457 The nodemap data file hasn't been fixed, more tests can be inserted:
458
459 $ hg debugnodemap --dump-disk | f --bytes=256 --hexdump --size
460 size=121088
461 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
462 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
463 0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
464 0030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
465 0040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
466 0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
467 0060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
468 0070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
469 0080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
470 0090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
471 00a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
472 00b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
473 00c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
474 00d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
475 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
476 00f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
477
478 $ mv ../tmp-data-file $FILE
438 $ mv ../tmp-data-file $FILE
479 $ mv ../tmp-docket .hg/store/00changelog.n
439 $ mv ../tmp-docket .hg/store/00changelog.n
480
440
481 Check transaction related property
441 Check transaction related property
482 ==================================
442 ==================================
483
443
484 An up to date nodemap should be available to shell hooks,
444 An up to date nodemap should be available to shell hooks,
485
445
486 $ echo dsljfl > a
446 $ echo dsljfl > a
487 $ hg add a
447 $ hg add a
488 $ hg ci -m a
448 $ hg ci -m a
489 $ hg debugnodemap --metadata
449 $ hg debugnodemap --metadata
490 uid: ???????? (glob)
450 uid: ???????? (glob)
491 tip-rev: 5003
451 tip-rev: 5003
492 tip-node: a52c5079765b5865d97b993b303a18740113bbb2
452 tip-node: a52c5079765b5865d97b993b303a18740113bbb2
493 data-length: 121088
453 data-length: 121088
494 data-unused: 0
454 data-unused: 0
495 data-unused: 0.000%
455 data-unused: 0.000%
496 $ echo babar2 > babar
456 $ echo babar2 > babar
497 $ 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"
498 uid: ???????? (glob)
458 uid: ???????? (glob)
499 tip-rev: 5004
459 tip-rev: 5004
500 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
460 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
501 data-length: 121280 (pure !)
461 data-length: 121280 (pure !)
502 data-length: 121280 (rust !)
462 data-length: 121280 (rust !)
503 data-length: 121088 (no-pure no-rust !)
463 data-length: 121088 (no-pure no-rust !)
504 data-unused: 192 (pure !)
464 data-unused: 192 (pure !)
505 data-unused: 192 (rust !)
465 data-unused: 192 (rust !)
506 data-unused: 0 (no-pure no-rust !)
466 data-unused: 0 (no-pure no-rust !)
507 data-unused: 0.158% (pure !)
467 data-unused: 0.158% (pure !)
508 data-unused: 0.158% (rust !)
468 data-unused: 0.158% (rust !)
509 data-unused: 0.000% (no-pure no-rust !)
469 data-unused: 0.000% (no-pure no-rust !)
510 $ hg debugnodemap --metadata
470 $ hg debugnodemap --metadata
511 uid: ???????? (glob)
471 uid: ???????? (glob)
512 tip-rev: 5004
472 tip-rev: 5004
513 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
473 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
514 data-length: 121280 (pure !)
474 data-length: 121280 (pure !)
515 data-length: 121280 (rust !)
475 data-length: 121280 (rust !)
516 data-length: 121088 (no-pure no-rust !)
476 data-length: 121088 (no-pure no-rust !)
517 data-unused: 192 (pure !)
477 data-unused: 192 (pure !)
518 data-unused: 192 (rust !)
478 data-unused: 192 (rust !)
519 data-unused: 0 (no-pure no-rust !)
479 data-unused: 0 (no-pure no-rust !)
520 data-unused: 0.158% (pure !)
480 data-unused: 0.158% (pure !)
521 data-unused: 0.158% (rust !)
481 data-unused: 0.158% (rust !)
522 data-unused: 0.000% (no-pure no-rust !)
482 data-unused: 0.000% (no-pure no-rust !)
523
483
524 Another process does not see the pending nodemap content during run.
484 Another process does not see the pending nodemap content during run.
525
485
526 $ echo qpoasp > a
486 $ echo qpoasp > a
527 $ hg ci -m a2 \
487 $ hg ci -m a2 \
528 > --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" \
529 > --config "hooks.txnclose=touch sync-txn-close" > output.txt 2>&1 &
489 > --config "hooks.txnclose=touch sync-txn-close" > output.txt 2>&1 &
530
490
531 (read the repository while the commit transaction is pending)
491 (read the repository while the commit transaction is pending)
532
492
533 $ sh "$RUNTESTDIR/testlib/wait-on-file" 20 sync-txn-pending && \
493 $ sh "$RUNTESTDIR/testlib/wait-on-file" 20 sync-txn-pending && \
534 > hg debugnodemap --metadata && \
494 > hg debugnodemap --metadata && \
535 > 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
536 uid: ???????? (glob)
496 uid: ???????? (glob)
537 tip-rev: 5004
497 tip-rev: 5004
538 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
498 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
539 data-length: 121280 (pure !)
499 data-length: 121280 (pure !)
540 data-length: 121280 (rust !)
500 data-length: 121280 (rust !)
541 data-length: 121088 (no-pure no-rust !)
501 data-length: 121088 (no-pure no-rust !)
542 data-unused: 192 (pure !)
502 data-unused: 192 (pure !)
543 data-unused: 192 (rust !)
503 data-unused: 192 (rust !)
544 data-unused: 0 (no-pure no-rust !)
504 data-unused: 0 (no-pure no-rust !)
545 data-unused: 0.158% (pure !)
505 data-unused: 0.158% (pure !)
546 data-unused: 0.158% (rust !)
506 data-unused: 0.158% (rust !)
547 data-unused: 0.000% (no-pure no-rust !)
507 data-unused: 0.000% (no-pure no-rust !)
548 $ hg debugnodemap --metadata
508 $ hg debugnodemap --metadata
549 uid: ???????? (glob)
509 uid: ???????? (glob)
550 tip-rev: 5005
510 tip-rev: 5005
551 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
511 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
552 data-length: 121536 (pure !)
512 data-length: 121536 (pure !)
553 data-length: 121536 (rust !)
513 data-length: 121536 (rust !)
554 data-length: 121088 (no-pure no-rust !)
514 data-length: 121088 (no-pure no-rust !)
555 data-unused: 448 (pure !)
515 data-unused: 448 (pure !)
556 data-unused: 448 (rust !)
516 data-unused: 448 (rust !)
557 data-unused: 0 (no-pure no-rust !)
517 data-unused: 0 (no-pure no-rust !)
558 data-unused: 0.369% (pure !)
518 data-unused: 0.369% (pure !)
559 data-unused: 0.369% (rust !)
519 data-unused: 0.369% (rust !)
560 data-unused: 0.000% (no-pure no-rust !)
520 data-unused: 0.000% (no-pure no-rust !)
561
521
562 $ cat output.txt
522 $ cat output.txt
563
523
564 Check that a failing transaction will properly revert the data
524 Check that a failing transaction will properly revert the data
565
525
566 $ echo plakfe > a
526 $ echo plakfe > a
567 $ f --size --sha256 .hg/store/00changelog-*.nd
527 $ f --size --sha256 .hg/store/00changelog-*.nd
568 .hg/store/00changelog-????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
528 .hg/store/00changelog-????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
569 .hg/store/00changelog-????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
529 .hg/store/00changelog-????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
570 .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 !)
571 $ 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"
572 transaction abort!
532 transaction abort!
573 rollback completed
533 rollback completed
574 abort: This is a late abort
534 abort: This is a late abort
575 [255]
535 [255]
576 $ hg debugnodemap --metadata
536 $ hg debugnodemap --metadata
577 uid: ???????? (glob)
537 uid: ???????? (glob)
578 tip-rev: 5005
538 tip-rev: 5005
579 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
539 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
580 data-length: 121536 (pure !)
540 data-length: 121536 (pure !)
581 data-length: 121536 (rust !)
541 data-length: 121536 (rust !)
582 data-length: 121088 (no-pure no-rust !)
542 data-length: 121088 (no-pure no-rust !)
583 data-unused: 448 (pure !)
543 data-unused: 448 (pure !)
584 data-unused: 448 (rust !)
544 data-unused: 448 (rust !)
585 data-unused: 0 (no-pure no-rust !)
545 data-unused: 0 (no-pure no-rust !)
586 data-unused: 0.369% (pure !)
546 data-unused: 0.369% (pure !)
587 data-unused: 0.369% (rust !)
547 data-unused: 0.369% (rust !)
588 data-unused: 0.000% (no-pure no-rust !)
548 data-unused: 0.000% (no-pure no-rust !)
589 $ f --size --sha256 .hg/store/00changelog-*.nd
549 $ f --size --sha256 .hg/store/00changelog-*.nd
590 .hg/store/00changelog-????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
550 .hg/store/00changelog-????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
591 .hg/store/00changelog-????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
551 .hg/store/00changelog-????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
592 .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 !)
593
553
594 Check that removing content does not confuse the nodemap
554 Check that removing content does not confuse the nodemap
595 --------------------------------------------------------
555 --------------------------------------------------------
596
556
597 removing data with rollback
557 removing data with rollback
598
558
599 $ echo aso > a
559 $ echo aso > a
600 $ hg ci -m a4
560 $ hg ci -m a4
601 $ hg rollback
561 $ hg rollback
602 repository tip rolled back to revision 5005 (undo commit)
562 repository tip rolled back to revision 5005 (undo commit)
603 working directory now based on revision 5005
563 working directory now based on revision 5005
604 $ hg id -r .
564 $ hg id -r .
605 90d5d3ba2fc4 tip
565 90d5d3ba2fc4 tip
606
566
607 removing data with strip
567 removing data with strip
608
568
609 $ echo aso > a
569 $ echo aso > a
610 $ hg ci -m a4
570 $ hg ci -m a4
611 $ hg --config extensions.strip= strip -r . --no-backup
571 $ hg --config extensions.strip= strip -r . --no-backup
612 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
613 $ hg id -r . --traceback
573 $ hg id -r . --traceback
614 90d5d3ba2fc4 tip
574 90d5d3ba2fc4 tip
615
575
616 (be a good citizen and regenerate the nodemap)
576 (be a good citizen and regenerate the nodemap)
617 $ hg debugupdatecaches
577 $ hg debugupdatecaches
618 $ hg debugnodemap --metadata
578 $ hg debugnodemap --metadata
619 uid: * (glob)
579 uid: * (glob)
620 tip-rev: 5005
580 tip-rev: 5005
621 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
581 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
622 data-length: 121088
582 data-length: 121088
623 data-unused: 0
583 data-unused: 0
624 data-unused: 0.000%
584 data-unused: 0.000%
625
585
626 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
627 ---------------------------------------------------------------------------
587 ---------------------------------------------------------------------------
628
588
629 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
630 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.
631 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
632 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
633 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
634
594
635 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
636 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.
637
597
638 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
639 read/write patterns.
599 read/write patterns.
640
600
641 $ cd ..
601 $ cd ..
642
602
643 #if rust
603 #if rust
644
604
645 $ cp -R test-repo race-repo
605 $ cp -R test-repo race-repo
646 $ 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
647 updating working directory
607 updating working directory
648 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
649 $ hg debugformat -R ./race-repo | egrep 'share-safe|persistent-nodemap'
609 $ hg debugformat -R ./race-repo | egrep 'share-safe|persistent-nodemap'
650 share-safe: yes
610 share-safe: yes
651 persistent-nodemap: yes
611 persistent-nodemap: yes
652 $ hg debugformat -R ./other-wc/ | egrep 'share-safe|persistent-nodemap'
612 $ hg debugformat -R ./other-wc/ | egrep 'share-safe|persistent-nodemap'
653 share-safe: yes
613 share-safe: yes
654 persistent-nodemap: yes
614 persistent-nodemap: yes
655 $ hg -R ./other-wc update 'min(head())'
615 $ hg -R ./other-wc update 'min(head())'
656 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
657 $ hg -R ./race-repo debugnodemap --metadata
617 $ hg -R ./race-repo debugnodemap --metadata
658 uid: 43c37dde
618 uid: 43c37dde
659 tip-rev: 5005
619 tip-rev: 5005
660 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
620 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
661 data-length: 121088
621 data-length: 121088
662 data-unused: 0
622 data-unused: 0
663 data-unused: 0.000%
623 data-unused: 0.000%
664 $ hg -R ./race-repo log -G -r 'head()'
624 $ hg -R ./race-repo log -G -r 'head()'
665 @ changeset: 5005:90d5d3ba2fc4
625 @ changeset: 5005:90d5d3ba2fc4
666 | tag: tip
626 | tag: tip
667 ~ user: test
627 ~ user: test
668 date: Thu Jan 01 00:00:00 1970 +0000
628 date: Thu Jan 01 00:00:00 1970 +0000
669 summary: a2
629 summary: a2
670
630
671 o changeset: 5001:16395c3cf7e2
631 o changeset: 5001:16395c3cf7e2
672 | user: test
632 | user: test
673 ~ date: Thu Jan 01 00:00:00 1970 +0000
633 ~ date: Thu Jan 01 00:00:00 1970 +0000
674 summary: foo
634 summary: foo
675
635
676 $ hg -R ./other-wc log -G -r 'head()'
636 $ hg -R ./other-wc log -G -r 'head()'
677 o changeset: 5005:90d5d3ba2fc4
637 o changeset: 5005:90d5d3ba2fc4
678 | tag: tip
638 | tag: tip
679 ~ user: test
639 ~ user: test
680 date: Thu Jan 01 00:00:00 1970 +0000
640 date: Thu Jan 01 00:00:00 1970 +0000
681 summary: a2
641 summary: a2
682
642
683 @ changeset: 5001:16395c3cf7e2
643 @ changeset: 5001:16395c3cf7e2
684 | user: test
644 | user: test
685 ~ date: Thu Jan 01 00:00:00 1970 +0000
645 ~ date: Thu Jan 01 00:00:00 1970 +0000
686 summary: foo
646 summary: foo
687
647
688 $ echo left-side-race > race-repo/left-side-race
648 $ echo left-side-race > race-repo/left-side-race
689 $ hg -R ./race-repo/ add race-repo/left-side-race
649 $ hg -R ./race-repo/ add race-repo/left-side-race
690
650
691 $ echo right-side-race > ./other-wc/right-side-race
651 $ echo right-side-race > ./other-wc/right-side-race
692 $ hg -R ./other-wc/ add ./other-wc/right-side-race
652 $ hg -R ./other-wc/ add ./other-wc/right-side-race
693
653
694 $ mkdir sync-files
654 $ mkdir sync-files
695 $ mkdir outputs
655 $ mkdir outputs
696 $ (
656 $ (
697 > hg -R ./race-repo/ commit -m left-side-commit \
657 > hg -R ./race-repo/ commit -m left-side-commit \
698 > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \
658 > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \
699 > --config 'devel.nodemap-race.role=left';
659 > --config 'devel.nodemap-race.role=left';
700 > touch sync-files/left-done
660 > touch sync-files/left-done
701 > ) > outputs/left.txt 2>&1 &
661 > ) > outputs/left.txt 2>&1 &
702 $ (
662 $ (
703 > hg -R ./other-wc/ commit -m right-side-commit \
663 > hg -R ./other-wc/ commit -m right-side-commit \
704 > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \
664 > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \
705 > --config 'devel.nodemap-race.role=right';
665 > --config 'devel.nodemap-race.role=right';
706 > touch sync-files/right-done
666 > touch sync-files/right-done
707 > ) > outputs/right.txt 2>&1 &
667 > ) > outputs/right.txt 2>&1 &
708 $ (
668 $ (
709 > hg -R ./race-repo/ check-nodemap-race \
669 > hg -R ./race-repo/ check-nodemap-race \
710 > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \
670 > --config "extensions.race=${RUNTESTDIR}/testlib/persistent-nodemap-race-ext.py" \
711 > --config 'devel.nodemap-race.role=reader';
671 > --config 'devel.nodemap-race.role=reader';
712 > touch sync-files/reader-done
672 > touch sync-files/reader-done
713 > ) > outputs/reader.txt 2>&1 &
673 > ) > outputs/reader.txt 2>&1 &
714 $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/left-done
674 $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/left-done
715 $ cat outputs/left.txt
675 $ cat outputs/left.txt
716 docket-details:
676 docket-details:
717 uid: 43c37dde
677 uid: 43c37dde
718 actual-tip: 5005
678 actual-tip: 5005
719 tip-rev: 5005
679 tip-rev: 5005
720 data-length: 121088
680 data-length: 121088
721 nodemap-race: left side locked and ready to commit
681 nodemap-race: left side locked and ready to commit
722 docket-details:
682 docket-details:
723 uid: 43c37dde
683 uid: 43c37dde
724 actual-tip: 5005
684 actual-tip: 5005
725 tip-rev: 5005
685 tip-rev: 5005
726 data-length: 121088
686 data-length: 121088
727 finalized changelog write
687 finalized changelog write
728 persisting changelog nodemap
688 persisting changelog nodemap
729 new data start at 121088
689 new data start at 121088
730 persisted changelog nodemap
690 persisted changelog nodemap
731 docket-details:
691 docket-details:
732 uid: 43c37dde
692 uid: 43c37dde
733 actual-tip: 5006
693 actual-tip: 5006
734 tip-rev: 5006
694 tip-rev: 5006
735 data-length: 121280
695 data-length: 121280
736 $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/right-done
696 $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/right-done
737 $ cat outputs/right.txt
697 $ cat outputs/right.txt
738 nodemap-race: right side start of the locking sequence
698 nodemap-race: right side start of the locking sequence
739 nodemap-race: right side reading changelog
699 nodemap-race: right side reading changelog
740 nodemap-race: right side reading of changelog is done
700 nodemap-race: right side reading of changelog is done
741 docket-details:
701 docket-details:
742 uid: 43c37dde
702 uid: 43c37dde
743 actual-tip: 5006
703 actual-tip: 5006
744 tip-rev: 5005
704 tip-rev: 5005
745 data-length: 121088
705 data-length: 121088
746 nodemap-race: right side ready to wait for the lock
706 nodemap-race: right side ready to wait for the lock
747 nodemap-race: right side locked and ready to commit
707 nodemap-race: right side locked and ready to commit
748 docket-details:
708 docket-details:
749 uid: 43c37dde
709 uid: 43c37dde
750 actual-tip: 5006
710 actual-tip: 5006
751 tip-rev: 5006
711 tip-rev: 5006
752 data-length: 121280
712 data-length: 121280
753 right ready to write, waiting for reader
713 right ready to write, waiting for reader
754 right proceeding with writing its changelog index and nodemap
714 right proceeding with writing its changelog index and nodemap
755 finalized changelog write
715 finalized changelog write
756 persisting changelog nodemap
716 persisting changelog nodemap
757 new data start at 121280
717 new data start at 121280
758 persisted changelog nodemap
718 persisted changelog nodemap
759 docket-details:
719 docket-details:
760 uid: 43c37dde
720 uid: 43c37dde
761 actual-tip: 5007
721 actual-tip: 5007
762 tip-rev: 5007
722 tip-rev: 5007
763 data-length: 121536
723 data-length: 121536
764 $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/reader-done
724 $ sh "$RUNTESTDIR"/testlib/wait-on-file 10 sync-files/reader-done
765 $ cat outputs/reader.txt
725 $ cat outputs/reader.txt
766 reader: reading changelog
726 reader: reading changelog
767 reader ready to read the changelog, waiting for right
727 reader ready to read the changelog, waiting for right
768 reader: nodemap docket read
728 reader: nodemap docket read
769 record-data-length: 121280
729 record-data-length: 121280
770 actual-data-length: 121280
730 actual-data-length: 121280
771 file-actual-length: 121536
731 file-actual-length: 121536
772 reader: changelog read
732 reader: changelog read
773 docket-details:
733 docket-details:
774 uid: 43c37dde
734 uid: 43c37dde
775 actual-tip: 5006
735 actual-tip: 5006
776 tip-rev: 5006
736 tip-rev: 5006
777 data-length: 121280
737 data-length: 121280
778 tip-rev: 5006
738 tip-rev: 5006
779 tip-node: 492901161367
739 tip-node: 492901161367
780 node-rev: 5006
740 node-rev: 5006
781
741
782 $ hg -R ./race-repo log -G -r 'head()'
742 $ hg -R ./race-repo log -G -r 'head()'
783 o changeset: 5007:ac4a2abde241
743 o changeset: 5007:ac4a2abde241
784 | tag: tip
744 | tag: tip
785 ~ parent: 5001:16395c3cf7e2
745 ~ parent: 5001:16395c3cf7e2
786 user: test
746 user: test
787 date: Thu Jan 01 00:00:00 1970 +0000
747 date: Thu Jan 01 00:00:00 1970 +0000
788 summary: right-side-commit
748 summary: right-side-commit
789
749
790 @ changeset: 5006:492901161367
750 @ changeset: 5006:492901161367
791 | user: test
751 | user: test
792 ~ date: Thu Jan 01 00:00:00 1970 +0000
752 ~ date: Thu Jan 01 00:00:00 1970 +0000
793 summary: left-side-commit
753 summary: left-side-commit
794
754
795 $ hg -R ./other-wc log -G -r 'head()'
755 $ hg -R ./other-wc log -G -r 'head()'
796 @ changeset: 5007:ac4a2abde241
756 @ changeset: 5007:ac4a2abde241
797 | tag: tip
757 | tag: tip
798 ~ parent: 5001:16395c3cf7e2
758 ~ parent: 5001:16395c3cf7e2
799 user: test
759 user: test
800 date: Thu Jan 01 00:00:00 1970 +0000
760 date: Thu Jan 01 00:00:00 1970 +0000
801 summary: right-side-commit
761 summary: right-side-commit
802
762
803 o changeset: 5006:492901161367
763 o changeset: 5006:492901161367
804 | user: test
764 | user: test
805 ~ date: Thu Jan 01 00:00:00 1970 +0000
765 ~ date: Thu Jan 01 00:00:00 1970 +0000
806 summary: left-side-commit
766 summary: left-side-commit
807
767
808 #endif
768 #endif
809
769
810 Test upgrade / downgrade
770 Test upgrade / downgrade
811 ========================
771 ========================
812
772
813 $ cd ./test-repo/
773 $ cd ./test-repo/
814
774
815 downgrading
775 downgrading
816
776
817 $ cat << EOF >> .hg/hgrc
777 $ cat << EOF >> .hg/hgrc
818 > [format]
778 > [format]
819 > use-persistent-nodemap=no
779 > use-persistent-nodemap=no
820 > EOF
780 > EOF
821 $ hg debugformat -v
781 $ hg debugformat -v
822 format-variant repo config default
782 format-variant repo config default
823 fncache: yes yes yes
783 fncache: yes yes yes
824 dirstate-v2: no no no
784 dirstate-v2: no no no
825 dotencode: yes yes yes
785 dotencode: yes yes yes
826 generaldelta: yes yes yes
786 generaldelta: yes yes yes
827 share-safe: yes yes no
787 share-safe: yes yes no
828 sparserevlog: yes yes yes
788 sparserevlog: yes yes yes
829 persistent-nodemap: yes no no
789 persistent-nodemap: yes no no
830 copies-sdc: no no no
790 copies-sdc: no no no
831 revlog-v2: no no no
791 revlog-v2: no no no
832 changelog-v2: no no no
792 changelog-v2: no no no
833 plain-cl-delta: yes yes yes
793 plain-cl-delta: yes yes yes
834 compression: zlib zlib zlib (no-zstd !)
794 compression: zlib zlib zlib (no-zstd !)
835 compression: zstd zstd zstd (zstd !)
795 compression: zstd zstd zstd (zstd !)
836 compression-level: default default default
796 compression-level: default default default
837 $ hg debugupgraderepo --run --no-backup --quiet
797 $ hg debugupgraderepo --run --no-backup --quiet
838 upgrade will perform the following actions:
798 upgrade will perform the following actions:
839
799
840 requirements
800 requirements
841 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 !)
842 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 !)
843 preserved: dotencode, exp-dirstate-v2, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !)
803 preserved: dotencode, exp-dirstate-v2, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !)
844 removed: persistent-nodemap
804 removed: persistent-nodemap
845
805
846 processed revlogs:
806 processed revlogs:
847 - all-filelogs
807 - all-filelogs
848 - changelog
808 - changelog
849 - manifest
809 - manifest
850
810
851 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
811 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
852 00changelog-*.nd (glob)
812 00changelog-*.nd (glob)
853 00manifest-*.nd (glob)
813 00manifest-*.nd (glob)
854 undo.backup.00changelog.n
814 undo.backup.00changelog.n
855 undo.backup.00manifest.n
815 undo.backup.00manifest.n
856 $ hg debugnodemap --metadata
816 $ hg debugnodemap --metadata
857
817
858
818
859 upgrading
819 upgrading
860
820
861 $ cat << EOF >> .hg/hgrc
821 $ cat << EOF >> .hg/hgrc
862 > [format]
822 > [format]
863 > use-persistent-nodemap=yes
823 > use-persistent-nodemap=yes
864 > EOF
824 > EOF
865 $ hg debugformat -v
825 $ hg debugformat -v
866 format-variant repo config default
826 format-variant repo config default
867 fncache: yes yes yes
827 fncache: yes yes yes
868 dirstate-v2: no no no
828 dirstate-v2: no no no
869 dotencode: yes yes yes
829 dotencode: yes yes yes
870 generaldelta: yes yes yes
830 generaldelta: yes yes yes
871 share-safe: yes yes no
831 share-safe: yes yes no
872 sparserevlog: yes yes yes
832 sparserevlog: yes yes yes
873 persistent-nodemap: no yes no
833 persistent-nodemap: no yes no
874 copies-sdc: no no no
834 copies-sdc: no no no
875 revlog-v2: no no no
835 revlog-v2: no no no
876 changelog-v2: no no no
836 changelog-v2: no no no
877 plain-cl-delta: yes yes yes
837 plain-cl-delta: yes yes yes
878 compression: zlib zlib zlib (no-zstd !)
838 compression: zlib zlib zlib (no-zstd !)
879 compression: zstd zstd zstd (zstd !)
839 compression: zstd zstd zstd (zstd !)
880 compression-level: default default default
840 compression-level: default default default
881 $ hg debugupgraderepo --run --no-backup --quiet
841 $ hg debugupgraderepo --run --no-backup --quiet
882 upgrade will perform the following actions:
842 upgrade will perform the following actions:
883
843
884 requirements
844 requirements
885 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-zstd no-dirstate-v2 !)
845 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-zstd no-dirstate-v2 !)
886 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd no-dirstate-v2 !)
846 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd no-dirstate-v2 !)
887 preserved: dotencode, exp-dirstate-v2, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !)
847 preserved: dotencode, exp-dirstate-v2, fncache, generaldelta, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !)
888 added: persistent-nodemap
848 added: persistent-nodemap
889
849
890 processed revlogs:
850 processed revlogs:
891 - all-filelogs
851 - all-filelogs
892 - changelog
852 - changelog
893 - manifest
853 - manifest
894
854
895 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
855 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
896 00changelog-*.nd (glob)
856 00changelog-*.nd (glob)
897 00changelog.n
857 00changelog.n
898 00manifest-*.nd (glob)
858 00manifest-*.nd (glob)
899 00manifest.n
859 00manifest.n
900 undo.backup.00changelog.n
860 undo.backup.00changelog.n
901 undo.backup.00manifest.n
861 undo.backup.00manifest.n
902
862
903 $ hg debugnodemap --metadata
863 $ hg debugnodemap --metadata
904 uid: * (glob)
864 uid: * (glob)
905 tip-rev: 5005
865 tip-rev: 5005
906 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
866 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
907 data-length: 121088
867 data-length: 121088
908 data-unused: 0
868 data-unused: 0
909 data-unused: 0.000%
869 data-unused: 0.000%
910
870
911 Running unrelated upgrade
871 Running unrelated upgrade
912
872
913 $ hg debugupgraderepo --run --no-backup --quiet --optimize re-delta-all
873 $ hg debugupgraderepo --run --no-backup --quiet --optimize re-delta-all
914 upgrade will perform the following actions:
874 upgrade will perform the following actions:
915
875
916 requirements
876 requirements
917 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (no-zstd no-dirstate-v2 !)
877 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (no-zstd no-dirstate-v2 !)
918 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd no-dirstate-v2 !)
878 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd no-dirstate-v2 !)
919 preserved: dotencode, exp-dirstate-v2, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !)
879 preserved: dotencode, exp-dirstate-v2, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, revlogv1, share-safe, sparserevlog, store (zstd dirstate-v2 !)
920
880
921 optimisations: re-delta-all
881 optimisations: re-delta-all
922
882
923 processed revlogs:
883 processed revlogs:
924 - all-filelogs
884 - all-filelogs
925 - changelog
885 - changelog
926 - manifest
886 - manifest
927
887
928 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
888 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
929 00changelog-*.nd (glob)
889 00changelog-*.nd (glob)
930 00changelog.n
890 00changelog.n
931 00manifest-*.nd (glob)
891 00manifest-*.nd (glob)
932 00manifest.n
892 00manifest.n
933
893
934 $ hg debugnodemap --metadata
894 $ hg debugnodemap --metadata
935 uid: * (glob)
895 uid: * (glob)
936 tip-rev: 5005
896 tip-rev: 5005
937 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
897 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
938 data-length: 121088
898 data-length: 121088
939 data-unused: 0
899 data-unused: 0
940 data-unused: 0.000%
900 data-unused: 0.000%
941
901
942 Persistent nodemap and local/streaming clone
902 Persistent nodemap and local/streaming clone
943 ============================================
903 ============================================
944
904
945 $ cd ..
905 $ cd ..
946
906
947 standard clone
907 standard clone
948 --------------
908 --------------
949
909
950 The persistent nodemap should exist after a streaming clone
910 The persistent nodemap should exist after a streaming clone
951
911
952 $ hg clone --pull --quiet -U test-repo standard-clone
912 $ hg clone --pull --quiet -U test-repo standard-clone
953 $ ls -1 standard-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
913 $ ls -1 standard-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
954 00changelog-*.nd (glob)
914 00changelog-*.nd (glob)
955 00changelog.n
915 00changelog.n
956 00manifest-*.nd (glob)
916 00manifest-*.nd (glob)
957 00manifest.n
917 00manifest.n
958 $ hg -R standard-clone debugnodemap --metadata
918 $ hg -R standard-clone debugnodemap --metadata
959 uid: * (glob)
919 uid: * (glob)
960 tip-rev: 5005
920 tip-rev: 5005
961 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
921 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
962 data-length: 121088
922 data-length: 121088
963 data-unused: 0
923 data-unused: 0
964 data-unused: 0.000%
924 data-unused: 0.000%
965
925
966
926
967 local clone
927 local clone
968 ------------
928 ------------
969
929
970 The persistent nodemap should exist after a streaming clone
930 The persistent nodemap should exist after a streaming clone
971
931
972 $ hg clone -U test-repo local-clone
932 $ hg clone -U test-repo local-clone
973 $ ls -1 local-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
933 $ ls -1 local-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
974 00changelog-*.nd (glob)
934 00changelog-*.nd (glob)
975 00changelog.n
935 00changelog.n
976 00manifest-*.nd (glob)
936 00manifest-*.nd (glob)
977 00manifest.n
937 00manifest.n
978 $ hg -R local-clone debugnodemap --metadata
938 $ hg -R local-clone debugnodemap --metadata
979 uid: * (glob)
939 uid: * (glob)
980 tip-rev: 5005
940 tip-rev: 5005
981 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
941 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
982 data-length: 121088
942 data-length: 121088
983 data-unused: 0
943 data-unused: 0
984 data-unused: 0.000%
944 data-unused: 0.000%
985
945
986 Test various corruption case
946 Test various corruption case
987 ============================
947 ============================
988
948
989 Missing datafile
949 Missing datafile
990 ----------------
950 ----------------
991
951
992 Test behavior with a missing datafile
952 Test behavior with a missing datafile
993
953
994 $ hg clone --quiet --pull test-repo corruption-test-repo
954 $ hg clone --quiet --pull test-repo corruption-test-repo
995 $ ls -1 corruption-test-repo/.hg/store/00changelog*
955 $ ls -1 corruption-test-repo/.hg/store/00changelog*
996 corruption-test-repo/.hg/store/00changelog-*.nd (glob)
956 corruption-test-repo/.hg/store/00changelog-*.nd (glob)
997 corruption-test-repo/.hg/store/00changelog.d
957 corruption-test-repo/.hg/store/00changelog.d
998 corruption-test-repo/.hg/store/00changelog.i
958 corruption-test-repo/.hg/store/00changelog.i
999 corruption-test-repo/.hg/store/00changelog.n
959 corruption-test-repo/.hg/store/00changelog.n
1000 $ rm corruption-test-repo/.hg/store/00changelog*.nd
960 $ rm corruption-test-repo/.hg/store/00changelog*.nd
1001 $ hg log -R corruption-test-repo -r .
961 $ hg log -R corruption-test-repo -r .
1002 changeset: 5005:90d5d3ba2fc4
962 changeset: 5005:90d5d3ba2fc4
1003 tag: tip
963 tag: tip
1004 user: test
964 user: test
1005 date: Thu Jan 01 00:00:00 1970 +0000
965 date: Thu Jan 01 00:00:00 1970 +0000
1006 summary: a2
966 summary: a2
1007
967
1008 $ ls -1 corruption-test-repo/.hg/store/00changelog*
968 $ ls -1 corruption-test-repo/.hg/store/00changelog*
1009 corruption-test-repo/.hg/store/00changelog.d
969 corruption-test-repo/.hg/store/00changelog.d
1010 corruption-test-repo/.hg/store/00changelog.i
970 corruption-test-repo/.hg/store/00changelog.i
1011 corruption-test-repo/.hg/store/00changelog.n
971 corruption-test-repo/.hg/store/00changelog.n
1012
972
1013 Truncated data file
973 Truncated data file
1014 -------------------
974 -------------------
1015
975
1016 Test behavior with a too short datafile
976 Test behavior with a too short datafile
1017
977
1018 rebuild the missing data
978 rebuild the missing data
1019 $ hg -R corruption-test-repo debugupdatecache
979 $ hg -R corruption-test-repo debugupdatecache
1020 $ ls -1 corruption-test-repo/.hg/store/00changelog*
980 $ ls -1 corruption-test-repo/.hg/store/00changelog*
1021 corruption-test-repo/.hg/store/00changelog-*.nd (glob)
981 corruption-test-repo/.hg/store/00changelog-*.nd (glob)
1022 corruption-test-repo/.hg/store/00changelog.d
982 corruption-test-repo/.hg/store/00changelog.d
1023 corruption-test-repo/.hg/store/00changelog.i
983 corruption-test-repo/.hg/store/00changelog.i
1024 corruption-test-repo/.hg/store/00changelog.n
984 corruption-test-repo/.hg/store/00changelog.n
1025
985
1026 truncate the file
986 truncate the file
1027
987
1028 $ datafilepath=`ls corruption-test-repo/.hg/store/00changelog*.nd`
988 $ datafilepath=`ls corruption-test-repo/.hg/store/00changelog*.nd`
1029 $ f -s $datafilepath
989 $ f -s $datafilepath
1030 corruption-test-repo/.hg/store/00changelog-*.nd: size=121088 (glob)
990 corruption-test-repo/.hg/store/00changelog-*.nd: size=121088 (glob)
1031 $ dd if=$datafilepath bs=1000 count=10 of=$datafilepath-tmp status=noxfer
991 $ dd if=$datafilepath bs=1000 count=10 of=$datafilepath-tmp status=noxfer
1032 10+0 records in
992 10+0 records in
1033 10+0 records out
993 10+0 records out
1034 $ mv $datafilepath-tmp $datafilepath
994 $ mv $datafilepath-tmp $datafilepath
1035 $ f -s $datafilepath
995 $ f -s $datafilepath
1036 corruption-test-repo/.hg/store/00changelog-*.nd: size=10000 (glob)
996 corruption-test-repo/.hg/store/00changelog-*.nd: size=10000 (glob)
1037
997
1038 Check that Mercurial reaction to this event
998 Check that Mercurial reaction to this event
1039
999
1040 $ hg -R corruption-test-repo log -r . --traceback
1000 $ hg -R corruption-test-repo log -r . --traceback
1041 changeset: 5005:90d5d3ba2fc4
1001 changeset: 5005:90d5d3ba2fc4
1042 tag: tip
1002 tag: tip
1043 user: test
1003 user: test
1044 date: Thu Jan 01 00:00:00 1970 +0000
1004 date: Thu Jan 01 00:00:00 1970 +0000
1045 summary: a2
1005 summary: a2
1046
1006
1047
1007
1048
1008
1049 stream clone
1009 stream clone
1050 ============
1010 ============
1051
1011
1052 The persistent nodemap should exist after a streaming clone
1012 The persistent nodemap should exist after a streaming clone
1053
1013
1054 Simple case
1014 Simple case
1055 -----------
1015 -----------
1056
1016
1057 No race condition
1017 No race condition
1058
1018
1059 $ hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/test-repo stream-clone --debug | egrep '00(changelog|manifest)'
1019 $ hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/test-repo stream-clone --debug | egrep '00(changelog|manifest)'
1060 adding [s] 00manifest.n (62 bytes)
1020 adding [s] 00manifest.n (62 bytes)
1061 adding [s] 00manifest-*.nd (118 KB) (glob)
1021 adding [s] 00manifest-*.nd (118 KB) (glob)
1062 adding [s] 00changelog.n (62 bytes)
1022 adding [s] 00changelog.n (62 bytes)
1063 adding [s] 00changelog-*.nd (118 KB) (glob)
1023 adding [s] 00changelog-*.nd (118 KB) (glob)
1064 adding [s] 00manifest.d (452 KB) (no-zstd !)
1024 adding [s] 00manifest.d (452 KB) (no-zstd !)
1065 adding [s] 00manifest.d (491 KB) (zstd !)
1025 adding [s] 00manifest.d (491 KB) (zstd !)
1066 adding [s] 00changelog.d (360 KB) (no-zstd !)
1026 adding [s] 00changelog.d (360 KB) (no-zstd !)
1067 adding [s] 00changelog.d (368 KB) (zstd !)
1027 adding [s] 00changelog.d (368 KB) (zstd !)
1068 adding [s] 00manifest.i (313 KB)
1028 adding [s] 00manifest.i (313 KB)
1069 adding [s] 00changelog.i (313 KB)
1029 adding [s] 00changelog.i (313 KB)
1070 $ 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)'
1071 00changelog-*.nd (glob)
1031 00changelog-*.nd (glob)
1072 00changelog.n
1032 00changelog.n
1073 00manifest-*.nd (glob)
1033 00manifest-*.nd (glob)
1074 00manifest.n
1034 00manifest.n
1075 $ hg -R stream-clone debugnodemap --metadata
1035 $ hg -R stream-clone debugnodemap --metadata
1076 uid: * (glob)
1036 uid: * (glob)
1077 tip-rev: 5005
1037 tip-rev: 5005
1078 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1038 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1079 data-length: 121088
1039 data-length: 121088
1080 data-unused: 0
1040 data-unused: 0
1081 data-unused: 0.000%
1041 data-unused: 0.000%
1082
1042
1083 new data appened
1043 new data appened
1084 -----------------
1044 -----------------
1085
1045
1086 Other commit happening on the server during the stream clone
1046 Other commit happening on the server during the stream clone
1087
1047
1088 setup the step-by-step stream cloning
1048 setup the step-by-step stream cloning
1089
1049
1090 $ HG_TEST_STREAM_WALKED_FILE_1="$TESTTMP/sync_file_walked_1"
1050 $ HG_TEST_STREAM_WALKED_FILE_1="$TESTTMP/sync_file_walked_1"
1091 $ export HG_TEST_STREAM_WALKED_FILE_1
1051 $ export HG_TEST_STREAM_WALKED_FILE_1
1092 $ HG_TEST_STREAM_WALKED_FILE_2="$TESTTMP/sync_file_walked_2"
1052 $ HG_TEST_STREAM_WALKED_FILE_2="$TESTTMP/sync_file_walked_2"
1093 $ export HG_TEST_STREAM_WALKED_FILE_2
1053 $ export HG_TEST_STREAM_WALKED_FILE_2
1094 $ HG_TEST_STREAM_WALKED_FILE_3="$TESTTMP/sync_file_walked_3"
1054 $ HG_TEST_STREAM_WALKED_FILE_3="$TESTTMP/sync_file_walked_3"
1095 $ export HG_TEST_STREAM_WALKED_FILE_3
1055 $ export HG_TEST_STREAM_WALKED_FILE_3
1096 $ cat << EOF >> test-repo/.hg/hgrc
1056 $ cat << EOF >> test-repo/.hg/hgrc
1097 > [extensions]
1057 > [extensions]
1098 > steps=$RUNTESTDIR/testlib/ext-stream-clone-steps.py
1058 > steps=$RUNTESTDIR/testlib/ext-stream-clone-steps.py
1099 > EOF
1059 > EOF
1100
1060
1101 Check and record file state beforehand
1061 Check and record file state beforehand
1102
1062
1103 $ f --size test-repo/.hg/store/00changelog*
1063 $ f --size test-repo/.hg/store/00changelog*
1104 test-repo/.hg/store/00changelog-*.nd: size=121088 (glob)
1064 test-repo/.hg/store/00changelog-*.nd: size=121088 (glob)
1105 test-repo/.hg/store/00changelog.d: size=376891 (zstd !)
1065 test-repo/.hg/store/00changelog.d: size=376891 (zstd !)
1106 test-repo/.hg/store/00changelog.d: size=368890 (no-zstd !)
1066 test-repo/.hg/store/00changelog.d: size=368890 (no-zstd !)
1107 test-repo/.hg/store/00changelog.i: size=320384
1067 test-repo/.hg/store/00changelog.i: size=320384
1108 test-repo/.hg/store/00changelog.n: size=62
1068 test-repo/.hg/store/00changelog.n: size=62
1109 $ hg -R test-repo debugnodemap --metadata | tee server-metadata.txt
1069 $ hg -R test-repo debugnodemap --metadata | tee server-metadata.txt
1110 uid: * (glob)
1070 uid: * (glob)
1111 tip-rev: 5005
1071 tip-rev: 5005
1112 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1072 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1113 data-length: 121088
1073 data-length: 121088
1114 data-unused: 0
1074 data-unused: 0
1115 data-unused: 0.000%
1075 data-unused: 0.000%
1116
1076
1117 Prepare a commit
1077 Prepare a commit
1118
1078
1119 $ echo foo >> test-repo/foo
1079 $ echo foo >> test-repo/foo
1120 $ hg -R test-repo/ add test-repo/foo
1080 $ hg -R test-repo/ add test-repo/foo
1121
1081
1122 Do a mix of clone and commit at the same time so that the file listed on disk differ at actual transfer time.
1082 Do a mix of clone and commit at the same time so that the file listed on disk differ at actual transfer time.
1123
1083
1124 $ (hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" 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) &
1084 $ (hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" 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) &
1125 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1
1085 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1
1126 $ hg -R test-repo/ commit -m foo
1086 $ hg -R test-repo/ commit -m foo
1127 $ touch $HG_TEST_STREAM_WALKED_FILE_2
1087 $ touch $HG_TEST_STREAM_WALKED_FILE_2
1128 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3
1088 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3
1129 $ cat clone-output
1089 $ cat clone-output
1130 adding [s] 00manifest.n (62 bytes)
1090 adding [s] 00manifest.n (62 bytes)
1131 adding [s] 00manifest-*.nd (118 KB) (glob)
1091 adding [s] 00manifest-*.nd (118 KB) (glob)
1132 adding [s] 00changelog.n (62 bytes)
1092 adding [s] 00changelog.n (62 bytes)
1133 adding [s] 00changelog-*.nd (118 KB) (glob)
1093 adding [s] 00changelog-*.nd (118 KB) (glob)
1134 adding [s] 00manifest.d (452 KB) (no-zstd !)
1094 adding [s] 00manifest.d (452 KB) (no-zstd !)
1135 adding [s] 00manifest.d (491 KB) (zstd !)
1095 adding [s] 00manifest.d (491 KB) (zstd !)
1136 adding [s] 00changelog.d (360 KB) (no-zstd !)
1096 adding [s] 00changelog.d (360 KB) (no-zstd !)
1137 adding [s] 00changelog.d (368 KB) (zstd !)
1097 adding [s] 00changelog.d (368 KB) (zstd !)
1138 adding [s] 00manifest.i (313 KB)
1098 adding [s] 00manifest.i (313 KB)
1139 adding [s] 00changelog.i (313 KB)
1099 adding [s] 00changelog.i (313 KB)
1140
1100
1141 Check the result state
1101 Check the result state
1142
1102
1143 $ f --size stream-clone-race-1/.hg/store/00changelog*
1103 $ f --size stream-clone-race-1/.hg/store/00changelog*
1144 stream-clone-race-1/.hg/store/00changelog-*.nd: size=121088 (glob)
1104 stream-clone-race-1/.hg/store/00changelog-*.nd: size=121088 (glob)
1145 stream-clone-race-1/.hg/store/00changelog.d: size=368890 (no-zstd !)
1105 stream-clone-race-1/.hg/store/00changelog.d: size=368890 (no-zstd !)
1146 stream-clone-race-1/.hg/store/00changelog.d: size=376891 (zstd !)
1106 stream-clone-race-1/.hg/store/00changelog.d: size=376891 (zstd !)
1147 stream-clone-race-1/.hg/store/00changelog.i: size=320384
1107 stream-clone-race-1/.hg/store/00changelog.i: size=320384
1148 stream-clone-race-1/.hg/store/00changelog.n: size=62
1108 stream-clone-race-1/.hg/store/00changelog.n: size=62
1149
1109
1150 $ hg -R stream-clone-race-1 debugnodemap --metadata | tee client-metadata.txt
1110 $ hg -R stream-clone-race-1 debugnodemap --metadata | tee client-metadata.txt
1151 uid: * (glob)
1111 uid: * (glob)
1152 tip-rev: 5005
1112 tip-rev: 5005
1153 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1113 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1154 data-length: 121088
1114 data-length: 121088
1155 data-unused: 0
1115 data-unused: 0
1156 data-unused: 0.000%
1116 data-unused: 0.000%
1157
1117
1158 We get a usable nodemap, so no rewrite would be needed and the metadata should be identical
1118 We get a usable nodemap, so no rewrite would be needed and the metadata should be identical
1159 (ie: the following diff should be empty)
1119 (ie: the following diff should be empty)
1160
1120
1161 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".
1121 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".
1162
1122
1163 #if no-rust no-pure
1123 #if no-rust no-pure
1164 $ diff -u server-metadata.txt client-metadata.txt
1124 $ diff -u server-metadata.txt client-metadata.txt
1165 --- server-metadata.txt * (glob)
1125 --- server-metadata.txt * (glob)
1166 +++ client-metadata.txt * (glob)
1126 +++ client-metadata.txt * (glob)
1167 @@ -1,4 +1,4 @@
1127 @@ -1,4 +1,4 @@
1168 -uid: * (glob)
1128 -uid: * (glob)
1169 +uid: * (glob)
1129 +uid: * (glob)
1170 tip-rev: 5005
1130 tip-rev: 5005
1171 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1131 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
1172 data-length: 121088
1132 data-length: 121088
1173 [1]
1133 [1]
1174 #else
1134 #else
1175 $ diff -u server-metadata.txt client-metadata.txt
1135 $ diff -u server-metadata.txt client-metadata.txt
1176 #endif
1136 #endif
1177
1137
1178
1138
1179 Clean up after the test.
1139 Clean up after the test.
1180
1140
1181 $ rm -f "$HG_TEST_STREAM_WALKED_FILE_1"
1141 $ rm -f "$HG_TEST_STREAM_WALKED_FILE_1"
1182 $ rm -f "$HG_TEST_STREAM_WALKED_FILE_2"
1142 $ rm -f "$HG_TEST_STREAM_WALKED_FILE_2"
1183 $ rm -f "$HG_TEST_STREAM_WALKED_FILE_3"
1143 $ rm -f "$HG_TEST_STREAM_WALKED_FILE_3"
1184
1144
1185 full regeneration
1145 full regeneration
1186 -----------------
1146 -----------------
1187
1147
1188 A full nodemap is generated
1148 A full nodemap is generated
1189
1149
1190 (ideally this test would append enough data to make sure the nodemap data file
1150 (ideally this test would append enough data to make sure the nodemap data file
1191 get changed, however to make thing simpler we will force the regeneration for
1151 get changed, however to make thing simpler we will force the regeneration for
1192 this test.
1152 this test.
1193
1153
1194 Check the initial state
1154 Check the initial state
1195
1155
1196 $ f --size test-repo/.hg/store/00changelog*
1156 $ f --size test-repo/.hg/store/00changelog*
1197 test-repo/.hg/store/00changelog-*.nd: size=121344 (glob) (rust !)
1157 test-repo/.hg/store/00changelog-*.nd: size=121344 (glob) (rust !)
1198 test-repo/.hg/store/00changelog-*.nd: size=121344 (glob) (pure !)
1158 test-repo/.hg/store/00changelog-*.nd: size=121344 (glob) (pure !)
1199 test-repo/.hg/store/00changelog-*.nd: size=121152 (glob) (no-rust no-pure !)
1159 test-repo/.hg/store/00changelog-*.nd: size=121152 (glob) (no-rust no-pure !)
1200 test-repo/.hg/store/00changelog.d: size=376950 (zstd !)
1160 test-repo/.hg/store/00changelog.d: size=376950 (zstd !)
1201 test-repo/.hg/store/00changelog.d: size=368949 (no-zstd !)
1161 test-repo/.hg/store/00changelog.d: size=368949 (no-zstd !)
1202 test-repo/.hg/store/00changelog.i: size=320448
1162 test-repo/.hg/store/00changelog.i: size=320448
1203 test-repo/.hg/store/00changelog.n: size=62
1163 test-repo/.hg/store/00changelog.n: size=62
1204 $ hg -R test-repo debugnodemap --metadata | tee server-metadata-2.txt
1164 $ hg -R test-repo debugnodemap --metadata | tee server-metadata-2.txt
1205 uid: * (glob)
1165 uid: * (glob)
1206 tip-rev: 5006
1166 tip-rev: 5006
1207 tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b
1167 tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b
1208 data-length: 121344 (rust !)
1168 data-length: 121344 (rust !)
1209 data-length: 121344 (pure !)
1169 data-length: 121344 (pure !)
1210 data-length: 121152 (no-rust no-pure !)
1170 data-length: 121152 (no-rust no-pure !)
1211 data-unused: 192 (rust !)
1171 data-unused: 192 (rust !)
1212 data-unused: 192 (pure !)
1172 data-unused: 192 (pure !)
1213 data-unused: 0 (no-rust no-pure !)
1173 data-unused: 0 (no-rust no-pure !)
1214 data-unused: 0.158% (rust !)
1174 data-unused: 0.158% (rust !)
1215 data-unused: 0.158% (pure !)
1175 data-unused: 0.158% (pure !)
1216 data-unused: 0.000% (no-rust no-pure !)
1176 data-unused: 0.000% (no-rust no-pure !)
1217
1177
1218 Performe the mix of clone and full refresh of the nodemap, so that the files
1178 Performe the mix of clone and full refresh of the nodemap, so that the files
1219 (and filenames) are different between listing time and actual transfer time.
1179 (and filenames) are different between listing time and actual transfer time.
1220
1180
1221 $ (hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" 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) &
1181 $ (hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" 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) &
1222 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1
1182 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_1
1223 $ rm test-repo/.hg/store/00changelog.n
1183 $ rm test-repo/.hg/store/00changelog.n
1224 $ rm test-repo/.hg/store/00changelog-*.nd
1184 $ rm test-repo/.hg/store/00changelog-*.nd
1225 $ hg -R test-repo/ debugupdatecache
1185 $ hg -R test-repo/ debugupdatecache
1226 $ touch $HG_TEST_STREAM_WALKED_FILE_2
1186 $ touch $HG_TEST_STREAM_WALKED_FILE_2
1227 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3
1187 $ $RUNTESTDIR/testlib/wait-on-file 10 $HG_TEST_STREAM_WALKED_FILE_3
1228
1188
1229 (note: the stream clone code wronly pick the `undo.` files)
1189 (note: the stream clone code wronly pick the `undo.` files)
1230
1190
1231 $ cat clone-output-2
1191 $ cat clone-output-2
1232 adding [s] undo.backup.00manifest.n (62 bytes) (known-bad-output !)
1192 adding [s] undo.backup.00manifest.n (62 bytes) (known-bad-output !)
1233 adding [s] undo.backup.00changelog.n (62 bytes) (known-bad-output !)
1193 adding [s] undo.backup.00changelog.n (62 bytes) (known-bad-output !)
1234 adding [s] 00manifest.n (62 bytes)
1194 adding [s] 00manifest.n (62 bytes)
1235 adding [s] 00manifest-*.nd (118 KB) (glob)
1195 adding [s] 00manifest-*.nd (118 KB) (glob)
1236 adding [s] 00changelog.n (62 bytes)
1196 adding [s] 00changelog.n (62 bytes)
1237 adding [s] 00changelog-*.nd (118 KB) (glob)
1197 adding [s] 00changelog-*.nd (118 KB) (glob)
1238 adding [s] 00manifest.d (492 KB) (zstd !)
1198 adding [s] 00manifest.d (492 KB) (zstd !)
1239 adding [s] 00manifest.d (452 KB) (no-zstd !)
1199 adding [s] 00manifest.d (452 KB) (no-zstd !)
1240 adding [s] 00changelog.d (360 KB) (no-zstd !)
1200 adding [s] 00changelog.d (360 KB) (no-zstd !)
1241 adding [s] 00changelog.d (368 KB) (zstd !)
1201 adding [s] 00changelog.d (368 KB) (zstd !)
1242 adding [s] 00manifest.i (313 KB)
1202 adding [s] 00manifest.i (313 KB)
1243 adding [s] 00changelog.i (313 KB)
1203 adding [s] 00changelog.i (313 KB)
1244
1204
1245 Check the result.
1205 Check the result.
1246
1206
1247 $ f --size stream-clone-race-2/.hg/store/00changelog*
1207 $ f --size stream-clone-race-2/.hg/store/00changelog*
1248 stream-clone-race-2/.hg/store/00changelog-*.nd: size=121344 (glob) (rust !)
1208 stream-clone-race-2/.hg/store/00changelog-*.nd: size=121344 (glob) (rust !)
1249 stream-clone-race-2/.hg/store/00changelog-*.nd: size=121344 (glob) (pure !)
1209 stream-clone-race-2/.hg/store/00changelog-*.nd: size=121344 (glob) (pure !)
1250 stream-clone-race-2/.hg/store/00changelog-*.nd: size=121152 (glob) (no-rust no-pure !)
1210 stream-clone-race-2/.hg/store/00changelog-*.nd: size=121152 (glob) (no-rust no-pure !)
1251 stream-clone-race-2/.hg/store/00changelog.d: size=376950 (zstd !)
1211 stream-clone-race-2/.hg/store/00changelog.d: size=376950 (zstd !)
1252 stream-clone-race-2/.hg/store/00changelog.d: size=368949 (no-zstd !)
1212 stream-clone-race-2/.hg/store/00changelog.d: size=368949 (no-zstd !)
1253 stream-clone-race-2/.hg/store/00changelog.i: size=320448
1213 stream-clone-race-2/.hg/store/00changelog.i: size=320448
1254 stream-clone-race-2/.hg/store/00changelog.n: size=62
1214 stream-clone-race-2/.hg/store/00changelog.n: size=62
1255
1215
1256 $ hg -R stream-clone-race-2 debugnodemap --metadata | tee client-metadata-2.txt
1216 $ hg -R stream-clone-race-2 debugnodemap --metadata | tee client-metadata-2.txt
1257 uid: * (glob)
1217 uid: * (glob)
1258 tip-rev: 5006
1218 tip-rev: 5006
1259 tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b
1219 tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b
1260 data-length: 121344 (rust !)
1220 data-length: 121344 (rust !)
1261 data-unused: 192 (rust !)
1221 data-unused: 192 (rust !)
1262 data-unused: 0.158% (rust !)
1222 data-unused: 0.158% (rust !)
1263 data-length: 121152 (no-rust no-pure !)
1223 data-length: 121152 (no-rust no-pure !)
1264 data-unused: 0 (no-rust no-pure !)
1224 data-unused: 0 (no-rust no-pure !)
1265 data-unused: 0.000% (no-rust no-pure !)
1225 data-unused: 0.000% (no-rust no-pure !)
1266 data-length: 121344 (pure !)
1226 data-length: 121344 (pure !)
1267 data-unused: 192 (pure !)
1227 data-unused: 192 (pure !)
1268 data-unused: 0.158% (pure !)
1228 data-unused: 0.158% (pure !)
1269
1229
1270 We get a usable nodemap, so no rewrite would be needed and the metadata should be identical
1230 We get a usable nodemap, so no rewrite would be needed and the metadata should be identical
1271 (ie: the following diff should be empty)
1231 (ie: the following diff should be empty)
1272
1232
1273 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".
1233 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".
1274
1234
1275 #if no-rust no-pure
1235 #if no-rust no-pure
1276 $ diff -u server-metadata-2.txt client-metadata-2.txt
1236 $ diff -u server-metadata-2.txt client-metadata-2.txt
1277 --- server-metadata-2.txt * (glob)
1237 --- server-metadata-2.txt * (glob)
1278 +++ client-metadata-2.txt * (glob)
1238 +++ client-metadata-2.txt * (glob)
1279 @@ -1,4 +1,4 @@
1239 @@ -1,4 +1,4 @@
1280 -uid: * (glob)
1240 -uid: * (glob)
1281 +uid: * (glob)
1241 +uid: * (glob)
1282 tip-rev: 5006
1242 tip-rev: 5006
1283 tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b
1243 tip-node: ed2ec1eef9aa2a0ec5057c51483bc148d03e810b
1284 data-length: 121152
1244 data-length: 121152
1285 [1]
1245 [1]
1286 #else
1246 #else
1287 $ diff -u server-metadata-2.txt client-metadata-2.txt
1247 $ diff -u server-metadata-2.txt client-metadata-2.txt
1288 #endif
1248 #endif
1289
1249
1290 Clean up after the test
1250 Clean up after the test
1291
1251
1292 $ rm -f $HG_TEST_STREAM_WALKED_FILE_1
1252 $ rm -f $HG_TEST_STREAM_WALKED_FILE_1
1293 $ rm -f $HG_TEST_STREAM_WALKED_FILE_2
1253 $ rm -f $HG_TEST_STREAM_WALKED_FILE_2
1294 $ rm -f $HG_TEST_STREAM_WALKED_FILE_3
1254 $ rm -f $HG_TEST_STREAM_WALKED_FILE_3
1295
1255
General Comments 0
You need to be logged in to leave comments. Login now