annotate rust/hg-core/src/dirstate_tree/status.rs @ 48893:6cd249556e20 stable

rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed The assumption that we need to rewrite (or append to) the dirstate if the ignore pattern hash has changed or if any cached directory mtimes have changed is only valid when using dirstate-v2. In dirstate-v1, neither of these things are written to disk.
author Rapha?l Gom?s <rgomes@octobus.net>
date Wed, 08 Jun 2022 19:15:58 +0200
parents dd6b67d5c256
children 288de6f5d724
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
48205
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48204
diff changeset
1 use crate::dirstate::entry::TruncatedTimestamp;
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
2 use crate::dirstate::status::IgnoreFnType;
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
3 use crate::dirstate::status::StatusPath;
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
4 use crate::dirstate_tree::dirstate_map::BorrowedPath;
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
5 use crate::dirstate_tree::dirstate_map::ChildNodesRef;
47126
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;
48893
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48825
diff changeset
7 use crate::dirstate_tree::dirstate_map::DirstateVersion;
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
8 use crate::dirstate_tree::dirstate_map::NodeData;
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
9 use crate::dirstate_tree::dirstate_map::NodeRef;
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
10 use crate::dirstate_tree::on_disk::DirstateV2ParseError;
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
11 use crate::matchers::get_ignore_function;
47126
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
12 use crate::matchers::Matcher;
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
13 use crate::utils::files::get_bytes_from_os_string;
47346
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
14 use crate::utils::files::get_path_from_bytes;
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
15 use crate::utils::hg_path::HgPath;
47129
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
16 use crate::BadMatch;
47126
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
17 use crate::DirstateStatus;
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
18 use crate::EntryState;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
19 use crate::HgPathBuf;
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
20 use crate::HgPathCow;
47126
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;
47132
c92e63762573 dirstate-tree: Add #[timed] attribute to `status` and `DirstateMap::read`
Simon Sapin <simon.sapin@octobus.net>
parents: 47131
diff changeset
24 use micro_timer::timed;
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
25 use rayon::prelude::*;
47415
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
26 use sha1::{Digest, Sha1};
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
27 use std::borrow::Cow;
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
28 use std::io;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
29 use std::path::Path;
47126
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
30 use std::path::PathBuf;
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
31 use std::sync::Mutex;
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
32 use std::time::SystemTime;
47126
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
33
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
34 /// 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: 47126
diff changeset
35 /// changeset.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
36 ///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
37 /// 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: 47126
diff changeset
38 /// 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: 47126
diff changeset
39 /// 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: 47126
diff changeset
40 /// 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: 47126
diff changeset
41 /// 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: 47126
diff changeset
42 /// `options` we may need to traverse the remaining subtree.
47132
c92e63762573 dirstate-tree: Add #[timed] attribute to `status` and `DirstateMap::read`
Simon Sapin <simon.sapin@octobus.net>
parents: 47131
diff changeset
43 #[timed]
48825
dd6b67d5c256 rust: fix unsound `OwningDirstateMap`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48812
diff changeset
44 pub fn status<'dirstate>(
dd6b67d5c256 rust: fix unsound `OwningDirstateMap`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48812
diff changeset
45 dmap: &'dirstate mut DirstateMap,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
46 matcher: &(dyn Matcher + Sync),
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
47 root_dir: PathBuf,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
48 ignore_files: Vec<PathBuf>,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
49 options: StatusOptions,
48825
dd6b67d5c256 rust: fix unsound `OwningDirstateMap`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48812
diff changeset
50 ) -> Result<(DirstateStatus<'dirstate>, Vec<PatternFileWarning>), StatusError>
dd6b67d5c256 rust: fix unsound `OwningDirstateMap`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48812
diff changeset
51 {
48812
e2f8ed37201c rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48794
diff changeset
52 // Force the global rayon threadpool to not exceed 16 concurrent threads.
e2f8ed37201c rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48794
diff changeset
53 // This is a stop-gap measure until we figure out why using more than 16
e2f8ed37201c rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48794
diff changeset
54 // threads makes `status` slower for each additional thread.
e2f8ed37201c rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48794
diff changeset
55 // We use `ok()` in case the global threadpool has already been
e2f8ed37201c rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48794
diff changeset
56 // instantiated in `rhg` or some other caller.
e2f8ed37201c rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48794
diff changeset
57 // TODO find the underlying cause and fix it, then remove this.
e2f8ed37201c rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48794
diff changeset
58 rayon::ThreadPoolBuilder::new()
e2f8ed37201c rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48794
diff changeset
59 .num_threads(16)
e2f8ed37201c rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48794
diff changeset
60 .build_global()
e2f8ed37201c rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48794
diff changeset
61 .ok();
e2f8ed37201c rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48794
diff changeset
62
47415
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
63 let (ignore_fn, warnings, patterns_changed): (IgnoreFnType, _, _) =
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
64 if options.list_ignored || options.list_unknown {
48893
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48825
diff changeset
65 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: 48825
diff changeset
66 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: 48825
diff changeset
67 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: 48825
diff changeset
68 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: 48825
diff changeset
69 &root_dir,
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48825
diff changeset
70 &mut |_pattern_bytes| {},
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48825
diff changeset
71 )?;
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48825
diff changeset
72 (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: 48825
diff changeset
73 }
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48825
diff changeset
74 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: 48825
diff changeset
75 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: 48825
diff changeset
76 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: 48825
diff changeset
77 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: 48825
diff changeset
78 &root_dir,
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48825
diff changeset
79 &mut |pattern_bytes| hasher.update(pattern_bytes),
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48825
diff changeset
80 )?;
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48825
diff changeset
81 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: 48825
diff changeset
82 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: 48825
diff changeset
83 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: 48825
diff changeset
84 (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: 48825
diff changeset
85 }
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48825
diff changeset
86 };
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48825
diff changeset
87 (ignore_fn, warnings, changed)
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
88 } else {
47415
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
89 (Box::new(|&_| true), vec![], None)
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
90 };
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
91
48538
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
92 let filesystem_time_at_status_start =
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
93 filesystem_now(&root_dir).ok().map(TruncatedTimestamp::from);
48750
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
94
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
95 // 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: 48538
diff changeset
96 // 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: 48538
diff changeset
97 // call to `read_dir` or `symlink_metadata`.
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
98 // 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: 48538
diff changeset
99 // repository root.
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
100
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
101 // 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: 48538
diff changeset
102 // `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: 48538
diff changeset
103 // library does not provide APIs based on those.
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
104 // 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: 48538
diff changeset
105 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: 48538
diff changeset
106 .ok()
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
107 .and_then(|cwd| root_dir.strip_prefix(cwd).ok())
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
108 {
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
109 relative
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
110 } else {
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
111 &root_dir
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
112 };
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
113
48468
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48439
diff changeset
114 let outcome = DirstateStatus {
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48439
diff changeset
115 filesystem_time_at_status_start,
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48439
diff changeset
116 ..Default::default()
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48439
diff changeset
117 };
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
118 let common = StatusCommon {
47344
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47343
diff changeset
119 dmap,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
120 options,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
121 matcher,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
122 ignore_fn,
48468
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48439
diff changeset
123 outcome: Mutex::new(outcome),
47415
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
124 ignore_patterns_have_changed: patterns_changed,
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
125 new_cachable_directories: Default::default(),
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
126 outated_cached_directories: Default::default(),
48468
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48439
diff changeset
127 filesystem_time_at_status_start,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
128 };
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
129 let is_at_repo_root = true;
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
130 let hg_path = &BorrowedPath::OnDisk(HgPath::new(""));
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
131 let has_ignored_ancestor = false;
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
132 let root_cached_mtime = None;
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
133 let root_dir_metadata = None;
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
134 // 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: 47353
diff changeset
135 // (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: 47353
diff changeset
136 // followed, using `std::fs::symlink_metadata`.)
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
137 common.traverse_fs_directory_and_dirstate(
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
138 has_ignored_ancestor,
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
139 dmap.root.as_ref(),
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
140 hg_path,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
141 &root_dir,
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
142 root_dir_metadata,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
143 root_cached_mtime,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
144 is_at_repo_root,
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
145 )?;
47356
04d1f17f49e7 dirstate-v2: Write .hg/dirstate back to disk on directory cache changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47355
diff changeset
146 let mut outcome = common.outcome.into_inner().unwrap();
47415
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
147 let new_cachable = common.new_cachable_directories.into_inner().unwrap();
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
148 let outdated = common.outated_cached_directories.into_inner().unwrap();
47415
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
149
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
150 outcome.dirty = common.ignore_patterns_have_changed == Some(true)
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
151 || !outdated.is_empty()
48893
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48825
diff changeset
152 || (!new_cachable.is_empty()
6cd249556e20 rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48825
diff changeset
153 && dmap.dirstate_version == DirstateVersion::V2);
47415
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
154
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
155 // 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: 47415
diff changeset
156 // directory is both
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
157 for path in &outdated {
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
158 let node = dmap.get_or_insert(path)?;
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
159 if let NodeData::CachedDirectory { .. } = &node.data {
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
160 node.data = NodeData::None
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
161 }
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
162 }
47415
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
163 for (path, mtime) in &new_cachable {
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
164 let node = dmap.get_or_insert(path)?;
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
165 match &node.data {
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
166 NodeData::Entry(_) => {} // Don’t overwrite an entry
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
167 NodeData::CachedDirectory { .. } | NodeData::None => {
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
168 node.data = NodeData::CachedDirectory { mtime: *mtime }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
169 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
170 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
171 }
47415
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
172
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
173 Ok((outcome, warnings))
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
174 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
175
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
176 /// 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: 47126
diff changeset
177 /// number of parameters passed to functions.
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
178 struct StatusCommon<'a, 'tree, 'on_disk: 'tree> {
47344
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47343
diff changeset
179 dmap: &'tree DirstateMap<'on_disk>,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
180 options: StatusOptions,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
181 matcher: &'a (dyn Matcher + Sync),
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
182 ignore_fn: IgnoreFnType<'a>,
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
183 outcome: Mutex<DirstateStatus<'on_disk>>,
48205
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48204
diff changeset
184 new_cachable_directories:
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48204
diff changeset
185 Mutex<Vec<(Cow<'on_disk, HgPath>, TruncatedTimestamp)>>,
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
186 outated_cached_directories: Mutex<Vec<Cow<'on_disk, HgPath>>>,
47415
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
187
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
188 /// 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: 47356
diff changeset
189 /// 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: 47356
diff changeset
190 /// 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: 47356
diff changeset
191 /// and therefore isn’t reading `.hgignore`.
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
192 ignore_patterns_have_changed: Option<bool>,
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
193
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
194 /// 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: 47353
diff changeset
195 /// and possibly truncated by the filesystem.
48538
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
196 filesystem_time_at_status_start: Option<TruncatedTimestamp>,
47126
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
197 }
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
198
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
199 enum Outcome {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
200 Modified,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
201 Added,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
202 Removed,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
203 Deleted,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
204 Clean,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
205 Ignored,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
206 Unknown,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
207 Unsure,
47126
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
208 }
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
209
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
210 impl<'a, 'tree, 'on_disk> StatusCommon<'a, 'tree, 'on_disk> {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
211 fn push_outcome(
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
212 &self,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
213 which: Outcome,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
214 dirstate_node: &NodeRef<'tree, 'on_disk>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
215 ) -> Result<(), DirstateV2ParseError> {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
216 let path = dirstate_node
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
217 .full_path_borrowed(self.dmap.on_disk)?
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
218 .detach_from_tree();
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
219 let copy_source = if self.options.list_copies {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
220 dirstate_node
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
221 .copy_source_borrowed(self.dmap.on_disk)?
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
222 .map(|source| source.detach_from_tree())
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
223 } else {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
224 None
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
225 };
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
226 self.push_outcome_common(which, path, copy_source);
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
227 Ok(())
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
228 }
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
229
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
230 fn push_outcome_without_copy_source(
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
231 &self,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
232 which: Outcome,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
233 path: &BorrowedPath<'_, 'on_disk>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
234 ) {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
235 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: 48468
diff changeset
236 }
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
237
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
238 fn push_outcome_common(
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
239 &self,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
240 which: Outcome,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
241 path: HgPathCow<'on_disk>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
242 copy_source: Option<HgPathCow<'on_disk>>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
243 ) {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
244 let mut outcome = self.outcome.lock().unwrap();
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
245 let vec = match which {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
246 Outcome::Modified => &mut outcome.modified,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
247 Outcome::Added => &mut outcome.added,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
248 Outcome::Removed => &mut outcome.removed,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
249 Outcome::Deleted => &mut outcome.deleted,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
250 Outcome::Clean => &mut outcome.clean,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
251 Outcome::Ignored => &mut outcome.ignored,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
252 Outcome::Unknown => &mut outcome.unknown,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
253 Outcome::Unsure => &mut outcome.unsure,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
254 };
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
255 vec.push(StatusPath { path, copy_source });
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
256 }
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
257
47129
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
258 fn read_dir(
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
259 &self,
47129
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
260 hg_path: &HgPath,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
261 fs_path: &Path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
262 is_at_repo_root: bool,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
263 ) -> Result<Vec<DirEntry>, ()> {
47346
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
264 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: 47344
diff changeset
265 .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: 47344
diff changeset
266 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
267
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
268 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: 47344
diff changeset
269 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: 47344
diff changeset
270 self.outcome
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
271 .lock()
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
272 .unwrap()
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
273 .bad
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
274 .push((hg_path.to_owned().into(), BadMatch::OsError(errno)))
47129
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
275 }
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
276
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
277 fn check_for_outdated_directory_cache(
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
278 &self,
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
279 dirstate_node: &NodeRef<'tree, 'on_disk>,
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
280 ) -> Result<(), DirstateV2ParseError> {
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
281 if self.ignore_patterns_have_changed == Some(true)
48205
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48204
diff changeset
282 && dirstate_node.cached_directory_mtime()?.is_some()
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
283 {
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
284 self.outated_cached_directories.lock().unwrap().push(
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
285 dirstate_node
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
286 .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: 47415
diff changeset
287 .detach_from_tree(),
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
288 )
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
289 }
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
290 Ok(())
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
291 }
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
292
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
293 /// 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: 47353
diff changeset
294 /// `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: 47353
diff changeset
295 /// need to call `read_dir`.
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
296 fn can_skip_fs_readdir(
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
297 &self,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
298 directory_metadata: Option<&std::fs::Metadata>,
48205
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48204
diff changeset
299 cached_directory_mtime: Option<TruncatedTimestamp>,
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
300 ) -> bool {
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
301 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: 47353
diff changeset
302 // 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: 47353
diff changeset
303 // dirstate entries.
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
304 // 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: 47353
diff changeset
305 return true;
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
306 }
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
307 if !self.options.list_ignored
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
308 && 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: 47479
diff changeset
309 {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
310 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: 47479
diff changeset
311 // 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: 47479
diff changeset
312 // 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: 47479
diff changeset
313 // directory eligible for `read_dir` caching.
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
314 if let Some(meta) = directory_metadata {
48230
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48205
diff changeset
315 if cached_mtime
48268
f45d35950db6 dirstate: rename a `very_likely_equal` method to `likely_equal`
Simon Sapin <simon.sapin@octobus.net>
parents: 48230
diff changeset
316 .likely_equal_to_mtime_of(meta)
48230
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48205
diff changeset
317 .unwrap_or(false)
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48205
diff changeset
318 {
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48205
diff changeset
319 // The mtime of that directory has not changed
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48205
diff changeset
320 // since then, which means that the results of
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48205
diff changeset
321 // `read_dir` should also be unchanged.
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48205
diff changeset
322 return true;
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
323 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
324 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
325 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
326 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
327 false
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
328 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
329
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
330 /// 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: 47479
diff changeset
331 /// corresponding dirstate node or are ignored.
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
332 fn traverse_fs_directory_and_dirstate(
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
333 &self,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
334 has_ignored_ancestor: bool,
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
335 dirstate_nodes: ChildNodesRef<'tree, 'on_disk>,
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
336 directory_hg_path: &BorrowedPath<'tree, 'on_disk>,
47129
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
337 directory_fs_path: &Path,
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
338 directory_metadata: Option<&std::fs::Metadata>,
48205
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48204
diff changeset
339 cached_directory_mtime: Option<TruncatedTimestamp>,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
340 is_at_repo_root: bool,
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
341 ) -> Result<bool, DirstateV2ParseError> {
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
342 if self.can_skip_fs_readdir(directory_metadata, cached_directory_mtime)
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
343 {
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
344 dirstate_nodes
47346
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
345 .par_iter()
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
346 .map(|dirstate_node| {
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
347 let fs_path = directory_fs_path.join(get_path_from_bytes(
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
348 dirstate_node.base_name(self.dmap.on_disk)?.as_bytes(),
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
349 ));
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
350 match std::fs::symlink_metadata(&fs_path) {
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
351 Ok(fs_metadata) => self.traverse_fs_and_dirstate(
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
352 &fs_path,
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
353 &fs_metadata,
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
354 dirstate_node,
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
355 has_ignored_ancestor,
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
356 ),
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
357 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: 47344
diff changeset
358 self.traverse_dirstate_only(dirstate_node)
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
359 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
360 Err(error) => {
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
361 let hg_path =
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
362 dirstate_node.full_path(self.dmap.on_disk)?;
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
363 Ok(self.io_error(error, hg_path))
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
364 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
365 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
366 })
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
367 .collect::<Result<_, _>>()?;
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
368
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
369 // 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: 47479
diff changeset
370 let children_all_have_dirstate_node_or_are_ignored = false;
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
371
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
372 return Ok(children_all_have_dirstate_node_or_are_ignored);
47346
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
373 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
374
47129
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
375 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: 47128
diff changeset
376 directory_hg_path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
377 directory_fs_path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
378 is_at_repo_root,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
379 ) {
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
380 entries
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
381 } else {
47352
5e12b6bfdd3e dirstate-tree: Fix status algorithm with unreadable directory
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
382 // Treat an unreadable directory (typically because of insufficient
5e12b6bfdd3e dirstate-tree: Fix status algorithm with unreadable directory
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
383 // 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: 47346
diff changeset
384 // already called `self.io_error` so a warning will be emitted.
5e12b6bfdd3e dirstate-tree: Fix status algorithm with unreadable directory
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
385 Vec::new()
47129
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
386 };
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
387
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
388 // `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: 47126
diff changeset
389
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
390 let dirstate_nodes = dirstate_nodes.sorted();
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
391 // `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: 47126
diff changeset
392 // https://github.com/rust-lang/rust/issues/34162
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
393 fs_entries.sort_unstable_by(|e1, e2| e1.base_name.cmp(&e2.base_name));
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
394
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
395 // 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: 47341
diff changeset
396 // callback below
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
397 for dirstate_node in &dirstate_nodes {
47344
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47343
diff changeset
398 dirstate_node.base_name(self.dmap.on_disk)?;
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
399 }
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
400 itertools::merge_join_by(
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
401 dirstate_nodes,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
402 &fs_entries,
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
403 |dirstate_node, fs_entry| {
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
404 // This `unwrap` never panics because we already propagated
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
405 // those errors above
47344
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47343
diff changeset
406 dirstate_node
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47343
diff changeset
407 .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: 47343
diff changeset
408 .unwrap()
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47343
diff changeset
409 .cmp(&fs_entry.base_name)
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
410 },
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
411 )
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
412 .par_bridge()
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
413 .map(|pair| {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
414 use itertools::EitherOrBoth::*;
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
415 let has_dirstate_node_or_is_ignored;
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
416 match pair {
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
417 Both(dirstate_node, fs_entry) => {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
418 self.traverse_fs_and_dirstate(
47346
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
419 &fs_entry.full_path,
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
420 &fs_entry.metadata,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
421 dirstate_node,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
422 has_ignored_ancestor,
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
423 )?;
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
424 has_dirstate_node_or_is_ignored = true
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
425 }
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
426 Left(dirstate_node) => {
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
427 self.traverse_dirstate_only(dirstate_node)?;
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
428 has_dirstate_node_or_is_ignored = true;
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
429 }
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
430 Right(fs_entry) => {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
431 has_dirstate_node_or_is_ignored = self.traverse_fs_only(
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
432 has_ignored_ancestor,
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
433 directory_hg_path,
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
434 fs_entry,
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
435 )
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
436 }
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
437 }
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
438 Ok(has_dirstate_node_or_is_ignored)
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
439 })
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
440 .try_reduce(|| true, |a, b| Ok(a && b))
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
441 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
442
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
443 fn traverse_fs_and_dirstate(
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
444 &self,
47346
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
445 fs_path: &Path,
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
446 fs_metadata: &std::fs::Metadata,
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
447 dirstate_node: NodeRef<'tree, 'on_disk>,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
448 has_ignored_ancestor: bool,
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
449 ) -> Result<(), DirstateV2ParseError> {
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
450 self.check_for_outdated_directory_cache(&dirstate_node)?;
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
451 let hg_path = &dirstate_node.full_path_borrowed(self.dmap.on_disk)?;
47346
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
452 let file_type = fs_metadata.file_type();
47128
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47127
diff changeset
453 let file_or_symlink = file_type.is_file() || file_type.is_symlink();
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47127
diff changeset
454 if !file_or_symlink {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
455 // 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: 47126
diff changeset
456 // `hg rm` or similar) or deleted before it could be
47128
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47127
diff changeset
457 // replaced by a directory or something else.
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
458 self.mark_removed_or_deleted_if_file(&dirstate_node)?;
47128
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47127
diff changeset
459 }
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47127
diff changeset
460 if file_type.is_dir() {
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47127
diff changeset
461 if self.options.collect_traversed_dirs {
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
462 self.outcome
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
463 .lock()
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
464 .unwrap()
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
465 .traversed
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
466 .push(hg_path.detach_from_tree())
47128
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47127
diff changeset
467 }
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
468 let is_ignored = has_ignored_ancestor || (self.ignore_fn)(hg_path);
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
469 let is_at_repo_root = false;
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
470 let children_all_have_dirstate_node_or_are_ignored = self
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
471 .traverse_fs_directory_and_dirstate(
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
472 is_ignored,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
473 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: 47353
diff changeset
474 hg_path,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
475 fs_path,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
476 Some(fs_metadata),
48205
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48204
diff changeset
477 dirstate_node.cached_directory_mtime()?,
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
478 is_at_repo_root,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
479 )?;
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
480 self.maybe_save_directory_mtime(
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
481 children_all_have_dirstate_node_or_are_ignored,
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
482 fs_metadata,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
483 dirstate_node,
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
484 )?
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
485 } else {
47128
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47127
diff changeset
486 if file_or_symlink && self.matcher.matches(hg_path) {
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
487 if let Some(state) = dirstate_node.state()? {
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
488 match state {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
489 EntryState::Added => {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
490 self.push_outcome(Outcome::Added, &dirstate_node)?
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
491 }
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
492 EntryState::Removed => self
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
493 .push_outcome(Outcome::Removed, &dirstate_node)?,
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
494 EntryState::Merged => self
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
495 .push_outcome(Outcome::Modified, &dirstate_node)?,
47346
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
496 EntryState::Normal => self
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
497 .handle_normal_file(&dirstate_node, fs_metadata)?,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
498 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
499 } else {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
500 // `node.entry.is_none()` indicates a "directory"
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
501 // node, but the filesystem has a file
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
502 self.mark_unknown_or_ignored(
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
503 has_ignored_ancestor,
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
504 hg_path,
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
505 );
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
506 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
507 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
508
47344
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47343
diff changeset
509 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: 47343
diff changeset
510 {
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
511 self.traverse_dirstate_only(child_node)?
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
512 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
513 }
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
514 Ok(())
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
515 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
516
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
517 fn maybe_save_directory_mtime(
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
518 &self,
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
519 children_all_have_dirstate_node_or_are_ignored: bool,
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
520 directory_metadata: &std::fs::Metadata,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
521 dirstate_node: NodeRef<'tree, 'on_disk>,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
522 ) -> Result<(), DirstateV2ParseError> {
48538
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
523 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: 48493
diff changeset
524 return Ok(());
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
525 }
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
526 // 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: 48493
diff changeset
527 // 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: 48493
diff changeset
528 // 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: 48493
diff changeset
529
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
530 // 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: 48493
diff changeset
531 // 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: 48493
diff changeset
532 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: 48493
diff changeset
533 &self.filesystem_time_at_status_start
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
534 {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
535 status_start
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
536 } else {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
537 return Ok(());
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
538 };
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
539
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
540 // 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: 48493
diff changeset
541 // 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: 48493
diff changeset
542 // 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: 48493
diff changeset
543 // 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: 48493
diff changeset
544 // only stores integer seconds), kernel (see
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
545 // https://stackoverflow.com/a/14393315/1162888), etc.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
546 let directory_mtime = if let Ok(option) =
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
547 TruncatedTimestamp::for_reliable_mtime_of(
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
548 directory_metadata,
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
549 status_start,
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
550 ) {
48538
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
551 if let Some(directory_mtime) = option {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
552 directory_mtime
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
553 } else {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
554 // The directory was modified too recently,
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
555 // don’t cache its `read_dir` results.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
556 //
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
557 // 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: 48493
diff changeset
558 // 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: 48493
diff changeset
559 // (possibly truncated) to `directory_mtime`
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
560 // 2. This `status` algorithm calls `read_dir`
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
561 // 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: 48493
diff changeset
562 // 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: 48493
diff changeset
563 // 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: 48493
diff changeset
564 // the mtime stays the same
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
565 //
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
566 // 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: 48493
diff changeset
567 // 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: 48493
diff changeset
568 // by the same script.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
569 return Ok(());
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
570 }
48538
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
571 } else {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
572 // OS/libc does not support mtime?
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
573 return Ok(());
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
574 };
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
575 // 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: 48493
diff changeset
576 // “progressed” since `directory_mtime`, so any further
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
577 // 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: 48493
diff changeset
578 // different mtime.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
579 //
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
580 // 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: 48493
diff changeset
581 // 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: 48493
diff changeset
582 // 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: 48493
diff changeset
583 // directory change could potentially happen during exactly
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
584 // the wrong tick.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
585 //
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
586 // 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: 48493
diff changeset
587 // unlikely enough in practice.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
588
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
589 let is_up_to_date =
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
590 if let Some(cached) = dirstate_node.cached_directory_mtime()? {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
591 cached.likely_equal(directory_mtime)
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
592 } else {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
593 false
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
594 };
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
595 if !is_up_to_date {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
596 let hg_path = dirstate_node
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
597 .full_path_borrowed(self.dmap.on_disk)?
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
598 .detach_from_tree();
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
599 self.new_cachable_directories
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
600 .lock()
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
601 .unwrap()
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
602 .push((hg_path, directory_mtime))
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
603 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
604 Ok(())
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
605 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
606
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
607 /// A file with `EntryState::Normal` in the dirstate was found in the
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
608 /// filesystem
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
609 fn handle_normal_file(
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
610 &self,
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
611 dirstate_node: &NodeRef<'tree, 'on_disk>,
47346
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
612 fs_metadata: &std::fs::Metadata,
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
613 ) -> Result<(), DirstateV2ParseError> {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
614 // Keep the low 31 bits
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
615 fn truncate_u64(value: u64) -> i32 {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
616 (value & 0x7FFF_FFFF) as i32
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
617 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
618
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
619 let entry = dirstate_node
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
620 .entry()?
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
621 .expect("handle_normal_file called with entry-less node");
47346
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
622 let mode_changed =
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
623 || self.options.check_exec && entry.mode_changed(fs_metadata);
48044
f2a9db29cb2d rust: Make the fields of DirstateEntry private
Simon Sapin <simon.sapin@octobus.net>
parents: 47480
diff changeset
624 let size = entry.size();
f2a9db29cb2d rust: Make the fields of DirstateEntry private
Simon Sapin <simon.sapin@octobus.net>
parents: 47480
diff changeset
625 let size_changed = size != truncate_u64(fs_metadata.len());
f2a9db29cb2d rust: Make the fields of DirstateEntry private
Simon Sapin <simon.sapin@octobus.net>
parents: 47480
diff changeset
626 if size >= 0 && size_changed && fs_metadata.file_type().is_symlink() {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
627 // issue6456: Size returned may be longer due to encryption
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
628 // on EXT-4 fscrypt. TODO maybe only do it on EXT4?
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
629 self.push_outcome(Outcome::Unsure, dirstate_node)?
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
630 } else if dirstate_node.has_copy_source()
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
631 || entry.is_from_other_parent()
48044
f2a9db29cb2d rust: Make the fields of DirstateEntry private
Simon Sapin <simon.sapin@octobus.net>
parents: 47480
diff changeset
632 || (size >= 0 && (size_changed || mode_changed()))
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
633 {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
634 self.push_outcome(Outcome::Modified, dirstate_node)?
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
635 } else {
48271
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
636 let mtime_looks_clean;
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
637 if let Some(dirstate_mtime) = entry.truncated_mtime() {
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
638 let fs_mtime = TruncatedTimestamp::for_mtime_of(fs_metadata)
48274
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48271
diff changeset
639 .expect("OS/libc does not support mtime?");
48439
b80e5e75d51e dirstate: remove `lastnormaltime` mechanism
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48274
diff changeset
640 // 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: 48274
diff changeset
641 // 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: 48274
diff changeset
642 // case where the issues the user would face
b80e5e75d51e dirstate: remove `lastnormaltime` mechanism
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48274
diff changeset
643 // would be a lot worse and there is nothing we
b80e5e75d51e dirstate: remove `lastnormaltime` mechanism
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48274
diff changeset
644 // can really do.
48271
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
645 mtime_looks_clean = fs_mtime.likely_equal(dirstate_mtime)
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
646 } else {
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
647 // No mtime in the dirstate entry
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
648 mtime_looks_clean = false
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
649 };
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
650 if !mtime_looks_clean {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
651 self.push_outcome(Outcome::Unsure, dirstate_node)?
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
652 } else if self.options.list_clean {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
653 self.push_outcome(Outcome::Clean, dirstate_node)?
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
654 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
655 }
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
656 Ok(())
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
657 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
658
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
659 /// A node in the dirstate tree has no corresponding filesystem entry
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
660 fn traverse_dirstate_only(
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
661 &self,
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
662 dirstate_node: NodeRef<'tree, 'on_disk>,
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
663 ) -> Result<(), DirstateV2ParseError> {
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
664 self.check_for_outdated_directory_cache(&dirstate_node)?;
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
665 self.mark_removed_or_deleted_if_file(&dirstate_node)?;
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
666 dirstate_node
47344
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47343
diff changeset
667 .children(self.dmap.on_disk)?
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
668 .par_iter()
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
669 .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: 47341
diff changeset
670 .collect()
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
671 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
672
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
673 /// 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: 47126
diff changeset
674 /// filesystem
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
675 ///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
676 /// Does nothing on a "directory" node
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
677 fn mark_removed_or_deleted_if_file(
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
678 &self,
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
679 dirstate_node: &NodeRef<'tree, 'on_disk>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
680 ) -> Result<(), DirstateV2ParseError> {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
681 if let Some(state) = dirstate_node.state()? {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
682 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: 48468
diff changeset
683 if self.matcher.matches(path) {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
684 if let EntryState::Removed = state {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
685 self.push_outcome(Outcome::Removed, dirstate_node)?
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
686 } else {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
687 self.push_outcome(Outcome::Deleted, &dirstate_node)?
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
688 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
689 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
690 }
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
691 Ok(())
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
692 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
693
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
694 /// Something in the filesystem has no corresponding dirstate node
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
695 ///
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
696 /// Returns whether that path is ignored
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
697 fn traverse_fs_only(
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
698 &self,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
699 has_ignored_ancestor: bool,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
700 directory_hg_path: &HgPath,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
701 fs_entry: &DirEntry,
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
702 ) -> bool {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
703 let hg_path = directory_hg_path.join(&fs_entry.base_name);
47128
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47127
diff changeset
704 let file_type = fs_entry.metadata.file_type();
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47127
diff changeset
705 let file_or_symlink = file_type.is_file() || file_type.is_symlink();
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47127
diff changeset
706 if file_type.is_dir() {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
707 let is_ignored =
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
708 has_ignored_ancestor || (self.ignore_fn)(&hg_path);
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
709 let traverse_children = if is_ignored {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
710 // Descendants of an ignored directory are all ignored
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
711 self.options.list_ignored
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
712 } else {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
713 // 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: 47126
diff changeset
714 // ignored
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
715 self.options.list_unknown || self.options.list_ignored
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
716 };
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
717 if traverse_children {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
718 let is_at_repo_root = false;
47129
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
719 if let Ok(children_fs_entries) = self.read_dir(
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
720 &hg_path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
721 &fs_entry.full_path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
722 is_at_repo_root,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
723 ) {
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
724 children_fs_entries.par_iter().for_each(|child_fs_entry| {
47129
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
725 self.traverse_fs_only(
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
726 is_ignored,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
727 &hg_path,
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
728 child_fs_entry,
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
729 );
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
730 })
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
731 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
732 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
733 if self.options.collect_traversed_dirs {
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
734 self.outcome.lock().unwrap().traversed.push(hg_path.into())
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
735 }
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
736 is_ignored
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
737 } else {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
738 if file_or_symlink {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
739 if self.matcher.matches(&hg_path) {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
740 self.mark_unknown_or_ignored(
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
741 has_ignored_ancestor,
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
742 &BorrowedPath::InMemory(&hg_path),
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
743 )
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
744 } else {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
745 // We haven’t computed whether this path is ignored. It
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
746 // might not be, and a future run of status might have a
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
747 // different matcher that matches it. So treat it as not
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
748 // ignored. That is, inhibit readdir caching of the parent
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
749 // directory.
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
750 false
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
751 }
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
752 } else {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
753 // This is neither a directory, a plain file, or a symlink.
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
754 // Treat it like an ignored file.
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
755 true
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
756 }
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
757 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
758 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
759
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
760 /// Returns whether that path is ignored
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
761 fn mark_unknown_or_ignored(
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
762 &self,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
763 has_ignored_ancestor: bool,
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
764 hg_path: &BorrowedPath<'_, 'on_disk>,
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
765 ) -> bool {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
766 let is_ignored = has_ignored_ancestor || (self.ignore_fn)(&hg_path);
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
767 if is_ignored {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
768 if self.options.list_ignored {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
769 self.push_outcome_without_copy_source(
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
770 Outcome::Ignored,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
771 hg_path,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
772 )
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
773 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
774 } else {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
775 if self.options.list_unknown {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
776 self.push_outcome_without_copy_source(
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
777 Outcome::Unknown,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
778 hg_path,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
779 )
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
780 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
781 }
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
782 is_ignored
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
783 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
784 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
785
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
786 struct DirEntry {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
787 base_name: HgPathBuf,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
788 full_path: PathBuf,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
789 metadata: std::fs::Metadata,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
790 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
791
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
792 impl DirEntry {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
793 /// Returns **unsorted** entries in the given directory, with name and
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
794 /// metadata.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
795 ///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
796 /// If a `.hg` sub-directory is encountered:
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
797 ///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
798 /// * At the repository root, ignore that sub-directory
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
799 /// * 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: 47126
diff changeset
800 /// list instead.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
801 fn read_dir(path: &Path, is_at_repo_root: bool) -> io::Result<Vec<Self>> {
48750
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
802 // `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: 48538
diff changeset
803 let at_cwd = path == Path::new("");
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
804 let read_dir_path = if at_cwd { Path::new(".") } else { path };
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
805 let mut results = Vec::new();
48750
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
806 for entry in read_dir_path.read_dir()? {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
807 let entry = entry?;
48378
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
808 let metadata = match entry.metadata() {
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
809 Ok(v) => v,
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
810 Err(e) => {
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
811 // race with file deletion?
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
812 if e.kind() == std::io::ErrorKind::NotFound {
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
813 continue;
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
814 } else {
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
815 return Err(e);
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
816 }
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
817 }
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
818 };
48750
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
819 let file_name = entry.file_name();
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
820 // FIXME don't do this when cached
48750
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
821 if file_name == ".hg" {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
822 if is_at_repo_root {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
823 // 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: 47126
diff changeset
824 continue;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
825 } else if metadata.is_dir() {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
826 // 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: 47126
diff changeset
827 // skip it entirely.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
828 return Ok(Vec::new());
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
829 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
830 }
48750
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
831 let full_path = if at_cwd {
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
832 file_name.clone().into()
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
833 } else {
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
834 entry.path()
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
835 };
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
836 let base_name = get_bytes_from_os_string(file_name).into();
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
837 results.push(DirEntry {
48750
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
838 base_name,
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
839 full_path,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
840 metadata,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
841 })
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
842 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
843 Ok(results)
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
844 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
845 }
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
846
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
847 /// 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: 47353
diff changeset
848 /// of the give repository.
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
849 ///
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
850 /// 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: 47353
diff changeset
851 /// 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: 47353
diff changeset
852 /// 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: 47353
diff changeset
853 /// 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: 47353
diff changeset
854 /// 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: 47353
diff changeset
855 /// store timestamps with different resolutions.
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
856 ///
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
857 /// 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: 47353
diff changeset
858 /// 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: 47353
diff changeset
859 /// date/time to be unknown.
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
860 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: 47353
diff changeset
861 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: 47353
diff changeset
862 .metadata()?
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
863 .modified()
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
864 }