author | Simon Sapin <simon.sapin@octobus.net> |
Fri, 28 May 2021 11:48:59 +0200 | |
changeset 47349 | 7138c863d0a1 |
parent 47347 | 73ddcedeaadf |
child 47350 | 04d1f17f49e7 |
permissions | -rw-r--r-- |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
1 |
use crate::dirstate::status::IgnoreFnType; |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
2 |
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
|
3 |
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
|
4 |
use crate::dirstate_tree::dirstate_map::DirstateMap; |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
5 |
use crate::dirstate_tree::dirstate_map::NodeData; |
47333
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47331
diff
changeset
|
6 |
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
|
7 |
use crate::dirstate_tree::on_disk::DirstateV2ParseError; |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
8 |
use crate::dirstate_tree::on_disk::Timestamp; |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
9 |
use crate::dirstate_tree::path_with_basename::WithBasename; |
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; |
47112
d5956136d19d
dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
11 |
use crate::matchers::Matcher; |
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; |
47338
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
13 |
use crate::utils::files::get_path_from_bytes; |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
14 |
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
|
15 |
use crate::BadMatch; |
47112
d5956136d19d
dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
16 |
use crate::DirstateStatus; |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
17 |
use crate::EntryState; |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
18 |
use crate::HgPathBuf; |
47112
d5956136d19d
dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
19 |
use crate::PatternFileWarning; |
d5956136d19d
dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
20 |
use crate::StatusError; |
d5956136d19d
dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
21 |
use crate::StatusOptions; |
47118
c92e63762573
dirstate-tree: Add #[timed] attribute to `status` and `DirstateMap::read`
Simon Sapin <simon.sapin@octobus.net>
parents:
47117
diff
changeset
|
22 |
use micro_timer::timed; |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
23 |
use rayon::prelude::*; |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
24 |
use std::borrow::Cow; |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
25 |
use std::io; |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
26 |
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
|
27 |
use std::path::PathBuf; |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
28 |
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
|
29 |
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
|
30 |
|
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
31 |
/// 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
|
32 |
/// changeset. |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
33 |
/// |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
34 |
/// 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
|
35 |
/// 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
|
36 |
/// 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
|
37 |
/// 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
|
38 |
/// 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
|
39 |
/// `options` we may need to traverse the remaining subtree. |
47118
c92e63762573
dirstate-tree: Add #[timed] attribute to `status` and `DirstateMap::read`
Simon Sapin <simon.sapin@octobus.net>
parents:
47117
diff
changeset
|
40 |
#[timed] |
47336
8d0260d0dbc9
dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents:
47335
diff
changeset
|
41 |
pub fn status<'tree, 'on_disk: 'tree>( |
8d0260d0dbc9
dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents:
47335
diff
changeset
|
42 |
dmap: &'tree mut DirstateMap<'on_disk>, |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
43 |
matcher: &(dyn Matcher + Sync), |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
44 |
root_dir: PathBuf, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
45 |
ignore_files: Vec<PathBuf>, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
46 |
options: StatusOptions, |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
47 |
) -> Result<(DirstateStatus<'on_disk>, Vec<PatternFileWarning>), StatusError> { |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
48 |
let (ignore_fn, warnings): (IgnoreFnType, _) = |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
49 |
if options.list_ignored || options.list_unknown { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
50 |
get_ignore_function(ignore_files, &root_dir)? |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
51 |
} else { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
52 |
(Box::new(|&_| true), vec![]) |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
53 |
}; |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
54 |
|
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
55 |
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
|
56 |
dmap, |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
57 |
options, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
58 |
matcher, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
59 |
ignore_fn, |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
60 |
outcome: Default::default(), |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
61 |
cached_directory_mtimes_to_add: Default::default(), |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
62 |
filesystem_time_at_status_start: filesystem_now(&root_dir).ok(), |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
63 |
}; |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
64 |
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
|
65 |
let hg_path = &BorrowedPath::OnDisk(HgPath::new("")); |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
66 |
let has_ignored_ancestor = false; |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
67 |
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
|
68 |
let root_dir_metadata = None; |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
69 |
// 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
|
70 |
// (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
|
71 |
// 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
|
72 |
common.traverse_fs_directory_and_dirstate( |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
73 |
has_ignored_ancestor, |
47333
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47331
diff
changeset
|
74 |
dmap.root.as_ref(), |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
75 |
hg_path, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
76 |
&root_dir, |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
77 |
root_dir_metadata, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
78 |
root_cached_mtime, |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
79 |
is_at_repo_root, |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
80 |
)?; |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
81 |
let outcome = common.outcome.into_inner().unwrap(); |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
82 |
let to_add = common.cached_directory_mtimes_to_add.into_inner().unwrap(); |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
83 |
for (path, mtime) in &to_add { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
84 |
let node = DirstateMap::get_or_insert_node( |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
85 |
dmap.on_disk, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
86 |
&mut dmap.root, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
87 |
path, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
88 |
WithBasename::to_cow_owned, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
89 |
|_| {}, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
90 |
)?; |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
91 |
match &node.data { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
92 |
NodeData::Entry(_) => {} // Don’t overwrite an entry |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
93 |
NodeData::CachedDirectory { .. } | NodeData::None => { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
94 |
node.data = NodeData::CachedDirectory { mtime: *mtime } |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
95 |
} |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
96 |
} |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
97 |
} |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
98 |
Ok((outcome, warnings)) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
99 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
100 |
|
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
101 |
/// 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
|
102 |
/// 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
|
103 |
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
|
104 |
dmap: &'tree DirstateMap<'on_disk>, |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
105 |
options: StatusOptions, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
106 |
matcher: &'a (dyn Matcher + Sync), |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
107 |
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
|
108 |
outcome: Mutex<DirstateStatus<'on_disk>>, |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
109 |
cached_directory_mtimes_to_add: |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
110 |
Mutex<Vec<(Cow<'on_disk, HgPath>, Timestamp)>>, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
111 |
|
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
112 |
/// 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
|
113 |
/// and possibly truncated by the filesystem. |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
114 |
filesystem_time_at_status_start: Option<SystemTime>, |
47112
d5956136d19d
dirstate-tree: Give to `status()` mutable access to the `DirstateMap`
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
115 |
} |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
116 |
|
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
117 |
impl<'a, 'tree, 'on_disk> StatusCommon<'a, 'tree, 'on_disk> { |
47115
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
118 |
fn read_dir( |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
119 |
&self, |
47115
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
120 |
hg_path: &HgPath, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
121 |
fs_path: &Path, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
122 |
is_at_repo_root: bool, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
123 |
) -> Result<Vec<DirEntry>, ()> { |
47338
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
124 |
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
|
125 |
.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
|
126 |
} |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
127 |
|
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
128 |
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
|
129 |
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
|
130 |
self.outcome |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
131 |
.lock() |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
132 |
.unwrap() |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
133 |
.bad |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
134 |
.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
|
135 |
} |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
136 |
|
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
137 |
/// 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
|
138 |
/// `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
|
139 |
/// 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
|
140 |
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
|
141 |
&self, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
142 |
directory_metadata: Option<&std::fs::Metadata>, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
143 |
cached_directory_mtime: Option<&Timestamp>, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
144 |
) -> bool { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
145 |
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
|
146 |
// 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
|
147 |
// dirstate entries. |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
148 |
// 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
|
149 |
return true; |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
150 |
} |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
151 |
if let Some(cached_mtime) = cached_directory_mtime { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
152 |
// The dirstate contains a cached mtime for this directory, set by |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
153 |
// a previous run of the `status` algorithm which found this |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
154 |
// directory eligible for `read_dir` caching. |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
155 |
if let Some(meta) = directory_metadata { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
156 |
if let Ok(current_mtime) = meta.modified() { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
157 |
if current_mtime == cached_mtime.into() { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
158 |
// The mtime of that directory has not changed since |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
159 |
// then, which means that the |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
160 |
// results of `read_dir` should also |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
161 |
// be unchanged. |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
162 |
return true; |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
163 |
} |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
164 |
} |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
165 |
} |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
166 |
} |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
167 |
false |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
168 |
} |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
169 |
|
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
170 |
/// Returns whether the filesystem directory was found to have any entry |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
171 |
/// that does not have a corresponding dirstate tree node. |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
172 |
fn traverse_fs_directory_and_dirstate( |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
173 |
&self, |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
174 |
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
|
175 |
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
|
176 |
directory_hg_path: &BorrowedPath<'tree, 'on_disk>, |
47115
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
177 |
directory_fs_path: &Path, |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
178 |
directory_metadata: Option<&std::fs::Metadata>, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
179 |
cached_directory_mtime: Option<&Timestamp>, |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
180 |
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
|
181 |
) -> Result<bool, DirstateV2ParseError> { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
182 |
if self.can_skip_fs_readdir(directory_metadata, cached_directory_mtime) |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
183 |
{ |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
184 |
dirstate_nodes |
47338
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
185 |
.par_iter() |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
186 |
.map(|dirstate_node| { |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
187 |
let fs_path = directory_fs_path.join(get_path_from_bytes( |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
188 |
dirstate_node.base_name(self.dmap.on_disk)?.as_bytes(), |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
189 |
)); |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
190 |
match std::fs::symlink_metadata(&fs_path) { |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
191 |
Ok(fs_metadata) => self.traverse_fs_and_dirstate( |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
192 |
&fs_path, |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
193 |
&fs_metadata, |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
194 |
dirstate_node, |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
195 |
has_ignored_ancestor, |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
196 |
), |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
197 |
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
|
198 |
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
|
199 |
} |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
200 |
Err(error) => { |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
201 |
let hg_path = |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
202 |
dirstate_node.full_path(self.dmap.on_disk)?; |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
203 |
Ok(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
|
204 |
} |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
205 |
} |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
206 |
}) |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
207 |
.collect::<Result<_, _>>()?; |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
208 |
|
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
209 |
// Conservatively don’t let the caller assume that there aren’t |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
210 |
// any, since we don’t know. |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
211 |
let directory_has_any_fs_only_entry = true; |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
212 |
|
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
213 |
return Ok(directory_has_any_fs_only_entry); |
47338
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
214 |
} |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
215 |
|
47115
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
216 |
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
|
217 |
directory_hg_path, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
218 |
directory_fs_path, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
219 |
is_at_repo_root, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
220 |
) { |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
221 |
entries |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
222 |
} else { |
47346
5e12b6bfdd3e
dirstate-tree: Fix status algorithm with unreadable directory
Simon Sapin <simon.sapin@octobus.net>
parents:
47338
diff
changeset
|
223 |
// 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
|
224 |
// 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
|
225 |
// already called `self.io_error` so a warning will be emitted. |
5e12b6bfdd3e
dirstate-tree: Fix status algorithm with unreadable directory
Simon Sapin <simon.sapin@octobus.net>
parents:
47338
diff
changeset
|
226 |
Vec::new() |
47115
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
227 |
}; |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
228 |
|
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
229 |
// `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
|
230 |
|
47333
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47331
diff
changeset
|
231 |
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
|
232 |
// `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
|
233 |
// https://github.com/rust-lang/rust/issues/34162 |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
234 |
fs_entries.sort_unstable_by(|e1, e2| e1.base_name.cmp(&e2.base_name)); |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
235 |
|
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
236 |
// 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
|
237 |
// callback below |
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
238 |
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
|
239 |
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
|
240 |
} |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
241 |
itertools::merge_join_by( |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
242 |
dirstate_nodes, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
243 |
&fs_entries, |
47333
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47331
diff
changeset
|
244 |
|dirstate_node, fs_entry| { |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
245 |
// 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
|
246 |
// 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
|
247 |
dirstate_node |
8d0260d0dbc9
dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents:
47335
diff
changeset
|
248 |
.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
|
249 |
.unwrap() |
8d0260d0dbc9
dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents:
47335
diff
changeset
|
250 |
.cmp(&fs_entry.base_name) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
251 |
}, |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
252 |
) |
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
253 |
.par_bridge() |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
254 |
.map(|pair| { |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
255 |
use itertools::EitherOrBoth::*; |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
256 |
let is_fs_only = pair.is_right(); |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
257 |
match pair { |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
258 |
Both(dirstate_node, fs_entry) => self |
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
259 |
.traverse_fs_and_dirstate( |
47338
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
260 |
&fs_entry.full_path, |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
261 |
&fs_entry.metadata, |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
262 |
dirstate_node, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
263 |
has_ignored_ancestor, |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
264 |
)?, |
47333
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47331
diff
changeset
|
265 |
Left(dirstate_node) => { |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
266 |
self.traverse_dirstate_only(dirstate_node)? |
47333
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47331
diff
changeset
|
267 |
} |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
268 |
Right(fs_entry) => self.traverse_fs_only( |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
269 |
has_ignored_ancestor, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
270 |
directory_hg_path, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
271 |
fs_entry, |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
272 |
), |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
273 |
} |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
274 |
Ok(is_fs_only) |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
275 |
}) |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
276 |
.try_reduce(|| false, |a, b| Ok(a || b)) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
277 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
278 |
|
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
279 |
fn traverse_fs_and_dirstate( |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
280 |
&self, |
47338
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
281 |
fs_path: &Path, |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
282 |
fs_metadata: &std::fs::Metadata, |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
283 |
dirstate_node: NodeRef<'tree, 'on_disk>, |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
284 |
has_ignored_ancestor: bool, |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
285 |
) -> Result<(), DirstateV2ParseError> { |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
286 |
let hg_path = &dirstate_node.full_path_borrowed(self.dmap.on_disk)?; |
47338
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
287 |
let file_type = fs_metadata.file_type(); |
47114
aeb03758f37a
dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47113
diff
changeset
|
288 |
let file_or_symlink = file_type.is_file() || file_type.is_symlink(); |
aeb03758f37a
dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47113
diff
changeset
|
289 |
if !file_or_symlink { |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
290 |
// 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
|
291 |
// `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
|
292 |
// replaced by a directory or something else. |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
293 |
self.mark_removed_or_deleted_if_file( |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
294 |
&hg_path, |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
295 |
dirstate_node.state()?, |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
296 |
); |
47114
aeb03758f37a
dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47113
diff
changeset
|
297 |
} |
aeb03758f37a
dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47113
diff
changeset
|
298 |
if file_type.is_dir() { |
aeb03758f37a
dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47113
diff
changeset
|
299 |
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
|
300 |
self.outcome |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
301 |
.lock() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
302 |
.unwrap() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
303 |
.traversed |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
304 |
.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
|
305 |
} |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
306 |
let is_ignored = has_ignored_ancestor || (self.ignore_fn)(hg_path); |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
307 |
let is_at_repo_root = false; |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
308 |
let directory_has_any_fs_only_entry = self |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
309 |
.traverse_fs_directory_and_dirstate( |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
310 |
is_ignored, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
311 |
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
|
312 |
hg_path, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
313 |
fs_path, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
314 |
Some(fs_metadata), |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
315 |
dirstate_node.cached_directory_mtime(), |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
316 |
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
|
317 |
)?; |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
318 |
self.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
|
319 |
directory_has_any_fs_only_entry, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
320 |
fs_metadata, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
321 |
dirstate_node, |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
322 |
)? |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
323 |
} else { |
47114
aeb03758f37a
dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47113
diff
changeset
|
324 |
if file_or_symlink && self.matcher.matches(hg_path) { |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
325 |
if let Some(state) = dirstate_node.state()? { |
47333
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47331
diff
changeset
|
326 |
match state { |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
327 |
EntryState::Added => self |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
328 |
.outcome |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
329 |
.lock() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
330 |
.unwrap() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
331 |
.added |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
332 |
.push(hg_path.detach_from_tree()), |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
333 |
EntryState::Removed => self |
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
334 |
.outcome |
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
335 |
.lock() |
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
336 |
.unwrap() |
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
337 |
.removed |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
338 |
.push(hg_path.detach_from_tree()), |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
339 |
EntryState::Merged => self |
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
340 |
.outcome |
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
341 |
.lock() |
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
342 |
.unwrap() |
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
343 |
.modified |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
344 |
.push(hg_path.detach_from_tree()), |
47338
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
345 |
EntryState::Normal => self |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
346 |
.handle_normal_file(&dirstate_node, fs_metadata)?, |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
347 |
// This variant is not used in DirstateMap |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
348 |
// nodes |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
349 |
EntryState::Unknown => unreachable!(), |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
350 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
351 |
} else { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
352 |
// `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
|
353 |
// node, but the filesystem has a file |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
354 |
self.mark_unknown_or_ignored(has_ignored_ancestor, hg_path) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
355 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
356 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
357 |
|
47336
8d0260d0dbc9
dirstate-v2: Make the dirstate bytes buffer available in more places
Simon Sapin <simon.sapin@octobus.net>
parents:
47335
diff
changeset
|
358 |
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
|
359 |
{ |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
360 |
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
|
361 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
362 |
} |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
363 |
Ok(()) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
364 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
365 |
|
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
366 |
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
|
367 |
&self, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
368 |
directory_has_any_fs_only_entry: bool, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
369 |
directory_metadata: &std::fs::Metadata, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
370 |
dirstate_node: NodeRef<'tree, 'on_disk>, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
371 |
) -> Result<(), DirstateV2ParseError> { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
372 |
if !directory_has_any_fs_only_entry { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
373 |
// All filesystem directory entries from `read_dir` have a |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
374 |
// corresponding node in the dirstate, so we can reconstitute the |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
375 |
// names of those entries without calling `read_dir` again. |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
376 |
if let (Some(status_start), Ok(directory_mtime)) = ( |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
377 |
&self.filesystem_time_at_status_start, |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
378 |
directory_metadata.modified(), |
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 |
// Although the Rust standard library’s `SystemTime` type |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
381 |
// has nanosecond precision, the times reported for a |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
382 |
// directory’s (or file’s) modified time may have lower |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
383 |
// resolution based on the filesystem (for example ext3 |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
384 |
// only stores integer seconds), kernel (see |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
385 |
// https://stackoverflow.com/a/14393315/1162888), etc. |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
386 |
if &directory_mtime >= status_start { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
387 |
// The directory was modified too recently, don’t cache its |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
388 |
// `read_dir` results. |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
389 |
// |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
390 |
// A timeline like this is possible: |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
391 |
// |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
392 |
// 1. A change to this directory (direct child was |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
393 |
// added or removed) cause its mtime to be set |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
394 |
// (possibly truncated) to `directory_mtime` |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
395 |
// 2. This `status` algorithm calls `read_dir` |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
396 |
// 3. An other change is made to the same directory is |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
397 |
// made so that calling `read_dir` agin would give |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
398 |
// different results, but soon enough after 1. that |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
399 |
// the mtime stays the same |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
400 |
// |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
401 |
// On a system where the time resolution poor, this |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
402 |
// scenario is not unlikely if all three steps are caused |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
403 |
// by the same script. |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
404 |
} else { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
405 |
// We’ve observed (through `status_start`) that time has |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
406 |
// “progressed” since `directory_mtime`, so any further |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
407 |
// change to this directory is extremely likely to cause a |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
408 |
// different mtime. |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
409 |
// |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
410 |
// Having the same mtime again is not entirely impossible |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
411 |
// since the system clock is not monotonous. It could jump |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
412 |
// backward to some point before `directory_mtime`, then a |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
413 |
// directory change could potentially happen during exactly |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
414 |
// the wrong tick. |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
415 |
// |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
416 |
// We deem this scenario (unlike the previous one) to be |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
417 |
// unlikely enough in practice. |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
418 |
let timestamp = directory_mtime.into(); |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
419 |
let cached = dirstate_node.cached_directory_mtime(); |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
420 |
if cached != Some(×tamp) { |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
421 |
let hg_path = dirstate_node |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
422 |
.full_path_borrowed(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
|
423 |
.detach_from_tree(); |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
424 |
self.cached_directory_mtimes_to_add |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
425 |
.lock() |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
426 |
.unwrap() |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
427 |
.push((hg_path, timestamp)) |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
428 |
} |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
429 |
} |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
430 |
} |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
431 |
} |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
432 |
Ok(()) |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
433 |
} |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
434 |
|
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
435 |
/// A file with `EntryState::Normal` in the dirstate was found in the |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
436 |
/// filesystem |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
437 |
fn handle_normal_file( |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
438 |
&self, |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
439 |
dirstate_node: &NodeRef<'tree, 'on_disk>, |
47338
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
440 |
fs_metadata: &std::fs::Metadata, |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
441 |
) -> Result<(), DirstateV2ParseError> { |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
442 |
// Keep the low 31 bits |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
443 |
fn truncate_u64(value: u64) -> i32 { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
444 |
(value & 0x7FFF_FFFF) as i32 |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
445 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
446 |
fn truncate_i64(value: i64) -> i32 { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
447 |
(value & 0x7FFF_FFFF) as i32 |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
448 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
449 |
|
47333
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47331
diff
changeset
|
450 |
let entry = dirstate_node |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
451 |
.entry()? |
47333
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47331
diff
changeset
|
452 |
.expect("handle_normal_file called with entry-less node"); |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
453 |
let hg_path = &dirstate_node.full_path_borrowed(self.dmap.on_disk)?; |
47338
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
454 |
let mode_changed = |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
455 |
|| self.options.check_exec && entry.mode_changed(fs_metadata); |
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
456 |
let size_changed = entry.size != truncate_u64(fs_metadata.len()); |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
457 |
if entry.size >= 0 |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
458 |
&& size_changed |
47338
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
459 |
&& 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
|
460 |
{ |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
461 |
// 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
|
462 |
// on EXT-4 fscrypt. TODO maybe only do it on EXT4? |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
463 |
self.outcome |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
464 |
.lock() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
465 |
.unwrap() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
466 |
.unsure |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
467 |
.push(hg_path.detach_from_tree()) |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
468 |
} 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
|
469 |
|| entry.is_from_other_parent() |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
470 |
|| (entry.size >= 0 && (size_changed || mode_changed())) |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
471 |
{ |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
472 |
self.outcome |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
473 |
.lock() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
474 |
.unwrap() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
475 |
.modified |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
476 |
.push(hg_path.detach_from_tree()) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
477 |
} else { |
47338
f27f2afb15da
dirstate-tree: Skip readdir() in `hg status -mard`
Simon Sapin <simon.sapin@octobus.net>
parents:
47336
diff
changeset
|
478 |
let mtime = mtime_seconds(fs_metadata); |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
479 |
if truncate_i64(mtime) != entry.mtime |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
480 |
|| mtime == self.options.last_normal_time |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
481 |
{ |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
482 |
self.outcome |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
483 |
.lock() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
484 |
.unwrap() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
485 |
.unsure |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
486 |
.push(hg_path.detach_from_tree()) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
487 |
} else if self.options.list_clean { |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
488 |
self.outcome |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
489 |
.lock() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
490 |
.unwrap() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
491 |
.clean |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
492 |
.push(hg_path.detach_from_tree()) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
493 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
494 |
} |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
495 |
Ok(()) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
496 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
497 |
|
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
498 |
/// 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
|
499 |
fn traverse_dirstate_only( |
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
500 |
&self, |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
501 |
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
|
502 |
) -> Result<(), DirstateV2ParseError> { |
47333
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47331
diff
changeset
|
503 |
self.mark_removed_or_deleted_if_file( |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
504 |
&dirstate_node.full_path_borrowed(self.dmap.on_disk)?, |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
505 |
dirstate_node.state()?, |
47333
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47331
diff
changeset
|
506 |
); |
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47331
diff
changeset
|
507 |
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
|
508 |
.children(self.dmap.on_disk)? |
47333
69530e5d4fe5
dirstate-tree: Add `NodeRef` and `ChildNodesRef` enums
Simon Sapin <simon.sapin@octobus.net>
parents:
47331
diff
changeset
|
509 |
.par_iter() |
47335
ed1583a845d2
dirstate-v2: Make more APIs fallible, returning Result
Simon Sapin <simon.sapin@octobus.net>
parents:
47333
diff
changeset
|
510 |
.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
|
511 |
.collect() |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
512 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
513 |
|
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
514 |
/// 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
|
515 |
/// filesystem |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
516 |
/// |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
517 |
/// Does nothing on a "directory" node |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
518 |
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
|
519 |
&self, |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
520 |
hg_path: &BorrowedPath<'tree, 'on_disk>, |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
521 |
dirstate_node_state: Option<EntryState>, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
522 |
) { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
523 |
if let Some(state) = dirstate_node_state { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
524 |
if self.matcher.matches(hg_path) { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
525 |
if let EntryState::Removed = state { |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
526 |
self.outcome |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
527 |
.lock() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
528 |
.unwrap() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
529 |
.removed |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
530 |
.push(hg_path.detach_from_tree()) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
531 |
} else { |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
532 |
self.outcome |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
533 |
.lock() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
534 |
.unwrap() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
535 |
.deleted |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
536 |
.push(hg_path.detach_from_tree()) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
537 |
} |
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 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
540 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
541 |
|
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
542 |
/// Something in the filesystem has no corresponding dirstate node |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
543 |
fn traverse_fs_only( |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
544 |
&self, |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
545 |
has_ignored_ancestor: bool, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
546 |
directory_hg_path: &HgPath, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
547 |
fs_entry: &DirEntry, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
548 |
) { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
549 |
let hg_path = directory_hg_path.join(&fs_entry.base_name); |
47114
aeb03758f37a
dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47113
diff
changeset
|
550 |
let file_type = fs_entry.metadata.file_type(); |
aeb03758f37a
dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47113
diff
changeset
|
551 |
let file_or_symlink = file_type.is_file() || file_type.is_symlink(); |
aeb03758f37a
dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47113
diff
changeset
|
552 |
if file_type.is_dir() { |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
553 |
let is_ignored = |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
554 |
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
|
555 |
let traverse_children = if is_ignored { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
556 |
// 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
|
557 |
self.options.list_ignored |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
558 |
} else { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
559 |
// 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
|
560 |
// ignored |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
561 |
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
|
562 |
}; |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
563 |
if traverse_children { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
564 |
let is_at_repo_root = false; |
47115
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
565 |
if let Ok(children_fs_entries) = self.read_dir( |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
566 |
&hg_path, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
567 |
&fs_entry.full_path, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
568 |
is_at_repo_root, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
569 |
) { |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
570 |
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
|
571 |
self.traverse_fs_only( |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
572 |
is_ignored, |
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
573 |
&hg_path, |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
574 |
child_fs_entry, |
47115
1b4f0f819f92
dirstate-tree: Handle I/O errors in status
Simon Sapin <simon.sapin@octobus.net>
parents:
47114
diff
changeset
|
575 |
) |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
576 |
}) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
577 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
578 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
579 |
if self.options.collect_traversed_dirs { |
47117
60d852ae7e7b
dirstate-tree: Paralellize the status algorithm with Rayon
Simon Sapin <simon.sapin@octobus.net>
parents:
47115
diff
changeset
|
580 |
self.outcome.lock().unwrap().traversed.push(hg_path.into()) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
581 |
} |
47114
aeb03758f37a
dirstate-tree: Ignore FIFOs etc. in the status algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47113
diff
changeset
|
582 |
} else if file_or_symlink && self.matcher.matches(&hg_path) { |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
583 |
self.mark_unknown_or_ignored( |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
584 |
has_ignored_ancestor, |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
585 |
&BorrowedPath::InMemory(&hg_path), |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
586 |
) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
587 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
588 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
589 |
|
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
590 |
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
|
591 |
&self, |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
592 |
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
|
593 |
hg_path: &BorrowedPath<'_, 'on_disk>, |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
594 |
) { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
595 |
let is_ignored = has_ignored_ancestor || (self.ignore_fn)(&hg_path); |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
596 |
if is_ignored { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
597 |
if self.options.list_ignored { |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
598 |
self.outcome |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
599 |
.lock() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
600 |
.unwrap() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
601 |
.ignored |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
602 |
.push(hg_path.detach_from_tree()) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
603 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
604 |
} else { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
605 |
if self.options.list_unknown { |
47347
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
606 |
self.outcome |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
607 |
.lock() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
608 |
.unwrap() |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
609 |
.unknown |
73ddcedeaadf
dirstate-tree: Change status() results to not borrow DirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents:
47346
diff
changeset
|
610 |
.push(hg_path.detach_from_tree()) |
47113
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
611 |
} |
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 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
614 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
615 |
|
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
616 |
#[cfg(unix)] // TODO |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
617 |
fn mtime_seconds(metadata: &std::fs::Metadata) -> i64 { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
618 |
// Going through `Metadata::modified()` would be portable, but would take |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
619 |
// care to construct a `SystemTime` value with sub-second precision just |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
620 |
// for us to throw that away here. |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
621 |
use std::os::unix::fs::MetadataExt; |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
622 |
metadata.mtime() |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
623 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
624 |
|
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
625 |
struct DirEntry { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
626 |
base_name: HgPathBuf, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
627 |
full_path: PathBuf, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
628 |
metadata: std::fs::Metadata, |
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 |
|
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
631 |
impl DirEntry { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
632 |
/// Returns **unsorted** entries in the given directory, with name and |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
633 |
/// metadata. |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
634 |
/// |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
635 |
/// 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
|
636 |
/// |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
637 |
/// * 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
|
638 |
/// * 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
|
639 |
/// list instead. |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
640 |
fn read_dir(path: &Path, is_at_repo_root: bool) -> io::Result<Vec<Self>> { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
641 |
let mut results = Vec::new(); |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
642 |
for entry in path.read_dir()? { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
643 |
let entry = entry?; |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
644 |
let metadata = entry.metadata()?; |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
645 |
let name = get_bytes_from_os_string(entry.file_name()); |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
646 |
// FIXME don't do this when cached |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
647 |
if name == b".hg" { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
648 |
if is_at_repo_root { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
649 |
// 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
|
650 |
continue; |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
651 |
} else if metadata.is_dir() { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
652 |
// 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
|
653 |
// skip it entirely. |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
654 |
return Ok(Vec::new()); |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
655 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
656 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
657 |
results.push(DirEntry { |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
658 |
base_name: name.into(), |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
659 |
full_path: entry.path(), |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
660 |
metadata, |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
661 |
}) |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
662 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
663 |
Ok(results) |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
664 |
} |
be579775c2d9
dirstate-tree: Add the new `status()` algorithm
Simon Sapin <simon.sapin@octobus.net>
parents:
47112
diff
changeset
|
665 |
} |
47349
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
666 |
|
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
667 |
/// 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
|
668 |
/// 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
|
669 |
/// |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
670 |
/// 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
|
671 |
/// 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
|
672 |
/// 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
|
673 |
/// 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
|
674 |
/// 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
|
675 |
/// 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
|
676 |
/// |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
677 |
/// 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
|
678 |
/// 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
|
679 |
/// 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
|
680 |
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
|
681 |
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
|
682 |
.metadata()? |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
683 |
.modified() |
7138c863d0a1
dirstate-v2: Skip readdir in status based on directory mtime
Simon Sapin <simon.sapin@octobus.net>
parents:
47347
diff
changeset
|
684 |
} |