##// END OF EJS Templates
dirstate: drop all logic around the "non-normal" sets...
marmoute -
r48875:060cd909 default
parent child Browse files
Show More
@@ -661,24 +661,6 b' static PyObject *dirstate_item_get_remov'
661 661 }
662 662 };
663 663
664 static PyObject *dm_nonnormal(dirstateItemObject *self)
665 {
666 if ((dirstate_item_c_v1_state(self) != 'n') ||
667 (dirstate_item_c_v1_mtime(self) == ambiguous_time)) {
668 Py_RETURN_TRUE;
669 } else {
670 Py_RETURN_FALSE;
671 }
672 };
673 static PyObject *dm_otherparent(dirstateItemObject *self)
674 {
675 if (dirstate_item_c_v1_mtime(self) == dirstate_v1_from_p2) {
676 Py_RETURN_TRUE;
677 } else {
678 Py_RETURN_FALSE;
679 }
680 };
681
682 664 static PyGetSetDef dirstate_item_getset[] = {
683 665 {"mode", (getter)dirstate_item_get_mode, NULL, "mode", NULL},
684 666 {"size", (getter)dirstate_item_get_size, NULL, "size", NULL},
@@ -693,8 +675,6 b' static PyGetSetDef dirstate_item_getset['
693 675 "from_p2_removed", NULL},
694 676 {"from_p2", (getter)dirstate_item_get_from_p2, NULL, "from_p2", NULL},
695 677 {"removed", (getter)dirstate_item_get_removed, NULL, "removed", NULL},
696 {"dm_nonnormal", (getter)dm_nonnormal, NULL, "dm_nonnormal", NULL},
697 {"dm_otherparent", (getter)dm_otherparent, NULL, "dm_otherparent", NULL},
698 678 {NULL} /* Sentinel */
699 679 };
700 680
@@ -831,70 +811,6 b' quit:'
831 811 }
832 812
833 813 /*
834 * Build a set of non-normal and other parent entries from the dirstate dmap
835 */
836 static PyObject *nonnormalotherparententries(PyObject *self, PyObject *args)
837 {
838 PyObject *dmap, *fname, *v;
839 PyObject *nonnset = NULL, *otherpset = NULL, *result = NULL;
840 Py_ssize_t pos;
841
842 if (!PyArg_ParseTuple(args, "O!:nonnormalentries", &PyDict_Type,
843 &dmap)) {
844 goto bail;
845 }
846
847 nonnset = PySet_New(NULL);
848 if (nonnset == NULL) {
849 goto bail;
850 }
851
852 otherpset = PySet_New(NULL);
853 if (otherpset == NULL) {
854 goto bail;
855 }
856
857 pos = 0;
858 while (PyDict_Next(dmap, &pos, &fname, &v)) {
859 dirstateItemObject *t;
860 if (!dirstate_tuple_check(v)) {
861 PyErr_SetString(PyExc_TypeError,
862 "expected a dirstate tuple");
863 goto bail;
864 }
865 t = (dirstateItemObject *)v;
866
867 if (dirstate_item_c_from_p2(t)) {
868 if (PySet_Add(otherpset, fname) == -1) {
869 goto bail;
870 }
871 }
872 if (!(t->flags & dirstate_flag_wc_tracked) ||
873 !(t->flags &
874 (dirstate_flag_p1_tracked | dirstate_flag_p2_tracked)) ||
875 (t->flags &
876 (dirstate_flag_possibly_dirty | dirstate_flag_merged))) {
877 if (PySet_Add(nonnset, fname) == -1) {
878 goto bail;
879 }
880 }
881 }
882
883 result = Py_BuildValue("(OO)", nonnset, otherpset);
884 if (result == NULL) {
885 goto bail;
886 }
887 Py_DECREF(nonnset);
888 Py_DECREF(otherpset);
889 return result;
890 bail:
891 Py_XDECREF(nonnset);
892 Py_XDECREF(otherpset);
893 Py_XDECREF(result);
894 return NULL;
895 }
896
897 /*
898 814 * Efficiently pack a dirstate object into its on-disk format.
899 815 */
900 816 static PyObject *pack_dirstate(PyObject *self, PyObject *args)
@@ -1226,9 +1142,6 b' PyObject *parse_index2(PyObject *self, P'
1226 1142
1227 1143 static PyMethodDef methods[] = {
1228 1144 {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
1229 {"nonnormalotherparententries", nonnormalotherparententries, METH_VARARGS,
1230 "create a set containing non-normal and other parent entries of given "
1231 "dirstate\n"},
1232 1145 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
1233 1146 {"parse_index2", (PyCFunction)parse_index2, METH_VARARGS | METH_KEYWORDS,
1234 1147 "parse a revlog index\n"},
@@ -62,12 +62,6 b' class dirstatemap(object):'
62 62
63 63 The dirstate also provides the following views onto the state:
64 64
65 - `nonnormalset` is a set of the filenames that have state other
66 than 'normal', or are normal but have an mtime of -1 ('normallookup').
67
68 - `otherparentset` is a set of the filenames that are marked as coming
69 from the second parent when the dirstate is currently being merged.
70
71 65 - `filefoldmap` is a dict mapping normalized filenames to the denormalized
72 66 form that they appear as in the dirstate.
73 67
@@ -112,8 +106,6 b' class dirstatemap(object):'
112 106 util.clearcachedproperty(self, b"_alldirs")
113 107 util.clearcachedproperty(self, b"filefoldmap")
114 108 util.clearcachedproperty(self, b"dirfoldmap")
115 util.clearcachedproperty(self, b"nonnormalset")
116 util.clearcachedproperty(self, b"otherparentset")
117 109
118 110 def items(self):
119 111 return pycompat.iteritems(self._map)
@@ -185,7 +177,6 b' class dirstatemap(object):'
185 177 size = size & rangemask
186 178 entry.set_clean(mode, size, mtime)
187 179 self.copymap.pop(filename, None)
188 self.nonnormalset.discard(filename)
189 180
190 181 def reset_state(
191 182 self,
@@ -218,7 +209,6 b' class dirstatemap(object):'
218 209 if not (p1_tracked or p2_tracked or wc_tracked):
219 210 old_entry = self._map.pop(filename, None)
220 211 self._dirs_decr(filename, old_entry=old_entry)
221 self.nonnormalset.discard(filename)
222 212 self.copymap.pop(filename, None)
223 213 return
224 214 elif merged:
@@ -271,14 +261,6 b' class dirstatemap(object):'
271 261 possibly_dirty=possibly_dirty,
272 262 parentfiledata=parentfiledata,
273 263 )
274 if entry.dm_nonnormal:
275 self.nonnormalset.add(filename)
276 else:
277 self.nonnormalset.discard(filename)
278 if entry.dm_otherparent:
279 self.otherparentset.add(filename)
280 else:
281 self.otherparentset.discard(filename)
282 264 self._map[filename] = entry
283 265
284 266 def set_tracked(self, filename):
@@ -297,8 +279,6 b' class dirstatemap(object):'
297 279 parentfiledata=None,
298 280 )
299 281 self._map[filename] = entry
300 if entry.dm_nonnormal:
301 self.nonnormalset.add(filename)
302 282 new = True
303 283 elif not entry.tracked:
304 284 self._dirs_incr(filename, entry)
@@ -321,29 +301,11 b' class dirstatemap(object):'
321 301 if not entry.merged:
322 302 self.copymap.pop(f, None)
323 303 if entry.added:
324 self.nonnormalset.discard(f)
325 304 self._map.pop(f, None)
326 305 else:
327 self.nonnormalset.add(f)
328 if entry.from_p2:
329 self.otherparentset.add(f)
330 306 entry.set_untracked()
331 307 return True
332 308
333 def nonnormalentries(self):
334 '''Compute the nonnormal dirstate entries from the dmap'''
335 try:
336 return parsers.nonnormalotherparententries(self._map)
337 except AttributeError:
338 nonnorm = set()
339 otherparent = set()
340 for fname, e in pycompat.iteritems(self._map):
341 if e.dm_nonnormal:
342 nonnorm.add(fname)
343 if e.from_p2:
344 otherparent.add(fname)
345 return nonnorm, otherparent
346
347 309 @propertycache
348 310 def filefoldmap(self):
349 311 """Returns a dictionary mapping normalized case paths to their
@@ -433,13 +395,7 b' class dirstatemap(object):'
433 395 self._dirtyparents = True
434 396 copies = {}
435 397 if fold_p2:
436 candidatefiles = self.non_normal_or_other_parent_paths()
437
438 for f in candidatefiles:
439 s = self.get(f)
440 if s is None:
441 continue
442
398 for f, s in pycompat.iteritems(self._map):
443 399 # Discard "merged" markers when moving away from a merge state
444 400 if s.merged or s.from_p2:
445 401 source = self.copymap.pop(f, None)
@@ -504,22 +460,6 b' class dirstatemap(object):'
504 460 )
505 461 st.close()
506 462 self._dirtyparents = False
507 self.nonnormalset, self.otherparentset = self.nonnormalentries()
508
509 @propertycache
510 def nonnormalset(self):
511 nonnorm, otherparents = self.nonnormalentries()
512 self.otherparentset = otherparents
513 return nonnorm
514
515 @propertycache
516 def otherparentset(self):
517 nonnorm, otherparents = self.nonnormalentries()
518 self.nonnormalset = nonnorm
519 return otherparents
520
521 def non_normal_or_other_parent_paths(self):
522 return self.nonnormalset.union(self.otherparentset)
523 463
524 464 @propertycache
525 465 def identity(self):
@@ -643,7 +583,6 b' if rustmod is not None:'
643 583 elif (p1_tracked or p2_tracked) and not wc_tracked:
644 584 # XXX might be merged and removed ?
645 585 self[filename] = DirstateItem.from_v1_data(b'r', 0, 0, 0)
646 self.nonnormalset.add(filename)
647 586 elif clean_p2 and wc_tracked:
648 587 if p1_tracked or self.get(filename) is not None:
649 588 # XXX the `self.get` call is catching some case in
@@ -670,7 +609,6 b' if rustmod is not None:'
670 609 raise error.ProgrammingError(msg)
671 610 mode, size, mtime = parentfiledata
672 611 self.addfile(filename, mode=mode, size=size, mtime=mtime)
673 self.nonnormalset.discard(filename)
674 612 else:
675 613 assert False, 'unreachable'
676 614
@@ -710,9 +648,6 b' if rustmod is not None:'
710 648 def removefile(self, *args, **kwargs):
711 649 return self._rustmap.removefile(*args, **kwargs)
712 650
713 def nonnormalentries(self):
714 return self._rustmap.nonnormalentries()
715
716 651 def get(self, *args, **kwargs):
717 652 return self._rustmap.get(*args, **kwargs)
718 653
@@ -790,13 +725,17 b' if rustmod is not None:'
790 725 self._dirtyparents = True
791 726 copies = {}
792 727 if fold_p2:
793 candidatefiles = self.non_normal_or_other_parent_paths()
794
795 for f in candidatefiles:
796 s = self.get(f)
797 if s is None:
798 continue
799
728 # Collect into an intermediate list to avoid a `RuntimeError`
729 # exception due to mutation during iteration.
730 # TODO: move this the whole loop to Rust where `iter_mut`
731 # enables in-place mutation of elements of a collection while
732 # iterating it, without mutating the collection itself.
733 candidatefiles = [
734 (f, s)
735 for f, s in self._rustmap.items()
736 if s.merged or s.from_p2
737 ]
738 for f, s in candidatefiles:
800 739 # Discard "merged" markers when moving away from a merge state
801 740 if s.merged:
802 741 source = self.copymap.get(f)
@@ -965,19 +904,6 b' if rustmod is not None:'
965 904 self._rustmap
966 905 return self.identity
967 906
968 @property
969 def nonnormalset(self):
970 nonnorm = self._rustmap.non_normal_entries()
971 return nonnorm
972
973 @propertycache
974 def otherparentset(self):
975 otherparents = self._rustmap.other_parent_entries()
976 return otherparents
977
978 def non_normal_or_other_parent_paths(self):
979 return self._rustmap.non_normal_or_other_parent_paths()
980
981 907 @propertycache
982 908 def dirfoldmap(self):
983 909 f = {}
@@ -361,22 +361,6 b' class DirstateItem(object):'
361 361 """
362 362 return self.removed and self._merged
363 363
364 @property
365 def dm_nonnormal(self):
366 """True is the entry is non-normal in the dirstatemap sense
367
368 There is no reason for any code, but the dirstatemap one to use this.
369 """
370 return self.v1_state() != b'n' or self.v1_mtime() == AMBIGUOUS_TIME
371
372 @property
373 def dm_otherparent(self):
374 """True is the entry is `otherparent` in the dirstatemap sense
375
376 There is no reason for any code, but the dirstatemap one to use this.
377 """
378 return self.v1_size() == FROM_P2
379
380 364 def v1_state(self):
381 365 """return a "state" suitable for v1 serialization"""
382 366 if not (self._p1_tracked or self._p2_tracked or self._wc_tracked):
@@ -6,6 +6,7 b''
6 6 // GNU General Public License version 2 or any later version.
7 7
8 8 use crate::dirstate::parsers::Timestamp;
9 use crate::errors::HgError;
9 10 use crate::{
10 11 dirstate::EntryState,
11 12 dirstate::SIZE_FROM_OTHER_PARENT,
@@ -16,7 +17,6 b' use crate::{'
16 17 StateMap,
17 18 };
18 19 use micro_timer::timed;
19 use std::collections::HashSet;
20 20 use std::iter::FromIterator;
21 21 use std::ops::Deref;
22 22
@@ -26,8 +26,6 b' pub struct DirstateMap {'
26 26 pub copy_map: CopyMap,
27 27 pub dirs: Option<DirsMultiset>,
28 28 pub all_dirs: Option<DirsMultiset>,
29 non_normal_set: Option<HashSet<HgPathBuf>>,
30 other_parent_set: Option<HashSet<HgPathBuf>>,
31 29 }
32 30
33 31 /// Should only really be used in python interface code, for clarity
@@ -58,8 +56,6 b' impl DirstateMap {'
58 56 pub fn clear(&mut self) {
59 57 self.state_map = StateMap::default();
60 58 self.copy_map.clear();
61 self.non_normal_set = None;
62 self.other_parent_set = None;
63 59 }
64 60
65 61 pub fn set_entry(&mut self, filename: &HgPath, entry: DirstateEntry) {
@@ -84,18 +80,6 b' impl DirstateMap {'
84 80 }
85 81 }
86 82 self.state_map.insert(filename.to_owned(), entry.to_owned());
87
88 if entry.is_non_normal() {
89 self.get_non_normal_other_parent_entries()
90 .0
91 .insert(filename.to_owned());
92 }
93
94 if entry.is_from_other_parent() {
95 self.get_non_normal_other_parent_entries()
96 .1
97 .insert(filename.to_owned());
98 }
99 83 Ok(())
100 84 }
101 85
@@ -126,9 +110,6 b' impl DirstateMap {'
126 110 {
127 111 // other parent
128 112 size = SIZE_FROM_OTHER_PARENT;
129 self.get_non_normal_other_parent_entries()
130 .1
131 .insert(filename.to_owned());
132 113 }
133 114 }
134 115 }
@@ -148,9 +129,6 b' impl DirstateMap {'
148 129
149 130 self.state_map
150 131 .insert(filename.to_owned(), DirstateEntry::new_removed(size));
151 self.get_non_normal_other_parent_entries()
152 .0
153 .insert(filename.to_owned());
154 132 Ok(())
155 133 }
156 134
@@ -173,92 +151,11 b' impl DirstateMap {'
173 151 all_dirs.delete_path(filename)?;
174 152 }
175 153 }
176 self.get_non_normal_other_parent_entries()
177 .0
178 .remove(filename);
179
180 154 self.copy_map.remove(filename);
181 155
182 156 Ok(())
183 157 }
184 158
185 pub fn non_normal_entries_remove(
186 &mut self,
187 key: impl AsRef<HgPath>,
188 ) -> bool {
189 self.get_non_normal_other_parent_entries()
190 .0
191 .remove(key.as_ref())
192 }
193
194 pub fn non_normal_entries_add(&mut self, key: impl AsRef<HgPath>) {
195 self.get_non_normal_other_parent_entries()
196 .0
197 .insert(key.as_ref().into());
198 }
199
200 pub fn non_normal_entries_union(
201 &mut self,
202 other: HashSet<HgPathBuf>,
203 ) -> Vec<HgPathBuf> {
204 self.get_non_normal_other_parent_entries()
205 .0
206 .union(&other)
207 .map(ToOwned::to_owned)
208 .collect()
209 }
210
211 pub fn get_non_normal_other_parent_entries(
212 &mut self,
213 ) -> (&mut HashSet<HgPathBuf>, &mut HashSet<HgPathBuf>) {
214 self.set_non_normal_other_parent_entries(false);
215 (
216 self.non_normal_set.as_mut().unwrap(),
217 self.other_parent_set.as_mut().unwrap(),
218 )
219 }
220
221 /// Useful to get immutable references to those sets in contexts where
222 /// you only have an immutable reference to the `DirstateMap`, like when
223 /// sharing references with Python.
224 ///
225 /// TODO, get rid of this along with the other "setter/getter" stuff when
226 /// a nice typestate plan is defined.
227 ///
228 /// # Panics
229 ///
230 /// Will panic if either set is `None`.
231 pub fn get_non_normal_other_parent_entries_panic(
232 &self,
233 ) -> (&HashSet<HgPathBuf>, &HashSet<HgPathBuf>) {
234 (
235 self.non_normal_set.as_ref().unwrap(),
236 self.other_parent_set.as_ref().unwrap(),
237 )
238 }
239
240 pub fn set_non_normal_other_parent_entries(&mut self, force: bool) {
241 if !force
242 && self.non_normal_set.is_some()
243 && self.other_parent_set.is_some()
244 {
245 return;
246 }
247 let mut non_normal = HashSet::new();
248 let mut other_parent = HashSet::new();
249
250 for (filename, entry) in self.state_map.iter() {
251 if entry.is_non_normal() {
252 non_normal.insert(filename.to_owned());
253 }
254 if entry.is_from_other_parent() {
255 other_parent.insert(filename.to_owned());
256 }
257 }
258 self.non_normal_set = Some(non_normal);
259 self.other_parent_set = Some(other_parent);
260 }
261
262 159 /// Both of these setters and their uses appear to be the simplest way to
263 160 /// emulate a Python lazy property, but it is ugly and unidiomatic.
264 161 /// TODO One day, rewriting this struct using the typestate might be a
@@ -326,12 +223,8 b' impl DirstateMap {'
326 223 &mut self,
327 224 parents: DirstateParents,
328 225 now: Timestamp,
329 ) -> Result<Vec<u8>, DirstateError> {
330 let packed =
331 pack_dirstate(&mut self.state_map, &self.copy_map, parents, now)?;
332
333 self.set_non_normal_other_parent_entries(true);
334 Ok(packed)
226 ) -> Result<Vec<u8>, HgError> {
227 pack_dirstate(&mut self.state_map, &self.copy_map, parents, now)
335 228 }
336 229 }
337 230
@@ -366,49 +259,5 b' mod tests {'
366 259 .unwrap();
367 260
368 261 assert_eq!(1, map.len());
369 assert_eq!(0, map.get_non_normal_other_parent_entries().0.len());
370 assert_eq!(0, map.get_non_normal_other_parent_entries().1.len());
371 }
372
373 #[test]
374 fn test_non_normal_other_parent_entries() {
375 let mut map: DirstateMap = [
376 (b"f1", (EntryState::Removed, 1337, 1337, 1337)),
377 (b"f2", (EntryState::Normal, 1337, 1337, -1)),
378 (b"f3", (EntryState::Normal, 1337, 1337, 1337)),
379 (b"f4", (EntryState::Normal, 1337, -2, 1337)),
380 (b"f5", (EntryState::Added, 1337, 1337, 1337)),
381 (b"f6", (EntryState::Added, 1337, 1337, -1)),
382 (b"f7", (EntryState::Merged, 1337, 1337, -1)),
383 (b"f8", (EntryState::Merged, 1337, 1337, 1337)),
384 (b"f9", (EntryState::Merged, 1337, -2, 1337)),
385 (b"fa", (EntryState::Added, 1337, -2, 1337)),
386 (b"fb", (EntryState::Removed, 1337, -2, 1337)),
387 ]
388 .iter()
389 .map(|(fname, (state, mode, size, mtime))| {
390 (
391 HgPathBuf::from_bytes(fname.as_ref()),
392 DirstateEntry::from_v1_data(*state, *mode, *size, *mtime),
393 )
394 })
395 .collect();
396
397 let mut non_normal = [
398 b"f1", b"f2", b"f4", b"f5", b"f6", b"f7", b"f8", b"f9", b"fa",
399 b"fb",
400 ]
401 .iter()
402 .map(|x| HgPathBuf::from_bytes(x.as_ref()))
403 .collect();
404
405 let mut other_parent = HashSet::new();
406 other_parent.insert(HgPathBuf::from_bytes(b"f4"));
407 let entries = map.get_non_normal_other_parent_entries();
408
409 assert_eq!(
410 (&mut non_normal, &mut other_parent),
411 (entries.0, entries.1)
412 );
413 262 }
414 263 }
@@ -294,11 +294,7 b' impl DirstateEntry {'
294 294 (self.state().into(), self.mode(), self.size(), self.mtime())
295 295 }
296 296
297 pub fn is_non_normal(&self) -> bool {
298 self.state() != EntryState::Normal || self.mtime() == MTIME_UNSET
299 }
300
301 pub fn is_from_other_parent(&self) -> bool {
297 pub(crate) fn is_from_other_parent(&self) -> bool {
302 298 self.state() == EntryState::Normal
303 299 && self.size() == SIZE_FROM_OTHER_PARENT
304 300 }
@@ -701,27 +701,6 b" impl<'on_disk> DirstateMap<'on_disk> {"
701 701 Ok(())
702 702 }
703 703
704 /// Return a faillilble iterator of full paths of nodes that have an
705 /// `entry` for which the given `predicate` returns true.
706 ///
707 /// Fallibility means that each iterator item is a `Result`, which may
708 /// indicate a parse error of the on-disk dirstate-v2 format. Such errors
709 /// should only happen if Mercurial is buggy or a repository is corrupted.
710 fn filter_full_paths<'tree>(
711 &'tree self,
712 predicate: impl Fn(&DirstateEntry) -> bool + 'tree,
713 ) -> impl Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + 'tree
714 {
715 filter_map_results(self.iter_nodes(), move |node| {
716 if let Some(entry) = node.entry()? {
717 if predicate(&entry) {
718 return Ok(Some(node.full_path(self.on_disk)?));
719 }
720 }
721 Ok(None)
722 })
723 }
724
725 704 fn count_dropped_path(unreachable_bytes: &mut u32, path: &Cow<HgPath>) {
726 705 if let Cow::Borrowed(path) = path {
727 706 *unreachable_bytes += path.len() as u32
@@ -917,69 +896,6 b" impl<'on_disk> super::dispatch::Dirstate"
917 896 Ok(())
918 897 }
919 898
920 fn non_normal_entries_contains(
921 &mut self,
922 key: &HgPath,
923 ) -> Result<bool, DirstateV2ParseError> {
924 Ok(if let Some(node) = self.get_node(key)? {
925 node.entry()?.map_or(false, |entry| entry.is_non_normal())
926 } else {
927 false
928 })
929 }
930
931 fn non_normal_entries_remove(&mut self, key: &HgPath) -> bool {
932 // Do nothing, this `DirstateMap` does not have a separate "non normal
933 // entries" set that need to be kept up to date.
934 if let Ok(Some(v)) = self.get(key) {
935 return v.is_non_normal();
936 }
937 false
938 }
939
940 fn non_normal_entries_add(&mut self, _key: &HgPath) {
941 // Do nothing, this `DirstateMap` does not have a separate "non normal
942 // entries" set that need to be kept up to date
943 }
944
945 fn non_normal_or_other_parent_paths(
946 &mut self,
947 ) -> Box<dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + '_>
948 {
949 Box::new(self.filter_full_paths(|entry| {
950 entry.is_non_normal() || entry.is_from_other_parent()
951 }))
952 }
953
954 fn set_non_normal_other_parent_entries(&mut self, _force: bool) {
955 // Do nothing, this `DirstateMap` does not have a separate "non normal
956 // entries" and "from other parent" sets that need to be recomputed
957 }
958
959 fn iter_non_normal_paths(
960 &mut self,
961 ) -> Box<
962 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
963 > {
964 self.iter_non_normal_paths_panic()
965 }
966
967 fn iter_non_normal_paths_panic(
968 &self,
969 ) -> Box<
970 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
971 > {
972 Box::new(self.filter_full_paths(|entry| entry.is_non_normal()))
973 }
974
975 fn iter_other_parent_paths(
976 &mut self,
977 ) -> Box<
978 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
979 > {
980 Box::new(self.filter_full_paths(|entry| entry.is_from_other_parent()))
981 }
982
983 899 fn has_tracked_dir(
984 900 &mut self,
985 901 directory: &HgPath,
@@ -67,82 +67,6 b' pub trait DirstateMapMethods {'
67 67 filename: &HgPath,
68 68 ) -> Result<(), DirstateError>;
69 69
70 /// Return whether the map has an "non-normal" entry for the given
71 /// filename. That is, any entry with a `state` other than
72 /// `EntryState::Normal` or with an ambiguous `mtime`.
73 fn non_normal_entries_contains(
74 &mut self,
75 key: &HgPath,
76 ) -> Result<bool, DirstateV2ParseError>;
77
78 /// Mark the given path as "normal" file. This is only relevant in the flat
79 /// dirstate map where there is a separate `HashSet` that needs to be kept
80 /// up to date.
81 /// Returns whether the key was present in the set.
82 fn non_normal_entries_remove(&mut self, key: &HgPath) -> bool;
83
84 /// Mark the given path as "non-normal" file.
85 /// This is only relevant in the flat dirstate map where there is a
86 /// separate `HashSet` that needs to be kept up to date.
87 fn non_normal_entries_add(&mut self, key: &HgPath);
88
89 /// Return an iterator of paths whose respective entry are either
90 /// "non-normal" (see `non_normal_entries_contains`) or "from other
91 /// parent".
92 ///
93 /// If that information is cached, create the cache as needed.
94 ///
95 /// "From other parent" is defined as `state == Normal && size == -2`.
96 ///
97 /// Because parse errors can happen during iteration, the iterated items
98 /// are `Result`s.
99 fn non_normal_or_other_parent_paths(
100 &mut self,
101 ) -> Box<dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + '_>;
102
103 /// Create the cache for `non_normal_or_other_parent_paths` if needed.
104 ///
105 /// If `force` is true, the cache is re-created even if it already exists.
106 fn set_non_normal_other_parent_entries(&mut self, force: bool);
107
108 /// Return an iterator of paths whose respective entry are "non-normal"
109 /// (see `non_normal_entries_contains`).
110 ///
111 /// If that information is cached, create the cache as needed.
112 ///
113 /// Because parse errors can happen during iteration, the iterated items
114 /// are `Result`s.
115 fn iter_non_normal_paths(
116 &mut self,
117 ) -> Box<
118 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
119 >;
120
121 /// Same as `iter_non_normal_paths`, but takes `&self` instead of `&mut
122 /// self`.
123 ///
124 /// Panics if a cache is necessary but does not exist yet.
125 fn iter_non_normal_paths_panic(
126 &self,
127 ) -> Box<
128 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
129 >;
130
131 /// Return an iterator of paths whose respective entry are "from other
132 /// parent".
133 ///
134 /// If that information is cached, create the cache as needed.
135 ///
136 /// "From other parent" is defined as `state == Normal && size == -2`.
137 ///
138 /// Because parse errors can happen during iteration, the iterated items
139 /// are `Result`s.
140 fn iter_other_parent_paths(
141 &mut self,
142 ) -> Box<
143 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
144 >;
145
146 70 /// Returns whether the sub-tree rooted at the given directory contains any
147 71 /// tracked file.
148 72 ///
@@ -330,66 +254,6 b' impl DirstateMapMethods for DirstateMap '
330 254 self.drop_entry_and_copy_source(filename)
331 255 }
332 256
333 fn non_normal_entries_contains(
334 &mut self,
335 key: &HgPath,
336 ) -> Result<bool, DirstateV2ParseError> {
337 let (non_normal, _other_parent) =
338 self.get_non_normal_other_parent_entries();
339 Ok(non_normal.contains(key))
340 }
341
342 fn non_normal_entries_remove(&mut self, key: &HgPath) -> bool {
343 self.non_normal_entries_remove(key)
344 }
345
346 fn non_normal_entries_add(&mut self, key: &HgPath) {
347 self.non_normal_entries_add(key)
348 }
349
350 fn non_normal_or_other_parent_paths(
351 &mut self,
352 ) -> Box<dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + '_>
353 {
354 let (non_normal, other_parent) =
355 self.get_non_normal_other_parent_entries();
356 Box::new(non_normal.union(other_parent).map(|p| Ok(&**p)))
357 }
358
359 fn set_non_normal_other_parent_entries(&mut self, force: bool) {
360 self.set_non_normal_other_parent_entries(force)
361 }
362
363 fn iter_non_normal_paths(
364 &mut self,
365 ) -> Box<
366 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
367 > {
368 let (non_normal, _other_parent) =
369 self.get_non_normal_other_parent_entries();
370 Box::new(non_normal.iter().map(|p| Ok(&**p)))
371 }
372
373 fn iter_non_normal_paths_panic(
374 &self,
375 ) -> Box<
376 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
377 > {
378 let (non_normal, _other_parent) =
379 self.get_non_normal_other_parent_entries_panic();
380 Box::new(non_normal.iter().map(|p| Ok(&**p)))
381 }
382
383 fn iter_other_parent_paths(
384 &mut self,
385 ) -> Box<
386 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
387 > {
388 let (_non_normal, other_parent) =
389 self.get_non_normal_other_parent_entries();
390 Box::new(other_parent.iter().map(|p| Ok(&**p)))
391 }
392
393 257 fn has_tracked_dir(
394 258 &mut self,
395 259 directory: &HgPath,
@@ -406,7 +270,7 b' impl DirstateMapMethods for DirstateMap '
406 270 parents: DirstateParents,
407 271 now: Timestamp,
408 272 ) -> Result<Vec<u8>, DirstateError> {
409 self.pack(parents, now)
273 Ok(self.pack(parents, now)?)
410 274 }
411 275
412 276 fn pack_v2(
@@ -51,56 +51,6 b' impl DirstateMapMethods for OwningDirsta'
51 51 self.get_mut().drop_entry_and_copy_source(filename)
52 52 }
53 53
54 fn non_normal_entries_contains(
55 &mut self,
56 key: &HgPath,
57 ) -> Result<bool, DirstateV2ParseError> {
58 self.get_mut().non_normal_entries_contains(key)
59 }
60
61 fn non_normal_entries_remove(&mut self, key: &HgPath) -> bool {
62 self.get_mut().non_normal_entries_remove(key)
63 }
64
65 fn non_normal_entries_add(&mut self, key: &HgPath) {
66 self.get_mut().non_normal_entries_add(key)
67 }
68
69 fn non_normal_or_other_parent_paths(
70 &mut self,
71 ) -> Box<dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + '_>
72 {
73 self.get_mut().non_normal_or_other_parent_paths()
74 }
75
76 fn set_non_normal_other_parent_entries(&mut self, force: bool) {
77 self.get_mut().set_non_normal_other_parent_entries(force)
78 }
79
80 fn iter_non_normal_paths(
81 &mut self,
82 ) -> Box<
83 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
84 > {
85 self.get_mut().iter_non_normal_paths()
86 }
87
88 fn iter_non_normal_paths_panic(
89 &self,
90 ) -> Box<
91 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
92 > {
93 self.get().iter_non_normal_paths_panic()
94 }
95
96 fn iter_other_parent_paths(
97 &mut self,
98 ) -> Box<
99 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
100 > {
101 self.get_mut().iter_other_parent_paths()
102 }
103
104 54 fn has_tracked_dir(
105 55 &mut self,
106 56 directory: &HgPath,
@@ -13,7 +13,6 b' mod copymap;'
13 13 mod dirs_multiset;
14 14 mod dirstate_map;
15 15 mod item;
16 mod non_normal_entries;
17 16 mod status;
18 17 use self::item::DirstateItem;
19 18 use crate::{
@@ -13,16 +13,12 b' use std::convert::TryInto;'
13 13
14 14 use cpython::{
15 15 exc, PyBool, PyBytes, PyClone, PyDict, PyErr, PyList, PyNone, PyObject,
16 PyResult, PySet, PyString, Python, PythonObject, ToPyObject,
17 UnsafePyLeaked,
16 PyResult, Python, PythonObject, ToPyObject, UnsafePyLeaked,
18 17 };
19 18
20 19 use crate::{
21 20 dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator},
22 21 dirstate::item::DirstateItem,
23 dirstate::non_normal_entries::{
24 NonNormalEntries, NonNormalEntriesIterator,
25 },
26 22 pybytes_deref::PyBytesDeref,
27 23 };
28 24 use hg::{
@@ -185,100 +181,6 b' py_class!(pub class DirstateMap |py| {'
185 181 Ok(PyNone)
186 182 }
187 183
188 def other_parent_entries(&self) -> PyResult<PyObject> {
189 let mut inner_shared = self.inner(py).borrow_mut();
190 let set = PySet::empty(py)?;
191 for path in inner_shared.iter_other_parent_paths() {
192 let path = path.map_err(|e| v2_error(py, e))?;
193 set.add(py, PyBytes::new(py, path.as_bytes()))?;
194 }
195 Ok(set.into_object())
196 }
197
198 def non_normal_entries(&self) -> PyResult<NonNormalEntries> {
199 NonNormalEntries::from_inner(py, self.clone_ref(py))
200 }
201
202 def non_normal_entries_contains(&self, key: PyObject) -> PyResult<bool> {
203 let key = key.extract::<PyBytes>(py)?;
204 self.inner(py)
205 .borrow_mut()
206 .non_normal_entries_contains(HgPath::new(key.data(py)))
207 .map_err(|e| v2_error(py, e))
208 }
209
210 def non_normal_entries_display(&self) -> PyResult<PyString> {
211 let mut inner = self.inner(py).borrow_mut();
212 let paths = inner
213 .iter_non_normal_paths()
214 .collect::<Result<Vec<_>, _>>()
215 .map_err(|e| v2_error(py, e))?;
216 let formatted = format!("NonNormalEntries: {}", hg::utils::join_display(paths, ", "));
217 Ok(PyString::new(py, &formatted))
218 }
219
220 def non_normal_entries_remove(&self, key: PyObject) -> PyResult<PyObject> {
221 let key = key.extract::<PyBytes>(py)?;
222 let key = key.data(py);
223 let was_present = self
224 .inner(py)
225 .borrow_mut()
226 .non_normal_entries_remove(HgPath::new(key));
227 if !was_present {
228 let msg = String::from_utf8_lossy(key);
229 Err(PyErr::new::<exc::KeyError, _>(py, msg))
230 } else {
231 Ok(py.None())
232 }
233 }
234
235 def non_normal_entries_discard(&self, key: PyObject) -> PyResult<PyObject>
236 {
237 let key = key.extract::<PyBytes>(py)?;
238 self
239 .inner(py)
240 .borrow_mut()
241 .non_normal_entries_remove(HgPath::new(key.data(py)));
242 Ok(py.None())
243 }
244
245 def non_normal_entries_add(&self, key: PyObject) -> PyResult<PyObject> {
246 let key = key.extract::<PyBytes>(py)?;
247 self
248 .inner(py)
249 .borrow_mut()
250 .non_normal_entries_add(HgPath::new(key.data(py)));
251 Ok(py.None())
252 }
253
254 def non_normal_or_other_parent_paths(&self) -> PyResult<PyList> {
255 let mut inner = self.inner(py).borrow_mut();
256
257 let ret = PyList::new(py, &[]);
258 for filename in inner.non_normal_or_other_parent_paths() {
259 let filename = filename.map_err(|e| v2_error(py, e))?;
260 let as_pystring = PyBytes::new(py, filename.as_bytes());
261 ret.append(py, as_pystring.into_object());
262 }
263 Ok(ret)
264 }
265
266 def non_normal_entries_iter(&self) -> PyResult<NonNormalEntriesIterator> {
267 // Make sure the sets are defined before we no longer have a mutable
268 // reference to the dmap.
269 self.inner(py)
270 .borrow_mut()
271 .set_non_normal_other_parent_entries(false);
272
273 let leaked_ref = self.inner(py).leak_immutable();
274
275 NonNormalEntriesIterator::from_inner(py, unsafe {
276 leaked_ref.map(py, |o| {
277 o.iter_non_normal_paths_panic()
278 })
279 })
280 }
281
282 184 def hastrackeddir(&self, d: PyObject) -> PyResult<PyBool> {
283 185 let d = d.extract::<PyBytes>(py)?;
284 186 Ok(self.inner(py).borrow_mut()
@@ -95,16 +95,6 b' py_class!(pub class DirstateItem |py| {'
95 95 Ok(self.entry(py).get().from_p2_removed())
96 96 }
97 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 98 def v1_state(&self) -> PyResult<PyBytes> {
109 99 let (state, _mode, _size, _mtime) = self.entry(py).get().v1_data();
110 100 let state_byte: u8 = state.into();
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now