Mercurial > public > mercurial-scm > hg-stable
annotate rust/hg-core/src/update.rs @ 52334:db065b33fa56
rust-dirstate: merge `dirstate_tree` module into `dirstate`
The historical reasonning for `dirstate_tree` existing in the first place is
that a new approach was needed for the tree-like dirstate and it was easier
to start somewhat fresh. Now that the former dirstate is (long) gone, we
can merge those two modules to avoid the confusion that even the module
creators sometimes get.
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Mon, 04 Nov 2024 11:00:58 +0100 |
parents | 65d516db7309 |
children | b422acba55f1 |
rev | line source |
---|---|
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
1 //! Tools for moving the repository to a given revision |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
2 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
3 use std::{ |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
4 fs::Permissions, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
5 io::Write, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
6 os::unix::fs::{MetadataExt, PermissionsExt}, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
7 path::Path, |
52183
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
8 sync::atomic::Ordering, |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
9 time::Duration, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
10 }; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
11 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
12 use crate::{ |
52334
db065b33fa56
rust-dirstate: merge `dirstate_tree` module into `dirstate`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52313
diff
changeset
|
13 dirstate::{dirstate_map::DirstateEntryReset, on_disk::write_tracked_key}, |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
14 dirstate::{ParentFileData, TruncatedTimestamp}, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
15 errors::{HgError, IoResultExt}, |
52308
bd8081e9fd62
rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52286
diff
changeset
|
16 exit_codes, narrow, |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
17 operations::{list_rev_tracked_files, ExpandedManifestEntry}, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
18 progress::Progress, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
19 repo::Repo, |
52308
bd8081e9fd62
rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52286
diff
changeset
|
20 revlog::filelog::Filelog, |
bd8081e9fd62
rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52286
diff
changeset
|
21 revlog::node::NULL_NODE, |
bd8081e9fd62
rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52286
diff
changeset
|
22 revlog::options::{default_revlog_options, RevlogOpenOptions}, |
bd8081e9fd62
rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52286
diff
changeset
|
23 revlog::RevlogError, |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
24 sparse, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
25 utils::{ |
52156
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
26 cap_default_rayon_threads, |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
27 files::{filesystem_now, get_path_from_bytes}, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
28 hg_path::{hg_path_to_path_buf, HgPath, HgPathError}, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
29 path_auditor::PathAuditor, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
30 }, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
31 vfs::{is_on_nfs_mount, VfsImpl}, |
52313 | 32 DirstateParents, UncheckedRevision, INTERRUPT_RECEIVED, |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
33 }; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
34 use crossbeam_channel::{Receiver, Sender}; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
35 use rayon::prelude::*; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
36 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
37 fn write_dirstate(repo: &Repo) -> Result<(), HgError> { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
38 repo.write_dirstate() |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
39 .map_err(|e| HgError::abort(e.to_string(), exit_codes::ABORT, None))?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
40 write_tracked_key(repo) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
41 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
42 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
43 /// Update the current working copy of `repo` to the given revision `to`, from |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
44 /// the null revision and set + write out the dirstate to reflect that. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
45 /// |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
46 /// Do not call this outside of a Python context. This does *not* handle any |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
47 /// of the checks, hooks, lock taking needed to setup and get out of this |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
48 /// update from the null revision. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
49 pub fn update_from_null( |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
50 repo: &Repo, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
51 to: UncheckedRevision, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
52 progress: &dyn Progress, |
52156
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
53 workers: Option<usize>, |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
54 ) -> Result<usize, HgError> { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
55 // Ignore the warnings, they've been displayed by Python already |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
56 // TODO non-Python clients: display narrow warnings |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
57 let (narrow_matcher, _) = narrow::matcher(repo)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
58 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
59 let files_for_rev = list_rev_tracked_files(repo, to, narrow_matcher) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
60 .map_err(handle_revlog_error)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
61 repo.manually_set_parents(DirstateParents { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
62 p1: repo.node(to).expect("update target should exist"), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
63 p2: NULL_NODE, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
64 })?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
65 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
66 // Filter the working copy according to the sparse spec |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
67 let tracked_files: Result<Vec<_>, _> = if !repo.has_sparse() { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
68 files_for_rev.iter().collect() |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
69 } else { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
70 // Ignore the warnings, they've been displayed by Python already |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
71 // TODO non-Python clients: display sparse warnings |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
72 let (sparse_matcher, _) = sparse::matcher(repo)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
73 files_for_rev |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
74 .iter() |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
75 .filter(|f| { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
76 match f { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
77 Ok(f) => sparse_matcher.matches(f.0), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
78 Err(_) => true, // Errors stop the update, include them |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
79 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
80 }) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
81 .collect() |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
82 }; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
83 let tracked_files = tracked_files?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
84 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
85 if tracked_files.is_empty() { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
86 // Still write the dirstate because we might not be in the null |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
87 // revision. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
88 // This can happen in narrow repos where all paths are excluded in |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
89 // this revision. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
90 write_dirstate(repo)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
91 return Ok(0); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
92 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
93 let store_vfs = &repo.store_vfs(); |
52286
039b7caeb4d9
rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
94 let options = default_revlog_options( |
039b7caeb4d9
rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
95 repo.config(), |
039b7caeb4d9
rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
96 repo.requirements(), |
52308
bd8081e9fd62
rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52286
diff
changeset
|
97 crate::revlog::RevlogType::Filelog, |
52286
039b7caeb4d9
rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
98 )?; |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
99 let (errors_sender, errors_receiver) = crossbeam_channel::unbounded(); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
100 let (files_sender, files_receiver) = crossbeam_channel::unbounded(); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
101 let working_directory_path = &repo.working_directory_path(); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
102 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
103 let files_count = tracked_files.len(); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
104 let chunks = chunk_tracked_files(tracked_files); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
105 progress.update(0, Some(files_count as u64)); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
106 |
52183
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
107 // TODO find a way (with `nix` or `signal-hook`?) of resetting the |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
108 // previous signal handler directly after. Currently, this is Python's |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
109 // job, but: |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
110 // - it introduces a (small) race between catching and resetting |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
111 // - it would break signal handlers in other contexts like `rhg`` |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
112 let _ = ctrlc::set_handler(|| { |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
113 INTERRUPT_RECEIVED.store(true, Ordering::Relaxed) |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
114 }); |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
115 |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
116 create_working_copy( |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
117 chunks, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
118 working_directory_path, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
119 store_vfs, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
120 options, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
121 files_sender, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
122 errors_sender, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
123 progress, |
52156
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
124 workers, |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
125 ); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
126 |
52183
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
127 // Reset the global interrupt now that we're done |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
128 if INTERRUPT_RECEIVED.swap(false, Ordering::Relaxed) { |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
129 // The threads have all exited early, let's re-raise |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
130 return Err(HgError::InterruptReceived); |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
131 } |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
132 |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
133 let errors: Vec<HgError> = errors_receiver.iter().collect(); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
134 if !errors.is_empty() { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
135 log::debug!("{} errors during update (see trace logs)", errors.len()); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
136 for error in errors.iter() { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
137 log::trace!("{}", error); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
138 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
139 // Best we can do is raise the first error (in order of the channel) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
140 return Err(errors.into_iter().next().expect("can never be empty")); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
141 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
142 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
143 // TODO try to run this concurrently to update the dirstate while we're |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
144 // still writing out the working copy to see if that improves performance. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
145 let total = update_dirstate(repo, files_receiver)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
146 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
147 write_dirstate(repo)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
148 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
149 Ok(total) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
150 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
151 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
152 fn handle_revlog_error(e: RevlogError) -> HgError { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
153 match e { |
52308
bd8081e9fd62
rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52286
diff
changeset
|
154 crate::revlog::RevlogError::Other(hg_error) => hg_error, |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
155 e => HgError::abort( |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
156 format!("revlog error: {}", e), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
157 exit_codes::ABORT, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
158 None, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
159 ), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
160 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
161 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
162 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
163 /// Preallocated size of Vec holding directory contents. This aims at |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
164 /// preventing the need for re-allocating the Vec in most cases. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
165 /// |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
166 /// The value is arbitrarily picked as a little over an average number of files |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
167 /// per directory done by looking at a few larger open-source repos. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
168 /// Most of the runtime is IO anyway, so this doesn't matter too much. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
169 const FILES_PER_DIRECTORY: usize = 16; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
170 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
171 /// Chunk files per directory prefix, so almost every directory is handled |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
172 /// in a separate thread, which works around the FS inode mutex. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
173 /// Chunking less (and doing approximately `files_count`/`threads`) actually |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
174 /// ends up being less performant: my hypothesis is `rayon`'s work stealing |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
175 /// being more efficient with tasks of varying lengths. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
176 #[logging_timer::time("trace")] |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
177 fn chunk_tracked_files( |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
178 tracked_files: Vec<ExpandedManifestEntry>, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
179 ) -> Vec<(&HgPath, Vec<ExpandedManifestEntry>)> { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
180 let files_count = tracked_files.len(); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
181 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
182 let mut chunks = Vec::with_capacity(files_count / FILES_PER_DIRECTORY); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
183 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
184 let mut current_chunk = Vec::with_capacity(FILES_PER_DIRECTORY); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
185 let mut last_directory = tracked_files[0].0.parent(); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
186 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
187 for file_info in tracked_files { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
188 let current_directory = file_info.0.parent(); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
189 let different_directory = current_directory != last_directory; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
190 if different_directory { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
191 chunks.push((last_directory, current_chunk)); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
192 current_chunk = Vec::with_capacity(FILES_PER_DIRECTORY); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
193 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
194 current_chunk.push(file_info); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
195 last_directory = current_directory; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
196 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
197 chunks.push((last_directory, current_chunk)); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
198 chunks |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
199 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
200 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
201 #[logging_timer::time("trace")] |
52156
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
202 #[allow(clippy::too_many_arguments)] |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
203 fn create_working_copy<'a: 'b, 'b>( |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
204 chunks: Vec<(&HgPath, Vec<ExpandedManifestEntry<'a>>)>, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
205 working_directory_path: &Path, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
206 store_vfs: &VfsImpl, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
207 options: RevlogOpenOptions, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
208 files_sender: Sender<(&'b HgPath, u32, usize, TruncatedTimestamp)>, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
209 error_sender: Sender<HgError>, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
210 progress: &dyn Progress, |
52156
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
211 workers: Option<usize>, |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
212 ) { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
213 let auditor = PathAuditor::new(working_directory_path); |
52183
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
214 |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
215 let work_closure = |(dir_path, chunk)| -> Result<(), HgError> { |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
216 if let Err(e) = working_copy_worker( |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
217 dir_path, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
218 chunk, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
219 working_directory_path, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
220 store_vfs, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
221 options, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
222 &files_sender, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
223 progress, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
224 &auditor, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
225 ) { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
226 error_sender |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
227 .send(e) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
228 .expect("channel should not be disconnected") |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
229 } |
52183
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
230 Ok(()) |
52156
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
231 }; |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
232 if let Some(workers) = workers { |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
233 if workers > 1 { |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
234 // Work in parallel, potentially restricting the number of threads |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
235 match rayon::ThreadPoolBuilder::new().num_threads(workers).build() |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
236 { |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
237 Err(error) => error_sender |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
238 .send(HgError::abort( |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
239 error.to_string(), |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
240 exit_codes::ABORT, |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
241 None, |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
242 )) |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
243 .expect("channel should not be disconnected"), |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
244 Ok(pool) => { |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
245 log::trace!("restricting update to {} threads", workers); |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
246 pool.install(|| { |
52183
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
247 let _ = |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
248 chunks.into_par_iter().try_for_each(work_closure); |
52156
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
249 }); |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
250 } |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
251 } |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
252 } else { |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
253 // Work sequentially, don't even invoke rayon |
52183
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
254 let _ = chunks.into_iter().try_for_each(work_closure); |
52156
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
255 } |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
256 } else { |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
257 // Work in parallel by default in the global threadpool |
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
258 let _ = cap_default_rayon_threads(); |
52183
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
259 let _ = chunks.into_par_iter().try_for_each(work_closure); |
52156
e6a44bc91bc2
rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52084
diff
changeset
|
260 } |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
261 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
262 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
263 /// Represents a work unit for a single thread, responsible for this set of |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
264 /// files and restoring them to the working copy. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
265 #[allow(clippy::too_many_arguments)] |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
266 fn working_copy_worker<'a: 'b, 'b>( |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
267 dir_path: &HgPath, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
268 chunk: Vec<ExpandedManifestEntry<'a>>, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
269 working_directory_path: &Path, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
270 store_vfs: &VfsImpl, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
271 options: RevlogOpenOptions, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
272 files_sender: &Sender<(&'b HgPath, u32, usize, TruncatedTimestamp)>, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
273 progress: &dyn Progress, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
274 auditor: &PathAuditor, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
275 ) -> Result<(), HgError> { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
276 let dir_path = |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
277 hg_path_to_path_buf(dir_path).expect("invalid path in manifest"); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
278 let dir_path = working_directory_path.join(dir_path); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
279 std::fs::create_dir_all(&dir_path).when_writing_file(&dir_path)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
280 |
52183
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
281 if INTERRUPT_RECEIVED.load(Ordering::Relaxed) { |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
282 // Stop working, the user has requested that we stop |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
283 return Err(HgError::InterruptReceived); |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
284 } |
96b113d22b34
rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52156
diff
changeset
|
285 |
52084
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
286 for (file, file_node, flags) in chunk { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
287 auditor.audit_path(file)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
288 let flags = flags.map(|f| f.into()); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
289 let path = |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
290 working_directory_path.join(get_path_from_bytes(file.as_bytes())); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
291 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
292 // Treemanifest is not supported |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
293 assert!(flags != Some(b't')); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
294 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
295 let filelog = Filelog::open_vfs(store_vfs, file, options)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
296 let filelog_revision_data = &filelog |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
297 .data_for_node(file_node) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
298 .map_err(handle_revlog_error)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
299 let file_data = filelog_revision_data.file_data()?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
300 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
301 if flags == Some(b'l') { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
302 let target = get_path_from_bytes(file_data); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
303 if let Err(e) = std::os::unix::fs::symlink(target, &path) { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
304 // If the path already exists either: |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
305 // - another process created this file while ignoring the |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
306 // lock => error |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
307 // - our check for the fast path is incorrect => error |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
308 // - this is a malicious repo/bundle and this is symlink that |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
309 // tries to write things where it shouldn't be able to. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
310 match e.kind() { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
311 std::io::ErrorKind::AlreadyExists => { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
312 let metadata = std::fs::symlink_metadata(&path) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
313 .when_reading_file(&path)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
314 if metadata.is_dir() { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
315 return Err(HgError::Path( |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
316 HgPathError::TraversesSymbolicLink { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
317 // Technically it should be one of the |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
318 // children, but good enough |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
319 path: file |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
320 .join(HgPath::new(b"*")) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
321 .to_owned(), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
322 symlink: file.to_owned(), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
323 }, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
324 )); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
325 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
326 return Err(e).when_writing_file(&path); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
327 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
328 _ => return Err(e).when_writing_file(&path), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
329 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
330 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
331 } else { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
332 let mut f = |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
333 std::fs::File::create(&path).when_writing_file(&path)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
334 f.write_all(file_data).when_writing_file(&path)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
335 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
336 if flags == Some(b'x') { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
337 std::fs::set_permissions(&path, Permissions::from_mode(0o755)) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
338 .when_writing_file(&path)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
339 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
340 let metadata = |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
341 std::fs::symlink_metadata(&path).when_reading_file(&path)?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
342 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
343 let mode = metadata.mode(); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
344 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
345 files_sender |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
346 .send(( |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
347 file, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
348 mode, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
349 file_data.len(), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
350 TruncatedTimestamp::for_mtime_of(&metadata) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
351 .when_reading_file(&path)?, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
352 )) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
353 .expect("channel should not be closed"); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
354 progress.increment(1, None); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
355 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
356 Ok(()) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
357 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
358 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
359 #[logging_timer::time("trace")] |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
360 fn update_dirstate( |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
361 repo: &Repo, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
362 files_receiver: Receiver<(&HgPath, u32, usize, TruncatedTimestamp)>, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
363 ) -> Result<usize, HgError> { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
364 let mut dirstate = repo |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
365 .dirstate_map_mut() |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
366 .map_err(|e| HgError::abort(e.to_string(), exit_codes::ABORT, None))?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
367 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
368 // (see the comments in `filter_ambiguous_files` in `merge.py` for more) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
369 // It turns out that (on Linux at least) the filesystem resolution time |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
370 // for most filesystems is based on the HZ kernel config. Their internal |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
371 // clocks do return nanoseconds if the hardware clock is precise enough, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
372 // which should be the case on most recent computers but are only updated |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
373 // every few milliseconds at best (every "jiffy"). |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
374 // |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
375 // We are still not concerned with fixing the race with other |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
376 // processes that might modify the working copy right after it was created |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
377 // within the same tick, because it is impossible to catch. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
378 // However, we might as well not race with operations that could run right |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
379 // after this one, especially other Mercurial operations that could be |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
380 // waiting for the wlock to change file contents and the dirstate. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
381 // |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
382 // Thus: wait until the filesystem clock has ticked to filter ambiguous |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
383 // entries and write the dirstate, but only for dirstate-v2, since v1 only |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
384 // has second-level granularity and waiting for a whole second is too much |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
385 // of a penalty in the general case. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
386 // Although we're assuming that people running dirstate-v2 on Linux |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
387 // don't have a second-granularity FS (with the exclusion of NFS), users |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
388 // can be surprising, and at some point in the future dirstate-v2 will |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
389 // become the default. To that end, we limit the wait time to 100ms and |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
390 // fall back to the filter method in case of a timeout. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
391 // |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
392 // +------------+------+--------------+ |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
393 // | version | wait | filter level | |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
394 // +------------+------+--------------+ |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
395 // | V1 | No | Second | |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
396 // | V2 | Yes | Nanosecond | |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
397 // | V2-slow-fs | No | Second | |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
398 // +------------+------+--------------+ |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
399 let dirstate_v2 = repo.use_dirstate_v2(); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
400 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
401 // Let's ignore NFS right off the bat |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
402 let mut fast_enough_fs = !is_on_nfs_mount(repo.working_directory_path()); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
403 let fs_time_now = if dirstate_v2 && fast_enough_fs { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
404 match wait_until_fs_tick(repo.working_directory_path()) { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
405 None => None, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
406 Some(Ok(time)) => Some(time), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
407 Some(Err(time)) => { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
408 fast_enough_fs = false; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
409 Some(time) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
410 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
411 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
412 } else { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
413 filesystem_now(repo.working_directory_path()) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
414 .ok() |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
415 .map(TruncatedTimestamp::from) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
416 }; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
417 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
418 let mut total = 0; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
419 for (filename, mode, size, mtime) in files_receiver.into_iter() { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
420 total += 1; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
421 // When using dirstate-v2 on a filesystem with reasonable performance |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
422 // this is basically always true unless you get a mtime from the |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
423 // far future. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
424 let has_meaningful_mtime = if let Some(fs_time) = fs_time_now { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
425 mtime.for_reliable_mtime_of_self(&fs_time).is_some_and(|t| { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
426 // Dirstate-v1 only has second-level information |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
427 !t.second_ambiguous || dirstate_v2 && fast_enough_fs |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
428 }) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
429 } else { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
430 // We somehow failed to write to the filesystem, so don't store |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
431 // the cache information. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
432 false |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
433 }; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
434 let reset = DirstateEntryReset { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
435 filename, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
436 wc_tracked: true, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
437 p1_tracked: true, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
438 p2_info: false, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
439 has_meaningful_mtime, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
440 parent_file_data_opt: Some(ParentFileData { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
441 mode_size: Some(( |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
442 mode, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
443 size.try_into().expect("invalid file size in manifest"), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
444 )), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
445 mtime: Some(mtime), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
446 }), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
447 from_empty: true, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
448 }; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
449 dirstate.reset_state(reset).map_err(|e| { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
450 HgError::abort(e.to_string(), exit_codes::ABORT, None) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
451 })?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
452 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
453 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
454 Ok(total) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
455 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
456 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
457 /// Wait until the next update from the filesystem time by writing in a loop |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
458 /// a new temporary file inside the working directory and checking if its time |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
459 /// differs from the first one observed. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
460 /// |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
461 /// Returns `None` if we are unable to get the filesystem time, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
462 /// `Some(Err(timestamp))` if we've timed out waiting for the filesystem clock |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
463 /// to tick, and `Some(Ok(timestamp))` if we've waited successfully. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
464 /// |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
465 /// On Linux, your average tick is going to be a "jiffy", or 1/HZ. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
466 /// HZ is your kernel's tick rate (if it has one configured) and the value |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
467 /// is the one returned by `grep 'CONFIG_HZ=' /boot/config-$(uname -r)`, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
468 /// again assuming a normal setup. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
469 /// |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
470 /// In my case (Alphare) at the time of writing, I get `CONFIG_HZ=250`, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
471 /// which equates to 4ms. |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
472 /// |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
473 /// This might change with a series that could make it to Linux 6.12: |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
474 /// https://lore.kernel.org/all/20241002-mgtime-v10-8-d1c4717f5284@kernel.org |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
475 fn wait_until_fs_tick( |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
476 working_directory_path: &Path, |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
477 ) -> Option<Result<TruncatedTimestamp, TruncatedTimestamp>> { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
478 let start = std::time::Instant::now(); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
479 let old_fs_time = filesystem_now(working_directory_path).ok()?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
480 let mut fs_time = filesystem_now(working_directory_path).ok()?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
481 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
482 const FS_TICK_WAIT_TIMEOUT: Duration = Duration::from_millis(100); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
483 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
484 while fs_time == old_fs_time { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
485 if std::time::Instant::now() - start > FS_TICK_WAIT_TIMEOUT { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
486 log::trace!( |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
487 "timed out waiting for the fs clock to tick after {:?}", |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
488 FS_TICK_WAIT_TIMEOUT |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
489 ); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
490 return Some(Err(TruncatedTimestamp::from(old_fs_time))); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
491 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
492 fs_time = filesystem_now(working_directory_path).ok()?; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
493 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
494 log::trace!( |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
495 "waited for {:?} before writing the dirstate", |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
496 fs_time.duration_since(old_fs_time) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
497 ); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
498 Some(Ok(TruncatedTimestamp::from(fs_time))) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
499 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
500 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
501 #[cfg(test)] |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
502 mod test { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
503 use super::*; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
504 use pretty_assertions::assert_eq; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
505 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
506 #[test] |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
507 fn test_chunk_tracked_files() { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
508 fn chunk(v: Vec<&'static str>) -> Vec<ExpandedManifestEntry> { |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
509 v.into_iter() |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
510 .map(|f| (HgPath::new(f.as_bytes()), NULL_NODE, None)) |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
511 .collect() |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
512 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
513 let p = HgPath::new; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
514 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
515 let files = chunk(vec!["a"]); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
516 let expected = vec![(p(""), chunk(vec!["a"]))]; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
517 assert_eq!(chunk_tracked_files(files), expected); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
518 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
519 let files = chunk(vec!["a", "b", "c"]); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
520 let expected = vec![(p(""), chunk(vec!["a", "b", "c"]))]; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
521 assert_eq!(chunk_tracked_files(files), expected); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
522 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
523 let files = chunk(vec![ |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
524 "dir/a-new", |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
525 "dir/a/mut", |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
526 "dir/a/mut-mut", |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
527 "dir/albert", |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
528 "dir/b", |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
529 "dir/subdir/c", |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
530 "dir/subdir/d", |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
531 "file", |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
532 ]); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
533 let expected = vec![ |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
534 (p("dir"), chunk(vec!["dir/a-new"])), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
535 (p("dir/a"), chunk(vec!["dir/a/mut", "dir/a/mut-mut"])), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
536 (p("dir"), chunk(vec!["dir/albert", "dir/b"])), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
537 (p("dir/subdir"), chunk(vec!["dir/subdir/c", "dir/subdir/d"])), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
538 (p(""), chunk(vec!["file"])), |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
539 ]; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
540 assert_eq!(chunk_tracked_files(files), expected); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
541 |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
542 // Doesn't get split |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
543 let large_dir = vec![ |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
544 "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
545 "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
546 ]; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
547 let files = chunk(large_dir.clone()); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
548 let expected = vec![(p(""), chunk(large_dir))]; |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
549 assert_eq!(chunk_tracked_files(files), expected); |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
550 } |
8b7123c8947b
update: add a Rust fast-path when updating from null (and clean)
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
551 } |