##// END OF EJS Templates
dirstate-v2: Separate iterators for dirfoldmap and debugdirstate...
dirstate-v2: Separate iterators for dirfoldmap and debugdirstate `dirstatemap.dirfoldmap` was recently changed to re-use a Rust iterator that was added for the `hg debugdirstate` command. That iterator was based on all nodes in the tree dirstate without an entry only existing to hold child nodes, and therefore being directories. However to optimize status further we may want to store additional nodes for unknown or ignored files and directories. At that point the two users of this iterator will want different things, so let’s make two iterators instead. See doc-comments in `dispatch.rs`. Differential Revision: https://phab.mercurial-scm.org/D11099

File last commit:

r48483:284a2026 default
r48483:284a2026 default
Show More
dirstate_map.rs
629 lines | 20.0 KiB | application/rls-services+xml | RustLexer
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 // dirstate_map.rs
//
// Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
//
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
//! Bindings for the `hg::dirstate::dirstate_map` file provided by the
//! `hg-core` package.
Simon Sapin
dirstate-tree: Give to `status()` mutable access to the `DirstateMap`...
r47882 use std::cell::{RefCell, RefMut};
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 use std::convert::TryInto;
use cpython::{
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44836 exc, ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyList,
Simon Sapin
rust: Remove handling of `parents` in `DirstateMap`...
r47891 PyObject, PyResult, PySet, PyString, Python, PythonObject, ToPyObject,
UnsafePyLeaked,
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 };
use crate::{
dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator},
dirstate-item: rename the class to DirstateItem...
r48328 dirstate::make_dirstate_item,
Simon Sapin
dirstate-v2: Separate iterators for dirfoldmap and debugdirstate...
r48483 dirstate::make_dirstate_item_raw,
Raphaël Gomès
rust-cpython: make `NonNormalEntires` iterable to fix `fsmonitor` (issue6276)...
r44903 dirstate::non_normal_entries::{
NonNormalEntries, NonNormalEntriesIterator,
},
Simon Sapin
dirstate-tree: Make `DirstateMap` borrow from a bytes buffer...
r47893 dirstate::owning::OwningDirstateMap,
Simon Sapin
rust: Make `DirstateParents`’s fields typed `Node`s...
r47337 parsers::dirstate_parents_to_pytuple,
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 };
use hg::{
Simon Sapin
rust: Add a Timestamp struct instead of abusing Duration...
r47871 dirstate::parsers::Timestamp,
dirstate: move the handling of special case within the dirstatemap...
r48310 dirstate::MTIME_UNSET,
dirstate::SIZE_NON_NORMAL,
Simon Sapin
dirstate-tree: Make Rust DirstateMap bindings go through a trait object...
r47863 dirstate_tree::dispatch::DirstateMapMethods,
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 dirstate_tree::on_disk::DirstateV2ParseError,
Simon Sapin
rust: Make `DirstateParents`’s fields typed `Node`s...
r47337 revlog::Node,
Simon Sapin
rust: Remove DirstateMap::file_fold_map...
r47879 utils::files::normalize_case,
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 utils::hg_path::{HgPath, HgPathBuf},
Simon Sapin
dirstate: Removed unused instances of `DirsMultiset`...
r48271 DirstateEntry, DirstateError, DirstateMap as RustDirstateMap,
DirstateParents, EntryState, StateMapIter,
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 };
// TODO
// This object needs to share references to multiple members of its Rust
// inner struct, namely `copy_map`, `dirs` and `all_dirs`.
// Right now `CopyMap` is done, but it needs to have an explicit reference
// to `RustDirstateMap` which itself needs to have an encapsulation for
// every method in `CopyMap` (copymapcopy, etc.).
// This is ugly and hard to maintain.
// The same logic applies to `dirs` and `all_dirs`, however the `Dirs`
// `py_class!` is already implemented and does not mention
// `RustDirstateMap`, rightfully so.
// All attributes also have to have a separate refcount data attribute for
// leaks, with all methods that go along for reference sharing.
py_class!(pub class DirstateMap |py| {
Simon Sapin
dirstate-tree: Make Rust DirstateMap bindings go through a trait object...
r47863 @shared data inner: Box<dyn DirstateMapMethods + Send>;
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999
Simon Sapin
rust: Read dirstate from disk in DirstateMap constructor...
r47892 /// Returns a `(dirstate_map, parents)` tuple
@staticmethod
Simon Sapin
dirstate-v2: Introduce a docket file...
r48474 def new_v1(
Simon Sapin
dirstate-v2: Change the on-disk format when the requirement is enabled...
r48055 use_dirstate_tree: bool,
on_disk: PyBytes,
) -> PyResult<PyObject> {
Simon Sapin
dirstate-v2: Introduce a docket file...
r48474 let (inner, parents) = if use_dirstate_tree {
let (map, parents) = OwningDirstateMap::new_v1(py, on_disk)
Simon Sapin
dirstate-v2: Separate iterators for dirfoldmap and debugdirstate...
r48483 .map_err(|e| dirstate_error(py, e))?;
Simon Sapin
rust: Read dirstate from disk in DirstateMap constructor...
r47892 (Box::new(map) as _, parents)
Simon Sapin
dirstate-tree: Empty shell for a second Rust DirstateMap implementation...
r47865 } else {
Simon Sapin
dirstate-tree: Make `DirstateMap` borrow from a bytes buffer...
r47893 let bytes = on_disk.data(py);
Simon Sapin
rust: Read dirstate from disk in DirstateMap constructor...
r47892 let mut map = RustDirstateMap::default();
Simon Sapin
dirstate-v2: Separate iterators for dirfoldmap and debugdirstate...
r48483 let parents = map.read(bytes).map_err(|e| dirstate_error(py, e))?;
Simon Sapin
rust: Read dirstate from disk in DirstateMap constructor...
r47892 (Box::new(map) as _, parents)
Simon Sapin
dirstate-tree: Empty shell for a second Rust DirstateMap implementation...
r47865 };
Simon Sapin
rust: Read dirstate from disk in DirstateMap constructor...
r47892 let map = Self::create_instance(py, inner)?;
let parents = parents.map(|p| dirstate_parents_to_pytuple(py, &p));
Ok((map, parents).to_py_object(py).into_object())
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 }
Simon Sapin
dirstate-v2: Introduce a docket file...
r48474 /// Returns a DirstateMap
@staticmethod
def new_v2(
on_disk: PyBytes,
Simon Sapin
dirstate-v2: Enforce data size read from the docket file...
r48475 data_size: usize,
Simon Sapin
dirstate-v2: Move fixed-size tree metadata into the docket file...
r48482 tree_metadata: PyBytes,
Simon Sapin
dirstate-v2: Introduce a docket file...
r48474 ) -> PyResult<PyObject> {
let dirstate_error = |e: DirstateError| {
PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
};
Simon Sapin
dirstate-v2: Move fixed-size tree metadata into the docket file...
r48482 let inner = OwningDirstateMap::new_v2(
py, on_disk, data_size, tree_metadata,
).map_err(dirstate_error)?;
Simon Sapin
dirstate-v2: Introduce a docket file...
r48474 let map = Self::create_instance(py, Box::new(inner))?;
Ok(map.into_object())
}
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 def clear(&self) -> PyResult<PyObject> {
Yuya Nishihara
rust-cpython: rename inner_shared() to inner()...
r44702 self.inner(py).borrow_mut().clear();
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 Ok(py.None())
}
def get(
&self,
key: PyObject,
default: Option<PyObject> = None
) -> PyResult<Option<PyObject>> {
let key = key.extract::<PyBytes>(py)?;
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 match self
.inner(py)
.borrow()
.get(HgPath::new(key.data(py)))
.map_err(|e| v2_error(py, e))?
{
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 Some(entry) => {
dirstate-item: rename the class to DirstateItem...
r48328 Ok(Some(make_dirstate_item(py, &entry)?))
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 },
None => Ok(default)
}
}
def addfile(
&self,
f: PyObject,
mode: PyObject,
size: PyObject,
dirstate: move the handling of special case within the dirstatemap...
r48310 mtime: PyObject,
dirstate: use a `added` parameter to _addpath...
r48314 added: PyObject,
dirstate: use a `merged` parameter to _addpath...
r48316 merged: PyObject,
dirstate: move the handling of special case within the dirstatemap...
r48310 from_p2: PyObject,
possibly_dirty: PyObject,
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 ) -> PyResult<PyObject> {
rust-dirstatemap: expand the wrapping code a bit...
r48307 let f = f.extract::<PyBytes>(py)?;
let filename = HgPath::new(f.data(py));
dirstate: use a `added` parameter to _addpath...
r48314 let mode = if mode.is_none(py) {
// fallback default value
0
} else {
mode.extract(py)?
};
dirstate: move the handling of special case within the dirstatemap...
r48310 let size = if size.is_none(py) {
// fallback default value
SIZE_NON_NORMAL
} else {
size.extract(py)?
};
let mtime = if mtime.is_none(py) {
// fallback default value
MTIME_UNSET
} else {
mtime.extract(py)?
};
rust-dirstatemap: expand the wrapping code a bit...
r48307 let entry = DirstateEntry {
dirstate: drop `state` to `_addpath`...
r48319 // XXX Arbitrary default value since the value is determined later
state: EntryState::Normal,
rust-dirstatemap: expand the wrapping code a bit...
r48307 mode: mode,
size: size,
mtime: mtime,
};
dirstate: use a `added` parameter to _addpath...
r48314 let added = added.extract::<PyBool>(py)?.is_true();
dirstate: use a `merged` parameter to _addpath...
r48316 let merged = merged.extract::<PyBool>(py)?.is_true();
dirstate: move the handling of special case within the dirstatemap...
r48310 let from_p2 = from_p2.extract::<PyBool>(py)?.is_true();
let possibly_dirty = possibly_dirty.extract::<PyBool>(py)?.is_true();
Yuya Nishihara
rust-cpython: rename inner_shared() to inner()...
r44702 self.inner(py).borrow_mut().add_file(
rust-dirstatemap: expand the wrapping code a bit...
r48307 filename,
entry,
dirstate: use a `added` parameter to _addpath...
r48314 added,
dirstate: use a `merged` parameter to _addpath...
r48316 merged,
dirstate: move the handling of special case within the dirstatemap...
r48310 from_p2,
possibly_dirty
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 ).and(Ok(py.None())).or_else(|e: DirstateError| {
Raphaël Gomès
rust-dirs: address failing tests for `dirs` impl with a temporary fix...
r44227 Err(PyErr::new::<exc::ValueError, _>(py, e.to_string()))
})
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 }
def removefile(
&self,
f: PyObject,
dirstate: move most of the `remove` logic with dirstatemap `removefile`...
r48300 in_merge: PyObject
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 ) -> PyResult<PyObject> {
Yuya Nishihara
rust-cpython: rename inner_shared() to inner()...
r44702 self.inner(py).borrow_mut()
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 .remove_file(
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
dirstate: move most of the `remove` logic with dirstatemap `removefile`...
r48300 in_merge.extract::<PyBool>(py)?.is_true(),
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 )
.or_else(|_| {
Err(PyErr::new::<exc::OSError, _>(
py,
"Dirstate error".to_string(),
))
})?;
Ok(py.None())
}
def dropfile(
&self,
f: PyObject,
) -> PyResult<PyBool> {
Yuya Nishihara
rust-cpython: rename inner_shared() to inner()...
r44702 self.inner(py).borrow_mut()
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 .drop_file(
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 )
.and_then(|b| Ok(b.to_py_object(py)))
Raphaël Gomès
rust: start plugging the dirstate tree behind a feature gate...
r46185 .or_else(|e| {
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 Err(PyErr::new::<exc::OSError, _>(
py,
Raphaël Gomès
rust: start plugging the dirstate tree behind a feature gate...
r46185 format!("Dirstate error: {}", e.to_string()),
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 ))
})
}
def clearambiguoustimes(
&self,
files: PyObject,
now: PyObject
) -> PyResult<PyObject> {
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 let files: PyResult<Vec<HgPathBuf>> = files
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 .iter(py)?
.map(|filename| {
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 Ok(HgPathBuf::from_bytes(
filename?.extract::<PyBytes>(py)?.data(py),
))
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 })
.collect();
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 self.inner(py)
.borrow_mut()
.clear_ambiguous_times(files?, now.extract(py)?)
.map_err(|e| v2_error(py, e))?;
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 Ok(py.None())
}
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44836 def other_parent_entries(&self) -> PyResult<PyObject> {
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44779 let mut inner_shared = self.inner(py).borrow_mut();
Simon Sapin
rust: Remove use of `py.eval()`...
r47653 let set = PySet::empty(py)?;
Simon Sapin
dirstate-tree: Abstract "non-normal" and "other parent" sets...
r47864 for path in inner_shared.iter_other_parent_paths() {
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 let path = path.map_err(|e| v2_error(py, e))?;
Simon Sapin
rust: Remove use of `py.eval()`...
r47653 set.add(py, PyBytes::new(py, path.as_bytes()))?;
}
Ok(set.into_object())
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44836 }
def non_normal_entries(&self) -> PyResult<NonNormalEntries> {
NonNormalEntries::from_inner(py, self.clone_ref(py))
}
def non_normal_entries_contains(&self, key: PyObject) -> PyResult<bool> {
let key = key.extract::<PyBytes>(py)?;
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 self.inner(py)
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44779 .borrow_mut()
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 .non_normal_entries_contains(HgPath::new(key.data(py)))
.map_err(|e| v2_error(py, e))
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44836 }
def non_normal_entries_display(&self) -> PyResult<PyString> {
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 let mut inner = self.inner(py).borrow_mut();
let paths = inner
.iter_non_normal_paths()
.collect::<Result<Vec<_>, _>>()
.map_err(|e| v2_error(py, e))?;
let formatted = format!("NonNormalEntries: {}", hg::utils::join_display(paths, ", "));
Ok(PyString::new(py, &formatted))
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44836 }
def non_normal_entries_remove(&self, key: PyObject) -> PyResult<PyObject> {
let key = key.extract::<PyBytes>(py)?;
self
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44779 .inner(py)
.borrow_mut()
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44836 .non_normal_entries_remove(HgPath::new(key.data(py)));
Ok(py.None())
}
Simon Sapin
dirstate-tree: Abstract "non-normal" and "other parent" sets...
r47864 def non_normal_or_other_parent_paths(&self) -> PyResult<PyList> {
let mut inner = self.inner(py).borrow_mut();
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44836
let ret = PyList::new(py, &[]);
Simon Sapin
dirstate-tree: Abstract "non-normal" and "other parent" sets...
r47864 for filename in inner.non_normal_or_other_parent_paths() {
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 let filename = filename.map_err(|e| v2_error(py, e))?;
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44836 let as_pystring = PyBytes::new(py, filename.as_bytes());
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44779 ret.append(py, as_pystring.into_object());
Raphaël Gomès
rust-dirstatemap: add `NonNormalEntries` class...
r44836 }
Ok(ret)
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 }
Raphaël Gomès
rust-cpython: make `NonNormalEntires` iterable to fix `fsmonitor` (issue6276)...
r44903 def non_normal_entries_iter(&self) -> PyResult<NonNormalEntriesIterator> {
// Make sure the sets are defined before we no longer have a mutable
// reference to the dmap.
self.inner(py)
.borrow_mut()
.set_non_normal_other_parent_entries(false);
let leaked_ref = self.inner(py).leak_immutable();
NonNormalEntriesIterator::from_inner(py, unsafe {
leaked_ref.map(py, |o| {
Simon Sapin
dirstate-tree: Abstract "non-normal" and "other parent" sets...
r47864 o.iter_non_normal_paths_panic()
Raphaël Gomès
rust-cpython: make `NonNormalEntires` iterable to fix `fsmonitor` (issue6276)...
r44903 })
})
}
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 def hastrackeddir(&self, d: PyObject) -> PyResult<PyBool> {
let d = d.extract::<PyBytes>(py)?;
Yuya Nishihara
rust-cpython: rename inner_shared() to inner()...
r44702 Ok(self.inner(py).borrow_mut()
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 .has_tracked_dir(HgPath::new(d.data(py)))
Raphaël Gomès
rust-dirs: handle forgotten `Result`s...
r44315 .map_err(|e| {
PyErr::new::<exc::ValueError, _>(py, e.to_string())
})?
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 .to_py_object(py))
}
def hasdir(&self, d: PyObject) -> PyResult<PyBool> {
let d = d.extract::<PyBytes>(py)?;
Yuya Nishihara
rust-cpython: rename inner_shared() to inner()...
r44702 Ok(self.inner(py).borrow_mut()
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 .has_dir(HgPath::new(d.data(py)))
Raphaël Gomès
rust-dirs: handle forgotten `Result`s...
r44315 .map_err(|e| {
PyErr::new::<exc::ValueError, _>(py, e.to_string())
})?
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 .to_py_object(py))
}
Simon Sapin
dirstate-v2: Introduce a docket file...
r48474 def write_v1(
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 &self,
p1: PyObject,
p2: PyObject,
now: PyObject
) -> PyResult<PyBytes> {
Simon Sapin
rust: Add a Timestamp struct instead of abusing Duration...
r47871 let now = Timestamp(now.extract(py)?);
Simon Sapin
dirstate-v2: Introduce a docket file...
r48474
let mut inner = self.inner(py).borrow_mut();
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 let parents = DirstateParents {
Yuya Nishihara
rust-dirstate: handle invalid length of p1/p2 parameters...
r43068 p1: extract_node_id(py, &p1)?,
p2: extract_node_id(py, &p2)?,
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 };
Simon Sapin
dirstate-v2: Introduce a docket file...
r48474 let result = inner.pack_v1(parents, now);
match result {
Ok(packed) => Ok(PyBytes::new(py, &packed)),
Err(_) => Err(PyErr::new::<exc::OSError, _>(
py,
"Dirstate error".to_string(),
)),
}
}
Simon Sapin
dirstate-v2: Support appending to the same data file...
r48478 /// Returns new data together with whether that data should be appended to
/// the existing data file whose content is at `self.on_disk` (True),
/// instead of written to a new data file (False).
Simon Sapin
dirstate-v2: Introduce a docket file...
r48474 def write_v2(
&self,
Simon Sapin
dirstate-v2: Support appending to the same data file...
r48478 now: PyObject,
can_append: bool,
) -> PyResult<PyObject> {
Simon Sapin
dirstate-v2: Introduce a docket file...
r48474 let now = Timestamp(now.extract(py)?);
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999
Simon Sapin
dirstate-v2: Change the on-disk format when the requirement is enabled...
r48055 let mut inner = self.inner(py).borrow_mut();
Simon Sapin
dirstate-v2: Support appending to the same data file...
r48478 let result = inner.pack_v2(now, can_append);
Simon Sapin
dirstate-v2: Change the on-disk format when the requirement is enabled...
r48055 match result {
Simon Sapin
dirstate-v2: Move fixed-size tree metadata into the docket file...
r48482 Ok((packed, tree_metadata, append)) => {
Simon Sapin
dirstate-v2: Support appending to the same data file...
r48478 let packed = PyBytes::new(py, &packed);
Simon Sapin
dirstate-v2: Move fixed-size tree metadata into the docket file...
r48482 let tree_metadata = PyBytes::new(py, &tree_metadata);
let tuple = (packed, tree_metadata, append);
Ok(tuple.to_py_object(py).into_object())
Simon Sapin
dirstate-v2: Support appending to the same data file...
r48478 },
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 Err(_) => Err(PyErr::new::<exc::OSError, _>(
py,
"Dirstate error".to_string(),
)),
}
}
def filefoldmapasdict(&self) -> PyResult<PyDict> {
let dict = PyDict::new(py);
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 for item in self.inner(py).borrow_mut().iter() {
let (path, entry) = item.map_err(|e| v2_error(py, e))?;
Simon Sapin
rust: Remove DirstateMap::file_fold_map...
r47879 if entry.state != EntryState::Removed {
let key = normalize_case(path);
let value = path;
dict.set_item(
py,
PyBytes::new(py, key.as_bytes()).into_object(),
PyBytes::new(py, value.as_bytes()).into_object(),
)?;
}
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 }
Ok(dict)
}
def __len__(&self) -> PyResult<usize> {
Yuya Nishihara
rust-cpython: rename inner_shared() to inner()...
r44702 Ok(self.inner(py).borrow().len())
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 }
def __contains__(&self, key: PyObject) -> PyResult<bool> {
let key = key.extract::<PyBytes>(py)?;
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 self.inner(py)
.borrow()
.contains_key(HgPath::new(key.data(py)))
.map_err(|e| v2_error(py, e))
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 }
def __getitem__(&self, key: PyObject) -> PyResult<PyObject> {
let key = key.extract::<PyBytes>(py)?;
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 let key = HgPath::new(key.data(py));
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 match self
.inner(py)
.borrow()
.get(key)
.map_err(|e| v2_error(py, e))?
{
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 Some(entry) => {
dirstate-item: rename the class to DirstateItem...
r48328 Ok(make_dirstate_item(py, &entry)?)
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 },
None => Err(PyErr::new::<exc::KeyError, _>(
py,
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 String::from_utf8_lossy(key.as_bytes()),
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 )),
}
}
def keys(&self) -> PyResult<DirstateMapKeysIterator> {
Yuya Nishihara
rust-cpython: rename inner_shared() to inner()...
r44702 let leaked_ref = self.inner(py).leak_immutable();
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 DirstateMapKeysIterator::from_inner(
py,
Yuya Nishihara
rust-cpython: make PyLeakedRef operations relatively safe...
r43579 unsafe { leaked_ref.map(py, |o| o.iter()) },
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 )
}
def items(&self) -> PyResult<DirstateMapItemsIterator> {
Yuya Nishihara
rust-cpython: rename inner_shared() to inner()...
r44702 let leaked_ref = self.inner(py).leak_immutable();
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 DirstateMapItemsIterator::from_inner(
py,
Yuya Nishihara
rust-cpython: make PyLeakedRef operations relatively safe...
r43579 unsafe { leaked_ref.map(py, |o| o.iter()) },
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 )
}
def __iter__(&self) -> PyResult<DirstateMapKeysIterator> {
Yuya Nishihara
rust-cpython: rename inner_shared() to inner()...
r44702 let leaked_ref = self.inner(py).leak_immutable();
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 DirstateMapKeysIterator::from_inner(
py,
Yuya Nishihara
rust-cpython: make PyLeakedRef operations relatively safe...
r43579 unsafe { leaked_ref.map(py, |o| o.iter()) },
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 )
}
// TODO all copymap* methods, see docstring above
def copymapcopy(&self) -> PyResult<PyDict> {
let dict = PyDict::new(py);
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 for item in self.inner(py).borrow().copy_map_iter() {
let (key, value) = item.map_err(|e| v2_error(py, e))?;
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 dict.set_item(
py,
Raphaël Gomès
rust: do a clippy pass...
r45500 PyBytes::new(py, key.as_bytes()),
PyBytes::new(py, value.as_bytes()),
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 )?;
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 }
Ok(dict)
}
def copymapgetitem(&self, key: PyObject) -> PyResult<PyBytes> {
let key = key.extract::<PyBytes>(py)?;
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 match self
.inner(py)
.borrow()
.copy_map_get(HgPath::new(key.data(py)))
.map_err(|e| v2_error(py, e))?
{
Raphaël Gomès
rust: do a clippy pass...
r45500 Some(copy) => Ok(PyBytes::new(py, copy.as_bytes())),
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 None => Err(PyErr::new::<exc::KeyError, _>(
py,
String::from_utf8_lossy(key.data(py)),
)),
}
}
def copymap(&self) -> PyResult<CopyMap> {
CopyMap::from_inner(py, self.clone_ref(py))
}
def copymaplen(&self) -> PyResult<usize> {
Simon Sapin
dirstate-tree: Make Rust DirstateMap bindings go through a trait object...
r47863 Ok(self.inner(py).borrow().copy_map_len())
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 }
def copymapcontains(&self, key: PyObject) -> PyResult<bool> {
let key = key.extract::<PyBytes>(py)?;
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 self.inner(py)
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 .borrow()
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 .copy_map_contains_key(HgPath::new(key.data(py)))
.map_err(|e| v2_error(py, e))
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 }
def copymapget(
&self,
key: PyObject,
default: Option<PyObject>
) -> PyResult<Option<PyObject>> {
let key = key.extract::<PyBytes>(py)?;
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 match self
Yuya Nishihara
rust-cpython: rename inner_shared() to inner()...
r44702 .inner(py)
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 .borrow()
Simon Sapin
dirstate-tree: Make Rust DirstateMap bindings go through a trait object...
r47863 .copy_map_get(HgPath::new(key.data(py)))
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 .map_err(|e| v2_error(py, e))?
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 {
Some(copy) => Ok(Some(
Raphaël Gomès
rust: do a clippy pass...
r45500 PyBytes::new(py, copy.as_bytes()).into_object(),
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 )),
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 None => Ok(default),
}
}
def copymapsetitem(
&self,
key: PyObject,
value: PyObject
) -> PyResult<PyObject> {
let key = key.extract::<PyBytes>(py)?;
let value = value.extract::<PyBytes>(py)?;
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 self.inner(py)
.borrow_mut()
.copy_map_insert(
HgPathBuf::from_bytes(key.data(py)),
HgPathBuf::from_bytes(value.data(py)),
)
.map_err(|e| v2_error(py, e))?;
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 Ok(py.None())
}
def copymappop(
&self,
key: PyObject,
default: Option<PyObject>
) -> PyResult<Option<PyObject>> {
let key = key.extract::<PyBytes>(py)?;
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 match self
Yuya Nishihara
rust-cpython: rename inner_shared() to inner()...
r44702 .inner(py)
Yuya Nishihara
rust-cpython: add panicking version of borrow_mut() and use it...
r44685 .borrow_mut()
Simon Sapin
dirstate-tree: Make Rust DirstateMap bindings go through a trait object...
r47863 .copy_map_remove(HgPath::new(key.data(py)))
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 .map_err(|e| v2_error(py, e))?
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 {
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 Some(_) => Ok(None),
None => Ok(default),
}
}
def copymapiter(&self) -> PyResult<CopyMapKeysIterator> {
Yuya Nishihara
rust-cpython: rename inner_shared() to inner()...
r44702 let leaked_ref = self.inner(py).leak_immutable();
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 CopyMapKeysIterator::from_inner(
py,
Simon Sapin
dirstate-tree: Make Rust DirstateMap bindings go through a trait object...
r47863 unsafe { leaked_ref.map(py, |o| o.copy_map_iter()) },
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 )
}
def copymapitemsiter(&self) -> PyResult<CopyMapItemsIterator> {
Yuya Nishihara
rust-cpython: rename inner_shared() to inner()...
r44702 let leaked_ref = self.inner(py).leak_immutable();
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 CopyMapItemsIterator::from_inner(
py,
Simon Sapin
dirstate-tree: Make Rust DirstateMap bindings go through a trait object...
r47863 unsafe { leaked_ref.map(py, |o| o.copy_map_iter()) },
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 )
}
Simon Sapin
dirstate-v2: Separate iterators for dirfoldmap and debugdirstate...
r48483 def tracked_dirs(&self) -> PyResult<PyList> {
Simon Sapin
dirstate-v2: Add --dirs to debugdirstate command...
r48140 let dirs = PyList::new(py, &[]);
Simon Sapin
dirstate-v2: Separate iterators for dirfoldmap and debugdirstate...
r48483 for path in self.inner(py).borrow_mut().iter_tracked_dirs()
.map_err(|e |dirstate_error(py, e))?
{
let path = path.map_err(|e| v2_error(py, e))?;
Simon Sapin
dirstate-v2: Add --dirs to debugdirstate command...
r48140 let path = PyBytes::new(py, path.as_bytes());
Simon Sapin
dirstate-v2: Separate iterators for dirfoldmap and debugdirstate...
r48483 dirs.append(py, path.into_object())
Simon Sapin
dirstate-v2: Add --dirs to debugdirstate command...
r48140 }
Ok(dirs)
}
Simon Sapin
dirstate-v2: Separate iterators for dirfoldmap and debugdirstate...
r48483 def debug_iter(&self) -> PyResult<PyList> {
let dirs = PyList::new(py, &[]);
for item in self.inner(py).borrow().debug_iter() {
let (path, (state, mode, size, mtime)) =
item.map_err(|e| v2_error(py, e))?;
let path = PyBytes::new(py, path.as_bytes());
let item = make_dirstate_item_raw(py, state, mode, size, mtime)?;
dirs.append(py, (path, item).to_py_object(py).into_object())
}
Ok(dirs)
}
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 });
impl DirstateMap {
Simon Sapin
dirstate-tree: Give to `status()` mutable access to the `DirstateMap`...
r47882 pub fn get_inner_mut<'a>(
Raphaël Gomès
rust-dirstate-status: rust-cpython bindings for `dirstate.status`...
r43567 &'a self,
py: Python<'a>,
Simon Sapin
dirstate-tree: Give to `status()` mutable access to the `DirstateMap`...
r47882 ) -> RefMut<'a, Box<dyn DirstateMapMethods + Send>> {
self.inner(py).borrow_mut()
Raphaël Gomès
rust-dirstate-status: rust-cpython bindings for `dirstate.status`...
r43567 }
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 fn translate_key(
py: Python,
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 res: Result<(&HgPath, DirstateEntry), DirstateV2ParseError>,
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 ) -> PyResult<Option<PyBytes>> {
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 let (f, _entry) = res.map_err(|e| v2_error(py, e))?;
Ok(Some(PyBytes::new(py, f.as_bytes())))
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 }
fn translate_key_value(
py: Python,
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 res: Result<(&HgPath, DirstateEntry), DirstateV2ParseError>,
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 ) -> PyResult<Option<(PyBytes, PyObject)>> {
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126 let (f, entry) = res.map_err(|e| v2_error(py, e))?;
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 Ok(Some((
Raphaël Gomès
rust: do a clippy pass...
r45500 PyBytes::new(py, f.as_bytes()),
dirstate-item: rename the class to DirstateItem...
r48328 make_dirstate_item(py, &entry)?,
Raphaël Gomès
rust: start plugging the dirstate tree behind a feature gate...
r46185 )))
}
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 }
Yuya Nishihara
rust-cpython: rename py_shared_iterator_impl to py_shared_iterator...
r43159 py_shared_iterator!(
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 DirstateMapKeysIterator,
Yuya Nishihara
rust-cpython: switch to upstreamed version of PySharedRefCell...
r44703 UnsafePyLeaked<StateMapIter<'static>>,
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 DirstateMap::translate_key,
Option<PyBytes>
);
Yuya Nishihara
rust-cpython: rename py_shared_iterator_impl to py_shared_iterator...
r43159 py_shared_iterator!(
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 DirstateMapItemsIterator,
Yuya Nishihara
rust-cpython: switch to upstreamed version of PySharedRefCell...
r44703 UnsafePyLeaked<StateMapIter<'static>>,
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 DirstateMap::translate_key_value,
Option<(PyBytes, PyObject)>
);
Yuya Nishihara
rust-dirstate: handle invalid length of p1/p2 parameters...
r43068
Simon Sapin
rust: Make `DirstateParents`’s fields typed `Node`s...
r47337 fn extract_node_id(py: Python, obj: &PyObject) -> PyResult<Node> {
Yuya Nishihara
rust-dirstate: handle invalid length of p1/p2 parameters...
r43068 let bytes = obj.extract::<PyBytes>(py)?;
match bytes.data(py).try_into() {
Ok(s) => Ok(s),
Err(e) => Err(PyErr::new::<exc::ValueError, _>(py, e.to_string())),
}
}
Simon Sapin
dirstate-v2: Make more APIs fallible, returning Result...
r48126
pub(super) fn v2_error(py: Python<'_>, _: DirstateV2ParseError) -> PyErr {
PyErr::new::<exc::ValueError, _>(py, "corrupted dirstate-v2")
}
Simon Sapin
dirstate-v2: Separate iterators for dirfoldmap and debugdirstate...
r48483
fn dirstate_error(py: Python<'_>, e: DirstateError) -> PyErr {
PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
}