annotate rust/hg-core/src/repo.rs @ 52071:e1fe336c007a

rust-repo: don't use on-disk dirstate parents in v1 This mistake was not causing any problems yet since we were never updating parents from Rust code. This is about to change, so let's fix it.
author Rapha?l Gom?s <rgomes@octobus.net>
date Wed, 02 Oct 2024 13:36:51 +0200
parents 28a0eb21ff04
children a8cf6a852f11
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};
51212
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
11 use crate::requirements::{
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
12 CHANGELOGV2_REQUIREMENT, GENERALDELTA_REQUIREMENT, NODEMAP_REQUIREMENT,
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
13 REVLOGV1_REQUIREMENT, REVLOGV2_REQUIREMENT,
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
14 };
47989
4d2a5ca060e3 rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents: 47988
diff changeset
15 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
16 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
17 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
18 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
19 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
20 use crate::utils::SliceExt;
51906
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
21 use crate::vfs::{is_dir, is_file, VfsImpl};
51212
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
22 use crate::{
52070
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
23 exit_codes, requirements, NodePrefix, RevlogDataConfig, RevlogDeltaConfig,
51905
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
24 RevlogFeatureConfig, RevlogType, RevlogVersionOptions, UncheckedRevision,
51212
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
25 };
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
26 use crate::{DirstateError, RevlogOpenOptions};
48465
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48463
diff changeset
27 use std::cell::{Ref, RefCell, RefMut};
46524
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
28 use std::collections::HashSet;
48467
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
29 use std::io::Seek;
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
30 use std::io::SeekFrom;
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
31 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
32 use std::path::{Path, PathBuf};
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
33
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
34 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
35
50252
a6b8b1ab9116 branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50010 49703
diff changeset
36 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
37
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
38 /// A repository on disk
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
39 pub struct Repo {
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
40 working_directory: PathBuf,
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
41 dot_hg: PathBuf,
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
42 store: PathBuf,
46524
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
43 requirements: HashSet<String>,
46545
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
44 config: Config,
49212
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49201
diff changeset
45 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
46 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
47 changelog: LazyCell<Changelog>,
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49201
diff changeset
48 manifestlog: LazyCell<Manifestlog>,
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
49 }
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
50
46514
1dcd9c9975ed rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
51 #[derive(Debug, derive_more::From)]
46545
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
52 pub enum RepoError {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
53 NotFound {
46555
d8730ff51d5a rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46545
diff changeset
54 at: PathBuf,
46514
1dcd9c9975ed rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
55 },
1dcd9c9975ed rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
56 #[from]
46545
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
57 ConfigParseError(ConfigParseError),
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
58 #[from]
46514
1dcd9c9975ed rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
59 Other(HgError),
1dcd9c9975ed rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
60 }
1dcd9c9975ed rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents: 46511
diff changeset
61
46545
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
62 impl From<ConfigError> for RepoError {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
63 fn from(error: ConfigError) -> Self {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
64 match error {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
65 ConfigError::Parse(error) => error.into(),
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
66 ConfigError::Other(error) => error.into(),
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
67 }
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
68 }
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
69 }
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
70
52070
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
71 impl From<RepoError> for HgError {
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
72 fn from(value: RepoError) -> Self {
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
73 match value {
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
74 RepoError::NotFound { at } => HgError::abort(
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
75 format!(
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
76 "abort: no repository found in '{}' (.hg not found)!",
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
77 at.display()
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
78 ),
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
79 exit_codes::ABORT,
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
80 None,
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
81 ),
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
82 RepoError::ConfigParseError(config_parse_error) => {
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
83 HgError::Abort {
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
84 message: String::from_utf8_lossy(
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
85 &config_parse_error.message,
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
86 )
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
87 .to_string(),
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
88 detailed_exit_code: exit_codes::CONFIG_PARSE_ERROR_ABORT,
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
89 hint: None,
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
90 }
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
91 }
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
92 RepoError::Other(hg_error) => hg_error,
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
93 }
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
94 }
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
95 }
28a0eb21ff04 rust-cpython: add a util to get a `Repo` from a python path
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52060
diff changeset
96
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
97 impl Repo {
47411
88119fffecc8 rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47410
diff changeset
98 /// 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
99 /// its ancestors
88119fffecc8 rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47410
diff changeset
100 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
101 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
102 // 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
103 // as-is.
88119fffecc8 rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47410
diff changeset
104 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
105 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
106 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
107 }
88119fffecc8 rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47410
diff changeset
108 }
50003
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49238
diff changeset
109 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
110 at: current_directory,
50003
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49238
diff changeset
111 })
47411
88119fffecc8 rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47410
diff changeset
112 }
88119fffecc8 rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47410
diff changeset
113
46557
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46555
diff changeset
114 /// 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
115 /// 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
116 /// ancestors.
46555
d8730ff51d5a rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46545
diff changeset
117 ///
46557
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46555
diff changeset
118 /// 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
119 /// 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
120 /// 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
121 /// 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
122 pub fn find(
d8730ff51d5a rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46545
diff changeset
123 config: &Config,
47410
ebdef6283798 rhg: read [paths] for `--repository` value
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47380
diff changeset
124 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
125 ) -> Result<Self, RepoError> {
d8730ff51d5a rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46545
diff changeset
126 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
127 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
128 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
129 } 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
130 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
131 } else {
50003
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49238
diff changeset
132 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
133 }
46555
d8730ff51d5a rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46545
diff changeset
134 } else {
47411
88119fffecc8 rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents: 47410
diff changeset
135 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
136 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
137 }
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
138 }
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
139
46524
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
140 /// 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
141 fn new_at_path(
f031fe1c6ede rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents: 46543
diff changeset
142 working_directory: PathBuf,
f031fe1c6ede rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents: 46543
diff changeset
143 config: &Config,
46545
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
144 ) -> Result<Self, RepoError> {
46524
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
145 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
146
50003
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49238
diff changeset
147 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
148 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
149
51906
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
150 let hg_vfs = VfsImpl {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
151 base: dot_hg.to_owned(),
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
152 };
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
153 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
154 let relative =
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
155 reqs.contains(requirements::RELATIVE_SHARED_REQUIREMENT);
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
156 let shared =
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
157 reqs.contains(requirements::SHARED_REQUIREMENT) || relative;
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 // From `mercurial/localrepo.py`:
95b276283b67 rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents: 46524
diff changeset
160 //
95b276283b67 rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents: 46524
diff changeset
161 // 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
162 // 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
163 // 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
164 // 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
165 // is not present, refer checkrequirementscompat() for that
95b276283b67 rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents: 46524
diff changeset
166 //
95b276283b67 rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents: 46524
diff changeset
167 // 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
168 // 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
169 // .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
170 // current repository needs to be reshared
95b276283b67 rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents: 46524
diff changeset
171 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
172
46524
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
173 let store_path;
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
174 if !shared {
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
175 store_path = dot_hg.join("store");
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
176 } else {
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
177 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
178 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
179 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
180 .to_owned();
46524
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
181 if relative {
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
182 shared_path = dot_hg.join(shared_path)
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
183 }
47779
cf5f8da2244c rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents: 47674
diff changeset
184 if !is_dir(&shared_path)? {
46524
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
185 return Err(HgError::corrupted(format!(
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
186 ".hg/sharedpath points to nonexistent directory {}",
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
187 shared_path.display()
46545
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
188 ))
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
189 .into());
46524
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
190 }
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 store_path = shared_path.join("store");
46525
95b276283b67 rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents: 46524
diff changeset
193
51906
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
194 let source_is_share_safe = requirements::load(VfsImpl {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
195 base: shared_path.to_owned(),
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
196 })?
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
197 .contains(requirements::SHARESAFE_REQUIREMENT);
46525
95b276283b67 rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents: 46524
diff changeset
198
48900
1d5fd9def5ac rhg: simplify the handling of share-safe config mismatch
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48547
diff changeset
199 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
200 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
201 }
46545
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
202
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
203 if share_safe {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
204 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
205 }
46524
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
206 }
46652
f64b6953db70 rhg: Bug fix: with share-safe, always read store requirements
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
207 if share_safe {
51906
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
208 reqs.extend(requirements::load(VfsImpl {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
209 base: store_path.to_owned(),
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
210 })?);
46652
f64b6953db70 rhg: Bug fix: with share-safe, always read store requirements
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
211 }
46524
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
212
46754
25e3dac511f0 rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents: 46753
diff changeset
213 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
214 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
215 } else {
25e3dac511f0 rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents: 46753
diff changeset
216 config.clone()
25e3dac511f0 rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents: 46753
diff changeset
217 };
46545
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
218
46524
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
219 let repo = Self {
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
220 requirements: reqs,
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
221 working_directory,
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
222 store: store_path,
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
223 dot_hg,
46545
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
224 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
225 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
226 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
227 changelog: LazyCell::new(),
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49201
diff changeset
228 manifestlog: LazyCell::new(),
46524
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
229 };
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
230
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
231 requirements::check(&repo)?;
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
232
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
233 Ok(repo)
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
234 }
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
235
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
236 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
237 &self.working_directory
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
238 }
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
239
46524
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
240 pub fn requirements(&self) -> &HashSet<String> {
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
241 &self.requirements
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
242 }
d03b0601e0eb rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents: 46514
diff changeset
243
46545
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
244 pub fn config(&self) -> &Config {
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
245 &self.config
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
246 }
d7685105e504 rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents: 46544
diff changeset
247
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
248 /// 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
249 /// (`.hg/store`).
51906
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
250 pub fn hg_vfs(&self) -> VfsImpl {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
251 VfsImpl {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
252 base: self.dot_hg.to_owned(),
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
253 }
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
254 }
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
255
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
256 /// For accessing repository store files (in `.hg/store`)
51906
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
257 pub fn store_vfs(&self) -> VfsImpl {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
258 VfsImpl {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
259 base: self.store.to_owned(),
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
260 }
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
261 }
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
262
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
263 /// For accessing the working copy
51906
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
264 pub fn working_directory_vfs(&self) -> VfsImpl {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
265 VfsImpl {
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
266 base: self.working_directory.to_owned(),
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
267 }
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
268 }
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46638
diff changeset
269
48463
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48457
diff changeset
270 pub fn try_with_wlock_no_wait<R>(
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48457
diff changeset
271 &self,
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48457
diff changeset
272 f: impl FnOnce() -> R,
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48457
diff changeset
273 ) -> Result<R, LockError> {
51906
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51905
diff changeset
274 try_with_lock_no_wait(&self.hg_vfs(), "wlock", f)
48463
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48457
diff changeset
275 }
5734b03ecf3e rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents: 48457
diff changeset
276
50387
1e2c6cda2309 rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
277 /// 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
278 /// 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
279 /// 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
280 /// 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
281 /// 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
282 /// 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
283 /// 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
284 /// 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
285 /// 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
286 /// 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
287 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
288 self.requirements
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 46822
diff changeset
289 .contains(requirements::DIRSTATE_V2_REQUIREMENT)
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 46822
diff changeset
290 }
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 46822
diff changeset
291
48457
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48084
diff changeset
292 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
293 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
294 }
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48084
diff changeset
295
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48084
diff changeset
296 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
297 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
298 }
005ae1a343f8 rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48084
diff changeset
299
49146
9b5334c1e499 rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents: 49145
diff changeset
300 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
301 self.requirements
9b5334c1e499 rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents: 49145
diff changeset
302 .contains(requirements::NODEMAP_REQUIREMENT)
9b5334c1e499 rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents: 49145
diff changeset
303 }
9b5334c1e499 rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents: 49145
diff changeset
304
47984
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
305 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
306 Ok(self
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
307 .hg_vfs()
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
308 .read("dirstate")
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
309 .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
310 .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
311 }
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
312
49703
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
313 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
314 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
315 Ok(self
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
316 .hg_vfs()
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
317 .symlink_metadata("dirstate")
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
318 .io_not_found_as_none()?
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
319 .map(|meta| meta.ino()))
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
320 }
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
321
47984
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
322 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
323 Ok(*self
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49201
diff changeset
324 .dirstate_parents
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49201
diff changeset
325 .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
326 }
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48463
diff changeset
327
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48463
diff changeset
328 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
329 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
330 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
331 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
332 } 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
333 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
334 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
335 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
336 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
337 Err(_) => {
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
338 log::info!(
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
339 "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
340 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
341 );
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
342 *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
343 &dirstate,
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
344 )?
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
345 }
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
346 }
47380
bd88b6bfd8da rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents: 46822
diff changeset
347 } else {
50003
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49238
diff changeset
348 *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
349 };
48465
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48463
diff changeset
350 self.dirstate_parents.set(parents);
47674
ff97e793ed36 dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents: 47413
diff changeset
351 Ok(parents)
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46638
diff changeset
352 }
47984
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
353
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
354 /// 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
355 /// 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
356 /// 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
357 /// 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
358 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
359 &self,
50252
a6b8b1ab9116 branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50010 49703
diff changeset
360 ) -> 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
361 assert!(
50387
1e2c6cda2309 rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50252
diff changeset
362 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
363 "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
364 );
49703
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
365 // 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
366 // 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
367 // 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
368 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
369 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
370 if dirstate.is_empty() {
49703
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
371 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
372 } else {
50389
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
373 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
374 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
375 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
376 Ok(docket) => {
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
377 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
378 Ok((
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
379 identity,
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
380 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
381 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
382 ))
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
383 }
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
384 Err(_) => {
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
385 log::info!(
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
386 "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
387 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
388 );
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
389 let parents =
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
390 *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
391 &dirstate,
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
392 )?;
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
393 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
394 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
395 }
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
396 }
48466
c7c23bb036c9 rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents: 48465
diff changeset
397 }
c7c23bb036c9 rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents: 48465
diff changeset
398 }
c7c23bb036c9 rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents: 48465
diff changeset
399
47984
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
400 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
401 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
402 // 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
403 // 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
404 // (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
405 // 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
406 // 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
407 // 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
408 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
409
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
410 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
411 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
412 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
413 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
414 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
415 }
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
416 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
417 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
418 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
419 )) => {
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
420 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
421 "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
422 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
423 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
424 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
425 );
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
426 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
427 }
50389
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
428 _ => {
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
429 log::info!(
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
430 "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
431 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
432 );
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
433 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
434 }
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
435 },
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
436 }
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
437 }
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
438 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
439 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
440 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
441 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
442 );
50252
a6b8b1ab9116 branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50010 49703
diff changeset
443 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
444 } else {
50389
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
445 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
446 }
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
447 }
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
448
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
449 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
450 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
451 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
452 let dirstate_file_contents = self.dirstate_file_contents()?;
52071
e1fe336c007a rust-repo: don't use on-disk dirstate parents in v1
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52070
diff changeset
453 let parents = self.dirstate_parents()?;
50389
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
454 if dirstate_file_contents.is_empty() {
52071
e1fe336c007a rust-repo: don't use on-disk dirstate parents in v1
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52070
diff changeset
455 self.dirstate_parents.set(parents);
52057
88aa21d654e5 rust-dirstate: actually remember the identity
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51906
diff changeset
456 Ok(OwningDirstateMap::new_empty(Vec::new(), identity))
50389
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
457 } else {
52071
e1fe336c007a rust-repo: don't use on-disk dirstate parents in v1
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52070
diff changeset
458 // Ignore the dirstate on-disk parents, they may have been set in
e1fe336c007a rust-repo: don't use on-disk dirstate parents in v1
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52070
diff changeset
459 // the repo before
e1fe336c007a rust-repo: don't use on-disk dirstate parents in v1
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52070
diff changeset
460 let (map, _) =
50389
bf16ef96defe rust-dirstate: fall back to v1 if reading v2 failed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50387
diff changeset
461 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
462 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
463 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
464 }
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
465 }
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
466
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
467 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
468 &self,
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
469 ) -> 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
470 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
471 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
472 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
473 if dirstate_file_contents.is_empty() {
52057
88aa21d654e5 rust-dirstate: actually remember the identity
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51906
diff changeset
474 return Ok(OwningDirstateMap::new_empty(Vec::new(), identity));
49685
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
475 }
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
476 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
477 &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
478 )?;
49692
2be6d5782728 dirstate: add a synchronisation point in the middle of the read
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49686
diff changeset
479 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
480 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
481 "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
482 );
49685
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
483 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
484 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
485 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
486
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 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
488 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
489 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
490
49685
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
491 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
492 // 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
493 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
494 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
495 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
496 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
497 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
498 // 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
499 // 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
500 //
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
501 // 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
502 // `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
503 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
504 // 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
505 // 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
506 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
507 }
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
508 _ => {
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
509 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
510 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
511 )
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
512 }
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
513 }
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
514 }
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
515 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
516 };
49703
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
517 OwningDirstateMap::new_v2(
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
518 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
519 )
49685
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
520 } 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
521 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
522 .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
523 .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
524 .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
525 {
49701
6cce0afc1454 rust-dirstate: remember the data file uuid dirstate was loaded with
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49697
diff changeset
526 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
527 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
528 ),
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
529 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
530 // 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
531 // 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
532 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
533 }
491f3dd080eb dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49692
diff changeset
534 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
535 }
49685
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
536 }?;
49680
ecd28d89c29e dirstate-v2: add devel config option to control write behavior
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49679
diff changeset
537
49685
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
538 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
539 .config()
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
540 .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
541 .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
542 .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
543 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
544 "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
545 "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
546 "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
547 _ => DirstateMapWriteMode::Auto,
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
548 };
49680
ecd28d89c29e dirstate-v2: add devel config option to control write behavior
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49679
diff changeset
549
49685
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
550 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
551
49685
cbd4c9234e25 rust-repo: move dirstate-v2 opening to a separate method
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49680
diff changeset
552 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
553 }
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
554
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
555 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
556 &self,
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
557 ) -> 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
558 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
559 }
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47984
diff changeset
560
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47984
diff changeset
561 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
562 &self,
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47984
diff changeset
563 ) -> 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
564 self.dirstate_map
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49201
diff changeset
565 .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
566 }
47987
21d25e9ee58e rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents: 47986
diff changeset
567
49145
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49073
diff changeset
568 fn new_changelog(&self) -> Result<Changelog, HgError> {
51905
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
569 Changelog::open(
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
570 &self.store_vfs(),
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
571 self.default_revlog_options(RevlogType::Changelog)?,
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
572 )
47986
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47984
diff changeset
573 }
47987
21d25e9ee58e rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents: 47986
diff changeset
574
47991
001d747c2baf rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents: 47989
diff changeset
575 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
576 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
577 }
21d25e9ee58e rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents: 47986
diff changeset
578
47991
001d747c2baf rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents: 47989
diff changeset
579 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
580 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
581 }
21d25e9ee58e rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents: 47986
diff changeset
582
49145
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49073
diff changeset
583 fn new_manifestlog(&self) -> Result<Manifestlog, HgError> {
51212
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
584 Manifestlog::open(
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
585 &self.store_vfs(),
51905
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
586 self.default_revlog_options(RevlogType::Manifestlog)?,
51212
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
587 )
47987
21d25e9ee58e rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents: 47986
diff changeset
588 }
21d25e9ee58e rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents: 47986
diff changeset
589
47991
001d747c2baf rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents: 47989
diff changeset
590 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
591 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
592 }
21d25e9ee58e rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents: 47986
diff changeset
593
47991
001d747c2baf rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents: 47989
diff changeset
594 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
595 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
596 }
47988
cfb6e6699b25 rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents: 47987
diff changeset
597
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
598 /// 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
599 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
600 &self,
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47991
diff changeset
601 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
602 ) -> 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
603 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
604 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
605 .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
606 .manifest_node()?
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47991
diff changeset
607 .into(),
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47991
diff changeset
608 )
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47991
diff changeset
609 }
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47991
diff changeset
610
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
611 /// 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
612 pub fn manifest_for_rev(
47988
cfb6e6699b25 rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents: 47987
diff changeset
613 &self,
50988
1928b770e3e7 rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50389
diff changeset
614 revision: UncheckedRevision,
47988
cfb6e6699b25 rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents: 47987
diff changeset
615 ) -> 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
616 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
617 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
618 .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
619 .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
620 .into(),
47992
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47991
diff changeset
621 )
47988
cfb6e6699b25 rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents: 47987
diff changeset
622 }
47989
4d2a5ca060e3 rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents: 47988
diff changeset
623
48547
7f633432ca92 rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48467
diff changeset
624 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
625 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
626 Ok(entry.tracked())
48547
7f633432ca92 rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48467
diff changeset
627 } else {
7f633432ca92 rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48467
diff changeset
628 Ok(false)
7f633432ca92 rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48467
diff changeset
629 }
7f633432ca92 rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48467
diff changeset
630 }
7f633432ca92 rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents: 48467
diff changeset
631
47991
001d747c2baf rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents: 47989
diff changeset
632 pub fn filelog(&self, path: &HgPath) -> Result<Filelog, HgError> {
51905
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
633 Filelog::open(
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
634 self,
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
635 path,
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
636 self.default_revlog_options(RevlogType::Filelog)?,
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
637 )
47989
4d2a5ca060e3 rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents: 47988
diff changeset
638 }
48467
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
639 /// 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
640 ///
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
641 /// The "wlock" must be held while calling this.
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
642 /// See for example `try_with_wlock_no_wait`.
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
643 ///
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
644 /// 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
645 /// lock?
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
646 pub fn write_dirstate(&self) -> Result<(), DirstateError> {
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
647 let map = self.dirstate_map()?;
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
648 // 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
649 // it’s unset
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
650 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
651 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
652 let (identity, uuid, data_size) =
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
653 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
654 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
655 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
656 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
657
49703
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
658 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
659 // 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
660 // 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
661 // 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
662 // 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
663 // `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
664 // 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
665 //
07d030b38097 rust-dirstate-v2: don't write dirstate if data file has changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49701
diff changeset
666 // 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
667 // 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
668 // (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
669 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
670 "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
671 );
07d030b38097 rust-dirstate-v2: don't write dirstate if data file has changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49701
diff changeset
672 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
673 }
07d030b38097 rust-dirstate-v2: don't write dirstate if data file has changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49701
diff changeset
674
07d030b38097 rust-dirstate-v2: don't write dirstate if data file has changed
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49701
diff changeset
675 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
676 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
677 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
678 } else {
1891086f6c7f dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 49671
diff changeset
679 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
680 };
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
681 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
682 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
683
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48844
diff changeset
684 // 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
685 // deletion.
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48844
diff changeset
686 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
687 Some(uuid) => {
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48844
diff changeset
688 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
689 .map_err(|_| {
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48844
diff changeset
690 HgError::corrupted(
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48844
diff changeset
691 "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
692 )
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48844
diff changeset
693 })?
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48844
diff changeset
694 .to_owned();
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48844
diff changeset
695 if append {
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48844
diff changeset
696 (as_str, None)
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48844
diff changeset
697 } else {
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48844
diff changeset
698 (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
699 }
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48844
diff changeset
700 }
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48844
diff changeset
701 None => (DirstateDocket::new_uid(), None),
48467
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
702 };
48847
f2ef6a4f918f rhg: fix dirstate-v2 data file removal system
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48844
diff changeset
703
48467
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
704 let data_filename = format!("dirstate.{}", uuid);
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
705 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
706 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
707 options.write(true);
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48847
diff changeset
708
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48847
diff changeset
709 // 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
710 //
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48847
diff changeset
711 // - 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
712 // 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
713 // 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
714 // all such garbage.
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48847
diff changeset
715 //
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48847
diff changeset
716 // - 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
717 // don't need that.
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48847
diff changeset
718 //
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48847
diff changeset
719 // - 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
720 // 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
721 // 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
722 // 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
723 //
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48847
diff changeset
724 if !append {
49671
f5e4248e5bce dirstate: add some debug output when writing the dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49669
diff changeset
725 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
726 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
727 } else {
f5e4248e5bce dirstate: add some debug output when writing the dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49669
diff changeset
728 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
729 }
48867
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48847
diff changeset
730
48467
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
731 let data_size = (|| {
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
732 // 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
733 // returns `ErrorKind::AlreadyExists`? Collision chance of two
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
734 // random IDs is one in 2**32
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
735 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
736 if append {
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48847
diff changeset
737 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
738 }
48867
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48847
diff changeset
739 file.write_all(&data)?;
2d0e22171ef9 rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 48847
diff changeset
740 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
741 file.stream_position()
48467
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
742 })()
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
743 .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
744
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
745 let packed_dirstate = DirstateDocket::serialize(
48467
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
746 parents,
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
747 tree_metadata,
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
748 data_size,
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
749 uuid.as_bytes(),
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
750 )
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
751 .map_err(|_: std::num::TryFromIntError| {
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
752 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
753 })?;
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
754
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
755 (packed_dirstate, old_uuid)
48467
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
756 } else {
49703
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
757 let identity = self.dirstate_identity()?;
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
758 if identity != map.old_identity() {
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
759 // 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
760 // 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
761 // 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
762 // `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
763 // reading anyway.
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
764 //
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
765 // 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
766 // without taking the lock.
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
767 // (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
768 log::debug!(
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
769 "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
770 );
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
771 return Ok(());
dbe09fb038fc rhg: remember the inode of .hg/dirstate
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49702
diff changeset
772 }
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
773 (map.pack_v1(parents)?, None)
48467
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
774 };
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
775
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
776 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
777 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
778 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
779 // 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
780 // 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
781 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
782 }
48467
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
783 Ok(())
2097f63575a5 rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents: 48466
diff changeset
784 }
51212
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
785
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
786 pub fn default_revlog_options(
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
787 &self,
51905
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
788 revlog_type: RevlogType,
51212
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
789 ) -> Result<RevlogOpenOptions, HgError> {
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
790 let requirements = self.requirements();
51905
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
791 let is_changelog = revlog_type == RevlogType::Changelog;
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
792 let version = if is_changelog
51212
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
793 && requirements.contains(CHANGELOGV2_REQUIREMENT)
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
794 {
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
795 let compute_rank = self
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
796 .config()
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
797 .get_bool(b"experimental", b"changelog-v2.compute-rank")?;
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
798 RevlogVersionOptions::ChangelogV2 { compute_rank }
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
799 } else if requirements.contains(REVLOGV2_REQUIREMENT) {
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
800 RevlogVersionOptions::V2
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
801 } else if requirements.contains(REVLOGV1_REQUIREMENT) {
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
802 RevlogVersionOptions::V1 {
51905
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
803 general_delta: requirements.contains(GENERALDELTA_REQUIREMENT),
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
804 inline: !is_changelog,
51212
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
805 }
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
806 } else {
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
807 RevlogVersionOptions::V0
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
808 };
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
809 Ok(RevlogOpenOptions {
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
810 version,
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
811 // We don't need to dance around the slow path like in the Python
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
812 // implementation since we know we have access to the fast code.
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
813 use_nodemap: requirements.contains(NODEMAP_REQUIREMENT),
51905
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
814 delta_config: RevlogDeltaConfig::new(
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
815 self.config(),
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
816 self.requirements(),
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
817 revlog_type,
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
818 )?,
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
819 data_config: RevlogDataConfig::new(
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
820 self.config(),
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
821 self.requirements(),
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
822 )?,
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
823 feature_config: RevlogFeatureConfig::new(
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
824 self.config(),
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
825 requirements,
69b804c8e09e rust: use new revlog configs in all revlog opening code
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51212
diff changeset
826 )?,
51212
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
827 })
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51118
diff changeset
828 }
52059
babfa9ddca0e rust-repo: add a method to get a `Node` from a `Revision` to the `Repo`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52057
diff changeset
829
babfa9ddca0e rust-repo: add a method to get a `Node` from a `Revision` to the `Repo`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52057
diff changeset
830 pub fn node(&self, rev: UncheckedRevision) -> Option<crate::Node> {
babfa9ddca0e rust-repo: add a method to get a `Node` from a `Revision` to the `Repo`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52057
diff changeset
831 self.changelog()
babfa9ddca0e rust-repo: add a method to get a `Node` from a `Revision` to the `Repo`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52057
diff changeset
832 .ok()
babfa9ddca0e rust-repo: add a method to get a `Node` from a `Revision` to the `Repo`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52057
diff changeset
833 .and_then(|c| c.node_from_rev(rev).copied())
babfa9ddca0e rust-repo: add a method to get a `Node` from a `Revision` to the `Repo`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52057
diff changeset
834 }
52060
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
835
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
836 /// Change the current working directory parents cached in the repo.
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
837 ///
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
838 /// TODO
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
839 /// This does *not* do a lot of what it expected from a full `set_parents`:
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
840 /// - parents should probably be stored in the dirstate
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
841 /// - dirstate should have a "changing parents" context
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
842 /// - dirstate should return copies if out of a merge context to be
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
843 /// discarded within the repo context
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
844 /// See `setparents` in `context.py`.
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
845 pub fn manually_set_parents(
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
846 &self,
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
847 new_parents: DirstateParents,
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
848 ) -> Result<(), HgError> {
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
849 let mut parents = self.dirstate_parents.value.borrow_mut();
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
850 *parents = Some(new_parents);
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
851 Ok(())
d7bc6e482033 rust-repo: add a method to set the current parents
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52059
diff changeset
852 }
47986
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47984
diff changeset
853 }
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47984
diff changeset
854
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47984
diff changeset
855 /// 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
856 ///
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47984
diff changeset
857 /// 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
858 /// 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
859 /// 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
860 /// 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
861 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
862 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
863 }
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47984
diff changeset
864
49212
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49201
diff changeset
865 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
866 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
867 Self {
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47984
diff changeset
868 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
869 }
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47984
diff changeset
870 }
fc208d6faed3 rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47984
diff changeset
871
48465
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48463
diff changeset
872 fn set(&self, value: T) {
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48463
diff changeset
873 *self.value.borrow_mut() = Some(value)
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48463
diff changeset
874 }
c8659e61073d rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents: 48463
diff changeset
875
49212
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49201
diff changeset
876 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
877 &self,
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49201
diff changeset
878 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
879 ) -> 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
880 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
881 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
882 drop(borrowed);
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
883 // 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
884 // 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
885 // needed.
49212
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49201
diff changeset
886 *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
887 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
888 }
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
889 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
890 }
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
891
49212
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49201
diff changeset
892 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
893 &self,
90a15199cbc6 rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49201
diff changeset
894 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
895 ) -> 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
896 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
897 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
898 *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
899 }
81aedf1fc897 rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents: 47980
diff changeset
900 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
901 }
46167
8a4914397d02 rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
902 }