Instead of plain byte arrays.
Details
Details
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Lint
Automatic diff as part of commit; lint not applicable. - Unit
Automatic diff as part of commit; unit tests not applicable.
Instead of plain byte arrays.
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
Path | Packages | |||
---|---|---|---|---|
M | rust/hg-core/src/dirstate.rs (5 lines) | |||
M | rust/hg-core/src/dirstate/dirstate_map.rs (10 lines) | |||
M | rust/hg-core/src/dirstate/parsers.rs (28 lines) | |||
M | rust/hg-core/src/revlog/node.rs (7 lines) | |||
M | rust/hg-cpython/src/dirstate/dirstate_map.rs (16 lines) | |||
M | rust/hg-cpython/src/parsers.rs (14 lines) |
Status | Author | Revision | |
---|---|---|---|
Closed | SimonSapin | ||
Closed | SimonSapin | ||
Closed | SimonSapin | ||
Closed | SimonSapin | ||
Closed | SimonSapin | ||
Closed | SimonSapin | ||
Closed | SimonSapin | ||
Closed | SimonSapin | ||
Closed | SimonSapin | ||
Closed | SimonSapin | ||
Closed | SimonSapin | ||
Closed | SimonSapin | ||
Closed | SimonSapin |
// dirstate module | // dirstate module | ||||
// | // | ||||
// Copyright 2019 Raphaël Gomès <rgomes@octobus.net> | // Copyright 2019 Raphaël Gomès <rgomes@octobus.net> | ||||
// | // | ||||
// This software may be used and distributed according to the terms of the | // This software may be used and distributed according to the terms of the | ||||
// GNU General Public License version 2 or any later version. | // GNU General Public License version 2 or any later version. | ||||
use crate::errors::HgError; | use crate::errors::HgError; | ||||
use crate::revlog::Node; | |||||
use crate::{utils::hg_path::HgPathBuf, FastHashMap}; | use crate::{utils::hg_path::HgPathBuf, FastHashMap}; | ||||
use bytes_cast::{unaligned, BytesCast}; | use bytes_cast::{unaligned, BytesCast}; | ||||
use std::collections::hash_map; | use std::collections::hash_map; | ||||
use std::convert::TryFrom; | use std::convert::TryFrom; | ||||
pub mod dirs_multiset; | pub mod dirs_multiset; | ||||
pub mod dirstate_map; | pub mod dirstate_map; | ||||
#[cfg(feature = "dirstate-tree")] | #[cfg(feature = "dirstate-tree")] | ||||
pub mod dirstate_tree; | pub mod dirstate_tree; | ||||
pub mod parsers; | pub mod parsers; | ||||
pub mod status; | pub mod status; | ||||
#[derive(Debug, PartialEq, Clone, BytesCast)] | #[derive(Debug, PartialEq, Clone, BytesCast)] | ||||
#[repr(C)] | #[repr(C)] | ||||
pub struct DirstateParents { | pub struct DirstateParents { | ||||
pub p1: [u8; 20], | pub p1: Node, | ||||
pub p2: [u8; 20], | pub p2: Node, | ||||
} | } | ||||
/// The C implementation uses all signed types. This will be an issue | /// The C implementation uses all signed types. This will be an issue | ||||
/// either when 4GB+ source files are commonplace or in 2038, whichever | /// either when 4GB+ source files are commonplace or in 2038, whichever | ||||
/// comes first. | /// comes first. | ||||
#[derive(Debug, PartialEq, Copy, Clone)] | #[derive(Debug, PartialEq, Copy, Clone)] | ||||
pub struct DirstateEntry { | pub struct DirstateEntry { | ||||
pub state: EntryState, | pub state: EntryState, |
// dirstate_map.rs | // dirstate_map.rs | ||||
// | // | ||||
// Copyright 2019 Raphaël Gomès <rgomes@octobus.net> | // Copyright 2019 Raphaël Gomès <rgomes@octobus.net> | ||||
// | // | ||||
// This software may be used and distributed according to the terms of the | // This software may be used and distributed according to the terms of the | ||||
// GNU General Public License version 2 or any later version. | // GNU General Public License version 2 or any later version. | ||||
use crate::errors::HgError; | use crate::errors::HgError; | ||||
use crate::revlog::node::NULL_NODE_ID; | use crate::revlog::node::NULL_NODE; | ||||
use crate::{ | use crate::{ | ||||
dirstate::{parsers::PARENT_SIZE, EntryState, SIZE_FROM_OTHER_PARENT}, | dirstate::{parsers::PARENT_SIZE, EntryState, SIZE_FROM_OTHER_PARENT}, | ||||
pack_dirstate, parse_dirstate, | pack_dirstate, parse_dirstate, | ||||
utils::{ | utils::{ | ||||
files::normalize_case, | files::normalize_case, | ||||
hg_path::{HgPath, HgPathBuf}, | hg_path::{HgPath, HgPathBuf}, | ||||
}, | }, | ||||
CopyMap, DirsMultiset, DirstateEntry, DirstateError, DirstateMapError, | CopyMap, DirsMultiset, DirstateEntry, DirstateError, DirstateMapError, | ||||
pub fn clear(&mut self) { | pub fn clear(&mut self) { | ||||
self.state_map = StateMap::default(); | self.state_map = StateMap::default(); | ||||
self.copy_map.clear(); | self.copy_map.clear(); | ||||
self.file_fold_map = None; | self.file_fold_map = None; | ||||
self.non_normal_set = None; | self.non_normal_set = None; | ||||
self.other_parent_set = None; | self.other_parent_set = None; | ||||
self.set_parents(&DirstateParents { | self.set_parents(&DirstateParents { | ||||
p1: NULL_NODE_ID, | p1: NULL_NODE, | ||||
p2: NULL_NODE_ID, | p2: NULL_NODE, | ||||
}) | }) | ||||
} | } | ||||
/// Add a tracked file to the dirstate | /// Add a tracked file to the dirstate | ||||
pub fn add_file( | pub fn add_file( | ||||
&mut self, | &mut self, | ||||
filename: &HgPath, | filename: &HgPath, | ||||
old_state: EntryState, | old_state: EntryState, | ||||
parents = DirstateParents { | parents = DirstateParents { | ||||
p1: file_contents[..PARENT_SIZE].try_into().unwrap(), | p1: file_contents[..PARENT_SIZE].try_into().unwrap(), | ||||
p2: file_contents[PARENT_SIZE..PARENT_SIZE * 2] | p2: file_contents[PARENT_SIZE..PARENT_SIZE * 2] | ||||
.try_into() | .try_into() | ||||
.unwrap(), | .unwrap(), | ||||
}; | }; | ||||
} else if file_contents.is_empty() { | } else if file_contents.is_empty() { | ||||
parents = DirstateParents { | parents = DirstateParents { | ||||
p1: NULL_NODE_ID, | p1: NULL_NODE, | ||||
p2: NULL_NODE_ID, | p2: NULL_NODE, | ||||
}; | }; | ||||
} else { | } else { | ||||
return Err( | return Err( | ||||
HgError::corrupted("Dirstate appears to be damaged").into() | HgError::corrupted("Dirstate appears to be damaged").into() | ||||
); | ); | ||||
} | } | ||||
self.parents = Some(parents); | self.parents = Some(parents); |
} | } | ||||
length | length | ||||
}) | }) | ||||
.sum(); | .sum(); | ||||
let expected_size = expected_size + PARENT_SIZE * 2; | let expected_size = expected_size + PARENT_SIZE * 2; | ||||
let mut packed = Vec::with_capacity(expected_size); | let mut packed = Vec::with_capacity(expected_size); | ||||
packed.extend(&parents.p1); | packed.extend(parents.p1.as_bytes()); | ||||
packed.extend(&parents.p2); | packed.extend(parents.p2.as_bytes()); | ||||
for (filename, entry) in state_map.iter_mut() { | for (filename, entry) in state_map.iter_mut() { | ||||
let new_filename = filename.to_owned(); | let new_filename = filename.to_owned(); | ||||
let mut new_mtime: i32 = entry.mtime; | let mut new_mtime: i32 = entry.mtime; | ||||
if entry.state == EntryState::Normal && entry.mtime == now { | if entry.state == EntryState::Normal && entry.mtime == now { | ||||
// The file was last modified "simultaneously" with the current | // The file was last modified "simultaneously" with the current | ||||
// write to dirstate (i.e. within the same second for file- | // write to dirstate (i.e. within the same second for file- | ||||
// systems with a granularity of 1 sec). This commonly happens | // systems with a granularity of 1 sec). This commonly happens | ||||
use crate::{utils::hg_path::HgPathBuf, FastHashMap}; | use crate::{utils::hg_path::HgPathBuf, FastHashMap}; | ||||
use pretty_assertions::assert_eq; | use pretty_assertions::assert_eq; | ||||
#[test] | #[test] | ||||
fn test_pack_dirstate_empty() { | fn test_pack_dirstate_empty() { | ||||
let mut state_map = StateMap::default(); | let mut state_map = StateMap::default(); | ||||
let copymap = FastHashMap::default(); | let copymap = FastHashMap::default(); | ||||
let parents = DirstateParents { | let parents = DirstateParents { | ||||
p1: *b"12345678910111213141", | p1: b"12345678910111213141".into(), | ||||
p2: *b"00000000000000000000", | p2: b"00000000000000000000".into(), | ||||
}; | }; | ||||
let now = Duration::new(15000000, 0); | let now = Duration::new(15000000, 0); | ||||
let expected = b"1234567891011121314100000000000000000000".to_vec(); | let expected = b"1234567891011121314100000000000000000000".to_vec(); | ||||
assert_eq!( | assert_eq!( | ||||
expected, | expected, | ||||
pack_dirstate(&mut state_map, ©map, parents, now).unwrap() | pack_dirstate(&mut state_map, ©map, parents, now).unwrap() | ||||
); | ); | ||||
)] | )] | ||||
.iter() | .iter() | ||||
.cloned() | .cloned() | ||||
.collect(); | .collect(); | ||||
let mut state_map = expected_state_map.clone(); | let mut state_map = expected_state_map.clone(); | ||||
let copymap = FastHashMap::default(); | let copymap = FastHashMap::default(); | ||||
let parents = DirstateParents { | let parents = DirstateParents { | ||||
p1: *b"12345678910111213141", | p1: b"12345678910111213141".into(), | ||||
p2: *b"00000000000000000000", | p2: b"00000000000000000000".into(), | ||||
}; | }; | ||||
let now = Duration::new(15000000, 0); | let now = Duration::new(15000000, 0); | ||||
let expected = [ | let expected = [ | ||||
49, 50, 51, 52, 53, 54, 55, 56, 57, 49, 48, 49, 49, 49, 50, 49, | 49, 50, 51, 52, 53, 54, 55, 56, 57, 49, 48, 49, 49, 49, 50, 49, | ||||
51, 49, 52, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, | 51, 49, 52, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, | ||||
48, 48, 48, 48, 48, 48, 48, 48, 110, 0, 0, 1, 164, 0, 0, 0, 0, 47, | 48, 48, 48, 48, 48, 48, 48, 48, 110, 0, 0, 1, 164, 0, 0, 0, 0, 47, | ||||
41, 58, 244, 0, 0, 0, 2, 102, 49, | 41, 58, 244, 0, 0, 0, 2, 102, 49, | ||||
] | ] | ||||
.collect(); | .collect(); | ||||
let mut state_map = expected_state_map.clone(); | let mut state_map = expected_state_map.clone(); | ||||
let mut copymap = FastHashMap::default(); | let mut copymap = FastHashMap::default(); | ||||
copymap.insert( | copymap.insert( | ||||
HgPathBuf::from_bytes(b"f1"), | HgPathBuf::from_bytes(b"f1"), | ||||
HgPathBuf::from_bytes(b"copyname"), | HgPathBuf::from_bytes(b"copyname"), | ||||
); | ); | ||||
let parents = DirstateParents { | let parents = DirstateParents { | ||||
p1: *b"12345678910111213141", | p1: b"12345678910111213141".into(), | ||||
p2: *b"00000000000000000000", | p2: b"00000000000000000000".into(), | ||||
}; | }; | ||||
let now = Duration::new(15000000, 0); | let now = Duration::new(15000000, 0); | ||||
let expected = [ | let expected = [ | ||||
49, 50, 51, 52, 53, 54, 55, 56, 57, 49, 48, 49, 49, 49, 50, 49, | 49, 50, 51, 52, 53, 54, 55, 56, 57, 49, 48, 49, 49, 49, 50, 49, | ||||
51, 49, 52, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, | 51, 49, 52, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, | ||||
48, 48, 48, 48, 48, 48, 48, 48, 110, 0, 0, 1, 164, 0, 0, 0, 0, 47, | 48, 48, 48, 48, 48, 48, 48, 48, 110, 0, 0, 1, 164, 0, 0, 0, 0, 47, | ||||
41, 58, 244, 0, 0, 0, 11, 102, 49, 0, 99, 111, 112, 121, 110, 97, | 41, 58, 244, 0, 0, 0, 11, 102, 49, 0, 99, 111, 112, 121, 110, 97, | ||||
109, 101, | 109, 101, | ||||
.cloned() | .cloned() | ||||
.collect(); | .collect(); | ||||
let mut copymap = FastHashMap::default(); | let mut copymap = FastHashMap::default(); | ||||
copymap.insert( | copymap.insert( | ||||
HgPathBuf::from_bytes(b"f1"), | HgPathBuf::from_bytes(b"f1"), | ||||
HgPathBuf::from_bytes(b"copyname"), | HgPathBuf::from_bytes(b"copyname"), | ||||
); | ); | ||||
let parents = DirstateParents { | let parents = DirstateParents { | ||||
p1: *b"12345678910111213141", | p1: b"12345678910111213141".into(), | ||||
p2: *b"00000000000000000000", | p2: b"00000000000000000000".into(), | ||||
}; | }; | ||||
let now = Duration::new(15000000, 0); | let now = Duration::new(15000000, 0); | ||||
let result = | let result = | ||||
pack_dirstate(&mut state_map, ©map, parents.clone(), now) | pack_dirstate(&mut state_map, ©map, parents.clone(), now) | ||||
.unwrap(); | .unwrap(); | ||||
let (new_parents, entries, copies) = | let (new_parents, entries, copies) = | ||||
parse_dirstate(result.as_slice()).unwrap(); | parse_dirstate(result.as_slice()).unwrap(); | ||||
HgPathBuf::from_bytes(b"f1"), | HgPathBuf::from_bytes(b"f1"), | ||||
HgPathBuf::from_bytes(b"copyname"), | HgPathBuf::from_bytes(b"copyname"), | ||||
); | ); | ||||
copymap.insert( | copymap.insert( | ||||
HgPathBuf::from_bytes(b"f4\xF6"), | HgPathBuf::from_bytes(b"f4\xF6"), | ||||
HgPathBuf::from_bytes(b"copyname2"), | HgPathBuf::from_bytes(b"copyname2"), | ||||
); | ); | ||||
let parents = DirstateParents { | let parents = DirstateParents { | ||||
p1: *b"12345678910111213141", | p1: b"12345678910111213141".into(), | ||||
p2: *b"00000000000000000000", | p2: b"00000000000000000000".into(), | ||||
}; | }; | ||||
let now = Duration::new(15000000, 0); | let now = Duration::new(15000000, 0); | ||||
let result = | let result = | ||||
pack_dirstate(&mut state_map, ©map, parents.clone(), now) | pack_dirstate(&mut state_map, ©map, parents.clone(), now) | ||||
.unwrap(); | .unwrap(); | ||||
let (new_parents, entries, copies) = | let (new_parents, entries, copies) = | ||||
parse_dirstate(result.as_slice()).unwrap(); | parse_dirstate(result.as_slice()).unwrap(); | ||||
.cloned() | .cloned() | ||||
.collect(); | .collect(); | ||||
let mut copymap = FastHashMap::default(); | let mut copymap = FastHashMap::default(); | ||||
copymap.insert( | copymap.insert( | ||||
HgPathBuf::from_bytes(b"f1"), | HgPathBuf::from_bytes(b"f1"), | ||||
HgPathBuf::from_bytes(b"copyname"), | HgPathBuf::from_bytes(b"copyname"), | ||||
); | ); | ||||
let parents = DirstateParents { | let parents = DirstateParents { | ||||
p1: *b"12345678910111213141", | p1: b"12345678910111213141".into(), | ||||
p2: *b"00000000000000000000", | p2: b"00000000000000000000".into(), | ||||
}; | }; | ||||
let now = Duration::new(15000000, 0); | let now = Duration::new(15000000, 0); | ||||
let result = | let result = | ||||
pack_dirstate(&mut state_map, ©map, parents.clone(), now) | pack_dirstate(&mut state_map, ©map, parents.clone(), now) | ||||
.unwrap(); | .unwrap(); | ||||
let (new_parents, entries, copies) = | let (new_parents, entries, copies) = | ||||
parse_dirstate(result.as_slice()).unwrap(); | parse_dirstate(result.as_slice()).unwrap(); |
#[inline] | #[inline] | ||||
fn try_from(bytes: &'_ [u8]) -> Result<Self, Self::Error> { | fn try_from(bytes: &'_ [u8]) -> Result<Self, Self::Error> { | ||||
let data = bytes.try_into()?; | let data = bytes.try_into()?; | ||||
Ok(Self { data }) | Ok(Self { data }) | ||||
} | } | ||||
} | } | ||||
impl From<&'_ NodeData> for Node { | |||||
#[inline] | |||||
fn from(data: &'_ NodeData) -> Self { | |||||
Self { data: *data } | |||||
} | |||||
} | |||||
impl fmt::LowerHex for Node { | impl fmt::LowerHex for Node { | ||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
for &byte in &self.data { | for &byte in &self.data { | ||||
write!(f, "{:02x}", byte)? | write!(f, "{:02x}", byte)? | ||||
} | } | ||||
Ok(()) | Ok(()) | ||||
} | } | ||||
} | } |
}; | }; | ||||
use crate::{ | use crate::{ | ||||
dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator}, | dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator}, | ||||
dirstate::non_normal_entries::{ | dirstate::non_normal_entries::{ | ||||
NonNormalEntries, NonNormalEntriesIterator, | NonNormalEntries, NonNormalEntriesIterator, | ||||
}, | }, | ||||
dirstate::{dirs_multiset::Dirs, make_dirstate_tuple}, | dirstate::{dirs_multiset::Dirs, make_dirstate_tuple}, | ||||
parsers::dirstate_parents_to_pytuple, | |||||
}; | }; | ||||
use hg::{ | use hg::{ | ||||
errors::HgError, | errors::HgError, | ||||
revlog::Node, | |||||
utils::hg_path::{HgPath, HgPathBuf}, | utils::hg_path::{HgPath, HgPathBuf}, | ||||
DirsMultiset, DirstateEntry, DirstateMap as RustDirstateMap, | DirsMultiset, DirstateEntry, DirstateMap as RustDirstateMap, | ||||
DirstateMapError, DirstateParents, EntryState, StateMapIter, PARENT_SIZE, | DirstateMapError, DirstateParents, EntryState, StateMapIter, | ||||
}; | }; | ||||
// TODO | // TODO | ||||
// This object needs to share references to multiple members of its Rust | // This object needs to share references to multiple members of its Rust | ||||
// inner struct, namely `copy_map`, `dirs` and `all_dirs`. | // inner struct, namely `copy_map`, `dirs` and `all_dirs`. | ||||
// Right now `CopyMap` is done, but it needs to have an explicit reference | // Right now `CopyMap` is done, but it needs to have an explicit reference | ||||
// to `RustDirstateMap` which itself needs to have an encapsulation for | // to `RustDirstateMap` which itself needs to have an encapsulation for | ||||
// every method in `CopyMap` (copymapcopy, etc.). | // every method in `CopyMap` (copymapcopy, etc.). | ||||
PyErr::new::<exc::ValueError, _>(py, e.to_string()) | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | ||||
})? | })? | ||||
.to_py_object(py)) | .to_py_object(py)) | ||||
} | } | ||||
def parents(&self, st: PyObject) -> PyResult<PyTuple> { | def parents(&self, st: PyObject) -> PyResult<PyTuple> { | ||||
self.inner(py).borrow_mut() | self.inner(py).borrow_mut() | ||||
.parents(st.extract::<PyBytes>(py)?.data(py)) | .parents(st.extract::<PyBytes>(py)?.data(py)) | ||||
.and_then(|d| { | .map(|parents| dirstate_parents_to_pytuple(py, parents)) | ||||
Ok((PyBytes::new(py, &d.p1), PyBytes::new(py, &d.p2)) | |||||
.to_py_object(py)) | |||||
}) | |||||
.or_else(|_| { | .or_else(|_| { | ||||
Err(PyErr::new::<exc::OSError, _>( | Err(PyErr::new::<exc::OSError, _>( | ||||
py, | py, | ||||
"Dirstate error".to_string(), | "Dirstate error".to_string(), | ||||
)) | )) | ||||
}) | }) | ||||
} | } | ||||
def setparents(&self, p1: PyObject, p2: PyObject) -> PyResult<PyObject> { | def setparents(&self, p1: PyObject, p2: PyObject) -> PyResult<PyObject> { | ||||
let p1 = extract_node_id(py, &p1)?; | let p1 = extract_node_id(py, &p1)?; | ||||
let p2 = extract_node_id(py, &p2)?; | let p2 = extract_node_id(py, &p2)?; | ||||
self.inner(py).borrow_mut() | self.inner(py).borrow_mut() | ||||
.set_parents(&DirstateParents { p1, p2 }); | .set_parents(&DirstateParents { p1, p2 }); | ||||
Ok(py.None()) | Ok(py.None()) | ||||
} | } | ||||
def read(&self, st: PyObject) -> PyResult<Option<PyObject>> { | def read(&self, st: PyObject) -> PyResult<Option<PyObject>> { | ||||
match self.inner(py).borrow_mut() | match self.inner(py).borrow_mut() | ||||
.read(st.extract::<PyBytes>(py)?.data(py)) | .read(st.extract::<PyBytes>(py)?.data(py)) | ||||
{ | { | ||||
Ok(Some(parents)) => Ok(Some( | Ok(Some(parents)) => Ok(Some( | ||||
(PyBytes::new(py, &parents.p1), PyBytes::new(py, &parents.p2)) | dirstate_parents_to_pytuple(py, parents) | ||||
.to_py_object(py) | .into_object() | ||||
.into_object(), | |||||
)), | )), | ||||
Ok(None) => Ok(Some(py.None())), | Ok(None) => Ok(Some(py.None())), | ||||
Err(_) => Err(PyErr::new::<exc::OSError, _>( | Err(_) => Err(PyErr::new::<exc::OSError, _>( | ||||
py, | py, | ||||
"Dirstate error".to_string(), | "Dirstate error".to_string(), | ||||
)), | )), | ||||
} | } | ||||
} | } | ||||
py_shared_iterator!( | py_shared_iterator!( | ||||
DirstateMapItemsIterator, | DirstateMapItemsIterator, | ||||
UnsafePyLeaked<StateMapIter<'static>>, | UnsafePyLeaked<StateMapIter<'static>>, | ||||
DirstateMap::translate_key_value, | DirstateMap::translate_key_value, | ||||
Option<(PyBytes, PyObject)> | Option<(PyBytes, PyObject)> | ||||
); | ); | ||||
fn extract_node_id(py: Python, obj: &PyObject) -> PyResult<[u8; PARENT_SIZE]> { | fn extract_node_id(py: Python, obj: &PyObject) -> PyResult<Node> { | ||||
let bytes = obj.extract::<PyBytes>(py)?; | let bytes = obj.extract::<PyBytes>(py)?; | ||||
match bytes.data(py).try_into() { | match bytes.data(py).try_into() { | ||||
Ok(s) => Ok(s), | Ok(s) => Ok(s), | ||||
Err(e) => Err(PyErr::new::<exc::ValueError, _>(py, e.to_string())), | Err(e) => Err(PyErr::new::<exc::ValueError, _>(py, e.to_string())), | ||||
} | } | ||||
} | } |
} | } | ||||
for (path, copy_path) in copy_map { | for (path, copy_path) in copy_map { | ||||
copymap.set_item( | copymap.set_item( | ||||
py, | py, | ||||
PyBytes::new(py, path.as_bytes()), | PyBytes::new(py, path.as_bytes()), | ||||
PyBytes::new(py, copy_path.as_bytes()), | PyBytes::new(py, copy_path.as_bytes()), | ||||
)?; | )?; | ||||
} | } | ||||
Ok( | Ok(dirstate_parents_to_pytuple(py, parents)) | ||||
(PyBytes::new(py, &parents.p1), PyBytes::new(py, &parents.p2)) | |||||
.to_py_object(py), | |||||
) | |||||
} | } | ||||
Err(e) => Err(PyErr::new::<exc::ValueError, _>(py, e.to_string())), | Err(e) => Err(PyErr::new::<exc::ValueError, _>(py, e.to_string())), | ||||
} | } | ||||
} | } | ||||
fn pack_dirstate_wrapper( | fn pack_dirstate_wrapper( | ||||
py: Python, | py: Python, | ||||
dmap: PyDict, | dmap: PyDict, | ||||
)?; | )?; | ||||
let sys = PyModule::import(py, "sys")?; | let sys = PyModule::import(py, "sys")?; | ||||
let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?; | let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?; | ||||
sys_modules.set_item(py, dotted_name, &m)?; | sys_modules.set_item(py, dotted_name, &m)?; | ||||
Ok(m) | Ok(m) | ||||
} | } | ||||
pub(crate) fn dirstate_parents_to_pytuple( | |||||
py: Python, | |||||
parents: &DirstateParents, | |||||
) -> PyTuple { | |||||
let p1 = PyBytes::new(py, parents.p1.as_bytes()); | |||||
let p2 = PyBytes::new(py, parents.p2.as_bytes()); | |||||
(p1, p2).to_py_object(py) | |||||
} |