Mercurial > hg-stable
annotate rust/hg-core/src/repo.rs @ 51118:532e74ad3ff6
rust: run a clippy pass with the latest stable version
Our current version of clippy is older than the latest stable.
The newest version has new lints that are moslty good advice, so let's apply
them ahead of time. This has the added benefit of reducing the noise for
developpers like myself that use clippy as an IDE helper, as well as being
more prepared for a future clippy upgrade.
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Mon, 06 Nov 2023 11:06:08 +0100 |
parents | 1928b770e3e7 |
children | 13f58ce70299 |
rev | line source |
---|---|
47987
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47986
diff
changeset
|
1 use crate::changelog::Changelog; |
46545
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
2 use crate::config::{Config, ConfigError, ConfigParseError}; |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
3 use crate::dirstate::DirstateParents; |
49679
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49671
diff
changeset
|
4 use crate::dirstate_tree::dirstate_map::DirstateMapWriteMode; |
48467
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
5 use crate::dirstate_tree::on_disk::Docket as DirstateDocket; |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
6 use crate::dirstate_tree::owning::OwningDirstateMap; |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
7 use crate::errors::HgResultExt; |
48467
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
8 use crate::errors::{HgError, IoResultExt}; |
48463
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48457
diff
changeset
|
9 use crate::lock::{try_with_lock_no_wait, LockError}; |
47988
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47987
diff
changeset
|
10 use crate::manifest::{Manifest, Manifestlog}; |
47989
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47988
diff
changeset
|
11 use crate::revlog::filelog::Filelog; |
50010
750409505286
rust-clippy: merge "revlog" module definition and struct implementation
Raphaël Gomès <rgomes@octobus.net>
parents:
50003
diff
changeset
|
12 use crate::revlog::RevlogError; |
49686
fc8e37c380d3
dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49685
diff
changeset
|
13 use crate::utils::debug::debug_wait_for_file_or_print; |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
14 use crate::utils::files::get_path_from_bytes; |
47989
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47988
diff
changeset
|
15 use crate::utils::hg_path::HgPath; |
46753
97ac588b6d9e
rhg: Don’t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents:
46748
diff
changeset
|
16 use crate::utils::SliceExt; |
47980
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
47977
diff
changeset
|
17 use crate::vfs::{is_dir, is_file, Vfs}; |
50988
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50389
diff
changeset
|
18 use crate::DirstateError; |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50389
diff
changeset
|
19 use crate::{requirements, NodePrefix, UncheckedRevision}; |
48465
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48463
diff
changeset
|
20 use std::cell::{Ref, RefCell, RefMut}; |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
21 use std::collections::HashSet; |
48467
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
22 use std::io::Seek; |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
23 use std::io::SeekFrom; |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
24 use std::io::Write as IoWrite; |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
25 use std::path::{Path, PathBuf}; |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
26 |
49697
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
27 const V2_MAX_READ_ATTEMPTS: usize = 5; |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
28 |
50252
a6b8b1ab9116
branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
diff
changeset
|
29 type DirstateMapIdentity = (Option<u64>, Option<Vec<u8>>, usize); |
a6b8b1ab9116
branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
diff
changeset
|
30 |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
31 /// A repository on disk |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
32 pub struct Repo { |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
33 working_directory: PathBuf, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
34 dot_hg: PathBuf, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
35 store: PathBuf, |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
36 requirements: HashSet<String>, |
46545
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
37 config: Config, |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
38 dirstate_parents: LazyCell<DirstateParents>, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
39 dirstate_map: LazyCell<OwningDirstateMap>, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
40 changelog: LazyCell<Changelog>, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
41 manifestlog: LazyCell<Manifestlog>, |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
42 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
43 |
46514
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
44 #[derive(Debug, derive_more::From)] |
46545
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
45 pub enum RepoError { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
46 NotFound { |
46555
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46545
diff
changeset
|
47 at: PathBuf, |
46514
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
48 }, |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
49 #[from] |
46545
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
50 ConfigParseError(ConfigParseError), |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
51 #[from] |
46514
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
52 Other(HgError), |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
53 } |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
54 |
46545
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
55 impl From<ConfigError> for RepoError { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
56 fn from(error: ConfigError) -> Self { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
57 match error { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
58 ConfigError::Parse(error) => error.into(), |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
59 ConfigError::Other(error) => error.into(), |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
60 } |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
61 } |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
62 } |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
63 |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
64 impl Repo { |
47411
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
65 /// tries to find nearest repository root in current working directory or |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
66 /// its ancestors |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
67 pub fn find_repo_root() -> Result<PathBuf, RepoError> { |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
68 let current_directory = crate::utils::current_dir()?; |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
69 // ancestors() is inclusive: it first yields `current_directory` |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
70 // as-is. |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
71 for ancestor in current_directory.ancestors() { |
47779
cf5f8da2244c
rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents:
47674
diff
changeset
|
72 if is_dir(ancestor.join(".hg"))? { |
47411
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
73 return Ok(ancestor.to_path_buf()); |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
74 } |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
75 } |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49238
diff
changeset
|
76 Err(RepoError::NotFound { |
47411
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
77 at: current_directory, |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49238
diff
changeset
|
78 }) |
47411
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
79 } |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
80 |
46557
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46555
diff
changeset
|
81 /// Find a repository, either at the given path (which must contain a `.hg` |
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46555
diff
changeset
|
82 /// sub-directory) or by searching the current directory and its |
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46555
diff
changeset
|
83 /// ancestors. |
46555
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46545
diff
changeset
|
84 /// |
46557
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46555
diff
changeset
|
85 /// A method with two very different "modes" like this usually a code smell |
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46555
diff
changeset
|
86 /// to make two methods instead, but in this case an `Option` is what rhg |
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46555
diff
changeset
|
87 /// sub-commands get from Clap for the `-R` / `--repository` CLI argument. |
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46555
diff
changeset
|
88 /// Having two methods would just move that `if` to almost all callers. |
46555
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46545
diff
changeset
|
89 pub fn find( |
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46545
diff
changeset
|
90 config: &Config, |
47410
ebdef6283798
rhg: read [paths] for `--repository` value
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47380
diff
changeset
|
91 explicit_path: Option<PathBuf>, |
46555
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46545
diff
changeset
|
92 ) -> Result<Self, RepoError> { |
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46545
diff
changeset
|
93 if let Some(root) = explicit_path { |
47779
cf5f8da2244c
rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents:
47674
diff
changeset
|
94 if is_dir(root.join(".hg"))? { |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49238
diff
changeset
|
95 Self::new_at_path(root, config) |
47779
cf5f8da2244c
rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents:
47674
diff
changeset
|
96 } else if is_file(&root)? { |
46743
dfd35823635b
rhg: Fall back to Python for bundle repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46741
diff
changeset
|
97 Err(HgError::unsupported("bundle repository").into()) |
46555
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46545
diff
changeset
|
98 } else { |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49238
diff
changeset
|
99 Err(RepoError::NotFound { at: root }) |
46514
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
100 } |
46555
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46545
diff
changeset
|
101 } else { |
47411
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
102 let root = Self::find_repo_root()?; |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47410
diff
changeset
|
103 Self::new_at_path(root, config) |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
104 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
105 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
106 |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
107 /// To be called after checking that `.hg` is a sub-directory |
46544
f031fe1c6ede
rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents:
46543
diff
changeset
|
108 fn new_at_path( |
f031fe1c6ede
rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents:
46543
diff
changeset
|
109 working_directory: PathBuf, |
f031fe1c6ede
rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents:
46543
diff
changeset
|
110 config: &Config, |
46545
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
111 ) -> Result<Self, RepoError> { |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
112 let dot_hg = working_directory.join(".hg"); |
46525
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
113 |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49238
diff
changeset
|
114 let mut repo_config_files = |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49238
diff
changeset
|
115 vec![dot_hg.join("hgrc"), dot_hg.join("hgrc-not-shared")]; |
46545
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
116 |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
117 let hg_vfs = Vfs { base: &dot_hg }; |
46525
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
118 let mut reqs = requirements::load_if_exists(hg_vfs)?; |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
119 let relative = |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
120 reqs.contains(requirements::RELATIVE_SHARED_REQUIREMENT); |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
121 let shared = |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
122 reqs.contains(requirements::SHARED_REQUIREMENT) || relative; |
46525
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
123 |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
124 // From `mercurial/localrepo.py`: |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
125 // |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
126 // if .hg/requires contains the sharesafe requirement, it means |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
127 // there exists a `.hg/store/requires` too and we should read it |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
128 // NOTE: presence of SHARESAFE_REQUIREMENT imply that store requirement |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
129 // is present. We never write SHARESAFE_REQUIREMENT for a repo if store |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
130 // is not present, refer checkrequirementscompat() for that |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
131 // |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
132 // However, if SHARESAFE_REQUIREMENT is not present, it means that the |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
133 // repository was shared the old way. We check the share source |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
134 // .hg/requires for SHARESAFE_REQUIREMENT to detect whether the |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
135 // current repository needs to be reshared |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
136 let share_safe = reqs.contains(requirements::SHARESAFE_REQUIREMENT); |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
137 |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
138 let store_path; |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
139 if !shared { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
140 store_path = dot_hg.join("store"); |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
141 } else { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
142 let bytes = hg_vfs.read("sharedpath")?; |
46708
e8cd519a0a34
rhg: Ignore trailing newlines in .hg/sharedpath
Simon Sapin <simon.sapin@octobus.net>
parents:
46652
diff
changeset
|
143 let mut shared_path = |
47977
696abab107b4
rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents:
47779
diff
changeset
|
144 get_path_from_bytes(bytes.trim_end_matches(|b| b == b'\n')) |
696abab107b4
rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents:
47779
diff
changeset
|
145 .to_owned(); |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
146 if relative { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
147 shared_path = dot_hg.join(shared_path) |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
148 } |
47779
cf5f8da2244c
rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents:
47674
diff
changeset
|
149 if !is_dir(&shared_path)? { |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
150 return Err(HgError::corrupted(format!( |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
151 ".hg/sharedpath points to nonexistent directory {}", |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
152 shared_path.display() |
46545
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
153 )) |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
154 .into()); |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
155 } |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
156 |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
157 store_path = shared_path.join("store"); |
46525
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
158 |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
159 let source_is_share_safe = |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
160 requirements::load(Vfs { base: &shared_path })? |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
161 .contains(requirements::SHARESAFE_REQUIREMENT); |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
162 |
48900
1d5fd9def5ac
rhg: simplify the handling of share-safe config mismatch
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48547
diff
changeset
|
163 if share_safe != source_is_share_safe { |
1d5fd9def5ac
rhg: simplify the handling of share-safe config mismatch
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48547
diff
changeset
|
164 return Err(HgError::unsupported("share-safe mismatch").into()); |
46525
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46524
diff
changeset
|
165 } |
46545
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
166 |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
167 if share_safe { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
168 repo_config_files.insert(0, shared_path.join("hgrc")) |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
169 } |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
170 } |
46652
f64b6953db70
rhg: Bug fix: with share-safe, always read store requirements
Simon Sapin <simon.sapin@octobus.net>
parents:
46640
diff
changeset
|
171 if share_safe { |
f64b6953db70
rhg: Bug fix: with share-safe, always read store requirements
Simon Sapin <simon.sapin@octobus.net>
parents:
46640
diff
changeset
|
172 reqs.extend(requirements::load(Vfs { base: &store_path })?); |
f64b6953db70
rhg: Bug fix: with share-safe, always read store requirements
Simon Sapin <simon.sapin@octobus.net>
parents:
46640
diff
changeset
|
173 } |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
174 |
46754
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46753
diff
changeset
|
175 let repo_config = if std::env::var_os("HGRCSKIPREPO").is_none() { |
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46753
diff
changeset
|
176 config.combine_with_repo(&repo_config_files)? |
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46753
diff
changeset
|
177 } else { |
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46753
diff
changeset
|
178 config.clone() |
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46753
diff
changeset
|
179 }; |
46545
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
180 |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
181 let repo = Self { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
182 requirements: reqs, |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
183 working_directory, |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
184 store: store_path, |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
185 dot_hg, |
46545
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
186 config: repo_config, |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
187 dirstate_parents: LazyCell::new(), |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
188 dirstate_map: LazyCell::new(), |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
189 changelog: LazyCell::new(), |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
190 manifestlog: LazyCell::new(), |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
191 }; |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
192 |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
193 requirements::check(&repo)?; |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
194 |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
195 Ok(repo) |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
196 } |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
197 |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
198 pub fn working_directory_path(&self) -> &Path { |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
199 &self.working_directory |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
200 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
201 |
46524
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
202 pub fn requirements(&self) -> &HashSet<String> { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
203 &self.requirements |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
204 } |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46514
diff
changeset
|
205 |
46545
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
206 pub fn config(&self) -> &Config { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
207 &self.config |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
208 } |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46544
diff
changeset
|
209 |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
210 /// For accessing repository files (in `.hg`), except for the store |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
211 /// (`.hg/store`). |
46638
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
46632
diff
changeset
|
212 pub fn hg_vfs(&self) -> Vfs<'_> { |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
213 Vfs { base: &self.dot_hg } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
214 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
215 |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
216 /// For accessing repository store files (in `.hg/store`) |
46638
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
46632
diff
changeset
|
217 pub fn store_vfs(&self) -> Vfs<'_> { |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
218 Vfs { base: &self.store } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
219 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
220 |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
221 /// For accessing the working copy |
46822
c71e8d9e7f2a
rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
46754
diff
changeset
|
222 pub fn working_directory_vfs(&self) -> Vfs<'_> { |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
223 Vfs { |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
224 base: &self.working_directory, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
225 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
226 } |
46640
755c31a1caf9
rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents:
46638
diff
changeset
|
227 |
48463
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48457
diff
changeset
|
228 pub fn try_with_wlock_no_wait<R>( |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48457
diff
changeset
|
229 &self, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48457
diff
changeset
|
230 f: impl FnOnce() -> R, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48457
diff
changeset
|
231 ) -> Result<R, LockError> { |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48457
diff
changeset
|
232 try_with_lock_no_wait(self.hg_vfs(), "wlock", f) |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48457
diff
changeset
|
233 } |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48457
diff
changeset
|
234 |
50387
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
235 /// Whether this repo should use dirstate-v2. |
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
236 /// The presence of `dirstate-v2` in the requirements does not mean that |
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
237 /// the on-disk dirstate is necessarily in version 2. In most cases, |
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
238 /// a dirstate-v2 file will indeed be found, but in rare cases (like the |
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
239 /// upgrade mechanism being cut short), the on-disk version will be a |
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
240 /// v1 file. |
50389
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
241 /// Semantically, having a requirement only means that a client cannot |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
242 /// properly understand or properly update the repo if it lacks the support |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
243 /// for the required feature, but not that that feature is actually used |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
244 /// in all occasions. |
50387
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
245 pub fn use_dirstate_v2(&self) -> bool { |
47380
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
246 self.requirements |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
247 .contains(requirements::DIRSTATE_V2_REQUIREMENT) |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
248 } |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
249 |
48457
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48084
diff
changeset
|
250 pub fn has_sparse(&self) -> bool { |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48084
diff
changeset
|
251 self.requirements.contains(requirements::SPARSE_REQUIREMENT) |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48084
diff
changeset
|
252 } |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48084
diff
changeset
|
253 |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48084
diff
changeset
|
254 pub fn has_narrow(&self) -> bool { |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48084
diff
changeset
|
255 self.requirements.contains(requirements::NARROW_REQUIREMENT) |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48084
diff
changeset
|
256 } |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48084
diff
changeset
|
257 |
49146
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49145
diff
changeset
|
258 pub fn has_nodemap(&self) -> bool { |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49145
diff
changeset
|
259 self.requirements |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49145
diff
changeset
|
260 .contains(requirements::NODEMAP_REQUIREMENT) |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49145
diff
changeset
|
261 } |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49145
diff
changeset
|
262 |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
263 fn dirstate_file_contents(&self) -> Result<Vec<u8>, HgError> { |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
264 Ok(self |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
265 .hg_vfs() |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
266 .read("dirstate") |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
267 .io_not_found_as_none()? |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49238
diff
changeset
|
268 .unwrap_or_default()) |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
269 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
270 |
49703
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
271 fn dirstate_identity(&self) -> Result<Option<u64>, HgError> { |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
272 use std::os::unix::fs::MetadataExt; |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
273 Ok(self |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
274 .hg_vfs() |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
275 .symlink_metadata("dirstate") |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
276 .io_not_found_as_none()? |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
277 .map(|meta| meta.ino())) |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
278 } |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
279 |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
280 pub fn dirstate_parents(&self) -> Result<DirstateParents, HgError> { |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
281 Ok(*self |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
282 .dirstate_parents |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
283 .get_or_init(|| self.read_dirstate_parents())?) |
48465
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48463
diff
changeset
|
284 } |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48463
diff
changeset
|
285 |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48463
diff
changeset
|
286 fn read_dirstate_parents(&self) -> Result<DirstateParents, HgError> { |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
287 let dirstate = self.dirstate_file_contents()?; |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
288 let parents = if dirstate.is_empty() { |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
289 DirstateParents::NULL |
50387
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
290 } else if self.use_dirstate_v2() { |
50389
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
291 let docket_res = |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
292 crate::dirstate_tree::on_disk::read_docket(&dirstate); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
293 match docket_res { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
294 Ok(docket) => docket.parents(), |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
295 Err(_) => { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
296 log::info!( |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
297 "Parsing dirstate docket failed, \ |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
298 falling back to dirstate-v1" |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
299 ); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
300 *crate::dirstate::parsers::parse_dirstate_parents( |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
301 &dirstate, |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
302 )? |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
303 } |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
304 } |
47380
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
305 } else { |
50003
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49238
diff
changeset
|
306 *crate::dirstate::parsers::parse_dirstate_parents(&dirstate)? |
47380
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
307 }; |
48465
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48463
diff
changeset
|
308 self.dirstate_parents.set(parents); |
47674
ff97e793ed36
dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents:
47413
diff
changeset
|
309 Ok(parents) |
46640
755c31a1caf9
rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents:
46638
diff
changeset
|
310 } |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
311 |
49702
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
312 /// Returns the information read from the dirstate docket necessary to |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
313 /// check if the data file has been updated/deleted by another process |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
314 /// since we last read the dirstate. |
49703
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
315 /// Namely, the inode, data file uuid and the data size. |
49702
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
316 fn get_dirstate_data_file_integrity( |
48466
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48465
diff
changeset
|
317 &self, |
50252
a6b8b1ab9116
branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
diff
changeset
|
318 ) -> Result<DirstateMapIdentity, HgError> { |
48466
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48465
diff
changeset
|
319 assert!( |
50387
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
320 self.use_dirstate_v2(), |
48466
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48465
diff
changeset
|
321 "accessing dirstate data file ID without dirstate-v2" |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48465
diff
changeset
|
322 ); |
49703
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
323 // Get the identity before the contents since we could have a race |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
324 // between the two. Having an identity that is too old is fine, but |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
325 // one that is younger than the content change is bad. |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
326 let identity = self.dirstate_identity()?; |
48466
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48465
diff
changeset
|
327 let dirstate = self.dirstate_file_contents()?; |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48465
diff
changeset
|
328 if dirstate.is_empty() { |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48465
diff
changeset
|
329 self.dirstate_parents.set(DirstateParents::NULL); |
49703
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
330 Ok((identity, None, 0)) |
48466
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48465
diff
changeset
|
331 } else { |
50389
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
332 let docket_res = |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
333 crate::dirstate_tree::on_disk::read_docket(&dirstate); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
334 match docket_res { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
335 Ok(docket) => { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
336 self.dirstate_parents.set(docket.parents()); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
337 Ok(( |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
338 identity, |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
339 Some(docket.uuid.to_owned()), |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
340 docket.data_size(), |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
341 )) |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
342 } |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
343 Err(_) => { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
344 log::info!( |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
345 "Parsing dirstate docket failed, \ |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
346 falling back to dirstate-v1" |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
347 ); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
348 let parents = |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
349 *crate::dirstate::parsers::parse_dirstate_parents( |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
350 &dirstate, |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
351 )?; |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
352 self.dirstate_parents.set(parents); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
353 Ok((identity, None, 0)) |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
354 } |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
355 } |
48466
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48465
diff
changeset
|
356 } |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48465
diff
changeset
|
357 } |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48465
diff
changeset
|
358 |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
359 fn new_dirstate_map(&self) -> Result<OwningDirstateMap, DirstateError> { |
50387
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
360 if self.use_dirstate_v2() { |
49697
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
361 // The v2 dirstate is split into a docket and a data file. |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
362 // Since we don't always take the `wlock` to read it |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
363 // (like in `hg status`), it is susceptible to races. |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
364 // A simple retry method should be enough since full rewrites |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
365 // only happen when too much garbage data is present and |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
366 // this race is unlikely. |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
367 let mut tries = 0; |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
368 |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
369 while tries < V2_MAX_READ_ATTEMPTS { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
370 tries += 1; |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
371 match self.read_docket_and_data_file() { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
372 Ok(m) => { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
373 return Ok(m); |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
374 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
375 Err(e) => match e { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
376 DirstateError::Common(HgError::RaceDetected( |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
377 context, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
378 )) => { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
379 log::info!( |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
380 "dirstate read race detected {} (retry {}/{})", |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
381 context, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
382 tries, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
383 V2_MAX_READ_ATTEMPTS, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
384 ); |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
385 continue; |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
386 } |
50389
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
387 _ => { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
388 log::info!( |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
389 "Reading dirstate v2 failed, \ |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
390 falling back to v1" |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
391 ); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
392 return self.new_dirstate_map_v1(); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
393 } |
49697
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
394 }, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
395 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
396 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
397 let error = HgError::abort( |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
398 format!("dirstate read race happened {tries} times in a row"), |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
399 255, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
400 None, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
401 ); |
50252
a6b8b1ab9116
branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
diff
changeset
|
402 Err(DirstateError::Common(error)) |
49685
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
403 } else { |
50389
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
404 self.new_dirstate_map_v1() |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
405 } |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
406 } |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
407 |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
408 fn new_dirstate_map_v1(&self) -> Result<OwningDirstateMap, DirstateError> { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
409 debug_wait_for_file_or_print(self.config(), "dirstate.pre-read-file"); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
410 let identity = self.dirstate_identity()?; |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
411 let dirstate_file_contents = self.dirstate_file_contents()?; |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
412 if dirstate_file_contents.is_empty() { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
413 self.dirstate_parents.set(DirstateParents::NULL); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
414 Ok(OwningDirstateMap::new_empty(Vec::new())) |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
415 } else { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
416 let (map, parents) = |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
417 OwningDirstateMap::new_v1(dirstate_file_contents, identity)?; |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
418 self.dirstate_parents.set(parents); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50387
diff
changeset
|
419 Ok(map) |
49685
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
420 } |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
421 } |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
422 |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
423 fn read_docket_and_data_file( |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
424 &self, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
425 ) -> Result<OwningDirstateMap, DirstateError> { |
49686
fc8e37c380d3
dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49685
diff
changeset
|
426 debug_wait_for_file_or_print(self.config(), "dirstate.pre-read-file"); |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
427 let dirstate_file_contents = self.dirstate_file_contents()?; |
49703
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
428 let identity = self.dirstate_identity()?; |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
429 if dirstate_file_contents.is_empty() { |
48465
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48463
diff
changeset
|
430 self.dirstate_parents.set(DirstateParents::NULL); |
49685
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
431 return Ok(OwningDirstateMap::new_empty(Vec::new())); |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
432 } |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
433 let docket = crate::dirstate_tree::on_disk::read_docket( |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
434 &dirstate_file_contents, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
435 )?; |
49692
2be6d5782728
dirstate: add a synchronisation point in the middle of the read
Raphaël Gomès <rgomes@octobus.net>
parents:
49686
diff
changeset
|
436 debug_wait_for_file_or_print( |
2be6d5782728
dirstate: add a synchronisation point in the middle of the read
Raphaël Gomès <rgomes@octobus.net>
parents:
49686
diff
changeset
|
437 self.config(), |
2be6d5782728
dirstate: add a synchronisation point in the middle of the read
Raphaël Gomès <rgomes@octobus.net>
parents:
49686
diff
changeset
|
438 "dirstate.post-docket-read-file", |
2be6d5782728
dirstate: add a synchronisation point in the middle of the read
Raphaël Gomès <rgomes@octobus.net>
parents:
49686
diff
changeset
|
439 ); |
49685
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
440 self.dirstate_parents.set(docket.parents()); |
49701
6cce0afc1454
rust-dirstate: remember the data file uuid dirstate was loaded with
Raphaël Gomès <rgomes@octobus.net>
parents:
49697
diff
changeset
|
441 let uuid = docket.uuid.to_owned(); |
49685
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
442 let data_size = docket.data_size(); |
49697
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
443 |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
444 let context = "between reading dirstate docket and data file"; |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
445 let race_error = HgError::RaceDetected(context.into()); |
49685
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
446 let metadata = docket.tree_metadata(); |
49697
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
447 |
49685
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
448 let mut map = if crate::vfs::is_on_nfs_mount(docket.data_filename()) { |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
449 // Don't mmap on NFS to prevent `SIGBUS` error on deletion |
49697
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
450 let contents = self.hg_vfs().read(docket.data_filename()); |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
451 let contents = match contents { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
452 Ok(c) => c, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
453 Err(HgError::IoError { error, context }) => { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
454 match error.raw_os_error().expect("real os error") { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
455 // 2 = ENOENT, No such file or directory |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
456 // 116 = ESTALE, Stale NFS file handle |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
457 // |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
458 // TODO match on `error.kind()` when |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
459 // `ErrorKind::StaleNetworkFileHandle` is stable. |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
460 2 | 116 => { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
461 // Race where the data file was deleted right after |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
462 // we read the docket, try again |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
463 return Err(race_error.into()); |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
464 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
465 _ => { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
466 return Err( |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
467 HgError::IoError { error, context }.into() |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
468 ) |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
469 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
470 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
471 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
472 Err(e) => return Err(e.into()), |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
473 }; |
49703
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
474 OwningDirstateMap::new_v2( |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
475 contents, data_size, metadata, uuid, identity, |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
476 ) |
49685
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
477 } else { |
49697
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
478 match self |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
479 .hg_vfs() |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
480 .mmap_open(docket.data_filename()) |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
481 .io_not_found_as_none() |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
482 { |
49701
6cce0afc1454
rust-dirstate: remember the data file uuid dirstate was loaded with
Raphaël Gomès <rgomes@octobus.net>
parents:
49697
diff
changeset
|
483 Ok(Some(data_mmap)) => OwningDirstateMap::new_v2( |
49703
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
484 data_mmap, data_size, metadata, uuid, identity, |
49701
6cce0afc1454
rust-dirstate: remember the data file uuid dirstate was loaded with
Raphaël Gomès <rgomes@octobus.net>
parents:
49697
diff
changeset
|
485 ), |
49697
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
486 Ok(None) => { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
487 // Race where the data file was deleted right after we |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
488 // read the docket, try again |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
489 return Err(race_error.into()); |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
490 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
491 Err(e) => return Err(e.into()), |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49692
diff
changeset
|
492 } |
49685
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
493 }?; |
49680
ecd28d89c29e
dirstate-v2: add devel config option to control write behavior
Raphaël Gomès <rgomes@octobus.net>
parents:
49679
diff
changeset
|
494 |
49685
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
495 let write_mode_config = self |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
496 .config() |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
497 .get_str(b"devel", b"dirstate.v2.data_update_mode") |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
498 .unwrap_or(Some("auto")) |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
499 .unwrap_or("auto"); // don't bother for devel options |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
500 let write_mode = match write_mode_config { |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
501 "auto" => DirstateMapWriteMode::Auto, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
502 "force-new" => DirstateMapWriteMode::ForceNewDataFile, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
503 "force-append" => DirstateMapWriteMode::ForceAppend, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
504 _ => DirstateMapWriteMode::Auto, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
505 }; |
49680
ecd28d89c29e
dirstate-v2: add devel config option to control write behavior
Raphaël Gomès <rgomes@octobus.net>
parents:
49679
diff
changeset
|
506 |
49685
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
507 map.with_dmap_mut(|m| m.set_write_mode(write_mode)); |
49680
ecd28d89c29e
dirstate-v2: add devel config option to control write behavior
Raphaël Gomès <rgomes@octobus.net>
parents:
49679
diff
changeset
|
508 |
49685
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
49680
diff
changeset
|
509 Ok(map) |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
510 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
511 |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
512 pub fn dirstate_map( |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
513 &self, |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
514 ) -> Result<Ref<OwningDirstateMap>, DirstateError> { |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
515 self.dirstate_map.get_or_init(|| self.new_dirstate_map()) |
47986
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
516 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
517 |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
518 pub fn dirstate_map_mut( |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
519 &self, |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
520 ) -> Result<RefMut<OwningDirstateMap>, DirstateError> { |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
521 self.dirstate_map |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
522 .get_mut_or_init(|| self.new_dirstate_map()) |
47986
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
523 } |
47987
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47986
diff
changeset
|
524 |
49145
a5ef50becea8
rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49073
diff
changeset
|
525 fn new_changelog(&self) -> Result<Changelog, HgError> { |
49146
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49145
diff
changeset
|
526 Changelog::open(&self.store_vfs(), self.has_nodemap()) |
47986
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
527 } |
47987
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47986
diff
changeset
|
528 |
47991
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47989
diff
changeset
|
529 pub fn changelog(&self) -> Result<Ref<Changelog>, HgError> { |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
530 self.changelog.get_or_init(|| self.new_changelog()) |
47987
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47986
diff
changeset
|
531 } |
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47986
diff
changeset
|
532 |
47991
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47989
diff
changeset
|
533 pub fn changelog_mut(&self) -> Result<RefMut<Changelog>, HgError> { |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
534 self.changelog.get_mut_or_init(|| self.new_changelog()) |
47987
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47986
diff
changeset
|
535 } |
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47986
diff
changeset
|
536 |
49145
a5ef50becea8
rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49073
diff
changeset
|
537 fn new_manifestlog(&self) -> Result<Manifestlog, HgError> { |
49146
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49145
diff
changeset
|
538 Manifestlog::open(&self.store_vfs(), self.has_nodemap()) |
47987
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47986
diff
changeset
|
539 } |
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47986
diff
changeset
|
540 |
47991
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47989
diff
changeset
|
541 pub fn manifestlog(&self) -> Result<Ref<Manifestlog>, HgError> { |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
542 self.manifestlog.get_or_init(|| self.new_manifestlog()) |
47987
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47986
diff
changeset
|
543 } |
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47986
diff
changeset
|
544 |
47991
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47989
diff
changeset
|
545 pub fn manifestlog_mut(&self) -> Result<RefMut<Manifestlog>, HgError> { |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
546 self.manifestlog.get_mut_or_init(|| self.new_manifestlog()) |
47987
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47986
diff
changeset
|
547 } |
47988
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47987
diff
changeset
|
548 |
47997
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47992
diff
changeset
|
549 /// Returns the manifest of the *changeset* with the given node ID |
47992
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
550 pub fn manifest_for_node( |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
551 &self, |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
552 node: impl Into<NodePrefix>, |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
553 ) -> Result<Manifest, RevlogError> { |
47997
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47992
diff
changeset
|
554 self.manifestlog()?.data_for_node( |
47992
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
555 self.changelog()? |
47997
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47992
diff
changeset
|
556 .data_for_node(node.into())? |
47992
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
557 .manifest_node()? |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
558 .into(), |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
559 ) |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
560 } |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
561 |
47997
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47992
diff
changeset
|
562 /// Returns the manifest of the *changeset* with the given revision number |
47992
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
563 pub fn manifest_for_rev( |
47988
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47987
diff
changeset
|
564 &self, |
50988
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50389
diff
changeset
|
565 revision: UncheckedRevision, |
47988
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47987
diff
changeset
|
566 ) -> Result<Manifest, RevlogError> { |
47997
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47992
diff
changeset
|
567 self.manifestlog()?.data_for_node( |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47992
diff
changeset
|
568 self.changelog()? |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47992
diff
changeset
|
569 .data_for_rev(revision)? |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47992
diff
changeset
|
570 .manifest_node()? |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47992
diff
changeset
|
571 .into(), |
47992
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
572 ) |
47988
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47987
diff
changeset
|
573 } |
47989
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47988
diff
changeset
|
574 |
48547
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48467
diff
changeset
|
575 pub fn has_subrepos(&self) -> Result<bool, DirstateError> { |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48467
diff
changeset
|
576 if let Some(entry) = self.dirstate_map()?.get(HgPath::new(".hgsub"))? { |
49191
3f5e207f78be
rust: use `entry.tracked()` directly
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
577 Ok(entry.tracked()) |
48547
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48467
diff
changeset
|
578 } else { |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48467
diff
changeset
|
579 Ok(false) |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48467
diff
changeset
|
580 } |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48467
diff
changeset
|
581 } |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48467
diff
changeset
|
582 |
47991
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47989
diff
changeset
|
583 pub fn filelog(&self, path: &HgPath) -> Result<Filelog, HgError> { |
47989
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47988
diff
changeset
|
584 Filelog::open(self, path) |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47988
diff
changeset
|
585 } |
48467
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
586 |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
587 /// Write to disk any updates that were made through `dirstate_map_mut`. |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
588 /// |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
589 /// The "wlock" must be held while calling this. |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
590 /// See for example `try_with_wlock_no_wait`. |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
591 /// |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
592 /// TODO: have a `WritableRepo` type only accessible while holding the |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
593 /// lock? |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
594 pub fn write_dirstate(&self) -> Result<(), DirstateError> { |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
595 let map = self.dirstate_map()?; |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
596 // TODO: Maintain a `DirstateMap::dirty` flag, and return early here if |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
597 // it’s unset |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
598 let parents = self.dirstate_parents()?; |
50387
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
599 let (packed_dirstate, old_uuid_to_remove) = if self.use_dirstate_v2() { |
49703
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
600 let (identity, uuid, data_size) = |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
601 self.get_dirstate_data_file_integrity()?; |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
602 let identity_changed = identity != map.old_identity(); |
49702
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
603 let uuid_changed = uuid.as_deref() != map.old_uuid(); |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
604 let data_length_changed = data_size != map.old_data_size(); |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
605 |
49703
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
606 if identity_changed || uuid_changed || data_length_changed { |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
607 // If any of identity, uuid or length have changed since |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
608 // last disk read, don't write. |
49702
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
609 // This is fine because either we're in a command that doesn't |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
610 // write anything too important (like `hg status`), or we're in |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
611 // `hg add` and we're supposed to have taken the lock before |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
612 // reading anyway. |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
613 // |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
614 // TODO complain loudly if we've changed anything important |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
615 // without taking the lock. |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
616 // (see `hg help config.format.use-dirstate-tracked-hint`) |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
617 log::debug!( |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
618 "dirstate has changed since last read, not updating." |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
619 ); |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
620 return Ok(()); |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
621 } |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
622 |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
49701
diff
changeset
|
623 let uuid_opt = map.old_uuid(); |
49679
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49671
diff
changeset
|
624 let write_mode = if uuid_opt.is_some() { |
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49671
diff
changeset
|
625 DirstateMapWriteMode::Auto |
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49671
diff
changeset
|
626 } else { |
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49671
diff
changeset
|
627 DirstateMapWriteMode::ForceNewDataFile |
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49671
diff
changeset
|
628 }; |
48843
dd2503a63d33
rust-dirstate-v2: save proper data size if no new data on append
Raphaël Gomès <rgomes@octobus.net>
parents:
48825
diff
changeset
|
629 let (data, tree_metadata, append, old_data_size) = |
49679
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
49671
diff
changeset
|
630 map.pack_v2(write_mode)?; |
48847
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
631 |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
632 // Reuse the uuid, or generate a new one, keeping the old for |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
633 // deletion. |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
634 let (uuid, old_uuid) = match uuid_opt { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
635 Some(uuid) => { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
636 let as_str = std::str::from_utf8(uuid) |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
637 .map_err(|_| { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
638 HgError::corrupted( |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
639 "non-UTF-8 dirstate data file ID", |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
640 ) |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
641 })? |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
642 .to_owned(); |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
643 if append { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
644 (as_str, None) |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
645 } else { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
646 (DirstateDocket::new_uid(), Some(as_str)) |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
647 } |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
648 } |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
649 None => (DirstateDocket::new_uid(), None), |
48467
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
650 }; |
48847
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
48844
diff
changeset
|
651 |
48467
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
652 let data_filename = format!("dirstate.{}", uuid); |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
653 let data_filename = self.hg_vfs().join(data_filename); |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
654 let mut options = std::fs::OpenOptions::new(); |
48867
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
655 options.write(true); |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
656 |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
657 // Why are we not using the O_APPEND flag when appending? |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
658 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
659 // - O_APPEND makes it trickier to deal with garbage at the end of |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
660 // the file, left by a previous uncommitted transaction. By |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
661 // starting the write at [old_data_size] we make sure we erase |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
662 // all such garbage. |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
663 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
664 // - O_APPEND requires to special-case 0-byte writes, whereas we |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
665 // don't need that. |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
666 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
667 // - Some OSes have bugs in implementation O_APPEND: |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
668 // revlog.py talks about a Solaris bug, but we also saw some ZFS |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
669 // bug: https://github.com/openzfs/zfs/pull/3124, |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
670 // https://github.com/openzfs/zfs/issues/13370 |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
671 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
672 if !append { |
49671
f5e4248e5bce
dirstate: add some debug output when writing the dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49669
diff
changeset
|
673 log::trace!("creating a new dirstate data file"); |
48867
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
674 options.create_new(true); |
49671
f5e4248e5bce
dirstate: add some debug output when writing the dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49669
diff
changeset
|
675 } else { |
f5e4248e5bce
dirstate: add some debug output when writing the dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49669
diff
changeset
|
676 log::trace!("appending to the dirstate data file"); |
48467
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
677 } |
48867
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
678 |
48467
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
679 let data_size = (|| { |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
680 // TODO: loop and try another random ID if !append and this |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
681 // returns `ErrorKind::AlreadyExists`? Collision chance of two |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
682 // random IDs is one in 2**32 |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
683 let mut file = options.open(&data_filename)?; |
48867
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
684 if append { |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
685 file.seek(SeekFrom::Start(old_data_size as u64))?; |
48843
dd2503a63d33
rust-dirstate-v2: save proper data size if no new data on append
Raphaël Gomès <rgomes@octobus.net>
parents:
48825
diff
changeset
|
686 } |
48867
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
687 file.write_all(&data)?; |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48847
diff
changeset
|
688 file.flush()?; |
51118
532e74ad3ff6
rust: run a clippy pass with the latest stable version
Raphaël Gomès <rgomes@octobus.net>
parents:
50988
diff
changeset
|
689 file.stream_position() |
48467
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
690 })() |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
691 .when_writing_file(&data_filename)?; |
48844
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
48843
diff
changeset
|
692 |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
48843
diff
changeset
|
693 let packed_dirstate = DirstateDocket::serialize( |
48467
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
694 parents, |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
695 tree_metadata, |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
696 data_size, |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
697 uuid.as_bytes(), |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
698 ) |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
699 .map_err(|_: std::num::TryFromIntError| { |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
700 HgError::corrupted("overflow in dirstate docket serialization") |
48844
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
48843
diff
changeset
|
701 })?; |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
48843
diff
changeset
|
702 |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
48843
diff
changeset
|
703 (packed_dirstate, old_uuid) |
48467
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
704 } else { |
49703
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
705 let identity = self.dirstate_identity()?; |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
706 if identity != map.old_identity() { |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
707 // If identity changed since last disk read, don't write. |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
708 // This is fine because either we're in a command that doesn't |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
709 // write anything too important (like `hg status`), or we're in |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
710 // `hg add` and we're supposed to have taken the lock before |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
711 // reading anyway. |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
712 // |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
713 // TODO complain loudly if we've changed anything important |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
714 // without taking the lock. |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
715 // (see `hg help config.format.use-dirstate-tracked-hint`) |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
716 log::debug!( |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
717 "dirstate has changed since last read, not updating." |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
718 ); |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
719 return Ok(()); |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
49702
diff
changeset
|
720 } |
48844
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
48843
diff
changeset
|
721 (map.pack_v1(parents)?, None) |
48467
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
722 }; |
48844
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
48843
diff
changeset
|
723 |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
48843
diff
changeset
|
724 let vfs = self.hg_vfs(); |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
48843
diff
changeset
|
725 vfs.atomic_write("dirstate", &packed_dirstate)?; |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
48843
diff
changeset
|
726 if let Some(uuid) = old_uuid_to_remove { |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
48843
diff
changeset
|
727 // Remove the old data file after the new docket pointing to the |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
48843
diff
changeset
|
728 // new data file was written. |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
48843
diff
changeset
|
729 vfs.remove_file(format!("dirstate.{}", uuid))?; |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
48843
diff
changeset
|
730 } |
48467
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
731 Ok(()) |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48466
diff
changeset
|
732 } |
47986
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
733 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
734 |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
735 /// Lazily-initialized component of `Repo` with interior mutability |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
736 /// |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
737 /// This differs from `OnceCell` in that the value can still be "deinitialized" |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
738 /// later by setting its inner `Option` to `None`. It also takes the |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
739 /// initialization function as an argument when the value is requested, not |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
740 /// when the instance is created. |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
741 struct LazyCell<T> { |
47986
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
742 value: RefCell<Option<T>>, |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
743 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
744 |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
745 impl<T> LazyCell<T> { |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
746 fn new() -> Self { |
47986
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
747 Self { |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
748 value: RefCell::new(None), |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
749 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
750 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
751 |
48465
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48463
diff
changeset
|
752 fn set(&self, value: T) { |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48463
diff
changeset
|
753 *self.value.borrow_mut() = Some(value) |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48463
diff
changeset
|
754 } |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48463
diff
changeset
|
755 |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
756 fn get_or_init<E>( |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
757 &self, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
758 init: impl Fn() -> Result<T, E>, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
759 ) -> Result<Ref<T>, E> { |
47986
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
760 let mut borrowed = self.value.borrow(); |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
761 if borrowed.is_none() { |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
762 drop(borrowed); |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
763 // Only use `borrow_mut` if it is really needed to avoid panic in |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
764 // case there is another outstanding borrow but mutation is not |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
765 // needed. |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
766 *self.value.borrow_mut() = Some(init()?); |
47986
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
767 borrowed = self.value.borrow() |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
768 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
769 Ok(Ref::map(borrowed, |option| option.as_ref().unwrap())) |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
770 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
771 |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
772 fn get_mut_or_init<E>( |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
773 &self, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
774 init: impl Fn() -> Result<T, E>, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
775 ) -> Result<RefMut<T>, E> { |
47986
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47984
diff
changeset
|
776 let mut borrowed = self.value.borrow_mut(); |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
777 if borrowed.is_none() { |
49212
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49201
diff
changeset
|
778 *borrowed = Some(init()?); |
47984
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
779 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
780 Ok(RefMut::map(borrowed, |option| option.as_mut().unwrap())) |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47980
diff
changeset
|
781 } |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
782 } |