##// END OF EJS Templates
rust-nodemap: falling back to C impl as mitigation...
Georges Racinet -
r48600:3fffb485 stable
parent child Browse files
Show More
@@ -59,12 +59,22 b' py_class!(pub class MixedIndex |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, node: PyBytes) -> PyResult<Option<Revision>> {
62 def get_rev(&self, pynode: 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, &node)?;
66 let node = node_from_py_bytes(py, &pynode)?;
67 nt.find_bin(idx, node.into()).map_err(|e| nodemap_error(py, e))
67 match nt.find_bin(idx, node.into())
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 }
68 }
78 }
69
79
70 /// same as `get_rev()` but raises a bare `error.RevlogError` if node
80 /// same as `get_rev()` but raises a bare `error.RevlogError` if node
@@ -94,27 +104,34 b' py_class!(pub class MixedIndex |py| {'
94 }
104 }
95 }
105 }
96
106
97 def partialmatch(&self, node: PyObject) -> PyResult<Option<PyBytes>> {
107 def partialmatch(&self, pynode: PyObject) -> PyResult<Option<PyBytes>> {
98 let opt = self.get_nodetree(py)?.borrow();
108 let opt = self.get_nodetree(py)?.borrow();
99 let nt = opt.as_ref().unwrap();
109 let nt = opt.as_ref().unwrap();
100 let idx = &*self.cindex(py).borrow();
110 let idx = &*self.cindex(py).borrow();
101
111
102 let node_as_string = if cfg!(feature = "python3-sys") {
112 let node_as_string = if cfg!(feature = "python3-sys") {
103 node.cast_as::<PyString>(py)?.to_string(py)?.to_string()
113 pynode.cast_as::<PyString>(py)?.to_string(py)?.to_string()
104 }
114 }
105 else {
115 else {
106 let node = node.extract::<PyBytes>(py)?;
116 let node = pynode.extract::<PyBytes>(py)?;
107 String::from_utf8_lossy(node.data(py)).to_string()
117 String::from_utf8_lossy(node.data(py)).to_string()
108 };
118 };
109
119
110 let prefix = NodePrefix::from_hex(&node_as_string).map_err(|_| PyErr::new::<ValueError, _>(py, "Invalid node or prefix"))?;
120 let prefix = NodePrefix::from_hex(&node_as_string).map_err(|_| PyErr::new::<ValueError, _>(py, "Invalid node or prefix"))?;
111
121
112 nt.find_bin(idx, prefix)
122 match nt.find_bin(idx, prefix) {
113 // TODO make an inner API returning the node directly
123 Ok(None) =>
114 .map(|opt| opt.map(
124 // fallback to C implementation, remove once
115 |rev| PyBytes::new(py, idx.node(rev).unwrap().as_bytes())))
125 // https://bz.mercurial-scm.org/show_bug.cgi?id=6554
116 .map_err(|e| nodemap_error(py, e))
126 // is fixed (a simple backout should do)
117
127 self.call_cindex(
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 }
118 }
135 }
119
136
120 /// append an index entry
137 /// append an index entry
@@ -428,6 +428,46 b" mercurial don't crash"
428 data-length: 121088
428 data-length: 121088
429 data-unused: 0
429 data-unused: 0
430 data-unused: 0.000%
430 data-unused: 0.000%
431
432 Sub-case: fallback for corrupted data file
433 ------------------------------------------
434
435 Sabotaging the data file so that nodemap resolutions fail, triggering fallback to
436 (non-persistent) C implementation.
437
438
439 $ UUID=`hg debugnodemap --metadata| grep 'uid:' | \
440 > sed 's/uid: //'`
441 $ FILE=.hg/store/00changelog-"${UUID}".nd
442 $ python -c "fobj = open('$FILE', 'r+b'); fobj.write(b'\xff' * 121088); fobj.close()"
443
444 The nodemap data file is still considered in sync with the docket. This
445 would fail without the fallback to the (non-persistent) C implementation:
446
447 $ hg log -r b355ef8adce0949b8bdf6afc72ca853740d65944 -T '{rev}\n' --traceback
448 5002
449
450 The nodemap data file hasn't been fixed, more tests can be inserted:
451
452 $ hg debugnodemap --dump-disk | f --bytes=256 --hexdump --size
453 size=121088
454 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
455 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
456 0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
457 0030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
458 0040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
459 0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
460 0060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
461 0070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
462 0080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
463 0090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
464 00a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
465 00b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
466 00c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
467 00d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
468 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
469 00f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
470
431 $ mv ../tmp-data-file $FILE
471 $ mv ../tmp-data-file $FILE
432 $ mv ../tmp-docket .hg/store/00changelog.n
472 $ mv ../tmp-docket .hg/store/00changelog.n
433
473
General Comments 0
You need to be logged in to leave comments. Login now