##// END OF EJS Templates
rust: Make OwningDirstateMap generic and move it into hg-core...
Simon Sapin -
r48766:4afd6cc4 default
parent child Browse files
Show More
@@ -1,5 +1,7 b''
1 # This file is automatically @generated by Cargo.
1 # This file is automatically @generated by Cargo.
2 # It is not intended for manual editing.
2 # It is not intended for manual editing.
3 version = 3
4
3 [[package]]
5 [[package]]
4 name = "adler"
6 name = "adler"
5 version = "0.2.3"
7 version = "0.2.3"
@@ -396,6 +398,7 b' dependencies = ['
396 "regex",
398 "regex",
397 "same-file",
399 "same-file",
398 "sha-1",
400 "sha-1",
401 "stable_deref_trait",
399 "tempfile",
402 "tempfile",
400 "twox-hash",
403 "twox-hash",
401 "zstd",
404 "zstd",
@@ -411,6 +414,7 b' dependencies = ['
411 "hg-core",
414 "hg-core",
412 "libc",
415 "libc",
413 "log",
416 "log",
417 "stable_deref_trait",
414 ]
418 ]
415
419
416 [[package]]
420 [[package]]
@@ -865,6 +869,12 b' dependencies = ['
865 ]
869 ]
866
870
867 [[package]]
871 [[package]]
872 name = "stable_deref_trait"
873 version = "1.2.0"
874 source = "registry+https://github.com/rust-lang/crates.io-index"
875 checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
876
877 [[package]]
868 name = "static_assertions"
878 name = "static_assertions"
869 version = "1.1.0"
879 version = "1.1.0"
870 source = "registry+https://github.com/rust-lang/crates.io-index"
880 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -24,6 +24,7 b' regex = "1.3.9"'
24 sha-1 = "0.9.6"
24 sha-1 = "0.9.6"
25 twox-hash = "1.5.0"
25 twox-hash = "1.5.0"
26 same-file = "1.0.6"
26 same-file = "1.0.6"
27 stable_deref_trait = "1.2.0"
27 tempfile = "3.1.0"
28 tempfile = "3.1.0"
28 crossbeam-channel = "0.4"
29 crossbeam-channel = "0.4"
29 micro-timer = "0.3.0"
30 micro-timer = "0.3.0"
@@ -1,5 +1,7 b''
1 pub mod dirstate_map;
1 pub mod dirstate_map;
2 pub mod dispatch;
2 pub mod dispatch;
3 pub mod on_disk;
3 pub mod on_disk;
4 pub mod owning;
5 mod owning_dispatch;
4 pub mod path_with_basename;
6 pub mod path_with_basename;
5 pub mod status;
7 pub mod status;
@@ -1,11 +1,9 b''
1 use cpython::PyBytes;
1 use super::dirstate_map::DirstateMap;
2 use cpython::Python;
2 use stable_deref_trait::StableDeref;
3 use hg::dirstate_tree::dirstate_map::DirstateMap;
3 use std::ops::Deref;
4 use hg::DirstateError;
5 use hg::DirstateParents;
6
4
7 /// Keep a `DirstateMap<'on_disk>` next to the `on_disk` buffer that it
5 /// Keep a `DirstateMap<'on_disk>` next to the `on_disk` buffer that it
8 /// borrows. This is similar to the owning-ref crate.
6 /// borrows.
9 ///
7 ///
10 /// This is similar to [`OwningRef`] which is more limited because it
8 /// This is similar to [`OwningRef`] which is more limited because it
11 /// represents exactly one `&T` reference next to the value it borrows, as
9 /// represents exactly one `&T` reference next to the value it borrows, as
@@ -13,11 +11,11 b' use hg::DirstateParents;'
13 /// arbitrarily-nested data structures.
11 /// arbitrarily-nested data structures.
14 ///
12 ///
15 /// [`OwningRef`]: https://docs.rs/owning_ref/0.4.1/owning_ref/struct.OwningRef.html
13 /// [`OwningRef`]: https://docs.rs/owning_ref/0.4.1/owning_ref/struct.OwningRef.html
16 pub(super) struct OwningDirstateMap {
14 pub struct OwningDirstateMap {
17 /// Owned handle to a bytes buffer with a stable address.
15 /// Owned handle to a bytes buffer with a stable address.
18 ///
16 ///
19 /// See <https://docs.rs/owning_ref/0.4.1/owning_ref/trait.StableAddress.html>.
17 /// See <https://docs.rs/owning_ref/0.4.1/owning_ref/trait.StableAddress.html>.
20 on_disk: PyBytes,
18 on_disk: Box<dyn Deref<Target = [u8]> + Send>,
21
19
22 /// Pointer for `Box<DirstateMap<'on_disk>>`, typed-erased because the
20 /// Pointer for `Box<DirstateMap<'on_disk>>`, typed-erased because the
23 /// language cannot represent a lifetime referencing a sibling field.
21 /// language cannot represent a lifetime referencing a sibling field.
@@ -28,12 +26,13 b' pub(super) struct OwningDirstateMap {'
28 }
26 }
29
27
30 impl OwningDirstateMap {
28 impl OwningDirstateMap {
31 pub fn new_v1(
29 pub fn new_empty<OnDisk>(on_disk: OnDisk) -> Self
32 py: Python,
30 where
33 on_disk: PyBytes,
31 OnDisk: Deref<Target = [u8]> + StableDeref + Send + 'static,
34 ) -> Result<(Self, Option<DirstateParents>), DirstateError> {
32 {
35 let bytes: &'_ [u8] = on_disk.data(py);
33 let on_disk = Box::new(on_disk);
36 let (map, parents) = DirstateMap::new_v1(bytes)?;
34 let bytes: &'_ [u8] = &on_disk;
35 let map = DirstateMap::empty(bytes);
37
36
38 // Like in `bytes` above, this `'_` lifetime parameter borrows from
37 // Like in `bytes` above, this `'_` lifetime parameter borrows from
39 // the bytes buffer owned by `on_disk`.
38 // the bytes buffer owned by `on_disk`.
@@ -42,30 +41,12 b' impl OwningDirstateMap {'
42 // Erase the pointed type entirely in order to erase the lifetime.
41 // Erase the pointed type entirely in order to erase the lifetime.
43 let ptr: *mut () = ptr.cast();
42 let ptr: *mut () = ptr.cast();
44
43
45 Ok((Self { on_disk, ptr }, parents))
44 Self { on_disk, ptr }
46 }
45 }
47
46
48 pub fn new_v2(
47 pub fn get_mut_pair<'a>(
49 py: Python,
48 &'a mut self,
50 on_disk: PyBytes,
49 ) -> (&'a [u8], &'a mut DirstateMap<'a>) {
51 data_size: usize,
52 tree_metadata: PyBytes,
53 ) -> Result<Self, DirstateError> {
54 let bytes: &'_ [u8] = on_disk.data(py);
55 let map =
56 DirstateMap::new_v2(bytes, data_size, tree_metadata.data(py))?;
57
58 // Like in `bytes` above, this `'_` lifetime parameter borrows from
59 // the bytes buffer owned by `on_disk`.
60 let ptr: *mut DirstateMap<'_> = Box::into_raw(Box::new(map));
61
62 // Erase the pointed type entirely in order to erase the lifetime.
63 let ptr: *mut () = ptr.cast();
64
65 Ok(Self { on_disk, ptr })
66 }
67
68 pub fn get_mut<'a>(&'a mut self) -> &'a mut DirstateMap<'a> {
69 // SAFETY: We cast the type-erased pointer back to the same type it had
50 // SAFETY: We cast the type-erased pointer back to the same type it had
70 // in `new`, except with a different lifetime parameter. This time we
51 // in `new`, except with a different lifetime parameter. This time we
71 // connect the lifetime to that of `self`. This cast is valid because
52 // connect the lifetime to that of `self`. This cast is valid because
@@ -76,7 +57,11 b' impl OwningDirstateMap {'
76 // SAFETY: we dereference that pointer, connecting the lifetime of the
57 // SAFETY: we dereference that pointer, connecting the lifetime of the
77 // new `&mut` to that of `self`. This is valid because the
58 // new `&mut` to that of `self`. This is valid because the
78 // raw pointer is to a boxed value, and `self` owns that box.
59 // raw pointer is to a boxed value, and `self` owns that box.
79 unsafe { &mut *ptr }
60 (&self.on_disk, unsafe { &mut *ptr })
61 }
62
63 pub fn get_mut<'a>(&'a mut self) -> &'a mut DirstateMap<'a> {
64 self.get_mut_pair().1
80 }
65 }
81
66
82 pub fn get<'a>(&'a self) -> &'a DirstateMap<'a> {
67 pub fn get<'a>(&'a self) -> &'a DirstateMap<'a> {
@@ -84,6 +69,10 b' impl OwningDirstateMap {'
84 let ptr: *mut DirstateMap<'a> = self.ptr.cast();
69 let ptr: *mut DirstateMap<'a> = self.ptr.cast();
85 unsafe { &*ptr }
70 unsafe { &*ptr }
86 }
71 }
72
73 pub fn on_disk<'a>(&'a self) -> &'a [u8] {
74 &self.on_disk
75 }
87 }
76 }
88
77
89 impl Drop for OwningDirstateMap {
78 impl Drop for OwningDirstateMap {
@@ -105,13 +94,12 b' impl Drop for OwningDirstateMap {'
105 fn _static_assert_is_send<T: Send>() {}
94 fn _static_assert_is_send<T: Send>() {}
106
95
107 fn _static_assert_fields_are_send() {
96 fn _static_assert_fields_are_send() {
108 _static_assert_is_send::<PyBytes>();
109 _static_assert_is_send::<Box<DirstateMap<'_>>>();
97 _static_assert_is_send::<Box<DirstateMap<'_>>>();
110 }
98 }
111
99
112 // SAFETY: we don’t get this impl implicitly because `*mut (): !Send` because
100 // SAFETY: we don’t get this impl implicitly because `*mut (): !Send` because
113 // thread-safety of raw pointers is unknown in the general case. However this
101 // thread-safety of raw pointers is unknown in the general case. However this
114 // particular raw pointer represents a `Box<DirstateMap<'on_disk>>` that we
102 // particular raw pointer represents a `Box<DirstateMap<'on_disk>>` that we
115 // own. Since that `Box` and `PyBytes` are both `Send` as shown in above, it
103 // own. Since that `Box` is `Send` as shown in above, it is sound to mark
116 // is sound to mark this struct as `Send` too.
104 // this struct as `Send` too.
117 unsafe impl Send for OwningDirstateMap {}
105 unsafe impl Send for OwningDirstateMap {}
@@ -1,18 +1,18 b''
1 use crate::dirstate::owning::OwningDirstateMap;
1 use crate::dirstate::parsers::Timestamp;
2 use hg::dirstate::parsers::Timestamp;
2 use crate::dirstate_tree::dispatch::DirstateMapMethods;
3 use hg::dirstate_tree::dispatch::DirstateMapMethods;
3 use crate::dirstate_tree::on_disk::DirstateV2ParseError;
4 use hg::dirstate_tree::on_disk::DirstateV2ParseError;
4 use crate::dirstate_tree::owning::OwningDirstateMap;
5 use hg::matchers::Matcher;
5 use crate::matchers::Matcher;
6 use hg::utils::hg_path::{HgPath, HgPathBuf};
6 use crate::utils::hg_path::{HgPath, HgPathBuf};
7 use hg::CopyMapIter;
7 use crate::CopyMapIter;
8 use hg::DirstateEntry;
8 use crate::DirstateEntry;
9 use hg::DirstateError;
9 use crate::DirstateError;
10 use hg::DirstateParents;
10 use crate::DirstateParents;
11 use hg::DirstateStatus;
11 use crate::DirstateStatus;
12 use hg::PatternFileWarning;
12 use crate::PatternFileWarning;
13 use hg::StateMapIter;
13 use crate::StateMapIter;
14 use hg::StatusError;
14 use crate::StatusError;
15 use hg::StatusOptions;
15 use crate::StatusOptions;
16 use std::path::PathBuf;
16 use std::path::PathBuf;
17
17
18 impl DirstateMapMethods for OwningDirstateMap {
18 impl DirstateMapMethods for OwningDirstateMap {
@@ -26,6 +26,7 b' hg-core = { path = "../hg-core"}'
26 libc = '*'
26 libc = '*'
27 log = "0.4.8"
27 log = "0.4.8"
28 env_logger = "0.7.1"
28 env_logger = "0.7.1"
29 stable_deref_trait = "1.2.0"
29
30
30 [dependencies.cpython]
31 [dependencies.cpython]
31 version = "0.6.0"
32 version = "0.6.0"
@@ -12,9 +12,7 b''
12 mod copymap;
12 mod copymap;
13 mod dirs_multiset;
13 mod dirs_multiset;
14 mod dirstate_map;
14 mod dirstate_map;
15 mod dispatch;
16 mod non_normal_entries;
15 mod non_normal_entries;
17 mod owning;
18 mod status;
16 mod status;
19 use crate::{
17 use crate::{
20 dirstate::{
18 dirstate::{
@@ -24,15 +24,17 b' use crate::{'
24 dirstate::non_normal_entries::{
24 dirstate::non_normal_entries::{
25 NonNormalEntries, NonNormalEntriesIterator,
25 NonNormalEntries, NonNormalEntriesIterator,
26 },
26 },
27 dirstate::owning::OwningDirstateMap,
28 parsers::dirstate_parents_to_pytuple,
27 parsers::dirstate_parents_to_pytuple,
28 pybytes_deref::PyBytesDeref,
29 };
29 };
30 use hg::{
30 use hg::{
31 dirstate::parsers::Timestamp,
31 dirstate::parsers::Timestamp,
32 dirstate::MTIME_UNSET,
32 dirstate::MTIME_UNSET,
33 dirstate::SIZE_NON_NORMAL,
33 dirstate::SIZE_NON_NORMAL,
34 dirstate_tree::dirstate_map::DirstateMap as TreeDirstateMap,
34 dirstate_tree::dispatch::DirstateMapMethods,
35 dirstate_tree::dispatch::DirstateMapMethods,
35 dirstate_tree::on_disk::DirstateV2ParseError,
36 dirstate_tree::on_disk::DirstateV2ParseError,
37 dirstate_tree::owning::OwningDirstateMap,
36 revlog::Node,
38 revlog::Node,
37 utils::files::normalize_case,
39 utils::files::normalize_case,
38 utils::hg_path::{HgPath, HgPathBuf},
40 utils::hg_path::{HgPath, HgPathBuf},
@@ -62,8 +64,13 b' py_class!(pub class DirstateMap |py| {'
62 on_disk: PyBytes,
64 on_disk: PyBytes,
63 ) -> PyResult<PyObject> {
65 ) -> PyResult<PyObject> {
64 let (inner, parents) = if use_dirstate_tree {
66 let (inner, parents) = if use_dirstate_tree {
65 let (map, parents) = OwningDirstateMap::new_v1(py, on_disk)
67 let on_disk = PyBytesDeref::new(py, on_disk);
68 let mut map = OwningDirstateMap::new_empty(on_disk);
69 let (on_disk, map_placeholder) = map.get_mut_pair();
70
71 let (actual_map, parents) = TreeDirstateMap::new_v1(on_disk)
66 .map_err(|e| dirstate_error(py, e))?;
72 .map_err(|e| dirstate_error(py, e))?;
73 *map_placeholder = actual_map;
67 (Box::new(map) as _, parents)
74 (Box::new(map) as _, parents)
68 } else {
75 } else {
69 let bytes = on_disk.data(py);
76 let bytes = on_disk.data(py);
@@ -86,10 +93,13 b' py_class!(pub class DirstateMap |py| {'
86 let dirstate_error = |e: DirstateError| {
93 let dirstate_error = |e: DirstateError| {
87 PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
94 PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
88 };
95 };
89 let inner = OwningDirstateMap::new_v2(
96 let on_disk = PyBytesDeref::new(py, on_disk);
90 py, on_disk, data_size, tree_metadata,
97 let mut map = OwningDirstateMap::new_empty(on_disk);
98 let (on_disk, map_placeholder) = map.get_mut_pair();
99 *map_placeholder = TreeDirstateMap::new_v2(
100 on_disk, data_size, tree_metadata.data(py),
91 ).map_err(dirstate_error)?;
101 ).map_err(dirstate_error)?;
92 let map = Self::create_instance(py, Box::new(inner))?;
102 let map = Self::create_instance(py, Box::new(map))?;
93 Ok(map.into_object())
103 Ok(map.into_object())
94 }
104 }
95
105
@@ -1,4 +1,5 b''
1 use cpython::{PyBytes, Python};
1 use cpython::{PyBytes, Python};
2 use stable_deref_trait::StableDeref;
2
3
3 /// Safe abstraction over a `PyBytes` together with the `&[u8]` slice
4 /// Safe abstraction over a `PyBytes` together with the `&[u8]` slice
4 /// that borrows it. Implements `Deref<Target = [u8]>`.
5 /// that borrows it. Implements `Deref<Target = [u8]>`.
@@ -40,6 +41,8 b' impl std::ops::Deref for PyBytesDeref {'
40 }
41 }
41 }
42 }
42
43
44 unsafe impl StableDeref for PyBytesDeref {}
45
43 fn require_send<T: Send>() {}
46 fn require_send<T: Send>() {}
44
47
45 #[allow(unused)]
48 #[allow(unused)]
General Comments 0
You need to be logged in to leave comments. Login now