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