annotate rust/hg-core/src/dirstate_tree/status.rs @ 49550:363923bd51cd stable

dirstate-v2: hash the source of the ignore patterns as well Fixes the test introduced in the last changeset. This caused the hash to change, which means that the check in the test had to be adapted. Since this hash is only done as a caching mechanism, invalidation does not pose any backwards compatibility issues.
author Rapha?l Gom?s <rgomes@octobus.net>
date Wed, 02 Nov 2022 12:05:34 +0100
parents 8ee3889bab92
children c52435820bbd 18282cf18aa2
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;
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
8 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
9 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
10 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
11 use crate::matchers::Matcher;
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
12 use crate::utils::files::get_bytes_from_os_string;
49550
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
13 use crate::utils::files::get_bytes_from_path;
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::HgPathBuf;
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
19 use crate::HgPathCow;
47126
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
20 use crate::PatternFileWarning;
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
21 use crate::StatusError;
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
22 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
23 use micro_timer::timed;
49524
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
24 use once_cell::sync::OnceCell;
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,
49550
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
70 &mut |_source, _pattern_bytes| {},
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
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,
49550
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
79 &mut |source, pattern_bytes| {
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
80 // If inside the repo, use the relative version to
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
81 // make it deterministic inside tests.
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
82 // The performance hit should be negligible.
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
83 let source = source
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
84 .strip_prefix(&root_dir)
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
85 .unwrap_or(source);
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
86 let source = get_bytes_from_path(source);
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
87
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
88 let mut subhasher = Sha1::new();
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
89 subhasher.update(pattern_bytes);
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
90 let patterns_hash = subhasher.finalize();
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
91
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
92 hasher.update(source);
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
93 hasher.update(b" ");
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
94 hasher.update(patterns_hash);
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
95 hasher.update(b"\n");
363923bd51cd dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49547
diff changeset
96 },
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
97 )?;
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
98 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
99 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
100 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
101 (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
102 }
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
103 };
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
104 (ignore_fn, warnings, changed)
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
105 } else {
47415
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
106 (Box::new(|&_| true), vec![], None)
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
107 };
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
108
48538
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
109 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
110 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
111
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
112 // 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
113 // 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
114 // 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
115 // 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
116 // repository root.
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
117
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
118 // 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
119 // `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
120 // 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
121 // 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
122 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
123 .ok()
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
124 .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
125 {
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
126 relative
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
127 } else {
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
128 &root_dir
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
129 };
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
130
48468
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48439
diff changeset
131 let outcome = DirstateStatus {
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48439
diff changeset
132 filesystem_time_at_status_start,
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48439
diff changeset
133 ..Default::default()
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48439
diff changeset
134 };
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
135 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
136 dmap,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
137 options,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
138 matcher,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
139 ignore_fn,
48468
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48439
diff changeset
140 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
141 ignore_patterns_have_changed: patterns_changed,
49546
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49524
diff changeset
142 new_cacheable_directories: Default::default(),
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49524
diff changeset
143 outdated_cached_directories: Default::default(),
48468
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48439
diff changeset
144 filesystem_time_at_status_start,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
145 };
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
146 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
147 let hg_path = &BorrowedPath::OnDisk(HgPath::new(""));
49524
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
148 let has_ignored_ancestor = HasIgnoredAncestor::create(None, hg_path);
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
149 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
150 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
151 // 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
152 // (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
153 // 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
154 common.traverse_fs_directory_and_dirstate(
49524
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
155 &has_ignored_ancestor,
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
156 dmap.root.as_ref(),
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
157 hg_path,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
158 &root_dir,
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
159 root_dir_metadata,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
160 root_cached_mtime,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
161 is_at_repo_root,
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
162 )?;
47356
04d1f17f49e7 dirstate-v2: Write .hg/dirstate back to disk on directory cache changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47355
diff changeset
163 let mut outcome = common.outcome.into_inner().unwrap();
49546
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49524
diff changeset
164 let new_cacheable = common.new_cacheable_directories.into_inner().unwrap();
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49524
diff changeset
165 let outdated = common.outdated_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
166
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
167 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
168 || !outdated.is_empty()
49546
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49524
diff changeset
169 || (!new_cacheable.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
170 && 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
171
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
172 // 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
173 // directory is both
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
174 for path in &outdated {
49182
f3e8b0b0a8c2 rust-dirstatemap: add `clear_cached_mtime` helper method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48825
diff changeset
175 dmap.clear_cached_mtime(path)?;
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
176 }
49546
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49524
diff changeset
177 for (path, mtime) in &new_cacheable {
49183
464747faef14 rust-dirstatemap: add `set_cached_mtime` helper method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49182
diff changeset
178 dmap.set_cached_mtime(path, *mtime)?;
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
179 }
47415
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
180
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
181 Ok((outcome, warnings))
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
182 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
183
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
184 /// 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
185 /// 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
186 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
187 dmap: &'tree DirstateMap<'on_disk>,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
188 options: StatusOptions,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
189 matcher: &'a (dyn Matcher + Sync),
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
190 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
191 outcome: Mutex<DirstateStatus<'on_disk>>,
49546
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49524
diff changeset
192 /// New timestamps of directories to be used for caching their readdirs
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49524
diff changeset
193 new_cacheable_directories:
48205
320de901896a dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents: 48204
diff changeset
194 Mutex<Vec<(Cow<'on_disk, HgPath>, TruncatedTimestamp)>>,
49546
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49524
diff changeset
195 /// Used to invalidate the readdir cache of directories
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49524
diff changeset
196 outdated_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
197
0ef8231e413f dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents: 47356
diff changeset
198 /// 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
199 /// 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
200 /// 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
201 /// 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
202 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
203
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
204 /// 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
205 /// 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
206 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
207 }
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
208
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
209 enum Outcome {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
210 Modified,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
211 Added,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
212 Removed,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
213 Deleted,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
214 Clean,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
215 Ignored,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
216 Unknown,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
217 Unsure,
47126
d5956136d19d dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
218 }
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
219
49524
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
220 /// Lazy computation of whether a given path has a hgignored
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
221 /// ancestor.
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
222 struct HasIgnoredAncestor<'a> {
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
223 /// `path` and `parent` constitute the inputs to the computation,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
224 /// `cache` stores the outcome.
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
225 path: &'a HgPath,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
226 parent: Option<&'a HasIgnoredAncestor<'a>>,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
227 cache: OnceCell<bool>,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
228 }
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
229
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
230 impl<'a> HasIgnoredAncestor<'a> {
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
231 fn create(
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
232 parent: Option<&'a HasIgnoredAncestor<'a>>,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
233 path: &'a HgPath,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
234 ) -> HasIgnoredAncestor<'a> {
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
235 Self {
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
236 path,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
237 parent,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
238 cache: OnceCell::new(),
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
239 }
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
240 }
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
241
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
242 fn force<'b>(&self, ignore_fn: &IgnoreFnType<'b>) -> bool {
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
243 match self.parent {
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
244 None => false,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
245 Some(parent) => {
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
246 *(parent.cache.get_or_init(|| {
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
247 parent.force(ignore_fn) || ignore_fn(&self.path)
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
248 }))
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
249 }
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
250 }
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
251 }
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
252 }
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
253
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
254 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
255 fn push_outcome(
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
256 &self,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
257 which: Outcome,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
258 dirstate_node: &NodeRef<'tree, 'on_disk>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
259 ) -> Result<(), DirstateV2ParseError> {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
260 let path = dirstate_node
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
261 .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
262 .detach_from_tree();
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
263 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
264 dirstate_node
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
265 .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
266 .map(|source| source.detach_from_tree())
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
267 } else {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
268 None
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
269 };
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
270 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
271 Ok(())
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
272 }
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
273
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
274 fn push_outcome_without_copy_source(
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
275 &self,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
276 which: Outcome,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
277 path: &BorrowedPath<'_, 'on_disk>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
278 ) {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
279 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
280 }
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
281
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
282 fn push_outcome_common(
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
283 &self,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
284 which: Outcome,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
285 path: HgPathCow<'on_disk>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
286 copy_source: Option<HgPathCow<'on_disk>>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
287 ) {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
288 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
289 let vec = match which {
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
290 Outcome::Modified => &mut outcome.modified,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
291 Outcome::Added => &mut outcome.added,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
292 Outcome::Removed => &mut outcome.removed,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
293 Outcome::Deleted => &mut outcome.deleted,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
294 Outcome::Clean => &mut outcome.clean,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
295 Outcome::Ignored => &mut outcome.ignored,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
296 Outcome::Unknown => &mut outcome.unknown,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
297 Outcome::Unsure => &mut outcome.unsure,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
298 };
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
299 vec.push(StatusPath { path, copy_source });
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
300 }
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
301
47129
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
302 fn read_dir(
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
303 &self,
47129
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
304 hg_path: &HgPath,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
305 fs_path: &Path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
306 is_at_repo_root: bool,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
307 ) -> Result<Vec<DirEntry>, ()> {
47346
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
308 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
309 .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
310 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
311
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
312 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
313 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
314 self.outcome
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
315 .lock()
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
316 .unwrap()
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
317 .bad
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
318 .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
319 }
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
320
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
321 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
322 &self,
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
323 dirstate_node: &NodeRef<'tree, 'on_disk>,
49547
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
324 ) -> Result<bool, DirstateV2ParseError> {
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
325 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
326 && 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
327 {
49546
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49524
diff changeset
328 self.outdated_cached_directories.lock().unwrap().push(
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
329 dirstate_node
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
330 .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
331 .detach_from_tree(),
49547
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
332 );
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
333 return Ok(true);
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
334 }
49547
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
335 Ok(false)
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
336 }
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
337
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
338 /// 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
339 /// `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
340 /// 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
341 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
342 &self,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
343 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
344 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
345 ) -> bool {
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
346 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
347 // 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
348 // dirstate entries.
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
349 // 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
350 return true;
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
351 }
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
352 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
353 && 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
354 {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
355 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
356 // 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
357 // 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
358 // 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
359 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
360 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
361 .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
362 .unwrap_or(false)
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48205
diff changeset
363 {
15dedc0c5c35 status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents: 48205
diff changeset
364 // 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
365 // 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
366 // `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
367 return true;
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
368 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
369 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
370 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
371 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
372 false
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
373 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
374
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
375 /// 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
376 /// corresponding dirstate node or are ignored.
49524
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
377 fn traverse_fs_directory_and_dirstate<'ancestor>(
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
378 &self,
49524
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
379 has_ignored_ancestor: &'ancestor HasIgnoredAncestor<'ancestor>,
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
380 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
381 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
382 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
383 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
384 cached_directory_mtime: Option<TruncatedTimestamp>,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
385 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
386 ) -> Result<bool, DirstateV2ParseError> {
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
387 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
388 {
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
389 dirstate_nodes
47346
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
390 .par_iter()
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
391 .map(|dirstate_node| {
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
392 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
393 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
394 ));
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
395 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
396 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
397 &fs_path,
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
398 &fs_metadata,
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
399 dirstate_node,
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
400 has_ignored_ancestor,
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
401 ),
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
402 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
403 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
404 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
405 Err(error) => {
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
406 let hg_path =
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
407 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
408 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
409 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
410 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
411 })
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
412 .collect::<Result<_, _>>()?;
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
413
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
414 // 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
415 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
416
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
417 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
418 }
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
419
47129
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
420 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
421 directory_hg_path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
422 directory_fs_path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
423 is_at_repo_root,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
424 ) {
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
425 entries
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
426 } else {
47352
5e12b6bfdd3e dirstate-tree: Fix status algorithm with unreadable directory
Simon Sapin <simon.sapin@octobus.net>
parents: 47346
diff changeset
427 // 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
428 // 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
429 // 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
430 Vec::new()
47129
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
431 };
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
432
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
433 // `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
434
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
435 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
436 // `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
437 // 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
438 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
439
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
440 // 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
441 // callback below
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
442 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
443 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
444 }
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
445 itertools::merge_join_by(
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
446 dirstate_nodes,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
447 &fs_entries,
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
448 |dirstate_node, fs_entry| {
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
449 // 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
450 // 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
451 dirstate_node
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47343
diff changeset
452 .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
453 .unwrap()
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47343
diff changeset
454 .cmp(&fs_entry.base_name)
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
455 },
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
456 )
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
457 .par_bridge()
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
458 .map(|pair| {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
459 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
460 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
461 match pair {
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
462 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
463 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
464 &fs_entry.full_path,
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
465 &fs_entry.metadata,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
466 dirstate_node,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
467 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
468 )?;
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
469 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
470 }
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
471 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
472 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
473 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
474 }
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
475 Right(fs_entry) => {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
476 has_dirstate_node_or_is_ignored = self.traverse_fs_only(
49524
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
477 has_ignored_ancestor.force(&self.ignore_fn),
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
478 directory_hg_path,
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
479 fs_entry,
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
480 )
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
481 }
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
482 }
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
483 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
484 })
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
485 .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
486 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
487
49524
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
488 fn traverse_fs_and_dirstate<'ancestor>(
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
489 &self,
47346
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
490 fs_path: &Path,
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
491 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
492 dirstate_node: NodeRef<'tree, 'on_disk>,
49524
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
493 has_ignored_ancestor: &'ancestor HasIgnoredAncestor<'ancestor>,
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
494 ) -> Result<(), DirstateV2ParseError> {
49547
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
495 let outdated_dircache =
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
496 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
497 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
498 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
499 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
500 if !file_or_symlink {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
501 // 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
502 // `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
503 // 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
504 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
505 }
aeb03758f37a dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47127
diff changeset
506 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
507 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
508 self.outcome
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
509 .lock()
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
510 .unwrap()
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
511 .traversed
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
512 .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
513 }
49524
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
514 let is_ignored = HasIgnoredAncestor::create(
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
515 Some(&has_ignored_ancestor),
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
516 hg_path,
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
517 );
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
518 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
519 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
520 .traverse_fs_directory_and_dirstate(
49524
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
521 &is_ignored,
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
522 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
523 hg_path,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
524 fs_path,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
525 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
526 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
527 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
528 )?;
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
529 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
530 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
531 fs_metadata,
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
532 dirstate_node,
49547
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
533 outdated_dircache,
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
534 )?
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
535 } else {
49524
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
536 if file_or_symlink && self.matcher.matches(&hg_path) {
49197
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
537 if let Some(entry) = dirstate_node.entry()? {
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
538 if !entry.any_tracked() {
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
539 // Forward-compat if we start tracking unknown/ignored
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
540 // files for caching reasons
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
541 self.mark_unknown_or_ignored(
49524
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
542 has_ignored_ancestor.force(&self.ignore_fn),
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
543 &hg_path,
49197
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
544 );
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
545 }
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
546 if entry.added() {
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
547 self.push_outcome(Outcome::Added, &dirstate_node)?;
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
548 } else if entry.removed() {
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
549 self.push_outcome(Outcome::Removed, &dirstate_node)?;
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
550 } else if entry.modified() {
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
551 self.push_outcome(Outcome::Modified, &dirstate_node)?;
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
552 } else {
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
553 self.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
554 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
555 } else {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
556 // `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
557 // 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
558 self.mark_unknown_or_ignored(
49524
eb02decdf0ab dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49400
diff changeset
559 has_ignored_ancestor.force(&self.ignore_fn),
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
560 hg_path,
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
561 );
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
562 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
563 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
564
47344
8d0260d0dbc9 dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents: 47343
diff changeset
565 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
566 {
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
567 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
568 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
569 }
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
570 Ok(())
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
571 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
572
49547
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
573 /// Save directory mtime if applicable.
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
574 ///
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
575 /// `outdated_directory_cache` is `true` if we've just invalidated the
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
576 /// cache for this directory in `check_for_outdated_directory_cache`,
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
577 /// which forces the update.
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
578 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
579 &self,
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
580 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
581 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
582 dirstate_node: NodeRef<'tree, 'on_disk>,
49547
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
583 outdated_directory_cache: bool,
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
584 ) -> Result<(), DirstateV2ParseError> {
48538
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
585 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
586 return Ok(());
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
587 }
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
588 // 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
589 // 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
590 // 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
591
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
592 // 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
593 // 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
594 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
595 &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
596 {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
597 status_start
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
598 } else {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
599 return Ok(());
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
600 };
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
601
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
602 // 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
603 // 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
604 // 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
605 // 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
606 // 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
607 // 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
608 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
609 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
610 directory_metadata,
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
611 status_start,
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
612 ) {
48538
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
613 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
614 directory_mtime
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
615 } else {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
616 // 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
617 // 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
618 //
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
619 // 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
620 // 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
621 // (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
622 // 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
623 // 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
624 // 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
625 // 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
626 // 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
627 //
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
628 // 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
629 // 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
630 // by the same script.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
631 return Ok(());
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
632 }
48538
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
633 } else {
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
634 // 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
635 return Ok(());
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
636 };
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
637 // 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
638 // “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
639 // 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
640 // different mtime.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
641 //
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
642 // 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
643 // 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
644 // 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
645 // 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
646 // the wrong tick.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
647 //
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
648 // 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
649 // unlikely enough in practice.
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
650
49547
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
651 let is_up_to_date = if let Some(cached) =
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
652 dirstate_node.cached_directory_mtime()?
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
653 {
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
654 !outdated_directory_cache && cached.likely_equal(directory_mtime)
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
655 } else {
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
656 false
8ee3889bab92 rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49546
diff changeset
657 };
48538
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
658 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
659 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
660 .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
661 .detach_from_tree();
49546
ecf9788cd9c4 rust-status: fix typos and add docstrings to dircache related fields
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49524
diff changeset
662 self.new_cacheable_directories
48538
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
663 .lock()
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
664 .unwrap()
4afb9627dc77 dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents: 48493
diff changeset
665 .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
666 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
667 Ok(())
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
668 }
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
669
49197
c4ccd0346f5c rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49196
diff changeset
670 /// A file that is clean in the dirstate was found in the filesystem
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
671 fn handle_normal_file(
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
672 &self,
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
673 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
674 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
675 ) -> Result<(), DirstateV2ParseError> {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
676 // Keep the low 31 bits
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
677 fn truncate_u64(value: u64) -> i32 {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
678 (value & 0x7FFF_FFFF) as i32
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
679 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
680
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
681 let entry = dirstate_node
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
682 .entry()?
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
683 .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
684 let mode_changed =
f27f2afb15da dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents: 47344
diff changeset
685 || 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
686 let size = entry.size();
f2a9db29cb2d rust: Make the fields of DirstateEntry private
Simon Sapin <simon.sapin@octobus.net>
parents: 47480
diff changeset
687 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
688 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
689 // 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
690 // 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
691 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
692 } 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
693 || entry.is_from_other_parent()
48044
f2a9db29cb2d rust: Make the fields of DirstateEntry private
Simon Sapin <simon.sapin@octobus.net>
parents: 47480
diff changeset
694 || (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
695 {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
696 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
697 } else {
48271
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
698 let mtime_looks_clean;
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
699 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
700 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
701 .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
702 // 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
703 // 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
704 // 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
705 // 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
706 // can really do.
48271
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
707 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
708 } else {
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
709 // 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
710 mtime_looks_clean = false
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
711 };
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents: 48268
diff changeset
712 if !mtime_looks_clean {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
713 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
714 } 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
715 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
716 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
717 }
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
718 Ok(())
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
719 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
720
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
721 /// 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
722 fn traverse_dirstate_only(
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
723 &self,
47353
73ddcedeaadf dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 47352
diff changeset
724 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
725 ) -> Result<(), DirstateV2ParseError> {
47479
c657beacdf2e dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents: 47415
diff changeset
726 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
727 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
728 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
729 .children(self.dmap.on_disk)?
47341
69530e5d4fe5 dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents: 47339
diff changeset
730 .par_iter()
47343
ed1583a845d2 dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents: 47341
diff changeset
731 .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
732 .collect()
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
733 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
734
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
735 /// 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
736 /// filesystem
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
737 ///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
738 /// Does nothing on a "directory" node
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
739 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
740 &self,
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
741 dirstate_node: &NodeRef<'tree, 'on_disk>,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
742 ) -> Result<(), DirstateV2ParseError> {
49196
126d253eb274 rust-status: stop using `state()` in `handle_normal_file`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49183
diff changeset
743 if let Some(entry) = dirstate_node.entry()? {
126d253eb274 rust-status: stop using `state()` in `handle_normal_file`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49183
diff changeset
744 if !entry.any_tracked() {
126d253eb274 rust-status: stop using `state()` in `handle_normal_file`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49183
diff changeset
745 // Future-compat for when we start storing ignored and unknown
126d253eb274 rust-status: stop using `state()` in `handle_normal_file`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49183
diff changeset
746 // files for caching reasons
126d253eb274 rust-status: stop using `state()` in `handle_normal_file`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49183
diff changeset
747 return Ok(());
126d253eb274 rust-status: stop using `state()` in `handle_normal_file`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49183
diff changeset
748 }
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
749 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
750 if self.matcher.matches(path) {
49196
126d253eb274 rust-status: stop using `state()` in `handle_normal_file`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49183
diff changeset
751 if entry.removed() {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
752 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
753 } else {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
754 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
755 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
756 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
757 }
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
758 Ok(())
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
759 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
760
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
761 /// 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
762 ///
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
763 /// 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
764 fn traverse_fs_only(
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
765 &self,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
766 has_ignored_ancestor: bool,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
767 directory_hg_path: &HgPath,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
768 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
769 ) -> bool {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
770 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
771 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
772 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
773 if file_type.is_dir() {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
774 let is_ignored =
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
775 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
776 let traverse_children = if is_ignored {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
777 // 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
778 self.options.list_ignored
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
779 } else {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
780 // 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
781 // ignored
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
782 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
783 };
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
784 if traverse_children {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
785 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
786 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
787 &hg_path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
788 &fs_entry.full_path,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
789 is_at_repo_root,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
790 ) {
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
791 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
792 self.traverse_fs_only(
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
793 is_ignored,
1b4f0f819f92 dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents: 47128
diff changeset
794 &hg_path,
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
795 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
796 );
47131
60d852ae7e7b dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents: 47129
diff changeset
797 })
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
798 }
49400
7e5377bdb66e rust-status: ignored directories are now correctly only listed if opted into
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49365
diff changeset
799 if self.options.collect_traversed_dirs {
7e5377bdb66e rust-status: ignored directories are now correctly only listed if opted into
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49365
diff changeset
800 self.outcome.lock().unwrap().traversed.push(hg_path.into())
7e5377bdb66e rust-status: ignored directories are now correctly only listed if opted into
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49365
diff changeset
801 }
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
802 }
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
803 is_ignored
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
804 } else {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
805 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
806 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
807 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
808 has_ignored_ancestor,
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
809 &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
810 )
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
811 } else {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
812 // 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
813 // 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
814 // 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
815 // 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
816 // directory.
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
817 false
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
818 }
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
819 } else {
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
820 // 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
821 // 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
822 true
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
823 }
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
824 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
825 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
826
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
827 /// 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
828 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
829 &self,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
830 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
831 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
832 ) -> bool {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
833 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
834 if is_ignored {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
835 if self.options.list_ignored {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
836 self.push_outcome_without_copy_source(
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
837 Outcome::Ignored,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
838 hg_path,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
839 )
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
840 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
841 } else {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
842 if self.options.list_unknown {
48493
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
843 self.push_outcome_without_copy_source(
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
844 Outcome::Unknown,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
845 hg_path,
473af5cbc209 rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents: 48468
diff changeset
846 )
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
847 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
848 }
47480
94e38822d395 status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents: 47479
diff changeset
849 is_ignored
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
850 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
851 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
852
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
853 struct DirEntry {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
854 base_name: HgPathBuf,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
855 full_path: PathBuf,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
856 metadata: std::fs::Metadata,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
857 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
858
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
859 impl DirEntry {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
860 /// 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
861 /// metadata.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
862 ///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
863 /// 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
864 ///
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
865 /// * 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
866 /// * 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
867 /// list instead.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
868 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
869 // `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
870 let at_cwd = path == Path::new("");
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
871 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
872 let mut results = Vec::new();
48750
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
873 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
874 let entry = entry?;
48378
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
875 let metadata = match entry.metadata() {
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
876 Ok(v) => v,
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
877 Err(e) => {
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
878 // race with file deletion?
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
879 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
880 continue;
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
881 } else {
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
882 return Err(e);
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
883 }
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
884 }
dcec16e799dd status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48274
diff changeset
885 };
48750
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
886 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
887 // 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
888 if file_name == ".hg" {
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
889 if is_at_repo_root {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
890 // 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
891 continue;
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
892 } else if metadata.is_dir() {
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
893 // 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
894 // skip it entirely.
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
895 return Ok(Vec::new());
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
896 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
897 }
48750
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
898 let full_path = if at_cwd {
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
899 file_name.clone().into()
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
900 } else {
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
901 entry.path()
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
902 };
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
903 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
904 results.push(DirEntry {
48750
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
905 base_name,
94e36b230990 status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents: 48538
diff changeset
906 full_path,
47127
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
907 metadata,
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
908 })
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
909 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
910 Ok(results)
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
911 }
be579775c2d9 dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents: 47126
diff changeset
912 }
47355
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
913
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
914 /// 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
915 /// 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
916 ///
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
917 /// 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
918 /// 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
919 /// 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
920 /// 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
921 /// 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
922 /// 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
923 ///
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
924 /// 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
925 /// 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
926 /// 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
927 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
928 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
929 .metadata()?
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
930 .modified()
7138c863d0a1 dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 47353
diff changeset
931 }