##// END OF EJS Templates
dirstate: add a `get_entry` method to the dirstate...
dirstate: add a `get_entry` method to the dirstate This method give access to the underlying `DirstateEntry` object (or an empty one if None was there). It should allow us to use the more semantic property of the entry instead of the state where we needs it. Differential Revision: https://phab.mercurial-scm.org/D11522

File last commit:

r48881:d3eb5f50 default
r48897:6a78715e default
Show More
item.rs
203 lines | 5.6 KiB | application/rls-services+xml | RustLexer
use cpython::exc;
use cpython::PyBytes;
use cpython::PyErr;
use cpython::PyNone;
use cpython::PyObject;
use cpython::PyResult;
use cpython::Python;
use cpython::PythonObject;
use hg::dirstate::entry::Flags;
use hg::dirstate::DirstateEntry;
use hg::dirstate::EntryState;
use std::cell::Cell;
use std::convert::TryFrom;
py_class!(pub class DirstateItem |py| {
data entry: Cell<DirstateEntry>;
def __new__(
_cls,
wc_tracked: bool = false,
p1_tracked: bool = false,
p2_tracked: bool = false,
merged: bool = false,
clean_p1: bool = false,
clean_p2: bool = false,
possibly_dirty: bool = false,
parentfiledata: Option<(i32, i32, i32)> = None,
) -> PyResult<DirstateItem> {
let mut flags = Flags::empty();
flags.set(Flags::WDIR_TRACKED, wc_tracked);
flags.set(Flags::P1_TRACKED, p1_tracked);
flags.set(Flags::P2_TRACKED, p2_tracked);
flags.set(Flags::MERGED, merged);
flags.set(Flags::CLEAN_P1, clean_p1);
flags.set(Flags::CLEAN_P2, clean_p2);
flags.set(Flags::POSSIBLY_DIRTY, possibly_dirty);
let entry = DirstateEntry::new(flags, parentfiledata);
DirstateItem::create_instance(py, Cell::new(entry))
}
@property
def state(&self) -> PyResult<PyBytes> {
let state_byte: u8 = self.entry(py).get().state().into();
Ok(PyBytes::new(py, &[state_byte]))
}
@property
def mode(&self) -> PyResult<i32> {
Ok(self.entry(py).get().mode())
}
@property
def size(&self) -> PyResult<i32> {
Ok(self.entry(py).get().size())
}
@property
def mtime(&self) -> PyResult<i32> {
Ok(self.entry(py).get().mtime())
}
@property
def tracked(&self) -> PyResult<bool> {
Ok(self.entry(py).get().tracked())
}
@property
def added(&self) -> PyResult<bool> {
Ok(self.entry(py).get().added())
}
@property
def merged(&self) -> PyResult<bool> {
Ok(self.entry(py).get().merged())
}
@property
def removed(&self) -> PyResult<bool> {
Ok(self.entry(py).get().removed())
}
@property
def from_p2(&self) -> PyResult<bool> {
Ok(self.entry(py).get().from_p2())
}
def v1_state(&self) -> PyResult<PyBytes> {
let (state, _mode, _size, _mtime) = self.entry(py).get().v1_data();
let state_byte: u8 = state.into();
Ok(PyBytes::new(py, &[state_byte]))
}
def v1_mode(&self) -> PyResult<i32> {
let (_state, mode, _size, _mtime) = self.entry(py).get().v1_data();
Ok(mode)
}
def v1_size(&self) -> PyResult<i32> {
let (_state, _mode, size, _mtime) = self.entry(py).get().v1_data();
Ok(size)
}
def v1_mtime(&self) -> PyResult<i32> {
let (_state, _mode, _size, mtime) = self.entry(py).get().v1_data();
Ok(mtime)
}
def need_delay(&self, now: i32) -> PyResult<bool> {
Ok(self.entry(py).get().mtime_is_ambiguous(now))
}
@classmethod
def from_v1_data(
_cls,
state: PyBytes,
mode: i32,
size: i32,
mtime: i32,
) -> PyResult<Self> {
let state = <[u8; 1]>::try_from(state.data(py))
.ok()
.and_then(|state| EntryState::try_from(state[0]).ok())
.ok_or_else(|| PyErr::new::<exc::ValueError, _>(py, "invalid state"))?;
let entry = DirstateEntry::from_v1_data(state, mode, size, mtime);
DirstateItem::create_instance(py, Cell::new(entry))
}
@classmethod
def new_added(_cls) -> PyResult<Self> {
let entry = DirstateEntry::new_added();
DirstateItem::create_instance(py, Cell::new(entry))
}
@classmethod
def new_merged(_cls) -> PyResult<Self> {
let entry = DirstateEntry::new_merged();
DirstateItem::create_instance(py, Cell::new(entry))
}
@classmethod
def new_from_p2(_cls) -> PyResult<Self> {
let entry = DirstateEntry::new_from_p2();
DirstateItem::create_instance(py, Cell::new(entry))
}
@classmethod
def new_possibly_dirty(_cls) -> PyResult<Self> {
let entry = DirstateEntry::new_possibly_dirty();
DirstateItem::create_instance(py, Cell::new(entry))
}
@classmethod
def new_normal(_cls, mode: i32, size: i32, mtime: i32) -> PyResult<Self> {
let entry = DirstateEntry::new_normal(mode, size, mtime);
DirstateItem::create_instance(py, Cell::new(entry))
}
def set_clean(
&self,
mode: i32,
size: i32,
mtime: i32,
) -> PyResult<PyNone> {
self.update(py, |entry| entry.set_clean(mode, size, mtime));
Ok(PyNone)
}
def set_possibly_dirty(&self) -> PyResult<PyNone> {
self.update(py, |entry| entry.set_possibly_dirty());
Ok(PyNone)
}
def set_tracked(&self) -> PyResult<PyNone> {
self.update(py, |entry| entry.set_tracked());
Ok(PyNone)
}
def set_untracked(&self) -> PyResult<PyNone> {
self.update(py, |entry| entry.set_untracked());
Ok(PyNone)
}
});
impl DirstateItem {
pub fn new_as_pyobject(
py: Python<'_>,
entry: DirstateEntry,
) -> PyResult<PyObject> {
Ok(DirstateItem::create_instance(py, Cell::new(entry))?.into_object())
}
pub fn get_entry(&self, py: Python<'_>) -> DirstateEntry {
self.entry(py).get()
}
// TODO: Use https://doc.rust-lang.org/std/cell/struct.Cell.html#method.update instead when it’s stable
pub fn update(&self, py: Python<'_>, f: impl FnOnce(&mut DirstateEntry)) {
let mut entry = self.entry(py).get();
f(&mut entry);
self.entry(py).set(entry)
}
}