##// END OF EJS Templates
rust-status: improve documentation and readability...
Raphaël Gomès -
r45672:470d306e default
parent child Browse files
Show More
@@ -69,7 +69,7 b' pub enum BadMatch {'
69 69 BadType(BadType),
70 70 }
71 71
72 /// Marker enum used to dispatch new status entries into the right collections.
72 /// Enum used to dispatch new status entries into the right collections.
73 73 /// Is similar to `crate::EntryState`, but represents the transient state of
74 74 /// entries during the lifetime of a command.
75 75 #[derive(Debug, Copy, Clone)]
@@ -94,10 +94,18 b' pub enum Dispatch {'
94 94 }
95 95
96 96 type IoResult<T> = std::io::Result<T>;
97
97 98 /// `Box<dyn Trait>` is syntactic sugar for `Box<dyn Trait, 'static>`, so add
98 99 /// an explicit lifetime here to not fight `'static` bounds "out of nowhere".
99 100 type IgnoreFnType<'a> = Box<dyn for<'r> Fn(&'r HgPath) -> bool + Sync + 'a>;
100 101
102 /// We have a good mix of owned (from directory traversal) and borrowed (from
103 /// the dirstate/explicit) paths, this comes up a lot.
104 type HgPathCow<'a> = Cow<'a, HgPath>;
105
106 /// A path with its computed ``Dispatch`` information
107 type DispatchedPath<'a> = (HgPathCow<'a>, Dispatch);
108
101 109 /// Dates and times that are outside the 31-bit signed range are compared
102 110 /// modulo 2^31. This should prevent hg from behaving badly with very large
103 111 /// files or corrupt dates while still having a high probability of detecting
@@ -232,22 +240,25 b' pub struct StatusOptions {'
232 240
233 241 #[derive(Debug)]
234 242 pub struct DirstateStatus<'a> {
235 pub modified: Vec<Cow<'a, HgPath>>,
236 pub added: Vec<Cow<'a, HgPath>>,
237 pub removed: Vec<Cow<'a, HgPath>>,
238 pub deleted: Vec<Cow<'a, HgPath>>,
239 pub clean: Vec<Cow<'a, HgPath>>,
240 pub ignored: Vec<Cow<'a, HgPath>>,
241 pub unknown: Vec<Cow<'a, HgPath>>,
242 pub bad: Vec<(Cow<'a, HgPath>, BadMatch)>,
243 pub modified: Vec<HgPathCow<'a>>,
244 pub added: Vec<HgPathCow<'a>>,
245 pub removed: Vec<HgPathCow<'a>>,
246 pub deleted: Vec<HgPathCow<'a>>,
247 pub clean: Vec<HgPathCow<'a>>,
248 pub ignored: Vec<HgPathCow<'a>>,
249 pub unknown: Vec<HgPathCow<'a>>,
250 pub bad: Vec<(HgPathCow<'a>, BadMatch)>,
243 251 /// Only filled if `collect_traversed_dirs` is `true`
244 252 pub traversed: Vec<HgPathBuf>,
245 253 }
246 254
247 255 #[derive(Debug)]
248 256 pub enum StatusError {
257 /// Generic IO error
249 258 IO(std::io::Error),
259 /// An invalid path that cannot be represented in Mercurial was found
250 260 Path(HgPathError),
261 /// An invalid "ignore" pattern was found
251 262 Pattern(PatternError),
252 263 }
253 264
@@ -279,6 +290,8 b' impl ToString for StatusError {'
279 290 }
280 291 }
281 292
293 /// Gives information about which files are changed in the working directory
294 /// and how, compared to the revision we're based on
282 295 pub struct Status<'a, M: Matcher + Sync> {
283 296 dmap: &'a DirstateMap,
284 297 matcher: &'a M,
@@ -319,6 +332,7 b' where'
319 332 ))
320 333 }
321 334
335 /// Is the path ignored?
322 336 pub fn is_ignored(&self, path: impl AsRef<HgPath>) -> bool {
323 337 (self.ignore_fn)(path.as_ref())
324 338 }
@@ -342,16 +356,15 b' where'
342 356 }
343 357 }
344 358
345 /// Get stat data about the files explicitly specified by match.
359 /// Get stat data about the files explicitly specified by the matcher.
360 /// Returns a tuple of the directories that need to be traversed and the
361 /// files with their corresponding `Dispatch`.
346 362 /// TODO subrepos
347 363 #[timed]
348 364 pub fn walk_explicit(
349 365 &self,
350 366 traversed_sender: crossbeam::Sender<HgPathBuf>,
351 ) -> (
352 Vec<(Cow<'a, HgPath>, Dispatch)>,
353 Vec<(Cow<'a, HgPath>, Dispatch)>,
354 ) {
367 ) -> (Vec<DispatchedPath<'a>>, Vec<DispatchedPath<'a>>) {
355 368 self.matcher
356 369 .file_set()
357 370 .unwrap_or(&DEFAULT_WORK)
@@ -443,8 +456,8 b' where'
443 456 pub fn traverse(
444 457 &self,
445 458 path: impl AsRef<HgPath>,
446 old_results: &FastHashMap<Cow<'a, HgPath>, Dispatch>,
447 results: &mut Vec<(Cow<'a, HgPath>, Dispatch)>,
459 old_results: &FastHashMap<HgPathCow<'a>, Dispatch>,
460 results: &mut Vec<DispatchedPath<'a>>,
448 461 traversed_sender: crossbeam::Sender<HgPathBuf>,
449 462 ) -> IoResult<()> {
450 463 // The traversal is done in parallel, so use a channel to gather
@@ -637,23 +650,25 b' where'
637 650
638 651 let skip_dot_hg = !directory.as_bytes().is_empty();
639 652 let entries = match list_directory(dir_path, skip_dot_hg) {
640 Err(e) => match e.kind() {
641 ErrorKind::NotFound | ErrorKind::PermissionDenied => {
642 files_sender
643 .send(Ok((
644 directory.to_owned(),
645 Dispatch::Bad(BadMatch::OsError(
646 // Unwrapping here is OK because the error
647 // always is a
648 // real os error
649 e.raw_os_error().unwrap(),
650 )),
651 )))
652 .unwrap();
653 return Ok(());
654 }
655 _ => return Err(e),
656 },
653 Err(e) => {
654 return match e.kind() {
655 ErrorKind::NotFound | ErrorKind::PermissionDenied => {
656 files_sender
657 .send(Ok((
658 directory.to_owned(),
659 Dispatch::Bad(BadMatch::OsError(
660 // Unwrapping here is OK because the error
661 // always is a
662 // real os error
663 e.raw_os_error().unwrap(),
664 )),
665 )))
666 .expect("receiver should outlive sender");
667 Ok(())
668 }
669 _ => Err(e),
670 };
671 }
657 672 Ok(entries) => entries,
658 673 };
659 674
@@ -686,12 +701,16 b' where'
686 701 })
687 702 }
688 703
704 /// Checks all files that are in the dirstate but were not found during the
705 /// working directory traversal. This means that the rest must
706 /// be either ignored, under a symlink or under a new nested repo.
707 ///
689 708 /// This takes a mutable reference to the results to account for the
690 709 /// `extend` in timings
691 710 #[timed]
692 711 fn handle_unknowns(
693 712 &self,
694 results: &mut Vec<(Cow<'a, HgPath>, Dispatch)>,
713 results: &mut Vec<DispatchedPath<'a>>,
695 714 ) -> IoResult<()> {
696 715 let to_visit: Vec<(&HgPath, &DirstateEntry)> =
697 716 if results.is_empty() && self.matcher.matches_everything() {
@@ -714,9 +733,6 b' where'
714 733 .collect()
715 734 };
716 735
717 // We walked all dirs under the roots that weren't ignored, and
718 // everything that matched was stat'ed and is already in results.
719 // The rest must thus be ignored or under a symlink.
720 736 let path_auditor = PathAuditor::new(&self.root_dir);
721 737
722 738 // TODO don't collect. Find a way of replicating the behavior of
@@ -766,13 +782,12 b' where'
766 782 Ok(())
767 783 }
768 784
785 /// Add the files in the dirstate to the results.
786 ///
769 787 /// This takes a mutable reference to the results to account for the
770 788 /// `extend` in timings
771 789 #[timed]
772 fn extend_from_dmap(
773 &self,
774 results: &mut Vec<(Cow<'a, HgPath>, Dispatch)>,
775 ) {
790 fn extend_from_dmap(&self, results: &mut Vec<DispatchedPath<'a>>) {
776 791 results.par_extend(self.dmap.par_iter().flat_map(
777 792 move |(filename, entry)| {
778 793 let filename: &HgPath = filename;
@@ -823,9 +838,9 b' where'
823 838
824 839 #[timed]
825 840 fn build_response<'a>(
826 results: impl IntoIterator<Item = (Cow<'a, HgPath>, Dispatch)>,
841 results: impl IntoIterator<Item = DispatchedPath<'a>>,
827 842 traversed: Vec<HgPathBuf>,
828 ) -> (Vec<Cow<'a, HgPath>>, DirstateStatus<'a>) {
843 ) -> (Vec<HgPathCow<'a>>, DirstateStatus<'a>) {
829 844 let mut lookup = vec![];
830 845 let mut modified = vec![];
831 846 let mut added = vec![];
@@ -881,7 +896,7 b" pub fn status<'a>("
881 896 ignore_files: Vec<PathBuf>,
882 897 options: StatusOptions,
883 898 ) -> StatusResult<(
884 (Vec<Cow<'a, HgPath>>, DirstateStatus<'a>),
899 (Vec<HgPathCow<'a>>, DirstateStatus<'a>),
885 900 Vec<PatternFileWarning>,
886 901 )> {
887 902 let (traversed_sender, traversed_receiver) =
@@ -922,16 +937,12 b" pub fn status<'a>("
922 937 }
923 938
924 939 if !matcher.is_exact() {
925 // Step 3: Check the remaining files from the dmap.
926 // If a dmap file is not in results yet, it was either
927 // a) not matched b) ignored, c) missing, or d) under a
928 // symlink directory.
929
930 940 if options.list_unknown {
931 941 st.handle_unknowns(&mut results)?;
932 942 } else {
933 // We may not have walked the full directory tree above, so stat
934 // and check everything we missed.
943 // TODO this is incorrect, see issue6335
944 // This requires a fix in both Python and Rust that can happen
945 // with other pending changes to `status`.
935 946 st.extend_from_dmap(&mut results);
936 947 }
937 948 }
General Comments 0
You need to be logged in to leave comments. Login now