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 |
|
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 |
|
|
44 | Self { on_disk, ptr } | |
46 | } |
|
45 | } | |
47 |
|
46 | |||
48 |
pub fn |
|
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` |
|
103 | // own. Since that `Box` is `Send` as shown in above, it is sound to mark | |
116 |
// |
|
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:: |
|
1 | use crate::dirstate::parsers::Timestamp; | |
2 | use hg::dirstate::parsers::Timestamp; |
|
2 | use crate::dirstate_tree::dispatch::DirstateMapMethods; | |
3 |
use |
|
3 | use crate::dirstate_tree::on_disk::DirstateV2ParseError; | |
4 |
use |
|
4 | use crate::dirstate_tree::owning::OwningDirstateMap; | |
5 |
use |
|
5 | use crate::matchers::Matcher; | |
6 |
use |
|
6 | use crate::utils::hg_path::{HgPath, HgPathBuf}; | |
7 |
use |
|
7 | use crate::CopyMapIter; | |
8 |
use |
|
8 | use crate::DirstateEntry; | |
9 |
use |
|
9 | use crate::DirstateError; | |
10 |
use |
|
10 | use crate::DirstateParents; | |
11 |
use |
|
11 | use crate::DirstateStatus; | |
12 |
use |
|
12 | use crate::PatternFileWarning; | |
13 |
use |
|
13 | use crate::StateMapIter; | |
14 |
use |
|
14 | use crate::StatusError; | |
15 |
use |
|
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 |
|
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( |
|
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