|
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 } |