annotate rust/hg-core/src/repo.rs @ 52285:94cf83d9a2c9

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