annotate rust/hg-core/src/update.rs @ 53042:cdd7bf612c7b stable tip

bundle-spec: properly format boolean parameter (issue6960) This was breaking automatic clone bundle generation. This changeset fixes it and add a test to catch it in the future.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 11 Mar 2025 02:29:42 +0100
parents b422acba55f1
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
52056
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,
52213
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
diff changeset
8 sync::atomic::Ordering,
52056
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::{
52299
b422acba55f1 rust-dirstate: remove star exports
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52298
diff changeset
13 dirstate::entry::{ParentFileData, TruncatedTimestamp},
52298
db065b33fa56 rust-dirstate: merge `dirstate_tree` module into `dirstate`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52251
diff changeset
14 dirstate::{dirstate_map::DirstateEntryReset, on_disk::write_tracked_key},
52056
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},
52178
bd8081e9fd62 rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
16 exit_codes, narrow,
52056
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,
52178
bd8081e9fd62 rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
20 revlog::filelog::Filelog,
bd8081e9fd62 rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
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: 52156
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: 52156
diff changeset
23 revlog::RevlogError,
52056
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::{
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
26 cap_default_rayon_threads,
52056
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},
52251
65d516db7309 branching: merge stable into default
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52178 52213
diff changeset
32 DirstateParents, UncheckedRevision, INTERRUPT_RECEIVED,
52056
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,
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
53 workers: Option<usize>,
52056
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();
52156
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
94 let options = default_revlog_options(
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
95 repo.config(),
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
96 repo.requirements(),
52178
bd8081e9fd62 rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
97 crate::revlog::RevlogType::Filelog,
52156
039b7caeb4d9 rust-revlog: introduce an `options` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
98 )?;
52056
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
52213
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
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: 52186
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: 52186
diff changeset
109 // job, but:
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
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: 52186
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: 52186
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: 52186
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: 52186
diff changeset
114 });
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
diff changeset
115
52056
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,
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
124 workers,
52056
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
52213
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
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: 52186
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: 52186
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: 52186
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: 52186
diff changeset
131 }
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
diff changeset
132
52056
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 {
52178
bd8081e9fd62 rust: don't star export from the `revlog` module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52156
diff changeset
154 crate::revlog::RevlogError::Other(hg_error) => hg_error,
52056
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")]
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
202 #[allow(clippy::too_many_arguments)]
52056
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,
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
211 workers: Option<usize>,
52056
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);
52213
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
diff changeset
214
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
diff changeset
215 let work_closure = |(dir_path, chunk)| -> Result<(), HgError> {
52056
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 }
52213
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
diff changeset
230 Ok(())
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
231 };
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
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: 52056
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: 52056
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: 52056
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: 52056
diff changeset
236 {
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
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: 52056
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: 52056
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: 52056
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: 52056
diff changeset
241 None,
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
242 ))
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
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: 52056
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: 52056
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: 52056
diff changeset
246 pool.install(|| {
52213
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
diff changeset
247 let _ =
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
diff changeset
248 chunks.into_par_iter().try_for_each(work_closure);
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
249 });
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
250 }
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
251 }
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
252 } else {
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
253 // Work sequentially, don't even invoke rayon
52213
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
diff changeset
254 let _ = chunks.into_iter().try_for_each(work_closure);
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
255 }
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
256 } else {
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
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: 52056
diff changeset
258 let _ = cap_default_rayon_threads();
52213
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
diff changeset
259 let _ = chunks.into_par_iter().try_for_each(work_closure);
52186
e6a44bc91bc2 rust-update: make `update_from_null` respect `worker.numcpu` config option
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52056
diff changeset
260 }
52056
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
52213
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
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: 52186
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: 52186
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: 52186
diff changeset
284 }
96b113d22b34 rust-update: handle SIGINT from long-running update threads
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52186
diff changeset
285
52056
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 }