Mercurial > public > mercurial-scm > hg-stable
annotate rust/hg-core/src/dirstate_tree/status.rs @ 50300:edcc35a4f1dc stable
dirstate: fix the bug in [status] dealing with committed&ignored directories
In particular, these directories can "infect" their sibling directories with
ignored status due to using a shared memoization cell by accident.
This fixes bug #6795.
author | Arseniy Alekseyev <aalekseyev@janestreet.com> |
---|---|
date | Tue, 14 Mar 2023 14:08:38 +0000 |
parents | bae51b50a5cf |
children | 14b57943ae6d |
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; |
48493
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
18 use crate::HgPathCow; |
47126
d5956136d19d
dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
19 use crate::PatternFileWarning; |
d5956136d19d
dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
20 use crate::StatusError; |
d5956136d19d
dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
21 use crate::StatusOptions; |
49524
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
22 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
|
23 use rayon::prelude::*; |
47415
0ef8231e413f
dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents:
47356
diff
changeset
|
24 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
|
25 use std::borrow::Cow; |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
26 use std::io; |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
27 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
|
28 use std::path::PathBuf; |
47131
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47129
diff
changeset
|
29 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
|
30 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
|
31 |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
32 /// 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
|
33 /// changeset. |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
34 /// |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
35 /// 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
|
36 /// 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
|
37 /// 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
|
38 /// 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
|
39 /// 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
|
40 /// `options` we may need to traverse the remaining subtree. |
49986
c15b415d1bff
rust: use `logging_timer` instead of `micro_timer`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49927
diff
changeset
|
41 #[logging_timer::time("trace")] |
48825
dd6b67d5c256
rust: fix unsound `OwningDirstateMap`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48812
diff
changeset
|
42 pub fn status<'dirstate>( |
dd6b67d5c256
rust: fix unsound `OwningDirstateMap`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48812
diff
changeset
|
43 dmap: &'dirstate mut DirstateMap, |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
44 matcher: &(dyn Matcher + Sync), |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
45 root_dir: PathBuf, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
46 ignore_files: Vec<PathBuf>, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
47 options: StatusOptions, |
48825
dd6b67d5c256
rust: fix unsound `OwningDirstateMap`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48812
diff
changeset
|
48 ) -> Result<(DirstateStatus<'dirstate>, Vec<PatternFileWarning>), StatusError> |
dd6b67d5c256
rust: fix unsound `OwningDirstateMap`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48812
diff
changeset
|
49 { |
48812
e2f8ed37201c
rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48794
diff
changeset
|
50 // 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
|
51 // 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
|
52 // 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
|
53 // 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
|
54 // 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
|
55 // 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
|
56 rayon::ThreadPoolBuilder::new() |
49597
c52435820bbd
rust-status: fix thread count ceiling
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49550
diff
changeset
|
57 .num_threads(16.min(rayon::current_num_threads())) |
48812
e2f8ed37201c
rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48794
diff
changeset
|
58 .build_global() |
e2f8ed37201c
rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48794
diff
changeset
|
59 .ok(); |
e2f8ed37201c
rust-status: cap the number of concurrent threads to 16
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48794
diff
changeset
|
60 |
47415
0ef8231e413f
dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents:
47356
diff
changeset
|
61 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
|
62 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
|
63 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
|
64 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
|
65 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
|
66 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
|
67 &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
|
68 &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
|
69 )?; |
6cd249556e20
rust-status: don't trigger dirstate v1 rewrite when only v2 data is changed
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48825
diff
changeset
|
70 (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
|
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 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
|
73 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
|
74 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
|
75 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
|
76 &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
|
77 &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
|
78 // 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
|
79 // 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
|
80 // 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
|
81 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
|
82 .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
|
83 .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
|
84 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
|
85 |
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 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
|
87 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
|
88 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
|
89 |
363923bd51cd
dirstate-v2: hash the source of the ignore patterns as well
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49547
diff
changeset
|
90 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
|
91 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
|
92 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
|
93 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
|
94 }, |
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
|
95 )?; |
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
|
96 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
|
97 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
|
98 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
|
99 (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
|
100 } |
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 }; |
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 (ignore_fn, warnings, changed) |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
103 } else { |
47415
0ef8231e413f
dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents:
47356
diff
changeset
|
104 (Box::new(|&_| true), vec![], None) |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
105 }; |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
106 |
48538
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
107 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
|
108 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
|
109 |
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
110 // 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
|
111 // 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
|
112 // 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
|
113 // 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
|
114 // repository root. |
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
115 |
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
116 // 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
|
117 // `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
|
118 // 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
|
119 // 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
|
120 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
|
121 .ok() |
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
122 .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
|
123 { |
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
124 relative |
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
125 } else { |
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
126 &root_dir |
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
127 }; |
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
128 |
48468
000130cfafb6
rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents:
48439
diff
changeset
|
129 let outcome = DirstateStatus { |
000130cfafb6
rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents:
48439
diff
changeset
|
130 filesystem_time_at_status_start, |
000130cfafb6
rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents:
48439
diff
changeset
|
131 ..Default::default() |
000130cfafb6
rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents:
48439
diff
changeset
|
132 }; |
47131
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47129
diff
changeset
|
133 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
|
134 dmap, |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
135 options, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
136 matcher, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
137 ignore_fn, |
48468
000130cfafb6
rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents:
48439
diff
changeset
|
138 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
|
139 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
|
140 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
|
141 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
|
142 filesystem_time_at_status_start, |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
143 }; |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
144 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
|
145 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
|
146 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
|
147 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
|
148 // 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
|
149 // (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
|
150 // 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
|
151 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
|
152 &has_ignored_ancestor, |
47341
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47339
diff
changeset
|
153 dmap.root.as_ref(), |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
154 hg_path, |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
155 &DirEntry { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
156 hg_path: Cow::Borrowed(HgPath::new(b"")), |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
157 fs_path: Cow::Borrowed(root_dir), |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
158 symlink_metadata: None, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
159 file_type: FakeFileType::Directory, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
160 }, |
47355
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
161 root_cached_mtime, |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
162 is_at_repo_root, |
47343
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47341
diff
changeset
|
163 )?; |
47356
04d1f17f49e7
dirstate-v2: Write .hg/dirstate back to disk on directory cache changes
Simon Sapin <simon.sapin@octobus.net>
parents:
47355
diff
changeset
|
164 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
|
165 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
|
166 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
|
167 |
0ef8231e413f
dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents:
47356
diff
changeset
|
168 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
|
169 || !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
|
170 || (!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
|
171 && 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
|
172 |
47479
c657beacdf2e
dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents:
47415
diff
changeset
|
173 // 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
|
174 // directory is both |
c657beacdf2e
dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents:
47415
diff
changeset
|
175 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
|
176 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
|
177 } |
49546
ecf9788cd9c4
rust-status: fix typos and add docstrings to dircache related fields
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49524
diff
changeset
|
178 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
|
179 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
|
180 } |
47415
0ef8231e413f
dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents:
47356
diff
changeset
|
181 |
47355
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
182 Ok((outcome, warnings)) |
47127
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 |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
185 /// 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
|
186 /// 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
|
187 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
|
188 dmap: &'tree DirstateMap<'on_disk>, |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
189 options: StatusOptions, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
190 matcher: &'a (dyn Matcher + Sync), |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
191 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
|
192 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
|
193 /// 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
|
194 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
|
195 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
|
196 /// 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
|
197 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
|
198 |
0ef8231e413f
dirstate-v2: Store a hash of ignore patterns (.hgignore)
Simon Sapin <simon.sapin@octobus.net>
parents:
47356
diff
changeset
|
199 /// 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
|
200 /// 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
|
201 /// 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
|
202 /// 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
|
203 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
|
204 |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
205 /// 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
|
206 /// 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
|
207 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
|
208 } |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
209 |
48493
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
210 enum Outcome { |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
211 Modified, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
212 Added, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
213 Removed, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
214 Deleted, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
215 Clean, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
216 Ignored, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
217 Unknown, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
218 Unsure, |
47126
d5956136d19d
dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
219 } |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
220 |
49524
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
221 /// 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
|
222 /// ancestor. |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
223 struct HasIgnoredAncestor<'a> { |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
224 /// `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
|
225 /// `cache` stores the outcome. |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
226 path: &'a HgPath, |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
227 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
|
228 cache: OnceCell<bool>, |
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 |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
231 impl<'a> HasIgnoredAncestor<'a> { |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
232 fn create( |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
233 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
|
234 path: &'a HgPath, |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
235 ) -> HasIgnoredAncestor<'a> { |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
236 Self { |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
237 path, |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
238 parent, |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
239 cache: OnceCell::new(), |
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 |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
243 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
|
244 match self.parent { |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
245 None => false, |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
246 Some(parent) => { |
50300
edcc35a4f1dc
dirstate: fix the bug in [status] dealing with committed&ignored directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
50294
diff
changeset
|
247 *(self.cache.get_or_init(|| { |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
248 parent.force(ignore_fn) || ignore_fn(self.path) |
49524
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 } |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
254 |
47353
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47352
diff
changeset
|
255 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
|
256 fn push_outcome( |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
257 &self, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
258 which: Outcome, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
259 dirstate_node: &NodeRef<'tree, 'on_disk>, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
260 ) -> Result<(), DirstateV2ParseError> { |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
261 let path = dirstate_node |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
262 .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
|
263 .detach_from_tree(); |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
264 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
|
265 dirstate_node |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
266 .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
|
267 .map(|source| source.detach_from_tree()) |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
268 } else { |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
269 None |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
270 }; |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
271 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
|
272 Ok(()) |
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 |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
275 fn push_outcome_without_copy_source( |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
276 &self, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
277 which: Outcome, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
278 path: &BorrowedPath<'_, 'on_disk>, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
279 ) { |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
280 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
|
281 } |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
282 |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
283 fn push_outcome_common( |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
284 &self, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
285 which: Outcome, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
286 path: HgPathCow<'on_disk>, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
287 copy_source: Option<HgPathCow<'on_disk>>, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
288 ) { |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
289 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
|
290 let vec = match which { |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
291 Outcome::Modified => &mut outcome.modified, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
292 Outcome::Added => &mut outcome.added, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
293 Outcome::Removed => &mut outcome.removed, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
294 Outcome::Deleted => &mut outcome.deleted, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
295 Outcome::Clean => &mut outcome.clean, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
296 Outcome::Ignored => &mut outcome.ignored, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
297 Outcome::Unknown => &mut outcome.unknown, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
298 Outcome::Unsure => &mut outcome.unsure, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
299 }; |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
300 vec.push(StatusPath { path, copy_source }); |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
301 } |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
302 |
47129
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47128
diff
changeset
|
303 fn read_dir( |
47131
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47129
diff
changeset
|
304 &self, |
47129
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47128
diff
changeset
|
305 hg_path: &HgPath, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47128
diff
changeset
|
306 fs_path: &Path, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47128
diff
changeset
|
307 is_at_repo_root: bool, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47128
diff
changeset
|
308 ) -> Result<Vec<DirEntry>, ()> { |
47346
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
309 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
|
310 .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
|
311 } |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
312 |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
313 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
|
314 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
|
315 self.outcome |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
316 .lock() |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
317 .unwrap() |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
318 .bad |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
319 .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
|
320 } |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47128
diff
changeset
|
321 |
47479
c657beacdf2e
dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents:
47415
diff
changeset
|
322 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
|
323 &self, |
c657beacdf2e
dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents:
47415
diff
changeset
|
324 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
|
325 ) -> 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
|
326 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
|
327 && 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
|
328 { |
49546
ecf9788cd9c4
rust-status: fix typos and add docstrings to dircache related fields
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49524
diff
changeset
|
329 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
|
330 dirstate_node |
c657beacdf2e
dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents:
47415
diff
changeset
|
331 .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
|
332 .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
|
333 ); |
8ee3889bab92
rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49546
diff
changeset
|
334 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
|
335 } |
49547
8ee3889bab92
rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49546
diff
changeset
|
336 Ok(false) |
47479
c657beacdf2e
dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents:
47415
diff
changeset
|
337 } |
c657beacdf2e
dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents:
47415
diff
changeset
|
338 |
47355
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
339 /// 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
|
340 /// `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
|
341 /// 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
|
342 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
|
343 &self, |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
344 directory_entry: &DirEntry, |
48205
320de901896a
dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents:
48204
diff
changeset
|
345 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
|
346 ) -> bool { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
347 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
|
348 // 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
|
349 // dirstate entries. |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
350 // 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
|
351 return true; |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
352 } |
47480
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
353 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
|
354 && 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
|
355 { |
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
356 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
|
357 // 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
|
358 // 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
|
359 // directory eligible for `read_dir` caching. |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
360 if let Ok(meta) = directory_entry.symlink_metadata() { |
48230
15dedc0c5c35
status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents:
48205
diff
changeset
|
361 if cached_mtime |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
362 .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
|
363 .unwrap_or(false) |
15dedc0c5c35
status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents:
48205
diff
changeset
|
364 { |
15dedc0c5c35
status: Extract TruncatedTimestamp from fs::Metadata without SystemTime
Simon Sapin <simon.sapin@octobus.net>
parents:
48205
diff
changeset
|
365 // 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
|
366 // 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
|
367 // `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
|
368 return true; |
47355
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 } |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
373 false |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
374 } |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
375 |
47480
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
376 /// 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
|
377 /// 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
|
378 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
|
379 &self, |
49524
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
380 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
|
381 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
|
382 directory_hg_path: &BorrowedPath<'tree, 'on_disk>, |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
383 directory_entry: &DirEntry, |
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> { |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
387 if self.can_skip_fs_readdir(directory_entry, 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
|
388 dirstate_nodes |
47346
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
389 .par_iter() |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
390 .map(|dirstate_node| { |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
391 let fs_path = &directory_entry.fs_path; |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
392 let fs_path = fs_path.join(get_path_from_bytes( |
47346
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) { |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
396 Ok(fs_metadata) => { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
397 let file_type = |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
398 match fs_metadata.file_type().try_into() { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
399 Ok(file_type) => file_type, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
400 Err(_) => return Ok(()), |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
401 }; |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
402 let entry = DirEntry { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
403 hg_path: Cow::Borrowed( |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
404 dirstate_node |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
405 .full_path(self.dmap.on_disk)?, |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
406 ), |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
407 fs_path: Cow::Borrowed(&fs_path), |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
408 symlink_metadata: Some(fs_metadata), |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
409 file_type, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
410 }; |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
411 self.traverse_fs_and_dirstate( |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
412 &entry, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
413 dirstate_node, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
414 has_ignored_ancestor, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
415 ) |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
416 } |
47346
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
417 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
|
418 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
|
419 } |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
420 Err(error) => { |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
421 let hg_path = |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
422 dirstate_node.full_path(self.dmap.on_disk)?; |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
423 self.io_error(error, hg_path); |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
424 Ok(()) |
47346
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
425 } |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
426 } |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
427 }) |
47355
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
428 .collect::<Result<_, _>>()?; |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
429 |
47480
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
430 // 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
|
431 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
|
432 |
47480
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
433 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
|
434 } |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47344
diff
changeset
|
435 |
50294
bae51b50a5cf
dirstate-v2: fix an incorrect handling of readdir errors
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
50003
diff
changeset
|
436 let readdir_succeeded; |
47129
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47128
diff
changeset
|
437 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
|
438 directory_hg_path, |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
439 &directory_entry.fs_path, |
47129
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47128
diff
changeset
|
440 is_at_repo_root, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47128
diff
changeset
|
441 ) { |
50294
bae51b50a5cf
dirstate-v2: fix an incorrect handling of readdir errors
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
50003
diff
changeset
|
442 readdir_succeeded = true; |
47129
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47128
diff
changeset
|
443 entries |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47128
diff
changeset
|
444 } else { |
47352
5e12b6bfdd3e
dirstate-tree: Fix status algorithm with unreadable directory
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
445 // 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
|
446 // 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
|
447 // already called `self.io_error` so a warning will be emitted. |
50294
bae51b50a5cf
dirstate-v2: fix an incorrect handling of readdir errors
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
50003
diff
changeset
|
448 // We still need to remember that there was an error so that we |
bae51b50a5cf
dirstate-v2: fix an incorrect handling of readdir errors
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
50003
diff
changeset
|
449 // know not to cache this result. |
bae51b50a5cf
dirstate-v2: fix an incorrect handling of readdir errors
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
50003
diff
changeset
|
450 readdir_succeeded = false; |
47352
5e12b6bfdd3e
dirstate-tree: Fix status algorithm with unreadable directory
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
451 Vec::new() |
47129
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47128
diff
changeset
|
452 }; |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
453 |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
454 // `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
|
455 |
47341
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47339
diff
changeset
|
456 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
|
457 // `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
|
458 // https://github.com/rust-lang/rust/issues/34162 |
49717
6b32d39e9a67
rust-status: make `DirEntry` attributes clearer
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49524
diff
changeset
|
459 fs_entries.sort_unstable_by(|e1, e2| e1.hg_path.cmp(&e2.hg_path)); |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
460 |
47343
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47341
diff
changeset
|
461 // 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
|
462 // callback below |
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47341
diff
changeset
|
463 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
|
464 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
|
465 } |
47131
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47129
diff
changeset
|
466 itertools::merge_join_by( |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
467 dirstate_nodes, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
468 &fs_entries, |
47341
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47339
diff
changeset
|
469 |dirstate_node, fs_entry| { |
47343
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47341
diff
changeset
|
470 // 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
|
471 // 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
|
472 dirstate_node |
8d0260d0dbc9
dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents:
47343
diff
changeset
|
473 .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
|
474 .unwrap() |
49717
6b32d39e9a67
rust-status: make `DirEntry` attributes clearer
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49524
diff
changeset
|
475 .cmp(&fs_entry.hg_path) |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
476 }, |
47131
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47129
diff
changeset
|
477 ) |
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47129
diff
changeset
|
478 .par_bridge() |
47343
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47341
diff
changeset
|
479 .map(|pair| { |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
480 use itertools::EitherOrBoth::*; |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
481 let has_dirstate_node_or_is_ignored = match pair { |
47480
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
482 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
|
483 self.traverse_fs_and_dirstate( |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
484 fs_entry, |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
485 dirstate_node, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
486 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
|
487 )?; |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
488 true |
47480
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
489 } |
47341
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47339
diff
changeset
|
490 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
|
491 self.traverse_dirstate_only(dirstate_node)?; |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
492 true |
47341
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47339
diff
changeset
|
493 } |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
494 Right(fs_entry) => self.traverse_fs_only( |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
495 has_ignored_ancestor.force(&self.ignore_fn), |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
496 directory_hg_path, |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
497 fs_entry, |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
498 ), |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
499 }; |
47480
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
500 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
|
501 }) |
47480
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
502 .try_reduce(|| true, |a, b| Ok(a && b)) |
50294
bae51b50a5cf
dirstate-v2: fix an incorrect handling of readdir errors
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
50003
diff
changeset
|
503 .map(|res| res && readdir_succeeded) |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
504 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
505 |
49524
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
506 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
|
507 &self, |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
508 fs_entry: &DirEntry, |
47353
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47352
diff
changeset
|
509 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
|
510 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
|
511 ) -> Result<(), DirstateV2ParseError> { |
49547
8ee3889bab92
rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49546
diff
changeset
|
512 let outdated_dircache = |
8ee3889bab92
rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49546
diff
changeset
|
513 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
|
514 let hg_path = &dirstate_node.full_path_borrowed(self.dmap.on_disk)?; |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
515 let file_or_symlink = fs_entry.is_file() || fs_entry.is_symlink(); |
47128
aeb03758f37a
dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47127
diff
changeset
|
516 if !file_or_symlink { |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
517 // 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
|
518 // `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
|
519 // 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
|
520 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
|
521 } |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
522 if fs_entry.is_dir() { |
47128
aeb03758f37a
dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47127
diff
changeset
|
523 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
|
524 self.outcome |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47352
diff
changeset
|
525 .lock() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47352
diff
changeset
|
526 .unwrap() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47352
diff
changeset
|
527 .traversed |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47352
diff
changeset
|
528 .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
|
529 } |
49524
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
530 let is_ignored = HasIgnoredAncestor::create( |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
531 Some(has_ignored_ancestor), |
49524
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
532 hg_path, |
eb02decdf0ab
dirstate-v2: skip evaluation of hgignore regex on cached directories
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49400
diff
changeset
|
533 ); |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
534 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
|
535 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
|
536 .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
|
537 &is_ignored, |
47355
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
538 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
|
539 hg_path, |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
540 fs_entry, |
48205
320de901896a
dirstate-v2: Truncate directory mtimes to 31 bits of seconds
Simon Sapin <simon.sapin@octobus.net>
parents:
48204
diff
changeset
|
541 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
|
542 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
|
543 )?; |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
544 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
|
545 children_all_have_dirstate_node_or_are_ignored, |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
546 fs_entry, |
47355
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
547 dirstate_node, |
49547
8ee3889bab92
rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49546
diff
changeset
|
548 outdated_dircache, |
47343
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47341
diff
changeset
|
549 )? |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
550 } else { |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
551 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
|
552 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
|
553 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
|
554 // 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
|
555 // 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
|
556 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
|
557 has_ignored_ancestor.force(&self.ignore_fn), |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
558 hg_path, |
49197
c4ccd0346f5c
rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49196
diff
changeset
|
559 ); |
c4ccd0346f5c
rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49196
diff
changeset
|
560 } |
c4ccd0346f5c
rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49196
diff
changeset
|
561 if entry.added() { |
c4ccd0346f5c
rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49196
diff
changeset
|
562 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
|
563 } 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
|
564 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
|
565 } 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
|
566 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
|
567 } else { |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
568 self.handle_normal_file(&dirstate_node, fs_entry)?; |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
569 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
570 } else { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
571 // `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
|
572 // 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
|
573 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
|
574 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
|
575 hg_path, |
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
576 ); |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
577 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
578 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
579 |
47344
8d0260d0dbc9
dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents:
47343
diff
changeset
|
580 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
|
581 { |
47343
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47341
diff
changeset
|
582 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
|
583 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
584 } |
47343
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47341
diff
changeset
|
585 Ok(()) |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
586 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
587 |
49547
8ee3889bab92
rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49546
diff
changeset
|
588 /// 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
|
589 /// |
8ee3889bab92
rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49546
diff
changeset
|
590 /// `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
|
591 /// 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
|
592 /// 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
|
593 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
|
594 &self, |
47480
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
595 children_all_have_dirstate_node_or_are_ignored: bool, |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
596 directory_entry: &DirEntry, |
47355
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
597 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
|
598 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
|
599 ) -> Result<(), DirstateV2ParseError> { |
48538
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
600 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
|
601 return Ok(()); |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
602 } |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
603 // 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
|
604 // 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
|
605 // 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
|
606 |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
607 // 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
|
608 // 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
|
609 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
|
610 &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
|
611 { |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
612 status_start |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
613 } else { |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
614 return Ok(()); |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
615 }; |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
616 |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
617 // 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
|
618 // 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
|
619 // 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
|
620 // 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
|
621 // 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
|
622 // https://stackoverflow.com/a/14393315/1162888), etc. |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
623 let metadata = match directory_entry.symlink_metadata() { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
624 Ok(meta) => meta, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
625 Err(_) => return Ok(()), |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
626 }; |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
627 |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
628 let directory_mtime = match TruncatedTimestamp::for_reliable_mtime_of( |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
629 &metadata, |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
630 status_start, |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
631 ) { |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
632 Ok(Some(directory_mtime)) => directory_mtime, |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
633 Ok(None) => { |
48538
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
634 // 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
|
635 // 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
|
636 // |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
637 // 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
|
638 // 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
|
639 // (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
|
640 // 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
|
641 // 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
|
642 // 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
|
643 // 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
|
644 // 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
|
645 // |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
646 // 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
|
647 // 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
|
648 // by the same script. |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
649 return Ok(()); |
47355
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
650 } |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
651 Err(_) => { |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
652 // OS/libc does not support mtime? |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
653 return Ok(()); |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
654 } |
48538
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
655 }; |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
656 // 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
|
657 // “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
|
658 // 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
|
659 // different mtime. |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
660 // |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
661 // 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
|
662 // 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
|
663 // 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
|
664 // 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
|
665 // the wrong tick. |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
666 // |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
667 // 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
|
668 // unlikely enough in practice. |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
669 |
49547
8ee3889bab92
rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49546
diff
changeset
|
670 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
|
671 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
|
672 { |
8ee3889bab92
rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49546
diff
changeset
|
673 !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
|
674 } else { |
8ee3889bab92
rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49546
diff
changeset
|
675 false |
8ee3889bab92
rust-status: save new dircache even if just invalidated
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49546
diff
changeset
|
676 }; |
48538
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
677 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
|
678 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
|
679 .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
|
680 .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
|
681 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
|
682 .lock() |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
683 .unwrap() |
4afb9627dc77
dirstate-v2: Apply SECOND_AMBIGUOUS to directory mtimes too
Simon Sapin <simon.sapin@octobus.net>
parents:
48493
diff
changeset
|
684 .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
|
685 } |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
686 Ok(()) |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
687 } |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
688 |
49197
c4ccd0346f5c
rust-status: stop using `state()` in the dispatch logic
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49196
diff
changeset
|
689 /// 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
|
690 fn handle_normal_file( |
47131
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47129
diff
changeset
|
691 &self, |
47353
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47352
diff
changeset
|
692 dirstate_node: &NodeRef<'tree, 'on_disk>, |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
693 fs_entry: &DirEntry, |
47343
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47341
diff
changeset
|
694 ) -> Result<(), DirstateV2ParseError> { |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
695 // Keep the low 31 bits |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
696 fn truncate_u64(value: u64) -> i32 { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
697 (value & 0x7FFF_FFFF) as i32 |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
698 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
699 |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
700 let fs_metadata = match fs_entry.symlink_metadata() { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
701 Ok(meta) => meta, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
702 Err(_) => return Ok(()), |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
703 }; |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
704 |
47341
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47339
diff
changeset
|
705 let entry = dirstate_node |
47343
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47341
diff
changeset
|
706 .entry()? |
47341
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47339
diff
changeset
|
707 .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
|
708 let mode_changed = |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
709 || 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
|
710 let size = entry.size(); |
f2a9db29cb2d
rust: Make the fields of DirstateEntry private
Simon Sapin <simon.sapin@octobus.net>
parents:
47480
diff
changeset
|
711 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
|
712 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
|
713 // 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
|
714 // 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
|
715 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
|
716 } 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
|
717 || entry.is_from_other_parent() |
48044
f2a9db29cb2d
rust: Make the fields of DirstateEntry private
Simon Sapin <simon.sapin@octobus.net>
parents:
47480
diff
changeset
|
718 || (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
|
719 { |
48493
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
720 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
|
721 } else { |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
722 let mtime_looks_clean = if let Some(dirstate_mtime) = |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
723 entry.truncated_mtime() |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
724 { |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
725 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
|
726 .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
|
727 // 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
|
728 // 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
|
729 // 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
|
730 // 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
|
731 // can really do. |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
732 fs_mtime.likely_equal(dirstate_mtime) |
48271
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
48268
diff
changeset
|
733 } else { |
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
48268
diff
changeset
|
734 // No mtime in the dirstate entry |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
735 false |
48271
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
48268
diff
changeset
|
736 }; |
269ff8978086
dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
48268
diff
changeset
|
737 if !mtime_looks_clean { |
48493
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
738 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
|
739 } 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
|
740 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
|
741 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
742 } |
47343
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47341
diff
changeset
|
743 Ok(()) |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
744 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
745 |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
746 /// 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
|
747 fn traverse_dirstate_only( |
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47341
diff
changeset
|
748 &self, |
47353
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47352
diff
changeset
|
749 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
|
750 ) -> Result<(), DirstateV2ParseError> { |
47479
c657beacdf2e
dirstate-v2: Drop cached read_dir results after .hgignore changes
Simon Sapin <simon.sapin@octobus.net>
parents:
47415
diff
changeset
|
751 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
|
752 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
|
753 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
|
754 .children(self.dmap.on_disk)? |
47341
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47339
diff
changeset
|
755 .par_iter() |
47343
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47341
diff
changeset
|
756 .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
|
757 .collect() |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
758 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
759 |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
760 /// 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
|
761 /// filesystem |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
762 /// |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
763 /// Does nothing on a "directory" node |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
764 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
|
765 &self, |
48493
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
766 dirstate_node: &NodeRef<'tree, 'on_disk>, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
767 ) -> Result<(), DirstateV2ParseError> { |
49196
126d253eb274
rust-status: stop using `state()` in `handle_normal_file`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49183
diff
changeset
|
768 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
|
769 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
|
770 // 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
|
771 // 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
|
772 return Ok(()); |
126d253eb274
rust-status: stop using `state()` in `handle_normal_file`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49183
diff
changeset
|
773 } |
48493
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
774 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
|
775 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
|
776 if entry.removed() { |
48493
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
777 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
|
778 } else { |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
779 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
|
780 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
781 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
782 } |
48493
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
783 Ok(()) |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
784 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
785 |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
786 /// 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
|
787 /// |
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
788 /// 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
|
789 fn traverse_fs_only( |
47131
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47129
diff
changeset
|
790 &self, |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
791 has_ignored_ancestor: bool, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
792 directory_hg_path: &HgPath, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
793 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
|
794 ) -> bool { |
49717
6b32d39e9a67
rust-status: make `DirEntry` attributes clearer
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49524
diff
changeset
|
795 let hg_path = directory_hg_path.join(&fs_entry.hg_path); |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
796 let file_or_symlink = fs_entry.is_file() || fs_entry.is_symlink(); |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
797 if fs_entry.is_dir() { |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
798 let is_ignored = |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
799 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
|
800 let traverse_children = if is_ignored { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
801 // 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
|
802 self.options.list_ignored |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
803 } else { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
804 // 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
|
805 // ignored |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
806 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
|
807 }; |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
808 if traverse_children { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
809 let is_at_repo_root = false; |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
810 if let Ok(children_fs_entries) = |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
811 self.read_dir(&hg_path, &fs_entry.fs_path, is_at_repo_root) |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
812 { |
47131
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47129
diff
changeset
|
813 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
|
814 self.traverse_fs_only( |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47128
diff
changeset
|
815 is_ignored, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47128
diff
changeset
|
816 &hg_path, |
47131
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47129
diff
changeset
|
817 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
|
818 ); |
47131
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47129
diff
changeset
|
819 }) |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
820 } |
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
|
821 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
|
822 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
|
823 } |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
824 } |
47480
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
825 is_ignored |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
826 } else if file_or_symlink { |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
827 if self.matcher.matches(&hg_path) { |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
828 self.mark_unknown_or_ignored( |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
829 has_ignored_ancestor, |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
830 &BorrowedPath::InMemory(&hg_path), |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
831 ) |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
832 } else { |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
833 // We haven’t computed whether this path is ignored. It |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
834 // might not be, and a future run of status might have a |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
835 // different matcher that matches it. So treat it as not |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
836 // ignored. That is, inhibit readdir caching of the parent |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
837 // directory. |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
838 false |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
839 } |
47480
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
840 } else { |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
841 // This is neither a directory, a plain file, or a symlink. |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
842 // Treat it like an ignored file. |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
843 true |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
844 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
845 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
846 |
47480
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
847 /// 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
|
848 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
|
849 &self, |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
850 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
|
851 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
|
852 ) -> bool { |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
853 let is_ignored = has_ignored_ancestor || (self.ignore_fn)(hg_path); |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
854 if is_ignored { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
855 if self.options.list_ignored { |
48493
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
856 self.push_outcome_without_copy_source( |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
857 Outcome::Ignored, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
858 hg_path, |
473af5cbc209
rhg: Add support for `rhg status --copies`
Simon Sapin <simon.sapin@octobus.net>
parents:
48468
diff
changeset
|
859 ) |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
860 } |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
861 } else if self.options.list_unknown { |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49986
diff
changeset
|
862 self.push_outcome_without_copy_source(Outcome::Unknown, hg_path) |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
863 } |
47480
94e38822d395
status: Extend read_dir caching to directories with ignored files
Simon Sapin <simon.sapin@octobus.net>
parents:
47479
diff
changeset
|
864 is_ignored |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
865 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
866 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
867 |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
868 /// Since [`std::fs::FileType`] cannot be built directly, we emulate what we |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
869 /// care about. |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
870 #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
871 enum FakeFileType { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
872 File, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
873 Directory, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
874 Symlink, |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
875 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
876 |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
877 impl TryFrom<std::fs::FileType> for FakeFileType { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
878 type Error = (); |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
879 |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
880 fn try_from(f: std::fs::FileType) -> Result<Self, Self::Error> { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
881 if f.is_dir() { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
882 Ok(Self::Directory) |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
883 } else if f.is_file() { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
884 Ok(Self::File) |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
885 } else if f.is_symlink() { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
886 Ok(Self::Symlink) |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
887 } else { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
888 // Things like FIFO etc. |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
889 Err(()) |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
890 } |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
891 } |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
892 } |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
893 |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
894 struct DirEntry<'a> { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
895 /// Path as stored in the dirstate, or just the filename for optimization. |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
896 hg_path: HgPathCow<'a>, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
897 /// Filesystem path |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
898 fs_path: Cow<'a, Path>, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
899 /// Lazily computed |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
900 symlink_metadata: Option<std::fs::Metadata>, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
901 /// Already computed for ergonomics. |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
902 file_type: FakeFileType, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
903 } |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
904 |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
905 impl<'a> DirEntry<'a> { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
906 /// Returns **unsorted** entries in the given directory, with name, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
907 /// metadata and file type. |
47127
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 /// 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
|
910 /// |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
911 /// * 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
|
912 /// * 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
|
913 /// list instead. |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
914 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
|
915 // `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
|
916 let at_cwd = path == Path::new(""); |
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
917 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
|
918 let mut results = Vec::new(); |
48750
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
919 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
|
920 let entry = entry?; |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
921 let file_type = match entry.file_type() { |
48378
dcec16e799dd
status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48274
diff
changeset
|
922 Ok(v) => v, |
dcec16e799dd
status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48274
diff
changeset
|
923 Err(e) => { |
dcec16e799dd
status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48274
diff
changeset
|
924 // race with file deletion? |
dcec16e799dd
status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48274
diff
changeset
|
925 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
|
926 continue; |
dcec16e799dd
status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48274
diff
changeset
|
927 } else { |
dcec16e799dd
status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48274
diff
changeset
|
928 return Err(e); |
dcec16e799dd
status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48274
diff
changeset
|
929 } |
dcec16e799dd
status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48274
diff
changeset
|
930 } |
dcec16e799dd
status: fix hg status race against file deletion
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48274
diff
changeset
|
931 }; |
48750
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
932 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
|
933 // 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
|
934 if file_name == ".hg" { |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
935 if is_at_repo_root { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
936 // 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
|
937 continue; |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
938 } else if file_type.is_dir() { |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
939 // 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
|
940 // skip it entirely. |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
941 return Ok(Vec::new()); |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
942 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
943 } |
48750
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
944 let full_path = if at_cwd { |
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
945 file_name.clone().into() |
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
946 } else { |
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
947 entry.path() |
94e36b230990
status: prefer relative paths in Rust code
Simon Sapin <simon.sapin@octobus.net>
parents:
48538
diff
changeset
|
948 }; |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
949 let filename = |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
950 Cow::Owned(get_bytes_from_os_string(file_name).into()); |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
951 let file_type = match FakeFileType::try_from(file_type) { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
952 Ok(file_type) => file_type, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
953 Err(_) => continue, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
954 }; |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
955 results.push(DirEntry { |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
956 hg_path: filename, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
957 fs_path: Cow::Owned(full_path.to_path_buf()), |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
958 symlink_metadata: None, |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
959 file_type, |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
960 }) |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
961 } |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
962 Ok(results) |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
963 } |
49718
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
964 |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
965 fn symlink_metadata(&self) -> Result<std::fs::Metadata, std::io::Error> { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
966 match &self.symlink_metadata { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
967 Some(meta) => Ok(meta.clone()), |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
968 None => std::fs::symlink_metadata(&self.fs_path), |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
969 } |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
970 } |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
971 |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
972 fn is_dir(&self) -> bool { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
973 self.file_type == FakeFileType::Directory |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
974 } |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
975 |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
976 fn is_file(&self) -> bool { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
977 self.file_type == FakeFileType::File |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
978 } |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
979 |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
980 fn is_symlink(&self) -> bool { |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
981 self.file_type == FakeFileType::Symlink |
da48f170d203
rust-status: query fs traversal metadata lazily
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49717
diff
changeset
|
982 } |
47127
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47126
diff
changeset
|
983 } |
47355
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
984 |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
985 /// 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
|
986 /// 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
|
987 /// |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
988 /// 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
|
989 /// 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
|
990 /// 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
|
991 /// 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
|
992 /// 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
|
993 /// 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
|
994 /// |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
995 /// 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
|
996 /// 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
|
997 /// 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
|
998 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
|
999 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
|
1000 .metadata()? |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
1001 .modified() |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47353
diff
changeset
|
1002 } |