annotate rust/hg-core/src/dirstate_tree/status.rs @ 50864:76387f79befe

rust-status: only visit parts of the tree requested by the matcher This is an optimization that the matcher is designed to support, but we weren't doing it until now. This is primarily relevant for supporting "hg status [FILES]", where this optimization is crucial for getting good performance (without this optimization, that command will still scan the entire tree, and just filter it down after the fact). When this optimization fires we have to return false from traverse_fs_directory_and_dirstate, representing that that part of the tree *might* have new files which we didn't see because we skipped parts of it. This only affects the cached result of the status, and is necessary to make future status operations (which might use a different matcher) work properly.
author Spencer Baugh <sbaugh@janestreet.com>
date Wed, 02 Aug 2023 10:33:11 -0400
parents 264072107105
children 532e74ad3ff6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
48193
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48192
diff changeset
1 use crate::dirstate::entry::TruncatedTimestamp;
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
2 use crate::dirstate::status::IgnoreFnType;
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
3 use crate::dirstate::status::StatusPath;
47347
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
4 use crate::dirstate_tree::dirstate_map::BorrowedPath;
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
5 use crate::dirstate_tree::dirstate_map::ChildNodesRef;
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
6 use crate::dirstate_tree::dirstate_map::DirstateMap;
49337
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
7 use crate::dirstate_tree::dirstate_map::DirstateVersion;
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
8 use crate::dirstate_tree::dirstate_map::NodeRef;
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
9 use crate::dirstate_tree::on_disk::DirstateV2ParseError;
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
10 use crate::matchers::get_ignore_function;
50864
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
11 use crate::matchers::{Matcher, VisitChildrenSet};
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
12 use crate::utils::files::get_bytes_from_os_string;
49558
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
13 use crate::utils::files::get_bytes_from_path;
47338
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
14 use crate::utils::files::get_path_from_bytes;
50863
264072107105 rust-status: error on non-existent files in file_set
Spencer Baugh <sbaugh@janestreet.com>
parents: 50862
diff changeset
15 use crate::utils::hg_path::hg_path_to_path_buf;
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
16 use crate::utils::hg_path::HgPath;
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
17 use crate::BadMatch;
50862
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
18 use crate::BadType;
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
19 use crate::DirstateStatus;
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
20 use crate::HgPathCow;
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
21 use crate::PatternFileWarning;
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
22 use crate::StatusError;
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
23 use crate::StatusOptions;
49520
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
24 use once_cell::sync::OnceCell;
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
25 use rayon::prelude::*;
47409
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
26 use sha1::{Digest, Sha1};
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
27 use std::borrow::Cow;
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
28 use std::io;
50862
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
29 use std::os::unix::prelude::FileTypeExt;
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
30 use std::path::Path;
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
31 use std::path::PathBuf;
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
32 use std::sync::Mutex;
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
33 use std::time::SystemTime;
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
34
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
35 /// Returns the status of the working directory compared to its parent
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
36 /// changeset.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
37 ///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
38 /// This algorithm is based on traversing the filesystem tree (`fs` in function
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
39 /// and variable names) and dirstate tree at the same time. The core of this
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
40 /// traversal is the recursive `traverse_fs_directory_and_dirstate` function
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
41 /// and its use of `itertools::merge_join_by`. When reaching a path that only
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
42 /// exists in one of the two trees, depending on information requested by
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
43 /// `options` we may need to traverse the remaining subtree.
49913
c15b415d1bff rust: use `logging_timer` instead of `micro_timer`
Raphaël Gomès <rgomes@octobus.net>
parents: 49845
diff changeset
44 #[logging_timer::time("trace")]
49000
dd6b67d5c256 rust: fix unsound `OwningDirstateMap`
Raphaël Gomès <rgomes@octobus.net>
parents: 48973
diff changeset
45 pub fn status<'dirstate>(
dd6b67d5c256 rust: fix unsound `OwningDirstateMap`
Raphaël Gomès <rgomes@octobus.net>
parents: 48973
diff changeset
46 dmap: &'dirstate mut DirstateMap,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
47 matcher: &(dyn Matcher + Sync),
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
48 root_dir: PathBuf,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
49 ignore_files: Vec<PathBuf>,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
50 options: StatusOptions,
49000
dd6b67d5c256 rust: fix unsound `OwningDirstateMap`
Raphaël Gomès <rgomes@octobus.net>
parents: 48973
diff changeset
51 ) -> Result<(DirstateStatus<'dirstate>, Vec<PatternFileWarning>), StatusError>
dd6b67d5c256 rust: fix unsound `OwningDirstateMap`
Raphaël Gomès <rgomes@octobus.net>
parents: 48973
diff changeset
52 {
50321
14b57943ae6d rust: fix thread cap (for real this time)
Raphaël Gomès <rgomes@octobus.net>
parents: 50300
diff changeset
53 // Also cap for a Python caller of this function, but don't complain if
14b57943ae6d rust: fix thread cap (for real this time)
Raphaël Gomès <rgomes@octobus.net>
parents: 50300
diff changeset
54 // the global threadpool has already been set since this code path is also
14b57943ae6d rust: fix thread cap (for real this time)
Raphaël Gomès <rgomes@octobus.net>
parents: 50300
diff changeset
55 // being used by `rhg`, which calls this early.
14b57943ae6d rust: fix thread cap (for real this time)
Raphaël Gomès <rgomes@octobus.net>
parents: 50300
diff changeset
56 let _ = crate::utils::cap_default_rayon_threads();
48973
e2f8ed37201c rust-status: cap the number of concurrent threads to 16
Raphaël Gomès <rgomes@octobus.net>
parents: 48794
diff changeset
57
47409
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
58 let (ignore_fn, warnings, patterns_changed): (IgnoreFnType, _, _) =
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
59 if options.list_ignored || options.list_unknown {
49337
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
60 let (ignore_fn, warnings, changed) = match dmap.dirstate_version {
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
61 DirstateVersion::V1 => {
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
62 let (ignore_fn, warnings) = get_ignore_function(
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
63 ignore_files,
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
64 &root_dir,
49558
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
65 &mut |_source, _pattern_bytes| {},
49337
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
66 )?;
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
67 (ignore_fn, warnings, None)
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
68 }
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
69 DirstateVersion::V2 => {
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
70 let mut hasher = Sha1::new();
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
71 let (ignore_fn, warnings) = get_ignore_function(
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
72 ignore_files,
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
73 &root_dir,
49558
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
74 &mut |source, pattern_bytes| {
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
75 // If inside the repo, use the relative version to
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
76 // make it deterministic inside tests.
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
77 // The performance hit should be negligible.
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
78 let source = source
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
79 .strip_prefix(&root_dir)
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
80 .unwrap_or(source);
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
81 let source = get_bytes_from_path(source);
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
82
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
83 let mut subhasher = Sha1::new();
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
84 subhasher.update(pattern_bytes);
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
85 let patterns_hash = subhasher.finalize();
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
86
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
87 hasher.update(source);
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
88 hasher.update(b" ");
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
89 hasher.update(patterns_hash);
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
90 hasher.update(b"\n");
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Raphaël Gomès <rgomes@octobus.net>
parents: 49555
diff changeset
91 },
49337
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
92 )?;
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
93 let new_hash = *hasher.finalize().as_ref();
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
94 let changed = new_hash != dmap.ignore_patterns_hash;
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
95 dmap.ignore_patterns_hash = new_hash;
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
96 (ignore_fn, warnings, Some(changed))
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
97 }
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
98 };
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
99 (ignore_fn, warnings, changed)
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
100 } else {
47409
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
101 (Box::new(|&_| true), vec![], None)
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
102 };
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
103
48501
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
104 let filesystem_time_at_status_start =
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
105 filesystem_now(&root_dir).ok().map(TruncatedTimestamp::from);
48745
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
106
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
107 // If the repository is under the current directory, prefer using a
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
108 // relative path, so the kernel needs to traverse fewer directory in every
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
109 // call to `read_dir` or `symlink_metadata`.
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
110 // This is effective in the common case where the current directory is the
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
111 // repository root.
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
112
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
113 // TODO: Better yet would be to use libc functions like `openat` and
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
114 // `fstatat` to remove such repeated traversals entirely, but the standard
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
115 // library does not provide APIs based on those.
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
116 // Maybe with a crate like https://crates.io/crates/openat instead?
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
117 let root_dir = if let Some(relative) = std::env::current_dir()
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
118 .ok()
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
119 .and_then(|cwd| root_dir.strip_prefix(cwd).ok())
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
120 {
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
121 relative
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
122 } else {
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
123 &root_dir
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
124 };
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
125
48422
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
126 let outcome = DirstateStatus {
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
127 filesystem_time_at_status_start,
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
128 ..Default::default()
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
129 };
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
130 let common = StatusCommon {
47336
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47335
diff changeset
131 dmap,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
132 options,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
133 matcher,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
134 ignore_fn,
48422
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
135 outcome: Mutex::new(outcome),
47409
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
136 ignore_patterns_have_changed: patterns_changed,
49554
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
137 new_cacheable_directories: Default::default(),
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
138 outdated_cached_directories: Default::default(),
48422
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
139 filesystem_time_at_status_start,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
140 };
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
141 let is_at_repo_root = true;
47347
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
142 let hg_path = &BorrowedPath::OnDisk(HgPath::new(""));
49520
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
143 let has_ignored_ancestor = HasIgnoredAncestor::create(None, hg_path);
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
144 let root_cached_mtime = None;
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
145 // If the path we have for the repository root is a symlink, do follow it.
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
146 // (As opposed to symlinks within the working directory which are not
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
147 // followed, using `std::fs::symlink_metadata`.)
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
148 common.traverse_fs_directory_and_dirstate(
49520
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
149 &has_ignored_ancestor,
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
150 dmap.root.as_ref(),
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
151 hg_path,
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
152 &DirEntry {
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
153 hg_path: Cow::Borrowed(HgPath::new(b"")),
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
154 fs_path: Cow::Borrowed(root_dir),
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
155 symlink_metadata: None,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
156 file_type: FakeFileType::Directory,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
157 },
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
158 root_cached_mtime,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
159 is_at_repo_root,
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
160 )?;
50863
264072107105 rust-status: error on non-existent files in file_set
Spencer Baugh <sbaugh@janestreet.com>
parents: 50862
diff changeset
161 if let Some(file_set) = common.matcher.file_set() {
264072107105 rust-status: error on non-existent files in file_set
Spencer Baugh <sbaugh@janestreet.com>
parents: 50862
diff changeset
162 for file in file_set {
264072107105 rust-status: error on non-existent files in file_set
Spencer Baugh <sbaugh@janestreet.com>
parents: 50862
diff changeset
163 if !file.is_empty() && !dmap.has_node(file)? {
264072107105 rust-status: error on non-existent files in file_set
Spencer Baugh <sbaugh@janestreet.com>
parents: 50862
diff changeset
164 let path = hg_path_to_path_buf(file)?;
264072107105 rust-status: error on non-existent files in file_set
Spencer Baugh <sbaugh@janestreet.com>
parents: 50862
diff changeset
165 if let io::Result::Err(error) =
264072107105 rust-status: error on non-existent files in file_set
Spencer Baugh <sbaugh@janestreet.com>
parents: 50862
diff changeset
166 root_dir.join(path).symlink_metadata()
264072107105 rust-status: error on non-existent files in file_set
Spencer Baugh <sbaugh@janestreet.com>
parents: 50862
diff changeset
167 {
264072107105 rust-status: error on non-existent files in file_set
Spencer Baugh <sbaugh@janestreet.com>
parents: 50862
diff changeset
168 common.io_error(error, file)
264072107105 rust-status: error on non-existent files in file_set
Spencer Baugh <sbaugh@janestreet.com>
parents: 50862
diff changeset
169 }
264072107105 rust-status: error on non-existent files in file_set
Spencer Baugh <sbaugh@janestreet.com>
parents: 50862
diff changeset
170 }
264072107105 rust-status: error on non-existent files in file_set
Spencer Baugh <sbaugh@janestreet.com>
parents: 50862
diff changeset
171 }
264072107105 rust-status: error on non-existent files in file_set
Spencer Baugh <sbaugh@janestreet.com>
parents: 50862
diff changeset
172 }
47350
04d1f17f49e7 dirstate-v2: Write .hg/dirstate back to disk on directory cache changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47349
diff changeset
173 let mut outcome = common.outcome.into_inner().unwrap();
49554
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
174 let new_cacheable = common.new_cacheable_directories.into_inner().unwrap();
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
175 let outdated = common.outdated_cached_directories.into_inner().unwrap();
47409
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
176
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
177 outcome.dirty = common.ignore_patterns_have_changed == Some(true)
47474
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
178 || !outdated.is_empty()
49554
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
179 || (!new_cacheable.is_empty()
49337
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
180 && dmap.dirstate_version == DirstateVersion::V2);
47409
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
181
47474
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
182 // Remove outdated mtimes before adding new mtimes, in case a given
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
183 // directory is both
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
184 for path in &outdated {
49127
f3e8b0b0a8c2 rust-dirstatemap: add `clear_cached_mtime` helper method
Raphaël Gomès <rgomes@octobus.net>
parents: 49000
diff changeset
185 dmap.clear_cached_mtime(path)?;
47474
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
186 }
49554
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
187 for (path, mtime) in &new_cacheable {
49128
464747faef14 rust-dirstatemap: add `set_cached_mtime` helper method
Raphaël Gomès <rgomes@octobus.net>
parents: 49127
diff changeset
188 dmap.set_cached_mtime(path, *mtime)?;
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
189 }
47409
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
190
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
191 Ok((outcome, warnings))
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
192 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
193
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
194 /// Bag of random things needed by various parts of the algorithm. Reduces the
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
195 /// number of parameters passed to functions.
47347
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
196 struct StatusCommon<'a, 'tree, 'on_disk: 'tree> {
47336
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47335
diff changeset
197 dmap: &'tree DirstateMap<'on_disk>,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
198 options: StatusOptions,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
199 matcher: &'a (dyn Matcher + Sync),
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
200 ignore_fn: IgnoreFnType<'a>,
47347
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
201 outcome: Mutex<DirstateStatus<'on_disk>>,
49554
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
202 /// New timestamps of directories to be used for caching their readdirs
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
203 new_cacheable_directories:
48193
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48192
diff changeset
204 Mutex<Vec<(Cow<'on_disk, HgPath>, TruncatedTimestamp)>>,
49554
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
205 /// Used to invalidate the readdir cache of directories
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
206 outdated_cached_directories: Mutex<Vec<Cow<'on_disk, HgPath>>>,
47409
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
207
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
208 /// Whether ignore files like `.hgignore` have changed since the previous
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
209 /// time a `status()` call wrote their hash to the dirstate. `None` means
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
210 /// we don’t know as this run doesn’t list either ignored or uknown files
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
211 /// and therefore isn’t reading `.hgignore`.
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47350
diff changeset
212 ignore_patterns_have_changed: Option<bool>,
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
213
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
214 /// The current time at the start of the `status()` algorithm, as measured
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
215 /// and possibly truncated by the filesystem.
48501
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
216 filesystem_time_at_status_start: Option<TruncatedTimestamp>,
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
217 }
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
218
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
219 enum Outcome {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
220 Modified,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
221 Added,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
222 Removed,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
223 Deleted,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
224 Clean,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
225 Ignored,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
226 Unknown,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
227 Unsure,
47112
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
228 }
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
229
49520
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
230 /// Lazy computation of whether a given path has a hgignored
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
231 /// ancestor.
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
232 struct HasIgnoredAncestor<'a> {
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
233 /// `path` and `parent` constitute the inputs to the computation,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
234 /// `cache` stores the outcome.
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
235 path: &'a HgPath,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
236 parent: Option<&'a HasIgnoredAncestor<'a>>,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
237 cache: OnceCell<bool>,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
238 }
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
239
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
240 impl<'a> HasIgnoredAncestor<'a> {
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
241 fn create(
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
242 parent: Option<&'a HasIgnoredAncestor<'a>>,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
243 path: &'a HgPath,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
244 ) -> HasIgnoredAncestor<'a> {
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
245 Self {
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
246 path,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
247 parent,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
248 cache: OnceCell::new(),
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
249 }
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
250 }
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
251
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
252 fn force<'b>(&self, ignore_fn: &IgnoreFnType<'b>) -> bool {
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
253 match self.parent {
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
254 None => false,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
255 Some(parent) => {
50300
edcc35a4f1dc dirstate: fix the bug in [status] dealing with committed&ignored directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50294
diff changeset
256 *(self.cache.get_or_init(|| {
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
257 parent.force(ignore_fn) || ignore_fn(self.path)
49520
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
258 }))
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
259 }
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
260 }
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
261 }
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
262 }
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
263
47347
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
264 impl<'a, 'tree, 'on_disk> StatusCommon<'a, 'tree, 'on_disk> {
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
265 fn push_outcome(
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
266 &self,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
267 which: Outcome,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
268 dirstate_node: &NodeRef<'tree, 'on_disk>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
269 ) -> Result<(), DirstateV2ParseError> {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
270 let path = dirstate_node
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
271 .full_path_borrowed(self.dmap.on_disk)?
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
272 .detach_from_tree();
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
273 let copy_source = if self.options.list_copies {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
274 dirstate_node
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
275 .copy_source_borrowed(self.dmap.on_disk)?
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
276 .map(|source| source.detach_from_tree())
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
277 } else {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
278 None
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
279 };
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
280 self.push_outcome_common(which, path, copy_source);
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
281 Ok(())
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
282 }
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
283
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
284 fn push_outcome_without_copy_source(
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
285 &self,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
286 which: Outcome,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
287 path: &BorrowedPath<'_, 'on_disk>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
288 ) {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
289 self.push_outcome_common(which, path.detach_from_tree(), None)
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
290 }
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
291
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
292 fn push_outcome_common(
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
293 &self,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
294 which: Outcome,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
295 path: HgPathCow<'on_disk>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
296 copy_source: Option<HgPathCow<'on_disk>>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
297 ) {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
298 let mut outcome = self.outcome.lock().unwrap();
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
299 let vec = match which {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
300 Outcome::Modified => &mut outcome.modified,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
301 Outcome::Added => &mut outcome.added,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
302 Outcome::Removed => &mut outcome.removed,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
303 Outcome::Deleted => &mut outcome.deleted,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
304 Outcome::Clean => &mut outcome.clean,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
305 Outcome::Ignored => &mut outcome.ignored,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
306 Outcome::Unknown => &mut outcome.unknown,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
307 Outcome::Unsure => &mut outcome.unsure,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
308 };
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
309 vec.push(StatusPath { path, copy_source });
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
310 }
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
311
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
312 fn read_dir(
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
313 &self,
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
314 hg_path: &HgPath,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
315 fs_path: &Path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
316 is_at_repo_root: bool,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
317 ) -> Result<Vec<DirEntry>, ()> {
47338
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
318 DirEntry::read_dir(fs_path, is_at_repo_root)
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
319 .map_err(|error| self.io_error(error, hg_path))
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
320 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
321
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
322 fn io_error(&self, error: std::io::Error, hg_path: &HgPath) {
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
323 let errno = error.raw_os_error().expect("expected real OS error");
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
324 self.outcome
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
325 .lock()
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
326 .unwrap()
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
327 .bad
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
328 .push((hg_path.to_owned().into(), BadMatch::OsError(errno)))
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
329 }
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
330
47474
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
331 fn check_for_outdated_directory_cache(
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
332 &self,
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
333 dirstate_node: &NodeRef<'tree, 'on_disk>,
49555
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
334 ) -> Result<bool, DirstateV2ParseError> {
47474
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
335 if self.ignore_patterns_have_changed == Some(true)
48193
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48192
diff changeset
336 && dirstate_node.cached_directory_mtime()?.is_some()
47474
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
337 {
49554
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
338 self.outdated_cached_directories.lock().unwrap().push(
47474
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
339 dirstate_node
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
340 .full_path_borrowed(self.dmap.on_disk)?
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
341 .detach_from_tree(),
49555
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
342 );
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
343 return Ok(true);
47474
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
344 }
49555
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
345 Ok(false)
47474
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
346 }
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
347
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
348 /// If this returns true, we can get accurate results by only using
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
349 /// `symlink_metadata` for child nodes that exist in the dirstate and don’t
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
350 /// need to call `read_dir`.
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
351 fn can_skip_fs_readdir(
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
352 &self,
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
353 directory_entry: &DirEntry,
48193
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48192
diff changeset
354 cached_directory_mtime: Option<TruncatedTimestamp>,
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
355 ) -> bool {
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
356 if !self.options.list_unknown && !self.options.list_ignored {
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
357 // All states that we care about listing have corresponding
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
358 // dirstate entries.
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
359 // This happens for example with `hg status -mard`.
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
360 return true;
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
361 }
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
362 if !self.options.list_ignored
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
363 && self.ignore_patterns_have_changed == Some(false)
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
364 {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
365 if let Some(cached_mtime) = cached_directory_mtime {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
366 // The dirstate contains a cached mtime for this directory, set
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
367 // by a previous run of the `status` algorithm which found this
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
368 // directory eligible for `read_dir` caching.
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
369 if let Ok(meta) = directory_entry.symlink_metadata() {
48218
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48193
diff changeset
370 if cached_mtime
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
371 .likely_equal_to_mtime_of(&meta)
48218
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48193
diff changeset
372 .unwrap_or(false)
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48193
diff changeset
373 {
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48193
diff changeset
374 // The mtime of that directory has not changed
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48193
diff changeset
375 // since then, which means that the results of
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48193
diff changeset
376 // `read_dir` should also be unchanged.
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48193
diff changeset
377 return true;
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
378 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
379 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
380 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
381 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
382 false
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
383 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
384
50864
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
385 fn should_visit(set: &VisitChildrenSet, basename: &HgPath) -> bool {
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
386 match set {
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
387 VisitChildrenSet::This | VisitChildrenSet::Recursive => true,
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
388 VisitChildrenSet::Empty => false,
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
389 VisitChildrenSet::Set(children_to_visit) => {
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
390 children_to_visit.contains(basename)
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
391 }
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
392 }
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
393 }
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
394
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
395 /// Returns whether all child entries of the filesystem directory have a
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
396 /// corresponding dirstate node or are ignored.
49520
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
397 fn traverse_fs_directory_and_dirstate<'ancestor>(
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
398 &self,
49520
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
399 has_ignored_ancestor: &'ancestor HasIgnoredAncestor<'ancestor>,
47347
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
400 dirstate_nodes: ChildNodesRef<'tree, 'on_disk>,
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
401 directory_hg_path: &BorrowedPath<'tree, 'on_disk>,
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
402 directory_entry: &DirEntry,
48193
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48192
diff changeset
403 cached_directory_mtime: Option<TruncatedTimestamp>,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
404 is_at_repo_root: bool,
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
405 ) -> Result<bool, DirstateV2ParseError> {
50864
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
406 let children_set = self.matcher.visit_children_set(directory_hg_path);
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
407 if let VisitChildrenSet::Empty = children_set {
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
408 return Ok(false);
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
409 }
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
410 if self.can_skip_fs_readdir(directory_entry, cached_directory_mtime) {
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
411 dirstate_nodes
47338
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
412 .par_iter()
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
413 .map(|dirstate_node| {
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
414 let fs_path = &directory_entry.fs_path;
50864
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
415 let basename =
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
416 dirstate_node.base_name(self.dmap.on_disk)?.as_bytes();
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
417 let fs_path = fs_path.join(get_path_from_bytes(basename));
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
418 if !Self::should_visit(
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
419 &children_set,
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
420 HgPath::new(basename),
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
421 ) {
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
422 return Ok(());
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
423 }
47338
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
424 match std::fs::symlink_metadata(&fs_path) {
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
425 Ok(fs_metadata) => {
50862
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
426 let file_type = fs_metadata.file_type().into();
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
427 let entry = DirEntry {
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
428 hg_path: Cow::Borrowed(
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
429 dirstate_node
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
430 .full_path(self.dmap.on_disk)?,
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
431 ),
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
432 fs_path: Cow::Borrowed(&fs_path),
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
433 symlink_metadata: Some(fs_metadata),
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
434 file_type,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
435 };
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
436 self.traverse_fs_and_dirstate(
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
437 &entry,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
438 dirstate_node,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
439 has_ignored_ancestor,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
440 )
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
441 }
47338
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
442 Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
443 self.traverse_dirstate_only(dirstate_node)
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
444 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
445 Err(error) => {
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
446 let hg_path =
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
447 dirstate_node.full_path(self.dmap.on_disk)?;
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
448 self.io_error(error, hg_path);
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
449 Ok(())
47338
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
450 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
451 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
452 })
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
453 .collect::<Result<_, _>>()?;
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
454
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
455 // We don’t know, so conservatively say this isn’t the case
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
456 let children_all_have_dirstate_node_or_are_ignored = false;
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
457
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
458 return Ok(children_all_have_dirstate_node_or_are_ignored);
47338
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
459 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
460
50294
bae51b50a5cf dirstate-v2: fix an incorrect handling of readdir errors
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49930
diff changeset
461 let readdir_succeeded;
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
462 let mut fs_entries = if let Ok(entries) = self.read_dir(
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
463 directory_hg_path,
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
464 &directory_entry.fs_path,
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
465 is_at_repo_root,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
466 ) {
50294
bae51b50a5cf dirstate-v2: fix an incorrect handling of readdir errors
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49930
diff changeset
467 readdir_succeeded = true;
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
468 entries
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
469 } else {
47346
5e12b6bfdd3e dirstate-tree: Fix status algorithm with unreadable directory
Simon Sapin <simon.sapin@octobus.net>
parents: 47338
diff changeset
470 // Treat an unreadable directory (typically because of insufficient
5e12b6bfdd3e dirstate-tree: Fix status algorithm with unreadable directory
Simon Sapin <simon.sapin@octobus.net>
parents: 47338
diff changeset
471 // permissions) like an empty directory. `self.read_dir` has
5e12b6bfdd3e dirstate-tree: Fix status algorithm with unreadable directory
Simon Sapin <simon.sapin@octobus.net>
parents: 47338
diff changeset
472 // already called `self.io_error` so a warning will be emitted.
50294
bae51b50a5cf dirstate-v2: fix an incorrect handling of readdir errors
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49930
diff changeset
473 // We still need to remember that there was an error so that we
bae51b50a5cf dirstate-v2: fix an incorrect handling of readdir errors
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49930
diff changeset
474 // know not to cache this result.
bae51b50a5cf dirstate-v2: fix an incorrect handling of readdir errors
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49930
diff changeset
475 readdir_succeeded = false;
47346
5e12b6bfdd3e dirstate-tree: Fix status algorithm with unreadable directory
Simon Sapin <simon.sapin@octobus.net>
parents: 47338
diff changeset
476 Vec::new()
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
477 };
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
478
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
479 // `merge_join_by` requires both its input iterators to be sorted:
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
480
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
481 let dirstate_nodes = dirstate_nodes.sorted();
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
482 // `sort_unstable_by_key` doesn’t allow keys borrowing from the value:
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
483 // https://github.com/rust-lang/rust/issues/34162
49567
6b32d39e9a67 rust-status: make `DirEntry` attributes clearer
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
484 fs_entries.sort_unstable_by(|e1, e2| e1.hg_path.cmp(&e2.hg_path));
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
485
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
486 // Propagate here any error that would happen inside the comparison
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
487 // callback below
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
488 for dirstate_node in &dirstate_nodes {
47336
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47335
diff changeset
489 dirstate_node.base_name(self.dmap.on_disk)?;
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
490 }
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
491 itertools::merge_join_by(
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
492 dirstate_nodes,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
493 &fs_entries,
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
494 |dirstate_node, fs_entry| {
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
495 // This `unwrap` never panics because we already propagated
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
496 // those errors above
47336
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47335
diff changeset
497 dirstate_node
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47335
diff changeset
498 .base_name(self.dmap.on_disk)
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47335
diff changeset
499 .unwrap()
49567
6b32d39e9a67 rust-status: make `DirEntry` attributes clearer
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
500 .cmp(&fs_entry.hg_path)
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
501 },
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
502 )
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
503 .par_bridge()
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
504 .map(|pair| {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
505 use itertools::EitherOrBoth::*;
50864
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
506 let basename = match &pair {
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
507 Left(dirstate_node) | Both(dirstate_node, _) => HgPath::new(
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
508 dirstate_node.base_name(self.dmap.on_disk)?.as_bytes(),
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
509 ),
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
510 Right(fs_entry) => &fs_entry.hg_path,
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
511 };
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
512 if !Self::should_visit(&children_set, basename) {
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
513 return Ok(false);
76387f79befe rust-status: only visit parts of the tree requested by the matcher
Spencer Baugh <sbaugh@janestreet.com>
parents: 50863
diff changeset
514 }
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
515 let has_dirstate_node_or_is_ignored = match pair {
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
516 Both(dirstate_node, fs_entry) => {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
517 self.traverse_fs_and_dirstate(
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
518 fs_entry,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
519 dirstate_node,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
520 has_ignored_ancestor,
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
521 )?;
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
522 true
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
523 }
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
524 Left(dirstate_node) => {
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
525 self.traverse_dirstate_only(dirstate_node)?;
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
526 true
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
527 }
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
528 Right(fs_entry) => self.traverse_fs_only(
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
529 has_ignored_ancestor.force(&self.ignore_fn),
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
530 directory_hg_path,
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
531 fs_entry,
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
532 ),
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
533 };
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
534 Ok(has_dirstate_node_or_is_ignored)
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
535 })
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
536 .try_reduce(|| true, |a, b| Ok(a && b))
50294
bae51b50a5cf dirstate-v2: fix an incorrect handling of readdir errors
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49930
diff changeset
537 .map(|res| res && readdir_succeeded)
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
538 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
539
49520
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
540 fn traverse_fs_and_dirstate<'ancestor>(
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
541 &self,
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
542 fs_entry: &DirEntry,
47347
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
543 dirstate_node: NodeRef<'tree, 'on_disk>,
49520
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
544 has_ignored_ancestor: &'ancestor HasIgnoredAncestor<'ancestor>,
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
545 ) -> Result<(), DirstateV2ParseError> {
49555
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
546 let outdated_dircache =
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
547 self.check_for_outdated_directory_cache(&dirstate_node)?;
47347
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
548 let hg_path = &dirstate_node.full_path_borrowed(self.dmap.on_disk)?;
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
549 let file_or_symlink = fs_entry.is_file() || fs_entry.is_symlink();
47114
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
550 if !file_or_symlink {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
551 // If we previously had a file here, it was removed (with
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
552 // `hg rm` or similar) or deleted before it could be
47114
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
553 // replaced by a directory or something else.
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
554 self.mark_removed_or_deleted_if_file(&dirstate_node)?;
47114
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
555 }
50862
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
556 if let Some(bad_type) = fs_entry.is_bad() {
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
557 if self.matcher.exact_match(hg_path) {
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
558 let path = dirstate_node.full_path(self.dmap.on_disk)?;
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
559 self.outcome.lock().unwrap().bad.push((
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
560 path.to_owned().into(),
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
561 BadMatch::BadType(bad_type),
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
562 ))
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
563 }
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
564 }
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
565 if fs_entry.is_dir() {
47114
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
566 if self.options.collect_traversed_dirs {
47347
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
567 self.outcome
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
568 .lock()
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
569 .unwrap()
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
570 .traversed
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
571 .push(hg_path.detach_from_tree())
47114
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47113
diff changeset
572 }
49520
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
573 let is_ignored = HasIgnoredAncestor::create(
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
574 Some(has_ignored_ancestor),
49520
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
575 hg_path,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
576 );
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
577 let is_at_repo_root = false;
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
578 let children_all_have_dirstate_node_or_are_ignored = self
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
579 .traverse_fs_directory_and_dirstate(
49520
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
580 &is_ignored,
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
581 dirstate_node.children(self.dmap.on_disk)?,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
582 hg_path,
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
583 fs_entry,
48193
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48192
diff changeset
584 dirstate_node.cached_directory_mtime()?,
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
585 is_at_repo_root,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
586 )?;
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
587 self.maybe_save_directory_mtime(
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
588 children_all_have_dirstate_node_or_are_ignored,
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
589 fs_entry,
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
590 dirstate_node,
49555
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
591 outdated_dircache,
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
592 )?
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
593 } else {
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
594 if file_or_symlink && self.matcher.matches(hg_path) {
49142
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
595 if let Some(entry) = dirstate_node.entry()? {
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
596 if !entry.any_tracked() {
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
597 // Forward-compat if we start tracking unknown/ignored
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
598 // files for caching reasons
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
599 self.mark_unknown_or_ignored(
49520
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
600 has_ignored_ancestor.force(&self.ignore_fn),
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
601 hg_path,
49142
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
602 );
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
603 }
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
604 if entry.added() {
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
605 self.push_outcome(Outcome::Added, &dirstate_node)?;
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
606 } else if entry.removed() {
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
607 self.push_outcome(Outcome::Removed, &dirstate_node)?;
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
608 } else if entry.modified() {
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
609 self.push_outcome(Outcome::Modified, &dirstate_node)?;
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
610 } else {
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
611 self.handle_normal_file(&dirstate_node, fs_entry)?;
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
612 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
613 } else {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
614 // `node.entry.is_none()` indicates a "directory"
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
615 // node, but the filesystem has a file
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
616 self.mark_unknown_or_ignored(
49520
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49423
diff changeset
617 has_ignored_ancestor.force(&self.ignore_fn),
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
618 hg_path,
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
619 );
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
620 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
621 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
622
47336
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47335
diff changeset
623 for child_node in dirstate_node.children(self.dmap.on_disk)?.iter()
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47335
diff changeset
624 {
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
625 self.traverse_dirstate_only(child_node)?
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
626 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
627 }
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
628 Ok(())
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
629 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
630
49555
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
631 /// Save directory mtime if applicable.
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
632 ///
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
633 /// `outdated_directory_cache` is `true` if we've just invalidated the
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
634 /// cache for this directory in `check_for_outdated_directory_cache`,
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
635 /// which forces the update.
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
636 fn maybe_save_directory_mtime(
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
637 &self,
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
638 children_all_have_dirstate_node_or_are_ignored: bool,
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
639 directory_entry: &DirEntry,
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
640 dirstate_node: NodeRef<'tree, 'on_disk>,
49555
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
641 outdated_directory_cache: bool,
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
642 ) -> Result<(), DirstateV2ParseError> {
48501
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
643 if !children_all_have_dirstate_node_or_are_ignored {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
644 return Ok(());
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
645 }
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
646 // All filesystem directory entries from `read_dir` have a
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
647 // corresponding node in the dirstate, so we can reconstitute the
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
648 // names of those entries without calling `read_dir` again.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
649
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
650 // TODO: use let-else here and below when available:
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
651 // https://github.com/rust-lang/rust/issues/87335
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
652 let status_start = if let Some(status_start) =
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
653 &self.filesystem_time_at_status_start
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
654 {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
655 status_start
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
656 } else {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
657 return Ok(());
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
658 };
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
659
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
660 // Although the Rust standard library’s `SystemTime` type
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
661 // has nanosecond precision, the times reported for a
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
662 // directory’s (or file’s) modified time may have lower
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
663 // resolution based on the filesystem (for example ext3
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
664 // only stores integer seconds), kernel (see
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
665 // https://stackoverflow.com/a/14393315/1162888), etc.
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
666 let metadata = match directory_entry.symlink_metadata() {
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
667 Ok(meta) => meta,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
668 Err(_) => return Ok(()),
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
669 };
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
670
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
671 let directory_mtime = match TruncatedTimestamp::for_reliable_mtime_of(
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
672 &metadata,
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
673 status_start,
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
674 ) {
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
675 Ok(Some(directory_mtime)) => directory_mtime,
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
676 Ok(None) => {
48501
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
677 // The directory was modified too recently,
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
678 // don’t cache its `read_dir` results.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
679 //
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
680 // 1. A change to this directory (direct child was
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
681 // added or removed) cause its mtime to be set
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
682 // (possibly truncated) to `directory_mtime`
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
683 // 2. This `status` algorithm calls `read_dir`
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
684 // 3. An other change is made to the same directory is
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
685 // made so that calling `read_dir` agin would give
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
686 // different results, but soon enough after 1. that
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
687 // the mtime stays the same
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
688 //
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
689 // On a system where the time resolution poor, this
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
690 // scenario is not unlikely if all three steps are caused
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
691 // by the same script.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
692 return Ok(());
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
693 }
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
694 Err(_) => {
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
695 // OS/libc does not support mtime?
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
696 return Ok(());
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
697 }
48501
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
698 };
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
699 // We’ve observed (through `status_start`) that time has
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
700 // “progressed” since `directory_mtime`, so any further
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
701 // change to this directory is extremely likely to cause a
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
702 // different mtime.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
703 //
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
704 // Having the same mtime again is not entirely impossible
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
705 // since the system clock is not monotonous. It could jump
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
706 // backward to some point before `directory_mtime`, then a
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
707 // directory change could potentially happen during exactly
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
708 // the wrong tick.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
709 //
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
710 // We deem this scenario (unlike the previous one) to be
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
711 // unlikely enough in practice.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
712
49555
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
713 let is_up_to_date = if let Some(cached) =
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
714 dirstate_node.cached_directory_mtime()?
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
715 {
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
716 !outdated_directory_cache && cached.likely_equal(directory_mtime)
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
717 } else {
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
718 false
8ee3889bab92 rust-status: save new dircache even if just invalidated
Raphaël Gomès <rgomes@octobus.net>
parents: 49554
diff changeset
719 };
48501
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
720 if !is_up_to_date {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
721 let hg_path = dirstate_node
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
722 .full_path_borrowed(self.dmap.on_disk)?
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
723 .detach_from_tree();
49554
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
724 self.new_cacheable_directories
48501
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
725 .lock()
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
726 .unwrap()
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48454
diff changeset
727 .push((hg_path, directory_mtime))
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
728 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
729 Ok(())
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
730 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
731
49142
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Raphaël Gomès <rgomes@octobus.net>
parents: 49141
diff changeset
732 /// A file that is clean in the dirstate was found in the filesystem
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
733 fn handle_normal_file(
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
734 &self,
47347
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
735 dirstate_node: &NodeRef<'tree, 'on_disk>,
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
736 fs_entry: &DirEntry,
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
737 ) -> Result<(), DirstateV2ParseError> {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
738 // Keep the low 31 bits
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
739 fn truncate_u64(value: u64) -> i32 {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
740 (value & 0x7FFF_FFFF) as i32
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
741 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
742
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
743 let fs_metadata = match fs_entry.symlink_metadata() {
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
744 Ok(meta) => meta,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
745 Err(_) => return Ok(()),
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
746 };
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
747
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
748 let entry = dirstate_node
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
749 .entry()?
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
750 .expect("handle_normal_file called with entry-less node");
47338
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47336
diff changeset
751 let mode_changed =
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
752 || self.options.check_exec && entry.mode_changed(&fs_metadata);
48022
f2a9db29cb2d rust: Make the fields of DirstateEntry private
Simon Sapin <simon.sapin@octobus.net>
parents: 47475
diff changeset
753 let size = entry.size();
f2a9db29cb2d rust: Make the fields of DirstateEntry private
Simon Sapin <simon.sapin@octobus.net>
parents: 47475
diff changeset
754 let size_changed = size != truncate_u64(fs_metadata.len());
f2a9db29cb2d rust: Make the fields of DirstateEntry private
Simon Sapin <simon.sapin@octobus.net>
parents: 47475
diff changeset
755 if size >= 0 && size_changed && fs_metadata.file_type().is_symlink() {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
756 // issue6456: Size returned may be longer due to encryption
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
757 // on EXT-4 fscrypt. TODO maybe only do it on EXT4?
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
758 self.push_outcome(Outcome::Unsure, dirstate_node)?
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
759 } else if dirstate_node.has_copy_source()
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
760 || entry.is_from_other_parent()
48022
f2a9db29cb2d rust: Make the fields of DirstateEntry private
Simon Sapin <simon.sapin@octobus.net>
parents: 47475
diff changeset
761 || (size >= 0 && (size_changed || mode_changed()))
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
762 {
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
763 self.push_outcome(Outcome::Modified, dirstate_node)?
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
764 } else {
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
765 let mtime_looks_clean = if let Some(dirstate_mtime) =
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
766 entry.truncated_mtime()
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
767 {
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
768 let fs_mtime = TruncatedTimestamp::for_mtime_of(&fs_metadata)
48263
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
769 .expect("OS/libc does not support mtime?");
48391
b80e5e75d51e dirstate: remove `lastnormaltime` mechanism
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
770 // There might be a change in the future if for example the
b80e5e75d51e dirstate: remove `lastnormaltime` mechanism
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
771 // internal clock become off while process run, but this is a
b80e5e75d51e dirstate: remove `lastnormaltime` mechanism
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
772 // case where the issues the user would face
b80e5e75d51e dirstate: remove `lastnormaltime` mechanism
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
773 // would be a lot worse and there is nothing we
b80e5e75d51e dirstate: remove `lastnormaltime` mechanism
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
774 // can really do.
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
775 fs_mtime.likely_equal(dirstate_mtime)
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48257
diff changeset
776 } else {
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48257
diff changeset
777 // No mtime in the dirstate entry
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
778 false
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48257
diff changeset
779 };
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48257
diff changeset
780 if !mtime_looks_clean {
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
781 self.push_outcome(Outcome::Unsure, dirstate_node)?
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
782 } else if self.options.list_clean {
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
783 self.push_outcome(Outcome::Clean, dirstate_node)?
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
784 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
785 }
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
786 Ok(())
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
787 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
788
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
789 /// A node in the dirstate tree has no corresponding filesystem entry
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
790 fn traverse_dirstate_only(
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
791 &self,
47347
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
792 dirstate_node: NodeRef<'tree, 'on_disk>,
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
793 ) -> Result<(), DirstateV2ParseError> {
47474
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47409
diff changeset
794 self.check_for_outdated_directory_cache(&dirstate_node)?;
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
795 self.mark_removed_or_deleted_if_file(&dirstate_node)?;
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
796 dirstate_node
47336
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47335
diff changeset
797 .children(self.dmap.on_disk)?
47333
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47331
diff changeset
798 .par_iter()
47335
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
799 .map(|child_node| self.traverse_dirstate_only(child_node))
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47333
diff changeset
800 .collect()
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
801 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
802
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
803 /// A node in the dirstate tree has no corresponding *file* on the
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
804 /// filesystem
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
805 ///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
806 /// Does nothing on a "directory" node
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
807 fn mark_removed_or_deleted_if_file(
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
808 &self,
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
809 dirstate_node: &NodeRef<'tree, 'on_disk>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
810 ) -> Result<(), DirstateV2ParseError> {
49141
126d253eb274 rust-status: stop using `state()` in `handle_normal_file`
Raphaël Gomès <rgomes@octobus.net>
parents: 49128
diff changeset
811 if let Some(entry) = dirstate_node.entry()? {
126d253eb274 rust-status: stop using `state()` in `handle_normal_file`
Raphaël Gomès <rgomes@octobus.net>
parents: 49128
diff changeset
812 if !entry.any_tracked() {
126d253eb274 rust-status: stop using `state()` in `handle_normal_file`
Raphaël Gomès <rgomes@octobus.net>
parents: 49128
diff changeset
813 // Future-compat for when we start storing ignored and unknown
126d253eb274 rust-status: stop using `state()` in `handle_normal_file`
Raphaël Gomès <rgomes@octobus.net>
parents: 49128
diff changeset
814 // files for caching reasons
126d253eb274 rust-status: stop using `state()` in `handle_normal_file`
Raphaël Gomès <rgomes@octobus.net>
parents: 49128
diff changeset
815 return Ok(());
126d253eb274 rust-status: stop using `state()` in `handle_normal_file`
Raphaël Gomès <rgomes@octobus.net>
parents: 49128
diff changeset
816 }
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
817 let path = dirstate_node.full_path(self.dmap.on_disk)?;
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
818 if self.matcher.matches(path) {
49141
126d253eb274 rust-status: stop using `state()` in `handle_normal_file`
Raphaël Gomès <rgomes@octobus.net>
parents: 49128
diff changeset
819 if entry.removed() {
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
820 self.push_outcome(Outcome::Removed, dirstate_node)?
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
821 } else {
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
822 self.push_outcome(Outcome::Deleted, dirstate_node)?
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
823 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
824 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
825 }
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
826 Ok(())
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
827 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
828
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
829 /// Something in the filesystem has no corresponding dirstate node
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
830 ///
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
831 /// Returns whether that path is ignored
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
832 fn traverse_fs_only(
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
833 &self,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
834 has_ignored_ancestor: bool,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
835 directory_hg_path: &HgPath,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
836 fs_entry: &DirEntry,
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
837 ) -> bool {
49567
6b32d39e9a67 rust-status: make `DirEntry` attributes clearer
Raphaël Gomès <rgomes@octobus.net>
parents: 49520
diff changeset
838 let hg_path = directory_hg_path.join(&fs_entry.hg_path);
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
839 let file_or_symlink = fs_entry.is_file() || fs_entry.is_symlink();
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
840 if fs_entry.is_dir() {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
841 let is_ignored =
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
842 has_ignored_ancestor || (self.ignore_fn)(&hg_path);
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
843 let traverse_children = if is_ignored {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
844 // Descendants of an ignored directory are all ignored
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
845 self.options.list_ignored
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
846 } else {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
847 // Descendants of an unknown directory may be either unknown or
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
848 // ignored
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
849 self.options.list_unknown || self.options.list_ignored
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
850 };
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
851 if traverse_children {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
852 let is_at_repo_root = false;
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
853 if let Ok(children_fs_entries) =
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
854 self.read_dir(&hg_path, &fs_entry.fs_path, is_at_repo_root)
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
855 {
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
856 children_fs_entries.par_iter().for_each(|child_fs_entry| {
47115
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
857 self.traverse_fs_only(
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
858 is_ignored,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47114
diff changeset
859 &hg_path,
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
860 child_fs_entry,
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
861 );
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
862 })
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
863 }
49423
7e5377bdb66e rust-status: ignored directories are now correctly only listed if opted into
Raphaël Gomès <rgomes@octobus.net>
parents: 49365
diff changeset
864 if self.options.collect_traversed_dirs {
7e5377bdb66e rust-status: ignored directories are now correctly only listed if opted into
Raphaël Gomès <rgomes@octobus.net>
parents: 49365
diff changeset
865 self.outcome.lock().unwrap().traversed.push(hg_path.into())
7e5377bdb66e rust-status: ignored directories are now correctly only listed if opted into
Raphaël Gomès <rgomes@octobus.net>
parents: 49365
diff changeset
866 }
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
867 }
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
868 is_ignored
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
869 } else if file_or_symlink {
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
870 if self.matcher.matches(&hg_path) {
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
871 self.mark_unknown_or_ignored(
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
872 has_ignored_ancestor,
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
873 &BorrowedPath::InMemory(&hg_path),
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
874 )
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
875 } else {
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
876 // We haven’t computed whether this path is ignored. It
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
877 // might not be, and a future run of status might have a
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
878 // different matcher that matches it. So treat it as not
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
879 // ignored. That is, inhibit readdir caching of the parent
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
880 // directory.
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
881 false
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
882 }
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
883 } else {
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
884 // This is neither a directory, a plain file, or a symlink.
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
885 // Treat it like an ignored file.
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
886 true
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
887 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
888 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
889
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
890 /// Returns whether that path is ignored
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
891 fn mark_unknown_or_ignored(
47117
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47115
diff changeset
892 &self,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
893 has_ignored_ancestor: bool,
47347
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
894 hg_path: &BorrowedPath<'_, 'on_disk>,
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
895 ) -> bool {
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
896 let is_ignored = has_ignored_ancestor || (self.ignore_fn)(hg_path);
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
897 if is_ignored {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
898 if self.options.list_ignored {
48454
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
899 self.push_outcome_without_copy_source(
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
900 Outcome::Ignored,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
901 hg_path,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
902 )
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
903 }
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
904 } else if self.options.list_unknown {
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49913
diff changeset
905 self.push_outcome_without_copy_source(Outcome::Unknown, hg_path)
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
906 }
47475
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47474
diff changeset
907 is_ignored
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
908 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
909 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
910
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
911 /// Since [`std::fs::FileType`] cannot be built directly, we emulate what we
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
912 /// care about.
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
913 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
914 enum FakeFileType {
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
915 File,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
916 Directory,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
917 Symlink,
50862
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
918 BadType(BadType),
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
919 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
920
50862
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
921 impl From<std::fs::FileType> for FakeFileType {
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
922 fn from(f: std::fs::FileType) -> Self {
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
923 if f.is_dir() {
50862
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
924 Self::Directory
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
925 } else if f.is_file() {
50862
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
926 Self::File
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
927 } else if f.is_symlink() {
50862
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
928 Self::Symlink
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
929 } else if f.is_fifo() {
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
930 Self::BadType(BadType::FIFO)
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
931 } else if f.is_block_device() {
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
932 Self::BadType(BadType::BlockDevice)
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
933 } else if f.is_char_device() {
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
934 Self::BadType(BadType::CharacterDevice)
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
935 } else if f.is_socket() {
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
936 Self::BadType(BadType::Socket)
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
937 } else {
50862
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
938 Self::BadType(BadType::Unknown)
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
939 }
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
940 }
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
941 }
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
942
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
943 struct DirEntry<'a> {
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
944 /// Path as stored in the dirstate, or just the filename for optimization.
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
945 hg_path: HgPathCow<'a>,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
946 /// Filesystem path
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
947 fs_path: Cow<'a, Path>,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
948 /// Lazily computed
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
949 symlink_metadata: Option<std::fs::Metadata>,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
950 /// Already computed for ergonomics.
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
951 file_type: FakeFileType,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
952 }
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
953
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
954 impl<'a> DirEntry<'a> {
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
955 /// Returns **unsorted** entries in the given directory, with name,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
956 /// metadata and file type.
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
957 ///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
958 /// If a `.hg` sub-directory is encountered:
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
959 ///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
960 /// * At the repository root, ignore that sub-directory
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
961 /// * Elsewhere, we’re listing the content of a sub-repo. Return an empty
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
962 /// list instead.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
963 fn read_dir(path: &Path, is_at_repo_root: bool) -> io::Result<Vec<Self>> {
48745
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
964 // `read_dir` returns a "not found" error for the empty path
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
965 let at_cwd = path == Path::new("");
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
966 let read_dir_path = if at_cwd { Path::new(".") } else { path };
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
967 let mut results = Vec::new();
48745
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
968 for entry in read_dir_path.read_dir()? {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
969 let entry = entry?;
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
970 let file_type = match entry.file_type() {
48774
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48263
diff changeset
971 Ok(v) => v,
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48263
diff changeset
972 Err(e) => {
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48263
diff changeset
973 // race with file deletion?
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48263
diff changeset
974 if e.kind() == std::io::ErrorKind::NotFound {
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48263
diff changeset
975 continue;
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48263
diff changeset
976 } else {
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48263
diff changeset
977 return Err(e);
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48263
diff changeset
978 }
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48263
diff changeset
979 }
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48263
diff changeset
980 };
48745
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
981 let file_name = entry.file_name();
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
982 // FIXME don't do this when cached
48745
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
983 if file_name == ".hg" {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
984 if is_at_repo_root {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
985 // Skip the repo’s own .hg (might be a symlink)
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
986 continue;
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
987 } else if file_type.is_dir() {
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
988 // A .hg sub-directory at another location means a subrepo,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
989 // skip it entirely.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
990 return Ok(Vec::new());
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
991 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
992 }
48745
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
993 let full_path = if at_cwd {
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
994 file_name.clone().into()
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
995 } else {
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
996 entry.path()
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48501
diff changeset
997 };
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
998 let filename =
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
999 Cow::Owned(get_bytes_from_os_string(file_name).into());
50862
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
1000 let file_type = FakeFileType::from(file_type);
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
1001 results.push(DirEntry {
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1002 hg_path: filename,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1003 fs_path: Cow::Owned(full_path.to_path_buf()),
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1004 symlink_metadata: None,
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1005 file_type,
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
1006 })
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
1007 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
1008 Ok(results)
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
1009 }
49568
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1010
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1011 fn symlink_metadata(&self) -> Result<std::fs::Metadata, std::io::Error> {
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1012 match &self.symlink_metadata {
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1013 Some(meta) => Ok(meta.clone()),
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1014 None => std::fs::symlink_metadata(&self.fs_path),
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1015 }
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1016 }
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1017
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1018 fn is_dir(&self) -> bool {
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1019 self.file_type == FakeFileType::Directory
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1020 }
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1021
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1022 fn is_file(&self) -> bool {
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1023 self.file_type == FakeFileType::File
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1024 }
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1025
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1026 fn is_symlink(&self) -> bool {
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1027 self.file_type == FakeFileType::Symlink
da48f170d203 rust-status: query fs traversal metadata lazily
Raphaël Gomès <rgomes@octobus.net>
parents: 49567
diff changeset
1028 }
50862
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
1029
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
1030 fn is_bad(&self) -> Option<BadType> {
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
1031 match self.file_type {
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
1032 FakeFileType::BadType(ty) => Some(ty),
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
1033 _ => None,
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
1034 }
5efccea9cf38 rust-status: explicitly track bad file types
Spencer Baugh <sbaugh@janestreet.com>
parents: 50321
diff changeset
1035 }
47113
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47112
diff changeset
1036 }
47349
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1037
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1038 /// Return the `mtime` of a temporary file newly-created in the `.hg` directory
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1039 /// of the give repository.
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1040 ///
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1041 /// This is similar to `SystemTime::now()`, with the result truncated to the
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1042 /// same time resolution as other files’ modification times. Using `.hg`
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1043 /// instead of the system’s default temporary directory (such as `/tmp`) makes
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1044 /// it more likely the temporary file is in the same disk partition as contents
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1045 /// of the working directory, which can matter since different filesystems may
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1046 /// store timestamps with different resolutions.
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1047 ///
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1048 /// This may fail, typically if we lack write permissions. In that case we
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1049 /// should continue the `status()` algoritm anyway and consider the current
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1050 /// date/time to be unknown.
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1051 fn filesystem_now(repo_root: &Path) -> Result<SystemTime, io::Error> {
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1052 tempfile::tempfile_in(repo_root.join(".hg"))?
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1053 .metadata()?
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1054 .modified()
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47347
diff changeset
1055 }