rust/hg-cpython/src/dirstate/item.rs
changeset 48043 3e69bef2031a
child 48045 32ef647821b2
equal deleted inserted replaced
48042:008959fcbfb2 48043:3e69bef2031a
       
     1 use cpython::exc;
       
     2 use cpython::PyBytes;
       
     3 use cpython::PyErr;
       
     4 use cpython::PyNone;
       
     5 use cpython::PyObject;
       
     6 use cpython::PyResult;
       
     7 use cpython::Python;
       
     8 use cpython::PythonObject;
       
     9 use hg::dirstate::entry::Flags;
       
    10 use hg::dirstate::DirstateEntry;
       
    11 use hg::dirstate::EntryState;
       
    12 use std::cell::Cell;
       
    13 use std::convert::TryFrom;
       
    14 
       
    15 py_class!(pub class DirstateItem |py| {
       
    16     data entry: Cell<DirstateEntry>;
       
    17 
       
    18     def __new__(
       
    19         _cls,
       
    20         wc_tracked: bool = false,
       
    21         p1_tracked: bool = false,
       
    22         p2_tracked: bool = false,
       
    23         merged: bool = false,
       
    24         clean_p1: bool = false,
       
    25         clean_p2: bool = false,
       
    26         possibly_dirty: bool = false,
       
    27         parentfiledata: Option<(i32, i32, i32)> = None,
       
    28 
       
    29     ) -> PyResult<DirstateItem> {
       
    30         let mut flags = Flags::empty();
       
    31         flags.set(Flags::WDIR_TRACKED, wc_tracked);
       
    32         flags.set(Flags::P1_TRACKED, p1_tracked);
       
    33         flags.set(Flags::P2_TRACKED, p2_tracked);
       
    34         flags.set(Flags::MERGED, merged);
       
    35         flags.set(Flags::CLEAN_P1, clean_p1);
       
    36         flags.set(Flags::CLEAN_P2, clean_p2);
       
    37         flags.set(Flags::POSSIBLY_DIRTY, possibly_dirty);
       
    38         let entry = DirstateEntry::new(flags, parentfiledata);
       
    39         DirstateItem::create_instance(py, Cell::new(entry))
       
    40     }
       
    41 
       
    42     @property
       
    43     def state(&self) -> PyResult<PyBytes> {
       
    44         let state_byte: u8 = self.entry(py).get().state().into();
       
    45         Ok(PyBytes::new(py, &[state_byte]))
       
    46     }
       
    47 
       
    48     @property
       
    49     def mode(&self) -> PyResult<i32> {
       
    50         Ok(self.entry(py).get().mode())
       
    51     }
       
    52 
       
    53     @property
       
    54     def size(&self) -> PyResult<i32> {
       
    55         Ok(self.entry(py).get().size())
       
    56     }
       
    57 
       
    58     @property
       
    59     def mtime(&self) -> PyResult<i32> {
       
    60         Ok(self.entry(py).get().mtime())
       
    61     }
       
    62 
       
    63     @property
       
    64     def tracked(&self) -> PyResult<bool> {
       
    65         Ok(self.entry(py).get().tracked())
       
    66     }
       
    67 
       
    68     @property
       
    69     def added(&self) -> PyResult<bool> {
       
    70         Ok(self.entry(py).get().added())
       
    71     }
       
    72 
       
    73     @property
       
    74     def merged(&self) -> PyResult<bool> {
       
    75         Ok(self.entry(py).get().merged())
       
    76     }
       
    77 
       
    78     @property
       
    79     def removed(&self) -> PyResult<bool> {
       
    80         Ok(self.entry(py).get().removed())
       
    81     }
       
    82 
       
    83     @property
       
    84     def from_p2(&self) -> PyResult<bool> {
       
    85         Ok(self.entry(py).get().from_p2())
       
    86     }
       
    87 
       
    88     @property
       
    89     def merged_removed(&self) -> PyResult<bool> {
       
    90         Ok(self.entry(py).get().merged_removed())
       
    91     }
       
    92 
       
    93     @property
       
    94     def from_p2_removed(&self) -> PyResult<bool> {
       
    95         Ok(self.entry(py).get().from_p2_removed())
       
    96     }
       
    97 
       
    98     @property
       
    99     def dm_nonnormal(&self) -> PyResult<bool> {
       
   100         Ok(self.entry(py).get().is_non_normal())
       
   101     }
       
   102 
       
   103     @property
       
   104     def dm_otherparent(&self) -> PyResult<bool> {
       
   105         Ok(self.entry(py).get().is_from_other_parent())
       
   106     }
       
   107 
       
   108     def v1_state(&self) -> PyResult<PyBytes> {
       
   109         let (state, _mode, _size, _mtime) = self.entry(py).get().v1_data();
       
   110         let state_byte: u8 = state.into();
       
   111         Ok(PyBytes::new(py, &[state_byte]))
       
   112     }
       
   113 
       
   114     def v1_mode(&self) -> PyResult<i32> {
       
   115         let (_state, mode, _size, _mtime) = self.entry(py).get().v1_data();
       
   116         Ok(mode)
       
   117     }
       
   118 
       
   119     def v1_size(&self) -> PyResult<i32> {
       
   120         let (_state, _mode, size, _mtime) = self.entry(py).get().v1_data();
       
   121         Ok(size)
       
   122     }
       
   123 
       
   124     def v1_mtime(&self) -> PyResult<i32> {
       
   125         let (_state, _mode, _size, mtime) = self.entry(py).get().v1_data();
       
   126         Ok(mtime)
       
   127     }
       
   128 
       
   129     def need_delay(&self, now: i32) -> PyResult<bool> {
       
   130         Ok(self.entry(py).get().mtime_is_ambiguous(now))
       
   131     }
       
   132 
       
   133     @classmethod
       
   134     def from_v1_data(
       
   135         _cls,
       
   136         state: PyBytes,
       
   137         mode: i32,
       
   138         size: i32,
       
   139         mtime: i32,
       
   140     ) -> PyResult<Self> {
       
   141         let state = <[u8; 1]>::try_from(state.data(py))
       
   142             .ok()
       
   143             .and_then(|state| EntryState::try_from(state[0]).ok())
       
   144             .ok_or_else(|| PyErr::new::<exc::ValueError, _>(py, "invalid state"))?;
       
   145         let entry = DirstateEntry::from_v1_data(state, mode, size, mtime);
       
   146         DirstateItem::create_instance(py, Cell::new(entry))
       
   147     }
       
   148 
       
   149     def set_clean(
       
   150         &self,
       
   151         mode: i32,
       
   152         size: i32,
       
   153         mtime: i32,
       
   154     ) -> PyResult<PyNone> {
       
   155         self.update(py, |entry| entry.set_clean(mode, size, mtime));
       
   156         Ok(PyNone)
       
   157     }
       
   158 
       
   159     def set_possibly_dirty(&self) -> PyResult<PyNone> {
       
   160         self.update(py, |entry| entry.set_possibly_dirty());
       
   161         Ok(PyNone)
       
   162     }
       
   163 
       
   164     def set_tracked(&self) -> PyResult<PyNone> {
       
   165         self.update(py, |entry| entry.set_tracked());
       
   166         Ok(PyNone)
       
   167     }
       
   168 
       
   169     def set_untracked(&self) -> PyResult<PyNone> {
       
   170         self.update(py, |entry| entry.set_untracked());
       
   171         Ok(PyNone)
       
   172     }
       
   173 });
       
   174 
       
   175 impl DirstateItem {
       
   176     pub fn new_as_pyobject(
       
   177         py: Python<'_>,
       
   178         entry: DirstateEntry,
       
   179     ) -> PyResult<PyObject> {
       
   180         Ok(DirstateItem::create_instance(py, Cell::new(entry))?.into_object())
       
   181     }
       
   182 
       
   183     // TODO: Use https://doc.rust-lang.org/std/cell/struct.Cell.html#method.update instead when it’s stable
       
   184     pub fn update(&self, py: Python<'_>, f: impl FnOnce(&mut DirstateEntry)) {
       
   185         let mut entry = self.entry(py).get();
       
   186         f(&mut entry);
       
   187         self.entry(py).set(entry)
       
   188     }
       
   189 }