##// END OF EJS Templates
persistent-nodemap: Fix Rust declarations for Revlog_CAPI signatures...
Simon Sapin -
r47141:7d0405e4 stable
parent child Browse files
Show More
@@ -1,176 +1,176
1 1 // cindex.rs
2 2 //
3 3 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
4 4 //
5 5 // This software may be used and distributed according to the terms of the
6 6 // GNU General Public License version 2 or any later version.
7 7
8 8 //! Bindings to use the Index defined by the parsers C extension
9 9 //!
10 10 //! Ideally, we should use an Index entirely implemented in Rust,
11 11 //! but this will take some time to get there.
12 12
13 13 use cpython::{
14 14 exc::ImportError, ObjectProtocol, PyClone, PyErr, PyObject, PyResult,
15 15 PyTuple, Python, PythonObject,
16 16 };
17 17 use hg::revlog::{Node, RevlogIndex};
18 18 use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION};
19 use libc::c_int;
19 use libc::{c_int, ssize_t};
20 20
21 21 const REVLOG_CABI_VERSION: c_int = 2;
22 22
23 23 #[repr(C)]
24 24 pub struct Revlog_CAPI {
25 25 abi_version: c_int,
26 26 index_length:
27 unsafe extern "C" fn(index: *mut revlog_capi::RawPyObject) -> c_int,
27 unsafe extern "C" fn(index: *mut revlog_capi::RawPyObject) -> ssize_t,
28 28 index_node: unsafe extern "C" fn(
29 29 index: *mut revlog_capi::RawPyObject,
30 rev: c_int,
30 rev: ssize_t,
31 31 ) -> *const Node,
32 32 index_parents: unsafe extern "C" fn(
33 33 index: *mut revlog_capi::RawPyObject,
34 34 rev: c_int,
35 35 ps: *mut [c_int; 2],
36 36 ) -> c_int,
37 37 }
38 38
39 39 py_capsule!(
40 40 from mercurial.cext.parsers import revlog_CAPI
41 41 as revlog_capi for Revlog_CAPI);
42 42
43 43 /// A `Graph` backed up by objects and functions from revlog.c
44 44 ///
45 45 /// This implementation of the `Graph` trait, relies on (pointers to)
46 46 /// - the C index object (`index` member)
47 47 /// - the `index_get_parents()` function (`parents` member)
48 48 ///
49 49 /// # Safety
50 50 ///
51 51 /// The C index itself is mutable, and this Rust exposition is **not
52 52 /// protected by the GIL**, meaning that this construct isn't safe with respect
53 53 /// to Python threads.
54 54 ///
55 55 /// All callers of this `Index` must acquire the GIL and must not release it
56 56 /// while working.
57 57 ///
58 58 /// # TODO find a solution to make it GIL safe again.
59 59 ///
60 60 /// This is non trivial, and can wait until we have a clearer picture with
61 61 /// more Rust Mercurial constructs.
62 62 ///
63 63 /// One possibility would be to a `GILProtectedIndex` wrapper enclosing
64 64 /// a `Python<'p>` marker and have it be the one implementing the
65 65 /// `Graph` trait, but this would mean the `Graph` implementor would become
66 66 /// likely to change between subsequent method invocations of the `hg-core`
67 67 /// objects (a serious change of the `hg-core` API):
68 68 /// either exposing ways to mutate the `Graph`, or making it a non persistent
69 69 /// parameter in the relevant methods that need one.
70 70 ///
71 71 /// Another possibility would be to introduce an abstract lock handle into
72 72 /// the core API, that would be tied to `GILGuard` / `Python<'p>`
73 73 /// in the case of the `cpython` crate bindings yet could leave room for other
74 74 /// mechanisms in other contexts.
75 75 pub struct Index {
76 76 index: PyObject,
77 77 capi: &'static Revlog_CAPI,
78 78 }
79 79
80 80 impl Index {
81 81 pub fn new(py: Python, index: PyObject) -> PyResult<Self> {
82 82 let capi = unsafe { revlog_capi::retrieve(py)? };
83 83 if capi.abi_version != REVLOG_CABI_VERSION {
84 84 return Err(PyErr::new::<ImportError, _>(
85 85 py,
86 86 format!(
87 87 "ABI version mismatch: the C ABI revlog version {} \
88 88 does not match the {} expected by Rust hg-cpython",
89 89 capi.abi_version, REVLOG_CABI_VERSION
90 90 ),
91 91 ));
92 92 }
93 93 Ok(Index { index, capi })
94 94 }
95 95
96 96 /// return a reference to the CPython Index object in this Struct
97 97 pub fn inner(&self) -> &PyObject {
98 98 &self.index
99 99 }
100 100
101 101 pub fn append(&mut self, py: Python, tup: PyTuple) -> PyResult<PyObject> {
102 102 self.index.call_method(
103 103 py,
104 104 "append",
105 105 PyTuple::new(py, &[tup.into_object()]),
106 106 None,
107 107 )
108 108 }
109 109 }
110 110
111 111 impl Clone for Index {
112 112 fn clone(&self) -> Self {
113 113 let guard = Python::acquire_gil();
114 114 Index {
115 115 index: self.index.clone_ref(guard.python()),
116 116 capi: self.capi,
117 117 }
118 118 }
119 119 }
120 120
121 121 impl PyClone for Index {
122 122 fn clone_ref(&self, py: Python) -> Self {
123 123 Index {
124 124 index: self.index.clone_ref(py),
125 125 capi: self.capi,
126 126 }
127 127 }
128 128 }
129 129
130 130 impl Graph for Index {
131 131 /// wrap a call to the C extern parents function
132 132 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError> {
133 133 if rev == WORKING_DIRECTORY_REVISION {
134 134 return Err(GraphError::WorkingDirectoryUnsupported);
135 135 }
136 136 let mut res: [c_int; 2] = [0; 2];
137 137 let code = unsafe {
138 138 (self.capi.index_parents)(
139 139 self.index.as_ptr(),
140 140 rev as c_int,
141 141 &mut res as *mut [c_int; 2],
142 142 )
143 143 };
144 144 match code {
145 145 0 => Ok(res),
146 146 _ => Err(GraphError::ParentOutOfRange(rev)),
147 147 }
148 148 }
149 149 }
150 150
151 151 impl RevlogIndex for Index {
152 152 /// Note C return type is Py_ssize_t (hence signed), but we shall
153 153 /// force it to unsigned, because it's a length
154 154 fn len(&self) -> usize {
155 155 unsafe { (self.capi.index_length)(self.index.as_ptr()) as usize }
156 156 }
157 157
158 158 fn node(&self, rev: Revision) -> Option<&Node> {
159 159 let raw = unsafe {
160 (self.capi.index_node)(self.index.as_ptr(), rev as c_int)
160 (self.capi.index_node)(self.index.as_ptr(), rev as ssize_t)
161 161 };
162 162 if raw.is_null() {
163 163 None
164 164 } else {
165 165 // TODO it would be much better for the C layer to give us
166 166 // a length, since the hash length will change in the near
167 167 // future, but that's probably out of scope for the nodemap
168 168 // patch series.
169 169 //
170 170 // The root of that unsafety relies in the signature of
171 171 // `capi.index_node()` itself: returning a `Node` pointer
172 172 // whereas it's a `char *` in the C counterpart.
173 173 Some(unsafe { &*raw })
174 174 }
175 175 }
176 176 }
@@ -1,736 +1,744
1 1 ===================================
2 2 Test the persistent on-disk nodemap
3 3 ===================================
4 4
5 5 $ cat << EOF >> $HGRCPATH
6 6 > [format]
7 7 > use-persistent-nodemap=yes
8 8 > [devel]
9 9 > persistent-nodemap=yes
10 10 > EOF
11 11
12 12 $ hg init test-repo --config storage.revlog.persistent-nodemap.slow-path=allow
13 13 $ cd test-repo
14 14
15 15 Check handling of the default slow-path value
16 16
17 17 #if no-pure no-rust
18 18
19 19 $ hg id
20 20 abort: accessing `persistent-nodemap` repository without associated fast implementation.
21 21 (check `hg help config.format.use-persistent-nodemap` for details)
22 22 [255]
23 23
24 24 Unlock further check (we are here to test the feature)
25 25
26 26 $ cat << EOF >> $HGRCPATH
27 27 > [storage]
28 28 > # to avoid spamming the test
29 29 > revlog.persistent-nodemap.slow-path=allow
30 30 > EOF
31 31
32 32 #endif
33 33
34 34 #if rust
35 35
36 Reported bug: some Rust code panics when handling the null revision
36 Regression test for a previous bug in Rust/C FFI for the `Revlog_CAPI` capsule:
37 in places where `mercurial/cext/revlog.c` function signatures use `Py_ssize_t`
38 (64 bits on Linux x86_64), corresponding declarations in `rust/hg-cpython/src/cindex.rs`
39 incorrectly used `libc::c_int` (32 bits).
40 As a result, -1 passed from Rust for the null revision became 4294967295 in C.
37 41
38 $ hg log -r 00000000 2>&1 | grep panicked
39 thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', hg-cpython/src/revlog.rs:* (glob)
42 $ hg log -r 00000000
43 changeset: -1:000000000000
44 tag: tip
45 user:
46 date: Thu Jan 01 00:00:00 1970 +0000
47
40 48
41 49 #endif
42 50
43 51
44 52 $ hg debugformat
45 53 format-variant repo
46 54 fncache: yes
47 55 dotencode: yes
48 56 generaldelta: yes
49 57 share-safe: no
50 58 sparserevlog: yes
51 59 sidedata: no
52 60 persistent-nodemap: yes
53 61 copies-sdc: no
54 62 plain-cl-delta: yes
55 63 compression: zlib
56 64 compression-level: default
57 65 $ hg debugbuilddag .+5000 --new-file
58 66
59 67 $ hg debugnodemap --metadata
60 68 uid: ???????????????? (glob)
61 69 tip-rev: 5000
62 70 tip-node: 6b02b8c7b96654c25e86ba69eda198d7e6ad8b3c
63 71 data-length: 121088
64 72 data-unused: 0
65 73 data-unused: 0.000%
66 74 $ f --size .hg/store/00changelog.n
67 75 .hg/store/00changelog.n: size=70
68 76
69 77 Simple lookup works
70 78
71 79 $ ANYNODE=`hg log --template '{node|short}\n' --rev tip`
72 80 $ hg log -r "$ANYNODE" --template '{rev}\n'
73 81 5000
74 82
75 83
76 84 #if rust
77 85
78 86 $ f --sha256 .hg/store/00changelog-*.nd
79 87 .hg/store/00changelog-????????????????.nd: sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd (glob)
80 88
81 89 $ f --sha256 .hg/store/00manifest-*.nd
82 90 .hg/store/00manifest-????????????????.nd: sha256=97117b1c064ea2f86664a124589e47db0e254e8d34739b5c5cc5bf31c9da2b51 (glob)
83 91 $ hg debugnodemap --dump-new | f --sha256 --size
84 92 size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd
85 93 $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
86 94 size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd
87 95 0000: 00 00 00 91 00 00 00 20 00 00 00 bb 00 00 00 e7 |....... ........|
88 96 0010: 00 00 00 66 00 00 00 a1 00 00 01 13 00 00 01 22 |...f..........."|
89 97 0020: 00 00 00 23 00 00 00 fc 00 00 00 ba 00 00 00 5e |...#...........^|
90 98 0030: 00 00 00 df 00 00 01 4e 00 00 01 65 00 00 00 ab |.......N...e....|
91 99 0040: 00 00 00 a9 00 00 00 95 00 00 00 73 00 00 00 38 |...........s...8|
92 100 0050: 00 00 00 cc 00 00 00 92 00 00 00 90 00 00 00 69 |...............i|
93 101 0060: 00 00 00 ec 00 00 00 8d 00 00 01 4f 00 00 00 12 |...........O....|
94 102 0070: 00 00 02 0c 00 00 00 77 00 00 00 9c 00 00 00 8f |.......w........|
95 103 0080: 00 00 00 d5 00 00 00 6b 00 00 00 48 00 00 00 b3 |.......k...H....|
96 104 0090: 00 00 00 e5 00 00 00 b5 00 00 00 8e 00 00 00 ad |................|
97 105 00a0: 00 00 00 7b 00 00 00 7c 00 00 00 0b 00 00 00 2b |...{...|.......+|
98 106 00b0: 00 00 00 c6 00 00 00 1e 00 00 01 08 00 00 00 11 |................|
99 107 00c0: 00 00 01 30 00 00 00 26 00 00 01 9c 00 00 00 35 |...0...&.......5|
100 108 00d0: 00 00 00 b8 00 00 01 31 00 00 00 2c 00 00 00 55 |.......1...,...U|
101 109 00e0: 00 00 00 8a 00 00 00 9a 00 00 00 0c 00 00 01 1e |................|
102 110 00f0: 00 00 00 a4 00 00 00 83 00 00 00 c9 00 00 00 8c |................|
103 111
104 112
105 113 #else
106 114
107 115 $ f --sha256 .hg/store/00changelog-*.nd
108 116 .hg/store/00changelog-????????????????.nd: sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 (glob)
109 117 $ hg debugnodemap --dump-new | f --sha256 --size
110 118 size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79
111 119 $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
112 120 size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79
113 121 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
114 122 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
115 123 0020: ff ff ff ff ff ff f5 06 ff ff ff ff ff ff f3 e7 |................|
116 124 0030: ff ff ef ca ff ff ff ff ff ff ff ff ff ff ff ff |................|
117 125 0040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
118 126 0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ed 08 |................|
119 127 0060: ff ff ed 66 ff ff ff ff ff ff ff ff ff ff ff ff |...f............|
120 128 0070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
121 129 0080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
122 130 0090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f6 ed |................|
123 131 00a0: ff ff ff ff ff ff fe 61 ff ff ff ff ff ff ff ff |.......a........|
124 132 00b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
125 133 00c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
126 134 00d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
127 135 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f1 02 |................|
128 136 00f0: ff ff ff ff ff ff ed 1b ff ff ff ff ff ff ff ff |................|
129 137
130 138 #endif
131 139
132 140 $ hg debugnodemap --check
133 141 revision in index: 5001
134 142 revision in nodemap: 5001
135 143
136 144 add a new commit
137 145
138 146 $ hg up
139 147 5001 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 148 $ echo foo > foo
141 149 $ hg add foo
142 150
143 151
144 152 Check slow-path config value handling
145 153 -------------------------------------
146 154
147 155 #if no-pure no-rust
148 156
149 157 $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value"
150 158 unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value"
151 159 falling back to default value: abort
152 160 abort: accessing `persistent-nodemap` repository without associated fast implementation.
153 161 (check `hg help config.format.use-persistent-nodemap` for details)
154 162 [255]
155 163
156 164 $ hg log -r . --config "storage.revlog.persistent-nodemap.slow-path=warn"
157 165 warning: accessing `persistent-nodemap` repository without associated fast implementation.
158 166 (check `hg help config.format.use-persistent-nodemap` for details)
159 167 changeset: 5000:6b02b8c7b966
160 168 tag: tip
161 169 user: debugbuilddag
162 170 date: Thu Jan 01 01:23:20 1970 +0000
163 171 summary: r5000
164 172
165 173 $ hg ci -m 'foo' --config "storage.revlog.persistent-nodemap.slow-path=abort"
166 174 abort: accessing `persistent-nodemap` repository without associated fast implementation.
167 175 (check `hg help config.format.use-persistent-nodemap` for details)
168 176 [255]
169 177
170 178 #else
171 179
172 180 $ hg id --config "storage.revlog.persistent-nodemap.slow-path=invalid-value"
173 181 unknown value for config "storage.revlog.persistent-nodemap.slow-path": "invalid-value"
174 182 falling back to default value: abort
175 183 6b02b8c7b966+ tip
176 184
177 185 #endif
178 186
179 187 $ hg ci -m 'foo'
180 188
181 189 #if no-pure no-rust
182 190 $ hg debugnodemap --metadata
183 191 uid: ???????????????? (glob)
184 192 tip-rev: 5001
185 193 tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c
186 194 data-length: 121088
187 195 data-unused: 0
188 196 data-unused: 0.000%
189 197 #else
190 198 $ hg debugnodemap --metadata
191 199 uid: ???????????????? (glob)
192 200 tip-rev: 5001
193 201 tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c
194 202 data-length: 121344
195 203 data-unused: 256
196 204 data-unused: 0.211%
197 205 #endif
198 206
199 207 $ f --size .hg/store/00changelog.n
200 208 .hg/store/00changelog.n: size=70
201 209
202 210 (The pure code use the debug code that perform incremental update, the C code reencode from scratch)
203 211
204 212 #if pure
205 213 $ f --sha256 .hg/store/00changelog-*.nd --size
206 214 .hg/store/00changelog-????????????????.nd: size=121344, sha256=cce54c5da5bde3ad72a4938673ed4064c86231b9c64376b082b163fdb20f8f66 (glob)
207 215 #endif
208 216
209 217 #if rust
210 218 $ f --sha256 .hg/store/00changelog-*.nd --size
211 219 .hg/store/00changelog-????????????????.nd: size=121344, sha256=952b042fcf614ceb37b542b1b723e04f18f83efe99bee4e0f5ccd232ef470e58 (glob)
212 220 #endif
213 221
214 222 #if no-pure no-rust
215 223 $ f --sha256 .hg/store/00changelog-*.nd --size
216 224 .hg/store/00changelog-????????????????.nd: size=121088, sha256=df7c06a035b96cb28c7287d349d603baef43240be7736fe34eea419a49702e17 (glob)
217 225 #endif
218 226
219 227 $ hg debugnodemap --check
220 228 revision in index: 5002
221 229 revision in nodemap: 5002
222 230
223 231 Test code path without mmap
224 232 ---------------------------
225 233
226 234 $ echo bar > bar
227 235 $ hg add bar
228 236 $ hg ci -m 'bar' --config storage.revlog.persistent-nodemap.mmap=no
229 237
230 238 $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=yes
231 239 revision in index: 5003
232 240 revision in nodemap: 5003
233 241 $ hg debugnodemap --check --config storage.revlog.persistent-nodemap.mmap=no
234 242 revision in index: 5003
235 243 revision in nodemap: 5003
236 244
237 245
238 246 #if pure
239 247 $ hg debugnodemap --metadata
240 248 uid: ???????????????? (glob)
241 249 tip-rev: 5002
242 250 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
243 251 data-length: 121600
244 252 data-unused: 512
245 253 data-unused: 0.421%
246 254 $ f --sha256 .hg/store/00changelog-*.nd --size
247 255 .hg/store/00changelog-????????????????.nd: size=121600, sha256=def52503d049ccb823974af313a98a935319ba61f40f3aa06a8be4d35c215054 (glob)
248 256 #endif
249 257 #if rust
250 258 $ hg debugnodemap --metadata
251 259 uid: ???????????????? (glob)
252 260 tip-rev: 5002
253 261 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
254 262 data-length: 121600
255 263 data-unused: 512
256 264 data-unused: 0.421%
257 265 $ f --sha256 .hg/store/00changelog-*.nd --size
258 266 .hg/store/00changelog-????????????????.nd: size=121600, sha256=dacf5b5f1d4585fee7527d0e67cad5b1ba0930e6a0928f650f779aefb04ce3fb (glob)
259 267 #endif
260 268 #if no-pure no-rust
261 269 $ hg debugnodemap --metadata
262 270 uid: ???????????????? (glob)
263 271 tip-rev: 5002
264 272 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
265 273 data-length: 121088
266 274 data-unused: 0
267 275 data-unused: 0.000%
268 276 $ f --sha256 .hg/store/00changelog-*.nd --size
269 277 .hg/store/00changelog-????????????????.nd: size=121088, sha256=59fcede3e3cc587755916ceed29e3c33748cd1aa7d2f91828ac83e7979d935e8 (glob)
270 278 #endif
271 279
272 280 Test force warming the cache
273 281
274 282 $ rm .hg/store/00changelog.n
275 283 $ hg debugnodemap --metadata
276 284 $ hg debugupdatecache
277 285 #if pure
278 286 $ hg debugnodemap --metadata
279 287 uid: ???????????????? (glob)
280 288 tip-rev: 5002
281 289 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
282 290 data-length: 121088
283 291 data-unused: 0
284 292 data-unused: 0.000%
285 293 #else
286 294 $ hg debugnodemap --metadata
287 295 uid: ???????????????? (glob)
288 296 tip-rev: 5002
289 297 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
290 298 data-length: 121088
291 299 data-unused: 0
292 300 data-unused: 0.000%
293 301 #endif
294 302
295 303 Check out of sync nodemap
296 304 =========================
297 305
298 306 First copy old data on the side.
299 307
300 308 $ mkdir ../tmp-copies
301 309 $ cp .hg/store/00changelog-????????????????.nd .hg/store/00changelog.n ../tmp-copies
302 310
303 311 Nodemap lagging behind
304 312 ----------------------
305 313
306 314 make a new commit
307 315
308 316 $ echo bar2 > bar
309 317 $ hg ci -m 'bar2'
310 318 $ NODE=`hg log -r tip -T '{node}\n'`
311 319 $ hg log -r "$NODE" -T '{rev}\n'
312 320 5003
313 321
314 322 If the nodemap is lagging behind, it can catch up fine
315 323
316 324 $ hg debugnodemap --metadata
317 325 uid: ???????????????? (glob)
318 326 tip-rev: 5003
319 327 tip-node: c9329770f979ade2d16912267c38ba5f82fd37b3
320 328 data-length: 121344 (pure !)
321 329 data-length: 121344 (rust !)
322 330 data-length: 121152 (no-rust no-pure !)
323 331 data-unused: 192 (pure !)
324 332 data-unused: 192 (rust !)
325 333 data-unused: 0 (no-rust no-pure !)
326 334 data-unused: 0.158% (pure !)
327 335 data-unused: 0.158% (rust !)
328 336 data-unused: 0.000% (no-rust no-pure !)
329 337 $ cp -f ../tmp-copies/* .hg/store/
330 338 $ hg debugnodemap --metadata
331 339 uid: ???????????????? (glob)
332 340 tip-rev: 5002
333 341 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
334 342 data-length: 121088
335 343 data-unused: 0
336 344 data-unused: 0.000%
337 345 $ hg log -r "$NODE" -T '{rev}\n'
338 346 5003
339 347
340 348 changelog altered
341 349 -----------------
342 350
343 351 If the nodemap is not gated behind a requirements, an unaware client can alter
344 352 the repository so the revlog used to generate the nodemap is not longer
345 353 compatible with the persistent nodemap. We need to detect that.
346 354
347 355 $ hg up "$NODE~5"
348 356 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
349 357 $ echo bar > babar
350 358 $ hg add babar
351 359 $ hg ci -m 'babar'
352 360 created new head
353 361 $ OTHERNODE=`hg log -r tip -T '{node}\n'`
354 362 $ hg log -r "$OTHERNODE" -T '{rev}\n'
355 363 5004
356 364
357 365 $ hg --config extensions.strip= strip --rev "$NODE~1" --no-backup
358 366
359 367 the nodemap should detect the changelog have been tampered with and recover.
360 368
361 369 $ hg debugnodemap --metadata
362 370 uid: ???????????????? (glob)
363 371 tip-rev: 5002
364 372 tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944
365 373 data-length: 121536 (pure !)
366 374 data-length: 121088 (rust !)
367 375 data-length: 121088 (no-pure no-rust !)
368 376 data-unused: 448 (pure !)
369 377 data-unused: 0 (rust !)
370 378 data-unused: 0 (no-pure no-rust !)
371 379 data-unused: 0.000% (rust !)
372 380 data-unused: 0.369% (pure !)
373 381 data-unused: 0.000% (no-pure no-rust !)
374 382
375 383 $ cp -f ../tmp-copies/* .hg/store/
376 384 $ hg debugnodemap --metadata
377 385 uid: ???????????????? (glob)
378 386 tip-rev: 5002
379 387 tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
380 388 data-length: 121088
381 389 data-unused: 0
382 390 data-unused: 0.000%
383 391 $ hg log -r "$OTHERNODE" -T '{rev}\n'
384 392 5002
385 393
386 394 missing data file
387 395 -----------------
388 396
389 397 $ UUID=`hg debugnodemap --metadata| grep 'uid:' | \
390 398 > sed 's/uid: //'`
391 399 $ FILE=.hg/store/00changelog-"${UUID}".nd
392 400 $ mv $FILE ../tmp-data-file
393 401 $ cp .hg/store/00changelog.n ../tmp-docket
394 402
395 403 mercurial don't crash
396 404
397 405 $ hg log -r .
398 406 changeset: 5002:b355ef8adce0
399 407 tag: tip
400 408 parent: 4998:d918ad6d18d3
401 409 user: test
402 410 date: Thu Jan 01 00:00:00 1970 +0000
403 411 summary: babar
404 412
405 413 $ hg debugnodemap --metadata
406 414
407 415 $ hg debugupdatecache
408 416 $ hg debugnodemap --metadata
409 417 uid: * (glob)
410 418 tip-rev: 5002
411 419 tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944
412 420 data-length: 121088
413 421 data-unused: 0
414 422 data-unused: 0.000%
415 423 $ mv ../tmp-data-file $FILE
416 424 $ mv ../tmp-docket .hg/store/00changelog.n
417 425
418 426 Check transaction related property
419 427 ==================================
420 428
421 429 An up to date nodemap should be available to shell hooks,
422 430
423 431 $ echo dsljfl > a
424 432 $ hg add a
425 433 $ hg ci -m a
426 434 $ hg debugnodemap --metadata
427 435 uid: ???????????????? (glob)
428 436 tip-rev: 5003
429 437 tip-node: a52c5079765b5865d97b993b303a18740113bbb2
430 438 data-length: 121088
431 439 data-unused: 0
432 440 data-unused: 0.000%
433 441 $ echo babar2 > babar
434 442 $ hg ci -m 'babar2' --config "hooks.pretxnclose.nodemap-test=hg debugnodemap --metadata"
435 443 uid: ???????????????? (glob)
436 444 tip-rev: 5004
437 445 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
438 446 data-length: 121280 (pure !)
439 447 data-length: 121280 (rust !)
440 448 data-length: 121088 (no-pure no-rust !)
441 449 data-unused: 192 (pure !)
442 450 data-unused: 192 (rust !)
443 451 data-unused: 0 (no-pure no-rust !)
444 452 data-unused: 0.158% (pure !)
445 453 data-unused: 0.158% (rust !)
446 454 data-unused: 0.000% (no-pure no-rust !)
447 455 $ hg debugnodemap --metadata
448 456 uid: ???????????????? (glob)
449 457 tip-rev: 5004
450 458 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
451 459 data-length: 121280 (pure !)
452 460 data-length: 121280 (rust !)
453 461 data-length: 121088 (no-pure no-rust !)
454 462 data-unused: 192 (pure !)
455 463 data-unused: 192 (rust !)
456 464 data-unused: 0 (no-pure no-rust !)
457 465 data-unused: 0.158% (pure !)
458 466 data-unused: 0.158% (rust !)
459 467 data-unused: 0.000% (no-pure no-rust !)
460 468
461 469 Another process does not see the pending nodemap content during run.
462 470
463 471 $ PATH=$RUNTESTDIR/testlib/:$PATH
464 472 $ echo qpoasp > a
465 473 $ hg ci -m a2 \
466 474 > --config "hooks.pretxnclose=wait-on-file 20 sync-repo-read sync-txn-pending" \
467 475 > --config "hooks.txnclose=touch sync-txn-close" > output.txt 2>&1 &
468 476
469 477 (read the repository while the commit transaction is pending)
470 478
471 479 $ wait-on-file 20 sync-txn-pending && \
472 480 > hg debugnodemap --metadata && \
473 481 > wait-on-file 20 sync-txn-close sync-repo-read
474 482 uid: ???????????????? (glob)
475 483 tip-rev: 5004
476 484 tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
477 485 data-length: 121280 (pure !)
478 486 data-length: 121280 (rust !)
479 487 data-length: 121088 (no-pure no-rust !)
480 488 data-unused: 192 (pure !)
481 489 data-unused: 192 (rust !)
482 490 data-unused: 0 (no-pure no-rust !)
483 491 data-unused: 0.158% (pure !)
484 492 data-unused: 0.158% (rust !)
485 493 data-unused: 0.000% (no-pure no-rust !)
486 494 $ hg debugnodemap --metadata
487 495 uid: ???????????????? (glob)
488 496 tip-rev: 5005
489 497 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
490 498 data-length: 121536 (pure !)
491 499 data-length: 121536 (rust !)
492 500 data-length: 121088 (no-pure no-rust !)
493 501 data-unused: 448 (pure !)
494 502 data-unused: 448 (rust !)
495 503 data-unused: 0 (no-pure no-rust !)
496 504 data-unused: 0.369% (pure !)
497 505 data-unused: 0.369% (rust !)
498 506 data-unused: 0.000% (no-pure no-rust !)
499 507
500 508 $ cat output.txt
501 509
502 510 Check that a failing transaction will properly revert the data
503 511
504 512 $ echo plakfe > a
505 513 $ f --size --sha256 .hg/store/00changelog-*.nd
506 514 .hg/store/00changelog-????????????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
507 515 .hg/store/00changelog-????????????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
508 516 .hg/store/00changelog-????????????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !)
509 517 $ hg ci -m a3 --config "extensions.abort=$RUNTESTDIR/testlib/crash_transaction_late.py"
510 518 transaction abort!
511 519 rollback completed
512 520 abort: This is a late abort
513 521 [255]
514 522 $ hg debugnodemap --metadata
515 523 uid: ???????????????? (glob)
516 524 tip-rev: 5005
517 525 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
518 526 data-length: 121536 (pure !)
519 527 data-length: 121536 (rust !)
520 528 data-length: 121088 (no-pure no-rust !)
521 529 data-unused: 448 (pure !)
522 530 data-unused: 448 (rust !)
523 531 data-unused: 0 (no-pure no-rust !)
524 532 data-unused: 0.369% (pure !)
525 533 data-unused: 0.369% (rust !)
526 534 data-unused: 0.000% (no-pure no-rust !)
527 535 $ f --size --sha256 .hg/store/00changelog-*.nd
528 536 .hg/store/00changelog-????????????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
529 537 .hg/store/00changelog-????????????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
530 538 .hg/store/00changelog-????????????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !)
531 539
532 540 Check that removing content does not confuse the nodemap
533 541 --------------------------------------------------------
534 542
535 543 removing data with rollback
536 544
537 545 $ echo aso > a
538 546 $ hg ci -m a4
539 547 $ hg rollback
540 548 repository tip rolled back to revision 5005 (undo commit)
541 549 working directory now based on revision 5005
542 550 $ hg id -r .
543 551 90d5d3ba2fc4 tip
544 552
545 553 roming data with strip
546 554
547 555 $ echo aso > a
548 556 $ hg ci -m a4
549 557 $ hg --config extensions.strip= strip -r . --no-backup
550 558 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
551 559 $ hg id -r . --traceback
552 560 90d5d3ba2fc4 tip
553 561
554 562 Test upgrade / downgrade
555 563 ========================
556 564
557 565 downgrading
558 566
559 567 $ cat << EOF >> .hg/hgrc
560 568 > [format]
561 569 > use-persistent-nodemap=no
562 570 > EOF
563 571 $ hg debugformat -v
564 572 format-variant repo config default
565 573 fncache: yes yes yes
566 574 dotencode: yes yes yes
567 575 generaldelta: yes yes yes
568 576 share-safe: no no no
569 577 sparserevlog: yes yes yes
570 578 sidedata: no no no
571 579 persistent-nodemap: yes no no
572 580 copies-sdc: no no no
573 581 plain-cl-delta: yes yes yes
574 582 compression: zlib zlib zlib
575 583 compression-level: default default default
576 584 $ hg debugupgraderepo --run --no-backup --quiet
577 585 upgrade will perform the following actions:
578 586
579 587 requirements
580 588 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
581 589 removed: persistent-nodemap
582 590
583 591 processed revlogs:
584 592 - all-filelogs
585 593 - changelog
586 594 - manifest
587 595
588 596 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
589 597 [1]
590 598 $ hg debugnodemap --metadata
591 599
592 600
593 601 upgrading
594 602
595 603 $ cat << EOF >> .hg/hgrc
596 604 > [format]
597 605 > use-persistent-nodemap=yes
598 606 > EOF
599 607 $ hg debugformat -v
600 608 format-variant repo config default
601 609 fncache: yes yes yes
602 610 dotencode: yes yes yes
603 611 generaldelta: yes yes yes
604 612 share-safe: no no no
605 613 sparserevlog: yes yes yes
606 614 sidedata: no no no
607 615 persistent-nodemap: no yes no
608 616 copies-sdc: no no no
609 617 plain-cl-delta: yes yes yes
610 618 compression: zlib zlib zlib
611 619 compression-level: default default default
612 620 $ hg debugupgraderepo --run --no-backup --quiet
613 621 upgrade will perform the following actions:
614 622
615 623 requirements
616 624 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
617 625 added: persistent-nodemap
618 626
619 627 processed revlogs:
620 628 - all-filelogs
621 629 - changelog
622 630 - manifest
623 631
624 632 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
625 633 00changelog-*.nd (glob)
626 634 00changelog.n
627 635 00manifest-*.nd (glob)
628 636 00manifest.n
629 637
630 638 $ hg debugnodemap --metadata
631 639 uid: * (glob)
632 640 tip-rev: 5005
633 641 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
634 642 data-length: 121088
635 643 data-unused: 0
636 644 data-unused: 0.000%
637 645
638 646 Running unrelated upgrade
639 647
640 648 $ hg debugupgraderepo --run --no-backup --quiet --optimize re-delta-all
641 649 upgrade will perform the following actions:
642 650
643 651 requirements
644 652 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, sparserevlog, store
645 653
646 654 optimisations: re-delta-all
647 655
648 656 processed revlogs:
649 657 - all-filelogs
650 658 - changelog
651 659 - manifest
652 660
653 661 $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
654 662 00changelog-*.nd (glob)
655 663 00changelog.n
656 664 00manifest-*.nd (glob)
657 665 00manifest.n
658 666
659 667 $ hg debugnodemap --metadata
660 668 uid: * (glob)
661 669 tip-rev: 5005
662 670 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
663 671 data-length: 121088
664 672 data-unused: 0
665 673 data-unused: 0.000%
666 674
667 675 Persistent nodemap and local/streaming clone
668 676 ============================================
669 677
670 678 $ cd ..
671 679
672 680 standard clone
673 681 --------------
674 682
675 683 The persistent nodemap should exist after a streaming clone
676 684
677 685 $ hg clone --pull --quiet -U test-repo standard-clone
678 686 $ ls -1 standard-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
679 687 00changelog-*.nd (glob)
680 688 00changelog.n
681 689 00manifest-*.nd (glob)
682 690 00manifest.n
683 691 $ hg -R standard-clone debugnodemap --metadata
684 692 uid: * (glob)
685 693 tip-rev: 5005
686 694 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
687 695 data-length: 121088
688 696 data-unused: 0
689 697 data-unused: 0.000%
690 698
691 699
692 700 local clone
693 701 ------------
694 702
695 703 The persistent nodemap should exist after a streaming clone
696 704
697 705 $ hg clone -U test-repo local-clone
698 706 $ ls -1 local-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
699 707 00changelog-*.nd (glob)
700 708 00changelog.n
701 709 00manifest-*.nd (glob)
702 710 00manifest.n
703 711 $ hg -R local-clone debugnodemap --metadata
704 712 uid: * (glob)
705 713 tip-rev: 5005
706 714 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
707 715 data-length: 121088
708 716 data-unused: 0
709 717 data-unused: 0.000%
710 718
711 719 stream clone
712 720 ------------
713 721
714 722 The persistent nodemap should exist after a streaming clone
715 723
716 724 $ hg clone -U --stream --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/test-repo stream-clone --debug | egrep '00(changelog|manifest)'
717 725 adding [s] 00manifest.n (70 bytes)
718 726 adding [s] 00manifest.i (313 KB)
719 727 adding [s] 00manifest.d (452 KB)
720 728 adding [s] 00manifest-*.nd (118 KB) (glob)
721 729 adding [s] 00changelog.n (70 bytes)
722 730 adding [s] 00changelog.i (313 KB)
723 731 adding [s] 00changelog.d (360 KB)
724 732 adding [s] 00changelog-*.nd (118 KB) (glob)
725 733 $ ls -1 stream-clone/.hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
726 734 00changelog-*.nd (glob)
727 735 00changelog.n
728 736 00manifest-*.nd (glob)
729 737 00manifest.n
730 738 $ hg -R stream-clone debugnodemap --metadata
731 739 uid: * (glob)
732 740 tip-rev: 5005
733 741 tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
734 742 data-length: 121088
735 743 data-unused: 0
736 744 data-unused: 0.000%
General Comments 0
You need to be logged in to leave comments. Login now