##// END OF EJS Templates
dirstate-v2: Introduce a docket file...
dirstate-v2: Introduce a docket file .hg/dirstate now only contains some metadata to point to a separate data file named .hg/dirstate.{}.d with a random hexadecimal identifier. For now every update creates a new data file and removes the old one, but later we’ll (usually) append to an existing file. Separating into two files allows doing the "write to a temporary file then atomically rename into destination" dance with only a small docket file, without always rewriting a lot of data. Differential Revision: https://phab.mercurial-scm.org/D11088

File last commit:

r48474:ff97e793 default
r48474:ff97e793 default
Show More
dirstate_map.rs
606 lines | 19.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: also build DistateItem in dirstate.directories()...
r48367 dirstate::make_directory_item,
dirstate-item: rename the class to DirstateItem...
r48328 dirstate::make_dirstate_item,
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> {
let dirstate_error = |e: DirstateError| {
PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
Simon Sapin
rust: Read dirstate from disk in DirstateMap constructor...
r47892 };
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-tree: Make `DirstateMap` borrow from a bytes buffer...
r47893 .map_err(dirstate_error)?;
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();
let parents = map.read(bytes).map_err(dirstate_error)?;
(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,
) -> PyResult<PyObject> {
let dirstate_error = |e: DirstateError| {
PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
};
let inner = OwningDirstateMap::new_v2(py, on_disk)
.map_err(dirstate_error)?;
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(),
)),
}
}
def write_v2(
&self,
now: PyObject
) -> PyResult<PyBytes> {
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: Introduce a docket file...
r48474 let result = inner.pack_v2(now);
Simon Sapin
dirstate-v2: Change the on-disk format when the requirement is enabled...
r48055 match result {
Raphaël Gomès
rust-dirstate: rust-cpython bridge for dirstatemap...
r42999 Ok(packed) => Ok(PyBytes::new(py, &packed)),
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: Add --dirs to debugdirstate command...
r48140 def directories(&self) -> PyResult<PyList> {
let dirs = PyList::new(py, &[]);
for item in self.inner(py).borrow().iter_directories() {
let (path, mtime) = item.map_err(|e| v2_error(py, e))?;
let path = PyBytes::new(py, path.as_bytes());
let mtime = mtime.map(|t| t.0).unwrap_or(-1);
dirstate-item: also build DistateItem in dirstate.directories()...
r48367 let item = make_directory_item(py, mtime as i32)?;
let tuple = (path, item);
Simon Sapin
dirstate-v2: Add --dirs to debugdirstate command...
r48140 dirs.append(py, tuple.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")
}