Mercurial > hg
annotate rust/hg-core/src/repo.rs @ 50252:a6b8b1ab9116
branching: merge stable into default
The clippy god had to be appeased on some aspect.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Thu, 02 Mar 2023 19:02:52 +0100 |
parents | 750409505286 dbe09fb038fc |
children | 1e2c6cda2309 |
rev | line source |
---|---|
47959
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
1 use crate::changelog::Changelog; |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
2 use crate::config::{Config, ConfigError, ConfigParseError}; |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
3 use crate::dirstate::DirstateParents; |
50221
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50211
diff
changeset
|
4 use crate::dirstate_tree::dirstate_map::DirstateMapWriteMode; |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
5 use crate::dirstate_tree::on_disk::Docket as DirstateDocket; |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
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:
47952
diff
changeset
|
7 use crate::errors::HgResultExt; |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
8 use crate::errors::{HgError, IoResultExt}; |
48417
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
9 use crate::lock::{try_with_lock_no_wait, LockError}; |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
10 use crate::manifest::{Manifest, Manifestlog}; |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47960
diff
changeset
|
11 use crate::revlog::filelog::Filelog; |
49937
750409505286
rust-clippy: merge "revlog" module definition and struct implementation
Raphaël Gomès <rgomes@octobus.net>
parents:
49930
diff
changeset
|
12 use crate::revlog::RevlogError; |
50228
fc8e37c380d3
dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50227
diff
changeset
|
13 use crate::utils::debug::debug_wait_for_file_or_print; |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
14 use crate::utils::files::get_path_from_bytes; |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47960
diff
changeset
|
15 use crate::utils::hg_path::HgPath; |
46740
97ac588b6d9e
rhg: Don’t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents:
46735
diff
changeset
|
16 use crate::utils::SliceExt; |
47952
9cd35c8c6044
rust: Move VFS code to its own module
Simon Sapin <simon.sapin@octobus.net>
parents:
47949
diff
changeset
|
17 use crate::vfs::{is_dir, is_file, Vfs}; |
47964
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
18 use crate::{requirements, NodePrefix}; |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
19 use crate::{DirstateError, Revision}; |
48419
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
20 use std::cell::{Ref, RefCell, RefMut}; |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
21 use std::collections::HashSet; |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
22 use std::io::Seek; |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
23 use std::io::SeekFrom; |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
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 |
50239
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
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:
50234
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, |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
36 requirements: HashSet<String>, |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
37 config: Config, |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
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:
49164
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:
49164
diff
changeset
|
40 changelog: LazyCell<Changelog>, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
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 |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
44 #[derive(Debug, derive_more::From)] |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
45 pub enum RepoError { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
46 NotFound { |
46503
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
47 at: PathBuf, |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
48 }, |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
49 #[from] |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
50 ConfigParseError(ConfigParseError), |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
51 #[from] |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
52 Other(HgError), |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
53 } |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
54 |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
55 impl From<ConfigError> for RepoError { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
56 fn from(error: ConfigError) -> Self { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
57 match error { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
58 ConfigError::Parse(error) => error.into(), |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
59 ConfigError::Other(error) => error.into(), |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
60 } |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
61 } |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
62 } |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
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 { |
47405
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
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:
47404
diff
changeset
|
66 /// its ancestors |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
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:
47404
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:
47404
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:
47404
diff
changeset
|
70 // as-is. |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
71 for ancestor in current_directory.ancestors() { |
47780
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"))? { |
47405
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
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:
47404
diff
changeset
|
74 } |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
75 } |
49930
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49217
diff
changeset
|
76 Err(RepoError::NotFound { |
47405
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
77 at: current_directory, |
49930
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49217
diff
changeset
|
78 }) |
47405
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
79 } |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
80 |
46505
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
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:
46503
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:
46503
diff
changeset
|
83 /// ancestors. |
46503
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
84 /// |
46505
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
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:
46503
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:
46503
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:
46503
diff
changeset
|
88 /// Having two methods would just move that `if` to almost all callers. |
46503
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
89 pub fn find( |
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
90 config: &Config, |
47404
ebdef6283798
rhg: read [paths] for `--repository` value
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47374
diff
changeset
|
91 explicit_path: Option<PathBuf>, |
46503
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
92 ) -> Result<Self, RepoError> { |
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
93 if let Some(root) = explicit_path { |
47780
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"))? { |
49930
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49217
diff
changeset
|
95 Self::new_at_path(root, config) |
47780
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)? { |
46730
dfd35823635b
rhg: Fall back to Python for bundle repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46728
diff
changeset
|
97 Err(HgError::unsupported("bundle repository").into()) |
46503
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
98 } else { |
49930
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49217
diff
changeset
|
99 Err(RepoError::NotFound { at: root }) |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
100 } |
46503
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
101 } else { |
47405
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
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:
47404
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 |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
107 /// To be called after checking that `.hg` is a sub-directory |
46485
f031fe1c6ede
rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
108 fn new_at_path( |
f031fe1c6ede
rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
109 working_directory: PathBuf, |
f031fe1c6ede
rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
110 config: &Config, |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
111 ) -> Result<Self, RepoError> { |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
112 let dot_hg = working_directory.join(".hg"); |
46463
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
113 |
49930
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49217
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:
49217
diff
changeset
|
115 vec![dot_hg.join("hgrc"), dot_hg.join("hgrc-not-shared")]; |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
116 |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
117 let hg_vfs = Vfs { base: &dot_hg }; |
46463
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
118 let mut reqs = requirements::load_if_exists(hg_vfs)?; |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
119 let relative = |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
120 reqs.contains(requirements::RELATIVE_SHARED_REQUIREMENT); |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
121 let shared = |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
122 reqs.contains(requirements::SHARED_REQUIREMENT) || relative; |
46463
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
123 |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
124 // From `mercurial/localrepo.py`: |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
125 // |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
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:
46462
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:
46462
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:
46462
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:
46462
diff
changeset
|
130 // is not present, refer checkrequirementscompat() for that |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
131 // |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
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:
46462
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:
46462
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:
46462
diff
changeset
|
135 // current repository needs to be reshared |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
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:
46462
diff
changeset
|
137 |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
138 let store_path; |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
139 if !shared { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
140 store_path = dot_hg.join("store"); |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
141 } else { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
142 let bytes = hg_vfs.read("sharedpath")?; |
46669
e8cd519a0a34
rhg: Ignore trailing newlines in .hg/sharedpath
Simon Sapin <simon.sapin@octobus.net>
parents:
46613
diff
changeset
|
143 let mut shared_path = |
47949
696abab107b4
rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents:
47780
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:
47780
diff
changeset
|
145 .to_owned(); |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
146 if relative { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
147 shared_path = dot_hg.join(shared_path) |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
148 } |
47780
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)? { |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
150 return Err(HgError::corrupted(format!( |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
151 ".hg/sharedpath points to nonexistent directory {}", |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
152 shared_path.display() |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
153 )) |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
154 .into()); |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
155 } |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
156 |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
157 store_path = shared_path.join("store"); |
46463
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
158 |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
159 let source_is_share_safe = |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
160 requirements::load(Vfs { base: &shared_path })? |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
161 .contains(requirements::SHARESAFE_REQUIREMENT); |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
162 |
48809
1d5fd9def5ac
rhg: simplify the handling of share-safe config mismatch
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48510
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:
48510
diff
changeset
|
164 return Err(HgError::unsupported("share-safe mismatch").into()); |
46463
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
165 } |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
166 |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
167 if share_safe { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
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:
46485
diff
changeset
|
169 } |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
170 } |
46613
f64b6953db70
rhg: Bug fix: with share-safe, always read store requirements
Simon Sapin <simon.sapin@octobus.net>
parents:
46601
diff
changeset
|
171 if share_safe { |
f64b6953db70
rhg: Bug fix: with share-safe, always read store requirements
Simon Sapin <simon.sapin@octobus.net>
parents:
46601
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:
46601
diff
changeset
|
173 } |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
174 |
46741
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46740
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:
46740
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:
46740
diff
changeset
|
177 } else { |
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46740
diff
changeset
|
178 config.clone() |
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46740
diff
changeset
|
179 }; |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
180 |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
181 let repo = Self { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
182 requirements: reqs, |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
183 working_directory, |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
184 store: store_path, |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
185 dot_hg, |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
186 config: repo_config, |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
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:
49164
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:
49164
diff
changeset
|
189 changelog: LazyCell::new(), |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
190 manifestlog: LazyCell::new(), |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
191 }; |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
192 |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
193 requirements::check(&repo)?; |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
194 |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
195 Ok(repo) |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
196 } |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
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 |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
202 pub fn requirements(&self) -> &HashSet<String> { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
203 &self.requirements |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
204 } |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
205 |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
206 pub fn config(&self) -> &Config { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
207 &self.config |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
208 } |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
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`). |
46599
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
46593
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`) |
46599
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
46593
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:
46741
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 } |
46601
755c31a1caf9
rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents:
46599
diff
changeset
|
227 |
48417
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
228 pub fn try_with_wlock_no_wait<R>( |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
229 &self, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
230 f: impl FnOnce() -> R, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
231 ) -> Result<R, LockError> { |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
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:
48409
diff
changeset
|
233 } |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
234 |
47374
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
235 pub fn has_dirstate_v2(&self) -> bool { |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
236 self.requirements |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
237 .contains(requirements::DIRSTATE_V2_REQUIREMENT) |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
238 } |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
239 |
48409
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
240 pub fn has_sparse(&self) -> bool { |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
241 self.requirements.contains(requirements::SPARSE_REQUIREMENT) |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
242 } |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
243 |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
244 pub fn has_narrow(&self) -> bool { |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
245 self.requirements.contains(requirements::NARROW_REQUIREMENT) |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
246 } |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
247 |
49091
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
248 pub fn has_nodemap(&self) -> bool { |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
249 self.requirements |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
250 .contains(requirements::NODEMAP_REQUIREMENT) |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
251 } |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
252 |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
253 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:
47952
diff
changeset
|
254 Ok(self |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
255 .hg_vfs() |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
256 .read("dirstate") |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
257 .io_not_found_as_none()? |
49930
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49217
diff
changeset
|
258 .unwrap_or_default()) |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
259 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
260 |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
261 fn dirstate_identity(&self) -> Result<Option<u64>, HgError> { |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
262 use std::os::unix::fs::MetadataExt; |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
263 Ok(self |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
264 .hg_vfs() |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
265 .symlink_metadata("dirstate") |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
266 .io_not_found_as_none()? |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
267 .map(|meta| meta.ino())) |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
268 } |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
269 |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
270 pub fn dirstate_parents(&self) -> Result<DirstateParents, HgError> { |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
271 Ok(*self |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
272 .dirstate_parents |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
273 .get_or_init(|| self.read_dirstate_parents())?) |
48419
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
274 } |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
275 |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
276 fn read_dirstate_parents(&self) -> Result<DirstateParents, HgError> { |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
277 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:
47952
diff
changeset
|
278 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:
47952
diff
changeset
|
279 DirstateParents::NULL |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
280 } else if self.has_dirstate_v2() { |
48420
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
281 let docket = |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
282 crate::dirstate_tree::on_disk::read_docket(&dirstate)?; |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
283 docket.parents() |
47374
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
284 } else { |
49930
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49217
diff
changeset
|
285 *crate::dirstate::parsers::parse_dirstate_parents(&dirstate)? |
47374
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
286 }; |
48419
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
287 self.dirstate_parents.set(parents); |
47674
ff97e793ed36
dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents:
47407
diff
changeset
|
288 Ok(parents) |
46601
755c31a1caf9
rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents:
46599
diff
changeset
|
289 } |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
290 |
50244
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
291 /// 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:
50243
diff
changeset
|
292 /// 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:
50243
diff
changeset
|
293 /// since we last read the dirstate. |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
294 /// Namely, the inode, data file uuid and the data size. |
50244
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
295 fn get_dirstate_data_file_integrity( |
48420
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
296 &self, |
50252
a6b8b1ab9116
branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
diff
changeset
|
297 ) -> Result<DirstateMapIdentity, HgError> { |
48420
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
298 assert!( |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
299 self.has_dirstate_v2(), |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
300 "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:
48419
diff
changeset
|
301 ); |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
302 // 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:
50244
diff
changeset
|
303 // 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:
50244
diff
changeset
|
304 // 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:
50244
diff
changeset
|
305 let identity = self.dirstate_identity()?; |
48420
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
306 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:
48419
diff
changeset
|
307 if dirstate.is_empty() { |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
308 self.dirstate_parents.set(DirstateParents::NULL); |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
309 Ok((identity, None, 0)) |
48420
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
310 } else { |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
311 let docket = |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
312 crate::dirstate_tree::on_disk::read_docket(&dirstate)?; |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
313 self.dirstate_parents.set(docket.parents()); |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
314 Ok((identity, Some(docket.uuid.to_owned()), docket.data_size())) |
48420
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
315 } |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
316 } |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
317 |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
318 fn new_dirstate_map(&self) -> Result<OwningDirstateMap, DirstateError> { |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
319 if self.has_dirstate_v2() { |
50239
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
320 // 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:
50234
diff
changeset
|
321 // 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:
50234
diff
changeset
|
322 // (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:
50234
diff
changeset
|
323 // 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:
50234
diff
changeset
|
324 // 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:
50234
diff
changeset
|
325 // 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:
50234
diff
changeset
|
326 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:
50234
diff
changeset
|
327 |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
328 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:
50234
diff
changeset
|
329 tries += 1; |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
330 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:
50234
diff
changeset
|
331 Ok(m) => { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
332 return Ok(m); |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
333 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
334 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:
50234
diff
changeset
|
335 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:
50234
diff
changeset
|
336 context, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
337 )) => { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
338 log::info!( |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
339 "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:
50234
diff
changeset
|
340 context, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
341 tries, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
342 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:
50234
diff
changeset
|
343 ); |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
344 continue; |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
345 } |
50252
a6b8b1ab9116
branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
diff
changeset
|
346 _ => return Err(e), |
50239
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
347 }, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
348 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
349 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
350 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:
50234
diff
changeset
|
351 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:
50234
diff
changeset
|
352 255, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
353 None, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
354 ); |
50252
a6b8b1ab9116
branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
diff
changeset
|
355 Err(DirstateError::Common(error)) |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
356 } else { |
50228
fc8e37c380d3
dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50227
diff
changeset
|
357 debug_wait_for_file_or_print( |
fc8e37c380d3
dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50227
diff
changeset
|
358 self.config(), |
fc8e37c380d3
dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50227
diff
changeset
|
359 "dirstate.pre-read-file", |
fc8e37c380d3
dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50227
diff
changeset
|
360 ); |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
361 let identity = self.dirstate_identity()?; |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
362 let dirstate_file_contents = self.dirstate_file_contents()?; |
50252
a6b8b1ab9116
branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
diff
changeset
|
363 if dirstate_file_contents.is_empty() { |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
364 self.dirstate_parents.set(DirstateParents::NULL); |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
365 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:
50222
diff
changeset
|
366 } else { |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
367 let (map, parents) = OwningDirstateMap::new_v1( |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
368 dirstate_file_contents, |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
369 identity, |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
370 )?; |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
371 self.dirstate_parents.set(parents); |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
372 Ok(map) |
50252
a6b8b1ab9116
branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
diff
changeset
|
373 } |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
374 } |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
375 } |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
376 |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
377 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:
50222
diff
changeset
|
378 &self, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
379 ) -> Result<OwningDirstateMap, DirstateError> { |
50228
fc8e37c380d3
dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50227
diff
changeset
|
380 debug_wait_for_file_or_print(self.config(), "dirstate.pre-read-file"); |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
381 let dirstate_file_contents = self.dirstate_file_contents()?; |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
382 let identity = self.dirstate_identity()?; |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
383 if dirstate_file_contents.is_empty() { |
48419
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
384 self.dirstate_parents.set(DirstateParents::NULL); |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
385 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:
50222
diff
changeset
|
386 } |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
387 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:
50222
diff
changeset
|
388 &dirstate_file_contents, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
389 )?; |
50234
2be6d5782728
dirstate: add a synchronisation point in the middle of the read
Raphaël Gomès <rgomes@octobus.net>
parents:
50228
diff
changeset
|
390 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:
50228
diff
changeset
|
391 self.config(), |
2be6d5782728
dirstate: add a synchronisation point in the middle of the read
Raphaël Gomès <rgomes@octobus.net>
parents:
50228
diff
changeset
|
392 "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:
50228
diff
changeset
|
393 ); |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
394 self.dirstate_parents.set(docket.parents()); |
50243
6cce0afc1454
rust-dirstate: remember the data file uuid dirstate was loaded with
Raphaël Gomès <rgomes@octobus.net>
parents:
50239
diff
changeset
|
395 let uuid = docket.uuid.to_owned(); |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
396 let data_size = docket.data_size(); |
50239
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
397 |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
398 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:
50234
diff
changeset
|
399 let race_error = HgError::RaceDetected(context.into()); |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
400 let metadata = docket.tree_metadata(); |
50239
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
401 |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
402 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:
50222
diff
changeset
|
403 // Don't mmap on NFS to prevent `SIGBUS` error on deletion |
50239
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
404 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:
50234
diff
changeset
|
405 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:
50234
diff
changeset
|
406 Ok(c) => c, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
407 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:
50234
diff
changeset
|
408 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:
50234
diff
changeset
|
409 // 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:
50234
diff
changeset
|
410 // 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:
50234
diff
changeset
|
411 // |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
412 // 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:
50234
diff
changeset
|
413 // `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:
50234
diff
changeset
|
414 2 | 116 => { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
415 // 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:
50234
diff
changeset
|
416 // 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:
50234
diff
changeset
|
417 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:
50234
diff
changeset
|
418 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
419 _ => { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
420 return Err( |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
421 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:
50234
diff
changeset
|
422 ) |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
423 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
424 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
425 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
426 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:
50234
diff
changeset
|
427 }; |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
428 OwningDirstateMap::new_v2( |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
429 contents, data_size, metadata, uuid, identity, |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
430 ) |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
431 } else { |
50239
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
432 match self |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
433 .hg_vfs() |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
434 .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:
50234
diff
changeset
|
435 .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:
50234
diff
changeset
|
436 { |
50243
6cce0afc1454
rust-dirstate: remember the data file uuid dirstate was loaded with
Raphaël Gomès <rgomes@octobus.net>
parents:
50239
diff
changeset
|
437 Ok(Some(data_mmap)) => OwningDirstateMap::new_v2( |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
438 data_mmap, data_size, metadata, uuid, identity, |
50243
6cce0afc1454
rust-dirstate: remember the data file uuid dirstate was loaded with
Raphaël Gomès <rgomes@octobus.net>
parents:
50239
diff
changeset
|
439 ), |
50239
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
440 Ok(None) => { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
441 // 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:
50234
diff
changeset
|
442 // 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:
50234
diff
changeset
|
443 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:
50234
diff
changeset
|
444 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
445 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:
50234
diff
changeset
|
446 } |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
447 }?; |
50222
ecd28d89c29e
dirstate-v2: add devel config option to control write behavior
Raphaël Gomès <rgomes@octobus.net>
parents:
50221
diff
changeset
|
448 |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
449 let write_mode_config = self |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
450 .config() |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
451 .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:
50222
diff
changeset
|
452 .unwrap_or(Some("auto")) |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
453 .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:
50222
diff
changeset
|
454 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:
50222
diff
changeset
|
455 "auto" => DirstateMapWriteMode::Auto, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
456 "force-new" => DirstateMapWriteMode::ForceNewDataFile, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
457 "force-append" => DirstateMapWriteMode::ForceAppend, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
458 _ => DirstateMapWriteMode::Auto, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
459 }; |
50222
ecd28d89c29e
dirstate-v2: add devel config option to control write behavior
Raphaël Gomès <rgomes@octobus.net>
parents:
50221
diff
changeset
|
460 |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
461 map.with_dmap_mut(|m| m.set_write_mode(write_mode)); |
50222
ecd28d89c29e
dirstate-v2: add devel config option to control write behavior
Raphaël Gomès <rgomes@octobus.net>
parents:
50221
diff
changeset
|
462 |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
463 Ok(map) |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
464 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
465 |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
466 pub fn dirstate_map( |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
467 &self, |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
468 ) -> Result<Ref<OwningDirstateMap>, DirstateError> { |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
469 self.dirstate_map.get_or_init(|| self.new_dirstate_map()) |
47958
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
470 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
471 |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
472 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:
47956
diff
changeset
|
473 &self, |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
474 ) -> Result<RefMut<OwningDirstateMap>, DirstateError> { |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
475 self.dirstate_map |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
476 .get_mut_or_init(|| self.new_dirstate_map()) |
47958
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
477 } |
47959
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
478 |
49090
a5ef50becea8
rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49005
diff
changeset
|
479 fn new_changelog(&self) -> Result<Changelog, HgError> { |
49091
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
480 Changelog::open(&self.store_vfs(), self.has_nodemap()) |
47958
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
481 } |
47959
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
482 |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
483 pub fn changelog(&self) -> Result<Ref<Changelog>, HgError> { |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
484 self.changelog.get_or_init(|| self.new_changelog()) |
47959
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
485 } |
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
486 |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
487 pub fn changelog_mut(&self) -> Result<RefMut<Changelog>, HgError> { |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
488 self.changelog.get_mut_or_init(|| self.new_changelog()) |
47959
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
489 } |
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
490 |
49090
a5ef50becea8
rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49005
diff
changeset
|
491 fn new_manifestlog(&self) -> Result<Manifestlog, HgError> { |
49091
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
492 Manifestlog::open(&self.store_vfs(), self.has_nodemap()) |
47959
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
493 } |
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
494 |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
495 pub fn manifestlog(&self) -> Result<Ref<Manifestlog>, HgError> { |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
496 self.manifestlog.get_or_init(|| self.new_manifestlog()) |
47959
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
497 } |
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
498 |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
499 pub fn manifestlog_mut(&self) -> Result<RefMut<Manifestlog>, HgError> { |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
500 self.manifestlog.get_mut_or_init(|| self.new_manifestlog()) |
47959
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
501 } |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
502 |
47969
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47964
diff
changeset
|
503 /// Returns the manifest of the *changeset* with the given node ID |
47964
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
504 pub fn manifest_for_node( |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
505 &self, |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
506 node: impl Into<NodePrefix>, |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
507 ) -> Result<Manifest, RevlogError> { |
47969
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47964
diff
changeset
|
508 self.manifestlog()?.data_for_node( |
47964
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
509 self.changelog()? |
47969
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47964
diff
changeset
|
510 .data_for_node(node.into())? |
47964
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
511 .manifest_node()? |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
512 .into(), |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
513 ) |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
514 } |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
515 |
47969
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47964
diff
changeset
|
516 /// Returns the manifest of the *changeset* with the given revision number |
47964
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
517 pub fn manifest_for_rev( |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
518 &self, |
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
519 revision: Revision, |
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
520 ) -> Result<Manifest, RevlogError> { |
47969
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47964
diff
changeset
|
521 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:
47964
diff
changeset
|
522 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:
47964
diff
changeset
|
523 .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:
47964
diff
changeset
|
524 .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:
47964
diff
changeset
|
525 .into(), |
47964
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
526 ) |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
527 } |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47960
diff
changeset
|
528 |
48510
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
529 pub fn has_subrepos(&self) -> Result<bool, DirstateError> { |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
530 if let Some(entry) = self.dirstate_map()?.get(HgPath::new(".hgsub"))? { |
49136
3f5e207f78be
rust: use `entry.tracked()` directly
Raphaël Gomès <rgomes@octobus.net>
parents:
49091
diff
changeset
|
531 Ok(entry.tracked()) |
48510
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
532 } else { |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
533 Ok(false) |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
534 } |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
535 } |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
536 |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
537 pub fn filelog(&self, path: &HgPath) -> Result<Filelog, HgError> { |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47960
diff
changeset
|
538 Filelog::open(self, path) |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47960
diff
changeset
|
539 } |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
540 |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
541 /// 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:
48420
diff
changeset
|
542 /// |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
543 /// The "wlock" must be held while calling this. |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
544 /// See for example `try_with_wlock_no_wait`. |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
545 /// |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
546 /// TODO: have a `WritableRepo` type only accessible while holding the |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
547 /// lock? |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
548 pub fn write_dirstate(&self) -> Result<(), DirstateError> { |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
549 let map = self.dirstate_map()?; |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
550 // TODO: Maintain a `DirstateMap::dirty` flag, and return early here if |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
551 // it’s unset |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
552 let parents = self.dirstate_parents()?; |
49146
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
49145
diff
changeset
|
553 let (packed_dirstate, old_uuid_to_remove) = if self.has_dirstate_v2() { |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
554 let (identity, uuid, data_size) = |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
555 self.get_dirstate_data_file_integrity()?; |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
556 let identity_changed = identity != map.old_identity(); |
50244
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
557 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:
50243
diff
changeset
|
558 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:
50243
diff
changeset
|
559 |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
560 if identity_changed || uuid_changed || data_length_changed { |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
561 // 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:
50244
diff
changeset
|
562 // last disk read, don't write. |
50244
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
563 // 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:
50243
diff
changeset
|
564 // 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:
50243
diff
changeset
|
565 // `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:
50243
diff
changeset
|
566 // reading anyway. |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
567 // |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
568 // 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:
50243
diff
changeset
|
569 // 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:
50243
diff
changeset
|
570 // (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:
50243
diff
changeset
|
571 log::debug!( |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
572 "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:
50243
diff
changeset
|
573 ); |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
574 return Ok(()); |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
575 } |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
576 |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
577 let uuid_opt = map.old_uuid(); |
50221
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50211
diff
changeset
|
578 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:
50211
diff
changeset
|
579 DirstateMapWriteMode::Auto |
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50211
diff
changeset
|
580 } else { |
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50211
diff
changeset
|
581 DirstateMapWriteMode::ForceNewDataFile |
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50211
diff
changeset
|
582 }; |
49145
dd2503a63d33
rust-dirstate-v2: save proper data size if no new data on append
Raphaël Gomès <rgomes@octobus.net>
parents:
49000
diff
changeset
|
583 let (data, tree_metadata, append, old_data_size) = |
50221
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50211
diff
changeset
|
584 map.pack_v2(write_mode)?; |
49150
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
585 |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
586 // 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:
49146
diff
changeset
|
587 // deletion. |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
588 let (uuid, old_uuid) = match uuid_opt { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
589 Some(uuid) => { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
590 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:
49146
diff
changeset
|
591 .map_err(|_| { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
592 HgError::corrupted( |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
593 "non-UTF-8 dirstate data file ID", |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
594 ) |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
595 })? |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
596 .to_owned(); |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
597 if append { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
598 (as_str, None) |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
599 } else { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
600 (DirstateDocket::new_uid(), Some(as_str)) |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
601 } |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
602 } |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
603 None => (DirstateDocket::new_uid(), None), |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
604 }; |
49150
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
605 |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
606 let data_filename = format!("dirstate.{}", uuid); |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
607 let data_filename = self.hg_vfs().join(data_filename); |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
608 let mut options = std::fs::OpenOptions::new(); |
49202
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
609 options.write(true); |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
610 |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
611 // 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:
49150
diff
changeset
|
612 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
613 // - 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:
49150
diff
changeset
|
614 // 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:
49150
diff
changeset
|
615 // 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:
49150
diff
changeset
|
616 // all such garbage. |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
617 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
618 // - 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:
49150
diff
changeset
|
619 // don't need that. |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
620 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
621 // - Some OSes have bugs in implementation O_APPEND: |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
622 // 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:
49150
diff
changeset
|
623 // bug: https://github.com/openzfs/zfs/pull/3124, |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
624 // https://github.com/openzfs/zfs/issues/13370 |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
625 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
626 if !append { |
50211
f5e4248e5bce
dirstate: add some debug output when writing the dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50180
diff
changeset
|
627 log::trace!("creating a new dirstate data file"); |
49202
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
628 options.create_new(true); |
50211
f5e4248e5bce
dirstate: add some debug output when writing the dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50180
diff
changeset
|
629 } else { |
f5e4248e5bce
dirstate: add some debug output when writing the dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50180
diff
changeset
|
630 log::trace!("appending to the dirstate data file"); |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
631 } |
49202
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
632 |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
633 let data_size = (|| { |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
634 // TODO: loop and try another random ID if !append and this |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
635 // returns `ErrorKind::AlreadyExists`? Collision chance of two |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
636 // random IDs is one in 2**32 |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
637 let mut file = options.open(&data_filename)?; |
49202
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
638 if append { |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
639 file.seek(SeekFrom::Start(old_data_size as u64))?; |
49145
dd2503a63d33
rust-dirstate-v2: save proper data size if no new data on append
Raphaël Gomès <rgomes@octobus.net>
parents:
49000
diff
changeset
|
640 } |
49202
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
641 file.write_all(&data)?; |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
642 file.flush()?; |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
643 file.seek(SeekFrom::Current(0)) |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
644 })() |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
645 .when_writing_file(&data_filename)?; |
49146
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
49145
diff
changeset
|
646 |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
49145
diff
changeset
|
647 let packed_dirstate = DirstateDocket::serialize( |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
648 parents, |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
649 tree_metadata, |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
650 data_size, |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
651 uuid.as_bytes(), |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
652 ) |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
653 .map_err(|_: std::num::TryFromIntError| { |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
654 HgError::corrupted("overflow in dirstate docket serialization") |
49146
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
49145
diff
changeset
|
655 })?; |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
49145
diff
changeset
|
656 |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
49145
diff
changeset
|
657 (packed_dirstate, old_uuid) |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
658 } else { |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
659 let identity = self.dirstate_identity()?; |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
660 if identity != map.old_identity() { |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
661 // 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:
50244
diff
changeset
|
662 // 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:
50244
diff
changeset
|
663 // 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:
50244
diff
changeset
|
664 // `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:
50244
diff
changeset
|
665 // reading anyway. |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
666 // |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
667 // 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:
50244
diff
changeset
|
668 // without taking the lock. |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
669 // (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:
50244
diff
changeset
|
670 log::debug!( |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
671 "dirstate has changed since last read, not updating." |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
672 ); |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
673 return Ok(()); |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
674 } |
49146
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
49145
diff
changeset
|
675 (map.pack_v1(parents)?, None) |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
676 }; |
49146
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
49145
diff
changeset
|
677 |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
49145
diff
changeset
|
678 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:
49145
diff
changeset
|
679 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:
49145
diff
changeset
|
680 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:
49145
diff
changeset
|
681 // 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:
49145
diff
changeset
|
682 // 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:
49145
diff
changeset
|
683 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:
49145
diff
changeset
|
684 } |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
685 Ok(()) |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
686 } |
47958
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
687 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
688 |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
689 /// 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:
47956
diff
changeset
|
690 /// |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
691 /// This differs from `OnceCell` in that the value can still be "deinitialized" |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
692 /// 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:
49164
diff
changeset
|
693 /// 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:
49164
diff
changeset
|
694 /// when the instance is created. |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
695 struct LazyCell<T> { |
47958
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
696 value: RefCell<Option<T>>, |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
697 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
698 |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
699 impl<T> LazyCell<T> { |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
700 fn new() -> Self { |
47958
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
701 Self { |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
702 value: RefCell::new(None), |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
703 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
704 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
705 |
48419
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
706 fn set(&self, value: T) { |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
707 *self.value.borrow_mut() = Some(value) |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
708 } |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
709 |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
710 fn get_or_init<E>( |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
711 &self, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
712 init: impl Fn() -> Result<T, E>, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
713 ) -> Result<Ref<T>, E> { |
47958
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
714 let mut borrowed = self.value.borrow(); |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
715 if borrowed.is_none() { |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
716 drop(borrowed); |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
717 // 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:
47952
diff
changeset
|
718 // 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:
47952
diff
changeset
|
719 // needed. |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
720 *self.value.borrow_mut() = Some(init()?); |
47958
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
721 borrowed = self.value.borrow() |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
722 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
723 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:
47952
diff
changeset
|
724 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
725 |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
726 fn get_mut_or_init<E>( |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
727 &self, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
728 init: impl Fn() -> Result<T, E>, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
729 ) -> Result<RefMut<T>, E> { |
47958
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
730 let mut borrowed = self.value.borrow_mut(); |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
731 if borrowed.is_none() { |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
732 *borrowed = Some(init()?); |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
733 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
734 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:
47952
diff
changeset
|
735 } |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
736 } |