Mercurial > hg
annotate rust/hg-core/src/repo.rs @ 50243:6cce0afc1454 stable
rust-dirstate: remember the data file uuid dirstate was loaded with
This will be used in the next patch to fix a race condition.
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Mon, 12 Dec 2022 17:08:12 +0100 |
parents | 491f3dd080eb |
children | 07d030b38097 |
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; |
47959
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
12 use crate::revlog::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 |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
29 /// A repository on disk |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
30 pub struct Repo { |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
31 working_directory: PathBuf, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
32 dot_hg: PathBuf, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
33 store: PathBuf, |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
34 requirements: HashSet<String>, |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
35 config: Config, |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
36 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
|
37 dirstate_data_file_uuid: LazyCell<Option<Vec<u8>>>, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
38 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
|
39 changelog: LazyCell<Changelog>, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
40 manifestlog: LazyCell<Manifestlog>, |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
41 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
42 |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
43 #[derive(Debug, derive_more::From)] |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
44 pub enum RepoError { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
45 NotFound { |
46503
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
46 at: PathBuf, |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
47 }, |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
48 #[from] |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
49 ConfigParseError(ConfigParseError), |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
50 #[from] |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
51 Other(HgError), |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
52 } |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
53 |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
54 impl From<ConfigError> for RepoError { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
55 fn from(error: ConfigError) -> Self { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
56 match error { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
57 ConfigError::Parse(error) => error.into(), |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
58 ConfigError::Other(error) => error.into(), |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
59 } |
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 |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
63 impl Repo { |
47405
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
64 /// 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
|
65 /// its ancestors |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
66 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
|
67 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
|
68 // 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
|
69 // as-is. |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
70 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
|
71 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
|
72 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
|
73 } |
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 return Err(RepoError::NotFound { |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
76 at: current_directory, |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
77 }); |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
78 } |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
79 |
46505
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
80 /// 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
|
81 /// 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
|
82 /// ancestors. |
46503
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
83 /// |
46505
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
84 /// 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
|
85 /// 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
|
86 /// 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
|
87 /// 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
|
88 pub fn find( |
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
89 config: &Config, |
47404
ebdef6283798
rhg: read [paths] for `--repository` value
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47374
diff
changeset
|
90 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
|
91 ) -> Result<Self, RepoError> { |
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
92 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
|
93 if is_dir(root.join(".hg"))? { |
46740
97ac588b6d9e
rhg: Don’t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents:
46735
diff
changeset
|
94 Self::new_at_path(root.to_owned(), config) |
47780
cf5f8da2244c
rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents:
47674
diff
changeset
|
95 } 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
|
96 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
|
97 } else { |
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
98 Err(RepoError::NotFound { |
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
99 at: root.to_owned(), |
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
100 }) |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
101 } |
46503
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
102 } else { |
47405
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
103 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
|
104 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
|
105 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
106 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
107 |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
108 /// 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
|
109 fn new_at_path( |
f031fe1c6ede
rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
110 working_directory: PathBuf, |
f031fe1c6ede
rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
111 config: &Config, |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
112 ) -> Result<Self, RepoError> { |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
113 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
|
114 |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
115 let mut repo_config_files = Vec::new(); |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
116 repo_config_files.push(dot_hg.join("hgrc")); |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
117 repo_config_files.push(dot_hg.join("hgrc-not-shared")); |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
118 |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
119 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
|
120 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
|
121 let relative = |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
122 reqs.contains(requirements::RELATIVE_SHARED_REQUIREMENT); |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
123 let shared = |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
124 reqs.contains(requirements::SHARED_REQUIREMENT) || relative; |
46463
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 // From `mercurial/localrepo.py`: |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
127 // |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
128 // 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
|
129 // 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
|
130 // 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
|
131 // 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
|
132 // is not present, refer checkrequirementscompat() for that |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
133 // |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
134 // 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
|
135 // 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
|
136 // .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
|
137 // current repository needs to be reshared |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
138 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
|
139 |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
140 let store_path; |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
141 if !shared { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
142 store_path = dot_hg.join("store"); |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
143 } else { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
144 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
|
145 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
|
146 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
|
147 .to_owned(); |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
148 if relative { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
149 shared_path = dot_hg.join(shared_path) |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
150 } |
47780
cf5f8da2244c
rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents:
47674
diff
changeset
|
151 if !is_dir(&shared_path)? { |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
152 return Err(HgError::corrupted(format!( |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
153 ".hg/sharedpath points to nonexistent directory {}", |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
154 shared_path.display() |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
155 )) |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
156 .into()); |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
157 } |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
158 |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
159 store_path = shared_path.join("store"); |
46463
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
160 |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
161 let source_is_share_safe = |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
162 requirements::load(Vfs { base: &shared_path })? |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
163 .contains(requirements::SHARESAFE_REQUIREMENT); |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
164 |
48809
1d5fd9def5ac
rhg: simplify the handling of share-safe config mismatch
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48510
diff
changeset
|
165 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
|
166 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
|
167 } |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
168 |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
169 if share_safe { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
170 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
|
171 } |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
172 } |
46613
f64b6953db70
rhg: Bug fix: with share-safe, always read store requirements
Simon Sapin <simon.sapin@octobus.net>
parents:
46601
diff
changeset
|
173 if share_safe { |
f64b6953db70
rhg: Bug fix: with share-safe, always read store requirements
Simon Sapin <simon.sapin@octobus.net>
parents:
46601
diff
changeset
|
174 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
|
175 } |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
176 |
46741
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46740
diff
changeset
|
177 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
|
178 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
|
179 } else { |
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46740
diff
changeset
|
180 config.clone() |
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46740
diff
changeset
|
181 }; |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
182 |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
183 let repo = Self { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
184 requirements: reqs, |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
185 working_directory, |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
186 store: store_path, |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
187 dot_hg, |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
188 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
|
189 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
|
190 dirstate_data_file_uuid: LazyCell::new(), |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
191 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
|
192 changelog: LazyCell::new(), |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
193 manifestlog: LazyCell::new(), |
46462
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 |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
196 requirements::check(&repo)?; |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
197 |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
198 Ok(repo) |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
199 } |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
200 |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
201 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
|
202 &self.working_directory |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
203 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
204 |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
205 pub fn requirements(&self) -> &HashSet<String> { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
206 &self.requirements |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
207 } |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
208 |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
209 pub fn config(&self) -> &Config { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
210 &self.config |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
211 } |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
212 |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
213 /// 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
|
214 /// (`.hg/store`). |
46599
1f55cd5b292f
rust: Add a log file rotation utility
Simon Sapin <simon.sapin@octobus.net>
parents:
46593
diff
changeset
|
215 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
|
216 Vfs { base: &self.dot_hg } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
217 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
218 |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
219 /// 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
|
220 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
|
221 Vfs { base: &self.store } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
222 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
223 |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
224 /// For accessing the working copy |
46822
c71e8d9e7f2a
rhg: Initial support for the 'status' command
Georges Racinet <georges.racinet@octobus.net>
parents:
46741
diff
changeset
|
225 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
|
226 Vfs { |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
227 base: &self.working_directory, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
228 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
229 } |
46601
755c31a1caf9
rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents:
46599
diff
changeset
|
230 |
48417
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
231 pub fn try_with_wlock_no_wait<R>( |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
232 &self, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
233 f: impl FnOnce() -> R, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
234 ) -> Result<R, LockError> { |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
235 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
|
236 } |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
237 |
47374
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
238 pub fn has_dirstate_v2(&self) -> bool { |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
239 self.requirements |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
240 .contains(requirements::DIRSTATE_V2_REQUIREMENT) |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
241 } |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
242 |
48409
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
243 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
|
244 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
|
245 } |
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 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
|
248 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
|
249 } |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
250 |
49091
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
251 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
|
252 self.requirements |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
253 .contains(requirements::NODEMAP_REQUIREMENT) |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
254 } |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
255 |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
256 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
|
257 Ok(self |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
258 .hg_vfs() |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
259 .read("dirstate") |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
260 .io_not_found_as_none()? |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
261 .unwrap_or(Vec::new())) |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
262 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
263 |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
264 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
|
265 Ok(*self |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
266 .dirstate_parents |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
267 .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
|
268 } |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
269 |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
270 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
|
271 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
|
272 let parents = if dirstate.is_empty() { |
48420
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
273 if 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
|
274 self.dirstate_data_file_uuid.set(None); |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
275 } |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
276 DirstateParents::NULL |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
277 } 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
|
278 let docket = |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
279 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
|
280 self.dirstate_data_file_uuid |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
281 .set(Some(docket.uuid.to_owned())); |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
282 docket.parents() |
47374
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
283 } else { |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
284 crate::dirstate::parsers::parse_dirstate_parents(&dirstate)? |
47674
ff97e793ed36
dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents:
47407
diff
changeset
|
285 .clone() |
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 |
48420
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
291 fn read_dirstate_data_file_uuid( |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
292 &self, |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
293 ) -> Result<Option<Vec<u8>>, HgError> { |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
294 assert!( |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
295 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
|
296 "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
|
297 ); |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
298 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
|
299 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
|
300 self.dirstate_parents.set(DirstateParents::NULL); |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
301 Ok(None) |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
302 } else { |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
303 let docket = |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
304 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
|
305 self.dirstate_parents.set(docket.parents()); |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
306 Ok(Some(docket.uuid.to_owned())) |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
307 } |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
308 } |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
309 |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
310 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
|
311 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
|
312 // 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
|
313 // 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
|
314 // (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
|
315 // 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
|
316 // 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
|
317 // 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
|
318 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
|
319 |
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 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
|
321 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
|
322 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
|
323 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
|
324 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
|
325 } |
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 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
|
327 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
|
328 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
|
329 )) => { |
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 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
|
331 "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
|
332 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
|
333 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
|
334 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
|
335 ); |
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 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
|
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 _ => 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
|
339 }, |
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 } |
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 } |
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 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
|
343 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
|
344 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
|
345 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
|
346 ); |
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 return 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
|
348 } 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
|
349 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
|
350 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
|
351 "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
|
352 ); |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
353 let dirstate_file_contents = self.dirstate_file_contents()?; |
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
|
354 return 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
|
355 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
|
356 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
|
357 } else { |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
358 let (map, parents) = |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
359 OwningDirstateMap::new_v1(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
|
360 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
|
361 Ok(map) |
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
|
362 }; |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
363 } |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
364 } |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
365 |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
366 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
|
367 &self, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
368 ) -> 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
|
369 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
|
370 let dirstate_file_contents = 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
|
371 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
|
372 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
|
373 self.dirstate_data_file_uuid.set(None); |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
374 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
|
375 } |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
376 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
|
377 &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
|
378 )?; |
50234
2be6d5782728
dirstate: add a synchronisation point in the middle of the read
Raphaël Gomès <rgomes@octobus.net>
parents:
50228
diff
changeset
|
379 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
|
380 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
|
381 "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
|
382 ); |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
383 self.dirstate_parents.set(docket.parents()); |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
384 self.dirstate_data_file_uuid |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
385 .set(Some(docket.uuid.to_owned())); |
50243
6cce0afc1454
rust-dirstate: remember the data file uuid dirstate was loaded with
Raphaël Gomès <rgomes@octobus.net>
parents:
50239
diff
changeset
|
386 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
|
387 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
|
388 |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
389 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
|
390 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
|
391 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
|
392 |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
393 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
|
394 // 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
|
395 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
|
396 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
|
397 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
|
398 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
|
399 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
|
400 // 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
|
401 // 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
|
402 // |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
403 // 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
|
404 // `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
|
405 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
|
406 // 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
|
407 // 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
|
408 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
|
409 } |
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 _ => { |
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 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
|
412 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
|
413 ) |
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 } |
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 } |
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 } |
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 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
|
418 }; |
50243
6cce0afc1454
rust-dirstate: remember the data file uuid dirstate was loaded with
Raphaël Gomès <rgomes@octobus.net>
parents:
50239
diff
changeset
|
419 OwningDirstateMap::new_v2(contents, data_size, metadata, uuid) |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
420 } 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
|
421 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
|
422 .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
|
423 .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
|
424 .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
|
425 { |
50243
6cce0afc1454
rust-dirstate: remember the data file uuid dirstate was loaded with
Raphaël Gomès <rgomes@octobus.net>
parents:
50239
diff
changeset
|
426 Ok(Some(data_mmap)) => OwningDirstateMap::new_v2( |
6cce0afc1454
rust-dirstate: remember the data file uuid dirstate was loaded with
Raphaël Gomès <rgomes@octobus.net>
parents:
50239
diff
changeset
|
427 data_mmap, data_size, metadata, uuid, |
6cce0afc1454
rust-dirstate: remember the data file uuid dirstate was loaded with
Raphaël Gomès <rgomes@octobus.net>
parents:
50239
diff
changeset
|
428 ), |
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
|
429 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
|
430 // 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
|
431 // 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
|
432 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
|
433 } |
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 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
|
435 } |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
436 }?; |
50222
ecd28d89c29e
dirstate-v2: add devel config option to control write behavior
Raphaël Gomès <rgomes@octobus.net>
parents:
50221
diff
changeset
|
437 |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
438 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
|
439 .config() |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
440 .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
|
441 .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
|
442 .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
|
443 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
|
444 "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
|
445 "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
|
446 "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
|
447 _ => DirstateMapWriteMode::Auto, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
448 }; |
50222
ecd28d89c29e
dirstate-v2: add devel config option to control write behavior
Raphaël Gomès <rgomes@octobus.net>
parents:
50221
diff
changeset
|
449 |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
450 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
|
451 |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
452 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
|
453 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
454 |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
455 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
|
456 &self, |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
457 ) -> 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
|
458 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
|
459 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
460 |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
461 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
|
462 &self, |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
463 ) -> 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
|
464 self.dirstate_map |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
465 .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
|
466 } |
47959
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
467 |
49090
a5ef50becea8
rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49005
diff
changeset
|
468 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
|
469 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
|
470 } |
47959
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
471 |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
472 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
|
473 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
|
474 } |
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
475 |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
476 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
|
477 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
|
478 } |
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
479 |
49090
a5ef50becea8
rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49005
diff
changeset
|
480 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
|
481 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
|
482 } |
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
483 |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
484 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
|
485 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
|
486 } |
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
487 |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
488 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
|
489 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
|
490 } |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
491 |
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
|
492 /// 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
|
493 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
|
494 &self, |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
495 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
|
496 ) -> 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
|
497 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
|
498 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
|
499 .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
|
500 .manifest_node()? |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
501 .into(), |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
502 ) |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
503 } |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
504 |
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
|
505 /// 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
|
506 pub fn manifest_for_rev( |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
507 &self, |
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
508 revision: Revision, |
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
509 ) -> 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
|
510 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
|
511 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
|
512 .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
|
513 .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
|
514 .into(), |
47964
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
515 ) |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
516 } |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47960
diff
changeset
|
517 |
48510
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
518 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
|
519 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
|
520 Ok(entry.tracked()) |
48510
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
521 } else { |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
522 Ok(false) |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
523 } |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
524 } |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
525 |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
526 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
|
527 Filelog::open(self, path) |
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47960
diff
changeset
|
528 } |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
529 |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
530 /// 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
|
531 /// |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
532 /// The "wlock" must be held while calling this. |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
533 /// See for example `try_with_wlock_no_wait`. |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
534 /// |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
535 /// 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
|
536 /// lock? |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
537 pub fn write_dirstate(&self) -> Result<(), DirstateError> { |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
538 let map = self.dirstate_map()?; |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
539 // 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
|
540 // it’s unset |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
541 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
|
542 let (packed_dirstate, old_uuid_to_remove) = if self.has_dirstate_v2() { |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
543 let uuid_opt = self |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
544 .dirstate_data_file_uuid |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
545 .get_or_init(|| self.read_dirstate_data_file_uuid())?; |
49150
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
546 let uuid_opt = uuid_opt.as_ref(); |
50221
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50211
diff
changeset
|
547 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
|
548 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
|
549 } else { |
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50211
diff
changeset
|
550 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
|
551 }; |
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
|
552 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
|
553 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
|
554 |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
555 // 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
|
556 // deletion. |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
557 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
|
558 Some(uuid) => { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
559 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
|
560 .map_err(|_| { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
561 HgError::corrupted( |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
562 "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
|
563 ) |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
564 })? |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
565 .to_owned(); |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
566 if append { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
567 (as_str, None) |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
568 } else { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
569 (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
|
570 } |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
571 } |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
572 None => (DirstateDocket::new_uid(), None), |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
573 }; |
49150
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
574 |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
575 let data_filename = format!("dirstate.{}", uuid); |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
576 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
|
577 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
|
578 options.write(true); |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
579 |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
580 // 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
|
581 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
582 // - 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
|
583 // 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
|
584 // 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
|
585 // all such garbage. |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
586 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
587 // - 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
|
588 // don't need that. |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
589 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
590 // - 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
|
591 // 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
|
592 // 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
|
593 // 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
|
594 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
595 if !append { |
50211
f5e4248e5bce
dirstate: add some debug output when writing the dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50180
diff
changeset
|
596 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
|
597 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
|
598 } else { |
f5e4248e5bce
dirstate: add some debug output when writing the dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50180
diff
changeset
|
599 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
|
600 } |
49202
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
601 |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
602 let data_size = (|| { |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
603 // 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
|
604 // returns `ErrorKind::AlreadyExists`? Collision chance of two |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
605 // random IDs is one in 2**32 |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
606 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
|
607 if append { |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
608 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
|
609 } |
49202
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
610 file.write_all(&data)?; |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
611 file.flush()?; |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
612 file.seek(SeekFrom::Current(0)) |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
613 })() |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
614 .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
|
615 |
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
|
616 let packed_dirstate = DirstateDocket::serialize( |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
617 parents, |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
618 tree_metadata, |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
619 data_size, |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
620 uuid.as_bytes(), |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
621 ) |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
622 .map_err(|_: std::num::TryFromIntError| { |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
623 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
|
624 })?; |
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
|
625 |
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
|
626 (packed_dirstate, old_uuid) |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
627 } else { |
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
|
628 (map.pack_v1(parents)?, None) |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
629 }; |
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
|
630 |
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
|
631 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
|
632 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
|
633 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
|
634 // 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
|
635 // 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
|
636 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
|
637 } |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
638 Ok(()) |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
639 } |
47958
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
640 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
641 |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
642 /// 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
|
643 /// |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
644 /// 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
|
645 /// 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
|
646 /// 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
|
647 /// 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
|
648 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
|
649 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
|
650 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
651 |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
652 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
|
653 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
|
654 Self { |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
655 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
|
656 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
657 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
658 |
48419
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
659 fn set(&self, value: T) { |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
660 *self.value.borrow_mut() = Some(value) |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
661 } |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
662 |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
663 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
|
664 &self, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
665 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
|
666 ) -> 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
|
667 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
|
668 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
|
669 drop(borrowed); |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
670 // 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
|
671 // 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
|
672 // needed. |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
673 *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
|
674 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
|
675 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
676 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
|
677 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
678 |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
679 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
|
680 &self, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
681 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
|
682 ) -> 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
|
683 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
|
684 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
|
685 *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
|
686 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
687 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
|
688 } |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
689 } |