Show More
@@ -941,6 +941,7 b' def debugdeltachain(ui, repo, file_=None' | |||||
941 | ), |
|
941 | ), | |
942 | (b'', b'dates', True, _(b'display the saved mtime')), |
|
942 | (b'', b'dates', True, _(b'display the saved mtime')), | |
943 | (b'', b'datesort', None, _(b'sort by saved mtime')), |
|
943 | (b'', b'datesort', None, _(b'sort by saved mtime')), | |
|
944 | (b'', b'dirs', False, _(b'display directories')), | |||
944 | ], |
|
945 | ], | |
945 | _(b'[OPTION]...'), |
|
946 | _(b'[OPTION]...'), | |
946 | ) |
|
947 | ) | |
@@ -956,7 +957,11 b' def debugstate(ui, repo, **opts):' | |||||
956 | keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename |
|
957 | keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename | |
957 | else: |
|
958 | else: | |
958 | keyfunc = None # sort by filename |
|
959 | keyfunc = None # sort by filename | |
959 |
|
|
960 | entries = list(pycompat.iteritems(repo.dirstate)) | |
|
961 | if opts['dirs']: | |||
|
962 | entries.extend(repo.dirstate.directories()) | |||
|
963 | entries.sort(key=keyfunc) | |||
|
964 | for file_, ent in entries: | |||
960 | if ent[3] == -1: |
|
965 | if ent[3] == -1: | |
961 | timestr = b'unset ' |
|
966 | timestr = b'unset ' | |
962 | elif nodates: |
|
967 | elif nodates: |
@@ -315,6 +315,9 b' class dirstate(object):' | |||||
315 |
|
315 | |||
316 | iteritems = items |
|
316 | iteritems = items | |
317 |
|
317 | |||
|
318 | def directories(self): | |||
|
319 | return self._map.directories() | |||
|
320 | ||||
318 | def parents(self): |
|
321 | def parents(self): | |
319 | return [self._validate(p) for p in self._pl] |
|
322 | return [self._validate(p) for p in self._pl] | |
320 |
|
323 | |||
@@ -1479,6 +1482,10 b' class dirstatemap(object):' | |||||
1479 | self._map |
|
1482 | self._map | |
1480 | return self.copymap |
|
1483 | return self.copymap | |
1481 |
|
1484 | |||
|
1485 | def directories(self): | |||
|
1486 | # Rust / dirstate-v2 only | |||
|
1487 | return [] | |||
|
1488 | ||||
1482 | def clear(self): |
|
1489 | def clear(self): | |
1483 | self._map.clear() |
|
1490 | self._map.clear() | |
1484 | self.copymap.clear() |
|
1491 | self.copymap.clear() | |
@@ -1806,6 +1813,9 b' if rustmod is not None:' | |||||
1806 | def copymap(self): |
|
1813 | def copymap(self): | |
1807 | return self._rustmap.copymap() |
|
1814 | return self._rustmap.copymap() | |
1808 |
|
1815 | |||
|
1816 | def directories(self): | |||
|
1817 | return self._rustmap.directories() | |||
|
1818 | ||||
1809 | def preload(self): |
|
1819 | def preload(self): | |
1810 | self._rustmap |
|
1820 | self._rustmap | |
1811 |
|
1821 |
@@ -129,7 +129,7 b' pub fn pack_entry(' | |||||
129 | } |
|
129 | } | |
130 |
|
130 | |||
131 | /// Seconds since the Unix epoch |
|
131 | /// Seconds since the Unix epoch | |
132 |
pub struct Timestamp(pub |
|
132 | pub struct Timestamp(pub i64); | |
133 |
|
133 | |||
134 | impl DirstateEntry { |
|
134 | impl DirstateEntry { | |
135 | pub fn mtime_is_ambiguous(&self, now: i32) -> bool { |
|
135 | pub fn mtime_is_ambiguous(&self, now: i32) -> bool { |
@@ -319,7 +319,7 b" impl<'tree, 'on_disk> NodeRef<'tree, 'on" | |||||
319 |
|
319 | |||
320 | pub(super) fn cached_directory_mtime( |
|
320 | pub(super) fn cached_directory_mtime( | |
321 | &self, |
|
321 | &self, | |
322 | ) -> Option<&on_disk::Timestamp> { |
|
322 | ) -> Option<&'tree on_disk::Timestamp> { | |
323 | match self { |
|
323 | match self { | |
324 | NodeRef::InMemory(_path, node) => match &node.data { |
|
324 | NodeRef::InMemory(_path, node) => match &node.data { | |
325 | NodeData::CachedDirectory { mtime } => Some(mtime), |
|
325 | NodeData::CachedDirectory { mtime } => Some(mtime), | |
@@ -1068,4 +1068,28 b" impl<'on_disk> super::dispatch::Dirstate" | |||||
1068 | }) |
|
1068 | }) | |
1069 | })) |
|
1069 | })) | |
1070 | } |
|
1070 | } | |
|
1071 | ||||
|
1072 | fn iter_directories( | |||
|
1073 | &self, | |||
|
1074 | ) -> Box< | |||
|
1075 | dyn Iterator< | |||
|
1076 | Item = Result< | |||
|
1077 | (&HgPath, Option<Timestamp>), | |||
|
1078 | DirstateV2ParseError, | |||
|
1079 | >, | |||
|
1080 | > + Send | |||
|
1081 | + '_, | |||
|
1082 | > { | |||
|
1083 | Box::new(filter_map_results(self.iter_nodes(), move |node| { | |||
|
1084 | Ok(if node.state()?.is_none() { | |||
|
1085 | Some(( | |||
|
1086 | node.full_path(self.on_disk)?, | |||
|
1087 | node.cached_directory_mtime() | |||
|
1088 | .map(|mtime| Timestamp(mtime.seconds())), | |||
|
1089 | )) | |||
|
1090 | } else { | |||
|
1091 | None | |||
|
1092 | }) | |||
|
1093 | })) | |||
1071 | } |
|
1094 | } | |
|
1095 | } |
@@ -143,6 +143,18 b' pub trait DirstateMapMethods {' | |||||
143 | ) -> Result<Option<DirstateEntry>, DirstateV2ParseError>; |
|
143 | ) -> Result<Option<DirstateEntry>, DirstateV2ParseError>; | |
144 |
|
144 | |||
145 | fn iter(&self) -> StateMapIter<'_>; |
|
145 | fn iter(&self) -> StateMapIter<'_>; | |
|
146 | ||||
|
147 | fn iter_directories( | |||
|
148 | &self, | |||
|
149 | ) -> Box< | |||
|
150 | dyn Iterator< | |||
|
151 | Item = Result< | |||
|
152 | (&HgPath, Option<Timestamp>), | |||
|
153 | DirstateV2ParseError, | |||
|
154 | >, | |||
|
155 | > + Send | |||
|
156 | + '_, | |||
|
157 | >; | |||
146 | } |
|
158 | } | |
147 |
|
159 | |||
148 | impl DirstateMapMethods for DirstateMap { |
|
160 | impl DirstateMapMethods for DirstateMap { | |
@@ -350,4 +362,18 b' impl DirstateMapMethods for DirstateMap ' | |||||
350 | fn iter(&self) -> StateMapIter<'_> { |
|
362 | fn iter(&self) -> StateMapIter<'_> { | |
351 | Box::new((&**self).iter().map(|(key, value)| Ok((&**key, *value)))) |
|
363 | Box::new((&**self).iter().map(|(key, value)| Ok((&**key, *value)))) | |
352 | } |
|
364 | } | |
|
365 | ||||
|
366 | fn iter_directories( | |||
|
367 | &self, | |||
|
368 | ) -> Box< | |||
|
369 | dyn Iterator< | |||
|
370 | Item = Result< | |||
|
371 | (&HgPath, Option<Timestamp>), | |||
|
372 | DirstateV2ParseError, | |||
|
373 | >, | |||
|
374 | > + Send | |||
|
375 | + '_, | |||
|
376 | > { | |||
|
377 | Box::new(std::iter::empty()) | |||
353 | } |
|
378 | } | |
|
379 | } |
@@ -352,6 +352,12 b' impl Entry {' | |||||
352 | } |
|
352 | } | |
353 | } |
|
353 | } | |
354 |
|
354 | |||
|
355 | impl Timestamp { | |||
|
356 | pub fn seconds(&self) -> i64 { | |||
|
357 | self.seconds.get() | |||
|
358 | } | |||
|
359 | } | |||
|
360 | ||||
355 | impl From<SystemTime> for Timestamp { |
|
361 | impl From<SystemTime> for Timestamp { | |
356 | fn from(system_time: SystemTime) -> Self { |
|
362 | fn from(system_time: SystemTime) -> Self { | |
357 | let (secs, nanos) = match system_time.duration_since(UNIX_EPOCH) { |
|
363 | let (secs, nanos) = match system_time.duration_since(UNIX_EPOCH) { |
@@ -535,6 +535,18 b' py_class!(pub class DirstateMap |py| {' | |||||
535 | ) |
|
535 | ) | |
536 | } |
|
536 | } | |
537 |
|
537 | |||
|
538 | def directories(&self) -> PyResult<PyList> { | |||
|
539 | let dirs = PyList::new(py, &[]); | |||
|
540 | for item in self.inner(py).borrow().iter_directories() { | |||
|
541 | let (path, mtime) = item.map_err(|e| v2_error(py, e))?; | |||
|
542 | let path = PyBytes::new(py, path.as_bytes()); | |||
|
543 | let mtime = mtime.map(|t| t.0).unwrap_or(-1); | |||
|
544 | let tuple = (path, (b'd', 0, 0, mtime)); | |||
|
545 | dirs.append(py, tuple.to_py_object(py).into_object()) | |||
|
546 | } | |||
|
547 | Ok(dirs) | |||
|
548 | } | |||
|
549 | ||||
538 | }); |
|
550 | }); | |
539 |
|
551 | |||
540 | impl DirstateMap { |
|
552 | impl DirstateMap { |
@@ -206,4 +206,18 b' impl DirstateMapMethods for OwningDirsta' | |||||
206 | fn iter(&self) -> StateMapIter<'_> { |
|
206 | fn iter(&self) -> StateMapIter<'_> { | |
207 | self.get().iter() |
|
207 | self.get().iter() | |
208 | } |
|
208 | } | |
|
209 | ||||
|
210 | fn iter_directories( | |||
|
211 | &self, | |||
|
212 | ) -> Box< | |||
|
213 | dyn Iterator< | |||
|
214 | Item = Result< | |||
|
215 | (&HgPath, Option<Timestamp>), | |||
|
216 | DirstateV2ParseError, | |||
|
217 | >, | |||
|
218 | > + Send | |||
|
219 | + '_, | |||
|
220 | > { | |||
|
221 | self.get().iter_directories() | |||
209 | } |
|
222 | } | |
|
223 | } |
@@ -98,7 +98,7 b' fn pack_dirstate_wrapper(' | |||||
98 | p1: p1.try_into().unwrap(), |
|
98 | p1: p1.try_into().unwrap(), | |
99 | p2: p2.try_into().unwrap(), |
|
99 | p2: p2.try_into().unwrap(), | |
100 | }, |
|
100 | }, | |
101 |
Timestamp(now.as_object().extract::< |
|
101 | Timestamp(now.as_object().extract::<i64>(py)?), | |
102 | ) { |
|
102 | ) { | |
103 | Ok(packed) => { |
|
103 | Ok(packed) => { | |
104 | for (filename, entry) in dirstate_map.iter() { |
|
104 | for (filename, entry) in dirstate_map.iter() { |
@@ -282,7 +282,7 b' Show all commands + options' | |||||
282 | debugdata: changelog, manifest, dir |
|
282 | debugdata: changelog, manifest, dir | |
283 | debugdate: extended |
|
283 | debugdate: extended | |
284 | debugdeltachain: changelog, manifest, dir, template |
|
284 | debugdeltachain: changelog, manifest, dir, template | |
285 | debugdirstate: nodates, dates, datesort |
|
285 | debugdirstate: nodates, dates, datesort, dirs | |
286 | debugdiscovery: old, nonheads, rev, seed, local-as-revs, remote-as-revs, ssh, remotecmd, insecure, template |
|
286 | debugdiscovery: old, nonheads, rev, seed, local-as-revs, remote-as-revs, ssh, remotecmd, insecure, template | |
287 | debugdownload: output |
|
287 | debugdownload: output | |
288 | debugextensions: template |
|
288 | debugextensions: template |
@@ -915,3 +915,46 b' Check using include flag while listing i' | |||||
915 | I A.hs |
|
915 | I A.hs | |
916 | I B.hs |
|
916 | I B.hs | |
917 | I ignored-folder/ctest.hs |
|
917 | I ignored-folder/ctest.hs | |
|
918 | ||||
|
919 | #if dirstate-v2 | |||
|
920 | ||||
|
921 | Check read_dir caching | |||
|
922 | ||||
|
923 | $ cd .. | |||
|
924 | $ hg init repo8 | |||
|
925 | $ cd repo8 | |||
|
926 | $ mkdir subdir | |||
|
927 | $ touch subdir/a subdir/b | |||
|
928 | $ hg ci -Aqm '#0' | |||
|
929 | ||||
|
930 | The cached mtime is initially unset | |||
|
931 | ||||
|
932 | $ hg debugdirstate --dirs --no-dates | grep '^d' | |||
|
933 | d 0 0 unset subdir | |||
|
934 | ||||
|
935 | It is still not set when there are unknown files | |||
|
936 | ||||
|
937 | $ touch subdir/unknown | |||
|
938 | $ hg status | |||
|
939 | ? subdir/unknown | |||
|
940 | $ hg debugdirstate --dirs --no-dates | grep '^d' | |||
|
941 | d 0 0 unset subdir | |||
|
942 | ||||
|
943 | Now the directory is eligible for caching, so its mtime is save in the dirstate | |||
|
944 | ||||
|
945 | $ rm subdir/unknown | |||
|
946 | $ hg status | |||
|
947 | $ hg debugdirstate --dirs --no-dates | grep '^d' | |||
|
948 | d 0 0 set subdir | |||
|
949 | ||||
|
950 | This time the command should be ever so slightly faster since it does not need `read_dir("subdir")` | |||
|
951 | ||||
|
952 | $ hg status | |||
|
953 | ||||
|
954 | Creating a new file changes the directory’s mtime, invalidating the cache | |||
|
955 | ||||
|
956 | $ touch subdir/unknown | |||
|
957 | $ hg status | |||
|
958 | ? subdir/unknown | |||
|
959 | ||||
|
960 | #endif |
General Comments 0
You need to be logged in to leave comments.
Login now