annotate rust/hg-core/src/repo.rs @ 51118:532e74ad3ff6

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