Mercurial > hg
annotate rust/hg-core/src/repo.rs @ 52046:28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
I suspect this will not be the last time we need to do something like this.
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Tue, 01 Oct 2024 13:45:18 +0200 |
parents | d7bc6e482033 |
children | e1fe336c007a |
rev | line source |
---|---|
47959
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
1 use crate::changelog::Changelog; |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
2 use crate::config::{Config, ConfigError, ConfigParseError}; |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
3 use crate::dirstate::DirstateParents; |
50221
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50211
diff
changeset
|
4 use crate::dirstate_tree::dirstate_map::DirstateMapWriteMode; |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
5 use crate::dirstate_tree::on_disk::Docket as DirstateDocket; |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
6 use crate::dirstate_tree::owning::OwningDirstateMap; |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
7 use crate::errors::HgResultExt; |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
8 use crate::errors::{HgError, IoResultExt}; |
48417
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
9 use crate::lock::{try_with_lock_no_wait, LockError}; |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
10 use crate::manifest::{Manifest, Manifestlog}; |
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
|
11 use crate::requirements::{ |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
12 CHANGELOGV2_REQUIREMENT, GENERALDELTA_REQUIREMENT, NODEMAP_REQUIREMENT, |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
13 REVLOGV1_REQUIREMENT, REVLOGV2_REQUIREMENT, |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
14 }; |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47960
diff
changeset
|
15 use crate::revlog::filelog::Filelog; |
49937
750409505286
rust-clippy: merge "revlog" module definition and struct implementation
Raphaël Gomès <rgomes@octobus.net>
parents:
49930
diff
changeset
|
16 use crate::revlog::RevlogError; |
50228
fc8e37c380d3
dirstate: add a synchronisation point before doing a full dirstate read
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50227
diff
changeset
|
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; |
51868 | 21 use crate::vfs::{is_dir, is_file, VfsImpl}; |
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
|
22 use crate::{ |
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
|
23 exit_codes, requirements, NodePrefix, RevlogDataConfig, RevlogDeltaConfig, |
51867
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
24 RevlogFeatureConfig, RevlogType, RevlogVersionOptions, UncheckedRevision, |
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
|
25 }; |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
26 use crate::{DirstateError, RevlogOpenOptions}; |
48419
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
27 use std::cell::{Ref, RefCell, RefMut}; |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
28 use std::collections::HashSet; |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
29 use std::io::Seek; |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
30 use std::io::SeekFrom; |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
31 use std::io::Write as IoWrite; |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
32 use std::path::{Path, PathBuf}; |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
33 |
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
|
34 const V2_MAX_READ_ATTEMPTS: usize = 5; |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
35 |
50252
a6b8b1ab9116
branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
diff
changeset
|
36 type DirstateMapIdentity = (Option<u64>, Option<Vec<u8>>, usize); |
a6b8b1ab9116
branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
diff
changeset
|
37 |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
38 /// A repository on disk |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
39 pub struct Repo { |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
40 working_directory: PathBuf, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
41 dot_hg: PathBuf, |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
42 store: PathBuf, |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
43 requirements: HashSet<String>, |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
44 config: Config, |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
45 dirstate_parents: LazyCell<DirstateParents>, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
46 dirstate_map: LazyCell<OwningDirstateMap>, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
47 changelog: LazyCell<Changelog>, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
48 manifestlog: LazyCell<Manifestlog>, |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
49 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
50 |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
51 #[derive(Debug, derive_more::From)] |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
52 pub enum RepoError { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
53 NotFound { |
46503
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
54 at: PathBuf, |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
55 }, |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
56 #[from] |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
57 ConfigParseError(ConfigParseError), |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
58 #[from] |
46446
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
59 Other(HgError), |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
60 } |
1dcd9c9975ed
rust: Fold find_root and check_requirements into Repo::find
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
61 |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
62 impl From<ConfigError> for RepoError { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
63 fn from(error: ConfigError) -> Self { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
64 match error { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
65 ConfigError::Parse(error) => error.into(), |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
66 ConfigError::Other(error) => error.into(), |
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 } |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
69 } |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
70 |
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
|
71 impl From<RepoError> for HgError { |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
72 fn from(value: RepoError) -> Self { |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
73 match value { |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
74 RepoError::NotFound { at } => HgError::abort( |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
75 format!( |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
76 "abort: no repository found in '{}' (.hg not found)!", |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
77 at.display() |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
78 ), |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
79 exit_codes::ABORT, |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
80 None, |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
81 ), |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
82 RepoError::ConfigParseError(config_parse_error) => { |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
83 HgError::Abort { |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
84 message: String::from_utf8_lossy( |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
85 &config_parse_error.message, |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
86 ) |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
87 .to_string(), |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
88 detailed_exit_code: exit_codes::CONFIG_PARSE_ERROR_ABORT, |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
89 hint: None, |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
52036
diff
changeset
|
90 } |
28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
Raphaël Gomès <rgomes@octobus.net>
parents:
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 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
|
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 } |
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
|
95 } |
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
|
96 |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
97 impl Repo { |
47405
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
98 /// tries to find nearest repository root in current working directory or |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
99 /// its ancestors |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
100 pub fn find_repo_root() -> Result<PathBuf, RepoError> { |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
101 let current_directory = crate::utils::current_dir()?; |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
102 // ancestors() is inclusive: it first yields `current_directory` |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
103 // as-is. |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
104 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
|
105 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
|
106 return Ok(ancestor.to_path_buf()); |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
107 } |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
108 } |
49930
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49217
diff
changeset
|
109 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
|
110 at: current_directory, |
49930
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49217
diff
changeset
|
111 }) |
47405
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
112 } |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
113 |
46505
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
114 /// Find a repository, either at the given path (which must contain a `.hg` |
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
115 /// sub-directory) or by searching the current directory and its |
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
116 /// ancestors. |
46503
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
117 /// |
46505
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
118 /// A method with two very different "modes" like this usually a code smell |
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
119 /// to make two methods instead, but in this case an `Option` is what rhg |
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
120 /// sub-commands get from Clap for the `-R` / `--repository` CLI argument. |
a25033eb43b5
rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
121 /// 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
|
122 pub fn find( |
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
123 config: &Config, |
47404
ebdef6283798
rhg: read [paths] for `--repository` value
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47374
diff
changeset
|
124 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
|
125 ) -> Result<Self, RepoError> { |
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
126 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
|
127 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
|
128 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
|
129 } 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
|
130 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
|
131 } else { |
49930
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49217
diff
changeset
|
132 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
|
133 } |
46503
d8730ff51d5a
rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46486
diff
changeset
|
134 } else { |
47405
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
135 let root = Self::find_repo_root()?; |
88119fffecc8
rhg: look for repository in ancestors also instead of cwd only
Pulkit Goyal <7895pulkit@gmail.com>
parents:
47404
diff
changeset
|
136 Self::new_at_path(root, config) |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
137 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
138 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
139 |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
140 /// 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
|
141 fn new_at_path( |
f031fe1c6ede
rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
142 working_directory: PathBuf, |
f031fe1c6ede
rhg: Abort based on config on share-safe mismatch
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
143 config: &Config, |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
144 ) -> Result<Self, RepoError> { |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
145 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
|
146 |
49930
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49217
diff
changeset
|
147 let mut repo_config_files = |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49217
diff
changeset
|
148 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
|
149 |
51868 | 150 let hg_vfs = VfsImpl { |
151 base: dot_hg.to_owned(), | |
152 }; | |
153 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
|
154 let relative = |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
155 reqs.contains(requirements::RELATIVE_SHARED_REQUIREMENT); |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
156 let shared = |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
157 reqs.contains(requirements::SHARED_REQUIREMENT) || relative; |
46463
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
158 |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
159 // From `mercurial/localrepo.py`: |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
160 // |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
161 // 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
|
162 // there exists a `.hg/store/requires` too and we should read it |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
163 // NOTE: presence of SHARESAFE_REQUIREMENT imply that store requirement |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
164 // is present. We never write SHARESAFE_REQUIREMENT for a repo if store |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
165 // is not present, refer checkrequirementscompat() for that |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
166 // |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
167 // However, if SHARESAFE_REQUIREMENT is not present, it means that the |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
168 // repository was shared the old way. We check the share source |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
169 // .hg/requires for SHARESAFE_REQUIREMENT to detect whether the |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
170 // current repository needs to be reshared |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
171 let share_safe = reqs.contains(requirements::SHARESAFE_REQUIREMENT); |
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
172 |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
173 let store_path; |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
174 if !shared { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
175 store_path = dot_hg.join("store"); |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
176 } else { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
177 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
|
178 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
|
179 get_path_from_bytes(bytes.trim_end_matches(|b| b == b'\n')) |
696abab107b4
rust: Generalize the `trim_end_newlines` utility of byte strings
Simon Sapin <simon.sapin@octobus.net>
parents:
47780
diff
changeset
|
180 .to_owned(); |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
181 if relative { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
182 shared_path = dot_hg.join(shared_path) |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
183 } |
47780
cf5f8da2244c
rhg: Propagate permission errors when finding a repository
Simon Sapin <simon.sapin@octobus.net>
parents:
47674
diff
changeset
|
184 if !is_dir(&shared_path)? { |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
185 return Err(HgError::corrupted(format!( |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
186 ".hg/sharedpath points to nonexistent directory {}", |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
187 shared_path.display() |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
188 )) |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
189 .into()); |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
190 } |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
191 |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
192 store_path = shared_path.join("store"); |
46463
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
193 |
51868 | 194 let source_is_share_safe = requirements::load(VfsImpl { |
195 base: shared_path.to_owned(), | |
196 })? | |
197 .contains(requirements::SHARESAFE_REQUIREMENT); | |
46463
95b276283b67
rhg: add support for share-safe
Simon Sapin <simon.sapin@octobus.net>
parents:
46462
diff
changeset
|
198 |
48809
1d5fd9def5ac
rhg: simplify the handling of share-safe config mismatch
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48510
diff
changeset
|
199 if share_safe != source_is_share_safe { |
1d5fd9def5ac
rhg: simplify the handling of share-safe config mismatch
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48510
diff
changeset
|
200 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
|
201 } |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
202 |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
203 if share_safe { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
204 repo_config_files.insert(0, shared_path.join("hgrc")) |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
205 } |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
206 } |
46613
f64b6953db70
rhg: Bug fix: with share-safe, always read store requirements
Simon Sapin <simon.sapin@octobus.net>
parents:
46601
diff
changeset
|
207 if share_safe { |
51868 | 208 reqs.extend(requirements::load(VfsImpl { |
209 base: store_path.to_owned(), | |
210 })?); | |
46613
f64b6953db70
rhg: Bug fix: with share-safe, always read store requirements
Simon Sapin <simon.sapin@octobus.net>
parents:
46601
diff
changeset
|
211 } |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
212 |
46741
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46740
diff
changeset
|
213 let repo_config = if std::env::var_os("HGRCSKIPREPO").is_none() { |
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46740
diff
changeset
|
214 config.combine_with_repo(&repo_config_files)? |
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46740
diff
changeset
|
215 } else { |
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46740
diff
changeset
|
216 config.clone() |
25e3dac511f0
rhg: Add support for the HGRCSKIPREPO environment variable
Simon Sapin <simon.sapin@octobus.net>
parents:
46740
diff
changeset
|
217 }; |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
218 |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
219 let repo = Self { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
220 requirements: reqs, |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
221 working_directory, |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
222 store: store_path, |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
223 dot_hg, |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
224 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
|
225 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
|
226 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
|
227 changelog: LazyCell::new(), |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
228 manifestlog: LazyCell::new(), |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
229 }; |
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 requirements::check(&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 Ok(repo) |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
234 } |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
235 |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
236 pub fn working_directory_path(&self) -> &Path { |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
237 &self.working_directory |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
238 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
239 |
46462
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
240 pub fn requirements(&self) -> &HashSet<String> { |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
241 &self.requirements |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
242 } |
d03b0601e0eb
rhg: initial support for shared repositories
Simon Sapin <simon.sapin@octobus.net>
parents:
46446
diff
changeset
|
243 |
46486
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
244 pub fn config(&self) -> &Config { |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
245 &self.config |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
246 } |
d7685105e504
rhg: Parse per-repository configuration
Simon Sapin <simon.sapin@octobus.net>
parents:
46485
diff
changeset
|
247 |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
248 /// For accessing repository files (in `.hg`), except for the store |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
249 /// (`.hg/store`). |
51868 | 250 pub fn hg_vfs(&self) -> VfsImpl { |
251 VfsImpl { | |
252 base: self.dot_hg.to_owned(), | |
253 } | |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
254 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
255 |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
256 /// For accessing repository store files (in `.hg/store`) |
51868 | 257 pub fn store_vfs(&self) -> VfsImpl { |
258 VfsImpl { | |
259 base: self.store.to_owned(), | |
260 } | |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
261 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
262 |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
263 /// For accessing the working copy |
51868 | 264 pub fn working_directory_vfs(&self) -> VfsImpl { |
265 VfsImpl { | |
266 base: self.working_directory.to_owned(), | |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
267 } |
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
268 } |
46601
755c31a1caf9
rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents:
46599
diff
changeset
|
269 |
48417
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
270 pub fn try_with_wlock_no_wait<R>( |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
271 &self, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
272 f: impl FnOnce() -> R, |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
273 ) -> Result<R, LockError> { |
51868 | 274 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
|
275 } |
5734b03ecf3e
rhg: Initial repository locking
Simon Sapin <simon.sapin@octobus.net>
parents:
48409
diff
changeset
|
276 |
50658
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
277 /// Whether this repo should use dirstate-v2. |
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
278 /// The presence of `dirstate-v2` in the requirements does not mean that |
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
279 /// the on-disk dirstate is necessarily in version 2. In most cases, |
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
280 /// a dirstate-v2 file will indeed be found, but in rare cases (like the |
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
281 /// upgrade mechanism being cut short), the on-disk version will be a |
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
282 /// v1 file. |
50660
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
283 /// Semantically, having a requirement only means that a client cannot |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
284 /// properly understand or properly update the repo if it lacks the support |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
285 /// for the required feature, but not that that feature is actually used |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
286 /// 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
|
287 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
|
288 self.requirements |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
289 .contains(requirements::DIRSTATE_V2_REQUIREMENT) |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
290 } |
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
291 |
48409
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
292 pub fn has_sparse(&self) -> bool { |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
293 self.requirements.contains(requirements::SPARSE_REQUIREMENT) |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
294 } |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
295 |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
296 pub fn has_narrow(&self) -> bool { |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
297 self.requirements.contains(requirements::NARROW_REQUIREMENT) |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
298 } |
005ae1a343f8
rhg: add support for narrow clones and sparse checkouts
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48069
diff
changeset
|
299 |
49091
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
300 pub fn has_nodemap(&self) -> bool { |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
301 self.requirements |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
302 .contains(requirements::NODEMAP_REQUIREMENT) |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
303 } |
9b5334c1e499
rust-repo: extract a function for checking nodemap requirement
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
304 |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
305 fn dirstate_file_contents(&self) -> Result<Vec<u8>, HgError> { |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
306 Ok(self |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
307 .hg_vfs() |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
308 .read("dirstate") |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
309 .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
|
310 .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
|
311 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
312 |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
313 fn dirstate_identity(&self) -> Result<Option<u64>, HgError> { |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
314 use std::os::unix::fs::MetadataExt; |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
315 Ok(self |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
316 .hg_vfs() |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
317 .symlink_metadata("dirstate") |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
318 .io_not_found_as_none()? |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
319 .map(|meta| meta.ino())) |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
320 } |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
321 |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
322 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
|
323 Ok(*self |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
324 .dirstate_parents |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
325 .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
|
326 } |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
327 |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
328 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
|
329 let dirstate = self.dirstate_file_contents()?; |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
330 let parents = if dirstate.is_empty() { |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
331 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
|
332 } 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
|
333 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
|
334 crate::dirstate_tree::on_disk::read_docket(&dirstate); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
335 match docket_res { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
336 Ok(docket) => docket.parents(), |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
337 Err(_) => { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
338 log::info!( |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
339 "Parsing dirstate docket failed, \ |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
340 falling back to dirstate-v1" |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
341 ); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
342 *crate::dirstate::parsers::parse_dirstate_parents( |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
343 &dirstate, |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
344 )? |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
345 } |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
346 } |
47374
bd88b6bfd8da
rhg: Add support for dirstate-v2
Simon Sapin <simon.sapin@octobus.net>
parents:
46822
diff
changeset
|
347 } else { |
49930
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents:
49217
diff
changeset
|
348 *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
|
349 }; |
48419
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
350 self.dirstate_parents.set(parents); |
47674
ff97e793ed36
dirstate-v2: Introduce a docket file
Simon Sapin <simon.sapin@octobus.net>
parents:
47407
diff
changeset
|
351 Ok(parents) |
46601
755c31a1caf9
rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents:
46599
diff
changeset
|
352 } |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
353 |
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
|
354 /// Returns the information read from the dirstate docket necessary to |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
355 /// check if the data file has been updated/deleted by another process |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
356 /// since we last read the dirstate. |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
357 /// Namely, the inode, data file uuid and the data size. |
50244
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
358 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
|
359 &self, |
50252
a6b8b1ab9116
branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
diff
changeset
|
360 ) -> Result<DirstateMapIdentity, HgError> { |
48420
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
361 assert!( |
50658
1e2c6cda2309
rust-dirstate: rename `has_dirstate_v2` to `use_dirstate_v2`
Raphaël Gomès <rgomes@octobus.net>
parents:
50252
diff
changeset
|
362 self.use_dirstate_v2(), |
48420
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
363 "accessing dirstate data file ID without dirstate-v2" |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
364 ); |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
365 // Get the identity before the contents since we could have a race |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
366 // between the two. Having an identity that is too old is fine, but |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
367 // one that is younger than the content change is bad. |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
368 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
|
369 let dirstate = self.dirstate_file_contents()?; |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
370 if dirstate.is_empty() { |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
371 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
|
372 } else { |
50660
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
373 let docket_res = |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
374 crate::dirstate_tree::on_disk::read_docket(&dirstate); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
375 match docket_res { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
376 Ok(docket) => { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
377 self.dirstate_parents.set(docket.parents()); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
378 Ok(( |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
379 identity, |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
380 Some(docket.uuid.to_owned()), |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
381 docket.data_size(), |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
382 )) |
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 Err(_) => { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
385 log::info!( |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
386 "Parsing dirstate docket failed, \ |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
387 falling back to dirstate-v1" |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
388 ); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
389 let parents = |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
390 *crate::dirstate::parsers::parse_dirstate_parents( |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
391 &dirstate, |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
392 )?; |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
393 self.dirstate_parents.set(parents); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
394 Ok((identity, None, 0)) |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
395 } |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
396 } |
48420
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
397 } |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
398 } |
c7c23bb036c9
rhg: Add lazy/cached dirstate data file ID parsing on Repo
Simon Sapin <simon.sapin@octobus.net>
parents:
48419
diff
changeset
|
399 |
47956
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
400 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
|
401 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
|
402 // The v2 dirstate is split into a docket and a data file. |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
403 // Since we don't always take the `wlock` to read it |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
404 // (like in `hg status`), it is susceptible to races. |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
405 // A simple retry method should be enough since full rewrites |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
406 // only happen when too much garbage data is present and |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
407 // this race is unlikely. |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
408 let mut tries = 0; |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
409 |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
410 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
|
411 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
|
412 match self.read_docket_and_data_file() { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
413 Ok(m) => { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
414 return Ok(m); |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
415 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
416 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
|
417 DirstateError::Common(HgError::RaceDetected( |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
418 context, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
419 )) => { |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
420 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
|
421 "dirstate read race detected {} (retry {}/{})", |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
422 context, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
423 tries, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
424 V2_MAX_READ_ATTEMPTS, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
425 ); |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
426 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
|
427 } |
50660
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
428 _ => { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
429 log::info!( |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
430 "Reading dirstate v2 failed, \ |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
431 falling back to v1" |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
432 ); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
433 return self.new_dirstate_map_v1(); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
434 } |
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
|
435 }, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
436 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
437 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
438 let error = HgError::abort( |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
439 format!("dirstate read race happened {tries} times in a row"), |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
440 255, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
441 None, |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
442 ); |
50252
a6b8b1ab9116
branching: merge stable into default
Pierre-Yves David <pierre-yves.david@octobus.net>
diff
changeset
|
443 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
|
444 } else { |
50660
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
445 self.new_dirstate_map_v1() |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
446 } |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
447 } |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
448 |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
449 fn new_dirstate_map_v1(&self) -> Result<OwningDirstateMap, DirstateError> { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
450 debug_wait_for_file_or_print(self.config(), "dirstate.pre-read-file"); |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
451 let identity = self.dirstate_identity()?; |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
452 let dirstate_file_contents = self.dirstate_file_contents()?; |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
453 if dirstate_file_contents.is_empty() { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
454 self.dirstate_parents.set(DirstateParents::NULL); |
52033
88aa21d654e5
rust-dirstate: actually remember the identity
Raphaël Gomès <rgomes@octobus.net>
parents:
51868
diff
changeset
|
455 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
|
456 } else { |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
457 let (map, parents) = |
bf16ef96defe
rust-dirstate: fall back to v1 if reading v2 failed
Raphaël Gomès <rgomes@octobus.net>
parents:
50658
diff
changeset
|
458 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
|
459 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
|
460 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
|
461 } |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
462 } |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
463 |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
464 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
|
465 &self, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
466 ) -> 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
|
467 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
|
468 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
|
469 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
|
470 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
|
471 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
|
472 } |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
473 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
|
474 &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
|
475 )?; |
50234
2be6d5782728
dirstate: add a synchronisation point in the middle of the read
Raphaël Gomès <rgomes@octobus.net>
parents:
50228
diff
changeset
|
476 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
|
477 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
|
478 "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
|
479 ); |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
480 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
|
481 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
|
482 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
|
483 |
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 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
|
485 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
|
486 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
|
487 |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
488 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
|
489 // 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
|
490 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
|
491 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
|
492 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
|
493 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
|
494 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
|
495 // 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
|
496 // 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
|
497 // |
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 // 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
|
499 // `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
|
500 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
|
501 // 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
|
502 // 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
|
503 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
|
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 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
|
507 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
|
508 ) |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
509 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
510 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
511 } |
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 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
|
513 }; |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
514 OwningDirstateMap::new_v2( |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
515 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
|
516 ) |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
517 } 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
|
518 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
|
519 .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
|
520 .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
|
521 .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
|
522 { |
50243
6cce0afc1454
rust-dirstate: remember the data file uuid dirstate was loaded with
Raphaël Gomès <rgomes@octobus.net>
parents:
50239
diff
changeset
|
523 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
|
524 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
|
525 ), |
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
|
526 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
|
527 // 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
|
528 // 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
|
529 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
|
530 } |
491f3dd080eb
dirstate: deal with read-race for pure rust code path (rhg)
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50234
diff
changeset
|
531 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
|
532 } |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
533 }?; |
50222
ecd28d89c29e
dirstate-v2: add devel config option to control write behavior
Raphaël Gomès <rgomes@octobus.net>
parents:
50221
diff
changeset
|
534 |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
535 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
|
536 .config() |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
537 .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
|
538 .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
|
539 .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
|
540 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
|
541 "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
|
542 "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
|
543 "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
|
544 _ => DirstateMapWriteMode::Auto, |
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
545 }; |
50222
ecd28d89c29e
dirstate-v2: add devel config option to control write behavior
Raphaël Gomès <rgomes@octobus.net>
parents:
50221
diff
changeset
|
546 |
50227
cbd4c9234e25
rust-repo: move dirstate-v2 opening to a separate method
Raphaël Gomès <rgomes@octobus.net>
parents:
50222
diff
changeset
|
547 map.with_dmap_mut(|m| m.set_write_mode(write_mode)); |
50222
ecd28d89c29e
dirstate-v2: add devel config option to control write behavior
Raphaël Gomès <rgomes@octobus.net>
parents:
50221
diff
changeset
|
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(), |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
568 self.default_revlog_options(RevlogType::Changelog)?, |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
569 ) |
47958
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
570 } |
47959
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
571 |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
572 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
|
573 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
|
574 } |
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_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
|
577 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
|
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 |
49090
a5ef50becea8
rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49005
diff
changeset
|
580 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
|
581 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
|
582 &self.store_vfs(), |
51867
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
583 self.default_revlog_options(RevlogType::Manifestlog)?, |
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
|
584 ) |
47959
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
585 } |
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
586 |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
587 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
|
588 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
|
589 } |
21d25e9ee58e
rust: Keep lazily-initialized Changelog and Manifest log on the Repo object
Simon Sapin <simon.sapin@octobus.net>
parents:
47958
diff
changeset
|
590 |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
591 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
|
592 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
|
593 } |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
594 |
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
|
595 /// 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
|
596 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
|
597 &self, |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
598 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
|
599 ) -> 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
|
600 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
|
601 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
|
602 .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
|
603 .manifest_node()? |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
604 .into(), |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
605 ) |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
606 } |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
607 |
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 /// 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
|
609 pub fn manifest_for_rev( |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
610 &self, |
50977
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50660
diff
changeset
|
611 revision: UncheckedRevision, |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
612 ) -> 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
|
613 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
|
614 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
|
615 .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
|
616 .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
|
617 .into(), |
47964
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
618 ) |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
619 } |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47960
diff
changeset
|
620 |
48510
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
621 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
|
622 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
|
623 Ok(entry.tracked()) |
48510
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
624 } else { |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
625 Ok(false) |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
626 } |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
627 } |
7f633432ca92
rhg: Sub-repositories are not supported
Simon Sapin <simon.sapin@octobus.net>
parents:
48421
diff
changeset
|
628 |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47961
diff
changeset
|
629 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
|
630 Filelog::open( |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
631 self, |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
632 path, |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
633 self.default_revlog_options(RevlogType::Filelog)?, |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
634 ) |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47960
diff
changeset
|
635 } |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
636 /// 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
|
637 /// |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
638 /// The "wlock" must be held while calling this. |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
639 /// See for example `try_with_wlock_no_wait`. |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
640 /// |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
641 /// 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
|
642 /// lock? |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
643 pub fn write_dirstate(&self) -> Result<(), DirstateError> { |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
644 let map = self.dirstate_map()?; |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
645 // 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
|
646 // it’s unset |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
647 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
|
648 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
|
649 let (identity, uuid, data_size) = |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
650 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
|
651 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
|
652 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
|
653 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
|
654 |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
655 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
|
656 // 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
|
657 // 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
|
658 // 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
|
659 // 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
|
660 // `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
|
661 // 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
|
662 // |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
663 // 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
|
664 // 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
|
665 // (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
|
666 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
|
667 "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
|
668 ); |
07d030b38097
rust-dirstate-v2: don't write dirstate if data file has changed
Raphaël Gomès <rgomes@octobus.net>
parents:
50243
diff
changeset
|
669 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
|
670 } |
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 |
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 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
|
673 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
|
674 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
|
675 } else { |
1891086f6c7f
dirstate: use more than a bool to control append behavior
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
50211
diff
changeset
|
676 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
|
677 }; |
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
|
678 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
|
679 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
|
680 |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
681 // 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
|
682 // deletion. |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
683 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
|
684 Some(uuid) => { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
685 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
|
686 .map_err(|_| { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
687 HgError::corrupted( |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
688 "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
|
689 ) |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
690 })? |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
691 .to_owned(); |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
692 if append { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
693 (as_str, None) |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
694 } else { |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
695 (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
|
696 } |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
697 } |
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
698 None => (DirstateDocket::new_uid(), None), |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
699 }; |
49150
f2ef6a4f918f
rhg: fix dirstate-v2 data file removal system
Raphaël Gomès <rgomes@octobus.net>
parents:
49146
diff
changeset
|
700 |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
701 let data_filename = format!("dirstate.{}", uuid); |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
702 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
|
703 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
|
704 options.write(true); |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
705 |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
706 // 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
|
707 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
708 // - 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
|
709 // 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
|
710 // 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
|
711 // all such garbage. |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
712 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
713 // - 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
|
714 // don't need that. |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
715 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
716 // - 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
|
717 // 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
|
718 // 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
|
719 // 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
|
720 // |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
721 if !append { |
50211
f5e4248e5bce
dirstate: add some debug output when writing the dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50180
diff
changeset
|
722 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
|
723 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
|
724 } else { |
f5e4248e5bce
dirstate: add some debug output when writing the dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50180
diff
changeset
|
725 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
|
726 } |
49202
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
727 |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
728 let data_size = (|| { |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
729 // 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
|
730 // returns `ErrorKind::AlreadyExists`? Collision chance of two |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
731 // random IDs is one in 2**32 |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
732 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
|
733 if append { |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
734 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
|
735 } |
49202
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
736 file.write_all(&data)?; |
2d0e22171ef9
rhg: align the dirstate v2 writing algorithm with python
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
49150
diff
changeset
|
737 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
|
738 file.stream_position() |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
739 })() |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
740 .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
|
741 |
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
|
742 let packed_dirstate = DirstateDocket::serialize( |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
743 parents, |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
744 tree_metadata, |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
745 data_size, |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
746 uuid.as_bytes(), |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
747 ) |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
748 .map_err(|_: std::num::TryFromIntError| { |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
749 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
|
750 })?; |
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
|
751 |
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
|
752 (packed_dirstate, old_uuid) |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
753 } else { |
50245
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
754 let identity = self.dirstate_identity()?; |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
755 if identity != map.old_identity() { |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
756 // 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
|
757 // 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
|
758 // 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
|
759 // `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
|
760 // reading anyway. |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
761 // |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
762 // 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
|
763 // without taking the lock. |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
764 // (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
|
765 log::debug!( |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
766 "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
|
767 ); |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
768 return Ok(()); |
dbe09fb038fc
rhg: remember the inode of .hg/dirstate
Raphaël Gomès <rgomes@octobus.net>
parents:
50244
diff
changeset
|
769 } |
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
|
770 (map.pack_v1(parents)?, None) |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
771 }; |
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
|
772 |
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
|
773 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
|
774 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
|
775 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
|
776 // 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
|
777 // new data file was written. |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
49145
diff
changeset
|
778 vfs.remove_file(format!("dirstate.{}", uuid))?; |
802e2c25dab8
rust-dirstate-v2: clean up previous data file after the docket is written
Raphaël Gomès <rgomes@octobus.net>
parents:
49145
diff
changeset
|
779 } |
48421
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
780 Ok(()) |
2097f63575a5
rhg: Add Repo::write_dirstate
Simon Sapin <simon.sapin@octobus.net>
parents:
48420
diff
changeset
|
781 } |
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
|
782 |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
783 pub fn default_revlog_options( |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
784 &self, |
51867
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
785 revlog_type: RevlogType, |
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
|
786 ) -> Result<RevlogOpenOptions, HgError> { |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
787 let requirements = self.requirements(); |
51867
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
788 let is_changelog = revlog_type == RevlogType::Changelog; |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
789 let version = if is_changelog |
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
|
790 && requirements.contains(CHANGELOGV2_REQUIREMENT) |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
791 { |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
792 let compute_rank = self |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
793 .config() |
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 .get_bool(b"experimental", b"changelog-v2.compute-rank")?; |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
795 RevlogVersionOptions::ChangelogV2 { compute_rank } |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
796 } else if requirements.contains(REVLOGV2_REQUIREMENT) { |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
797 RevlogVersionOptions::V2 |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
798 } else if requirements.contains(REVLOGV1_REQUIREMENT) { |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
799 RevlogVersionOptions::V1 { |
51867
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
800 general_delta: requirements.contains(GENERALDELTA_REQUIREMENT), |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
801 inline: !is_changelog, |
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
|
802 } |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
803 } else { |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
804 RevlogVersionOptions::V0 |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
805 }; |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
806 Ok(RevlogOpenOptions { |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
807 version, |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
808 // We don't need to dance around the slow path like in the Python |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
809 // implementation since we know we have access to the fast code. |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
810 use_nodemap: requirements.contains(NODEMAP_REQUIREMENT), |
51867
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
811 delta_config: RevlogDeltaConfig::new( |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
812 self.config(), |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
813 self.requirements(), |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
814 revlog_type, |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
815 )?, |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
816 data_config: RevlogDataConfig::new( |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
817 self.config(), |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
818 self.requirements(), |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
819 )?, |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
820 feature_config: RevlogFeatureConfig::new( |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
821 self.config(), |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
822 requirements, |
69b804c8e09e
rust: use new revlog configs in all revlog opening code
Raphaël Gomès <rgomes@octobus.net>
parents:
51191
diff
changeset
|
823 )?, |
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
|
824 }) |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
51120
diff
changeset
|
825 } |
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
|
826 |
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
|
827 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
|
828 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
|
829 .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
|
830 .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
|
831 } |
52036
d7bc6e482033
rust-repo: add a method to set the current parents
Raphaël Gomès <rgomes@octobus.net>
parents:
52035
diff
changeset
|
832 |
d7bc6e482033
rust-repo: add a method to set the current parents
Raphaël Gomès <rgomes@octobus.net>
parents:
52035
diff
changeset
|
833 /// 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
|
834 /// |
d7bc6e482033
rust-repo: add a method to set the current parents
Raphaël Gomès <rgomes@octobus.net>
parents:
52035
diff
changeset
|
835 /// TODO |
d7bc6e482033
rust-repo: add a method to set the current parents
Raphaël Gomès <rgomes@octobus.net>
parents:
52035
diff
changeset
|
836 /// 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
|
837 /// - 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
|
838 /// - 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
|
839 /// - 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
|
840 /// 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
|
841 /// 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
|
842 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
|
843 &self, |
d7bc6e482033
rust-repo: add a method to set the current parents
Raphaël Gomès <rgomes@octobus.net>
parents:
52035
diff
changeset
|
844 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
|
845 ) -> Result<(), HgError> { |
d7bc6e482033
rust-repo: add a method to set the current parents
Raphaël Gomès <rgomes@octobus.net>
parents:
52035
diff
changeset
|
846 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
|
847 *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
|
848 Ok(()) |
d7bc6e482033
rust-repo: add a method to set the current parents
Raphaël Gomès <rgomes@octobus.net>
parents:
52035
diff
changeset
|
849 } |
47958
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
850 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
851 |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
852 /// 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
|
853 /// |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
854 /// 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
|
855 /// 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
|
856 /// 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
|
857 /// 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
|
858 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
|
859 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
|
860 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
861 |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
862 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
|
863 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
|
864 Self { |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
865 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
|
866 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
867 } |
fc208d6faed3
rust: Move lazy initialization of `Repo::dirstate_map` into a generic struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47956
diff
changeset
|
868 |
48419
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
869 fn set(&self, value: T) { |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
870 *self.value.borrow_mut() = Some(value) |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
871 } |
c8659e61073d
rhg: Make Repo::dirstate_parents a LazyCell
Simon Sapin <simon.sapin@octobus.net>
parents:
48417
diff
changeset
|
872 |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
873 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
|
874 &self, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
875 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
|
876 ) -> 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
|
877 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
|
878 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
|
879 drop(borrowed); |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
880 // 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
|
881 // 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
|
882 // needed. |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
883 *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
|
884 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
|
885 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
886 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
|
887 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
888 |
49177
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
889 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
|
890 &self, |
90a15199cbc6
rust-repo: make `Send` by not storing functions in `LazyCell`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49164
diff
changeset
|
891 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
|
892 ) -> 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
|
893 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
|
894 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
|
895 *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
|
896 } |
81aedf1fc897
rust: Add Repo::dirstate_map and use it in `rhg status`
Simon Sapin <simon.sapin@octobus.net>
parents:
47952
diff
changeset
|
897 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
|
898 } |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
diff
changeset
|
899 } |